velocious 1.0.700 → 1.0.702
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/README.md +1 -0
- package/build/configuration-types.js +73 -3
- package/build/configuration.js +113 -20
- package/build/frontend-model-resource/base-resource.js +150 -2
- package/build/frontend-models/resource-definition.js +47 -0
- package/build/src/configuration-types.d.ts +168 -7
- package/build/src/configuration-types.d.ts.map +1 -1
- package/build/src/configuration-types.js +68 -4
- package/build/src/configuration.d.ts +22 -2
- package/build/src/configuration.d.ts.map +1 -1
- package/build/src/configuration.js +110 -20
- package/build/src/frontend-model-resource/base-resource.d.ts +76 -3
- package/build/src/frontend-model-resource/base-resource.d.ts.map +1 -1
- package/build/src/frontend-model-resource/base-resource.js +127 -3
- package/build/src/frontend-models/resource-definition.d.ts.map +1 -1
- package/build/src/frontend-models/resource-definition.js +43 -1
- package/build/src/sync/local-mutation-log.d.ts +6 -3
- package/build/src/sync/local-mutation-log.d.ts.map +1 -1
- package/build/src/sync/local-mutation-log.js +11 -4
- package/build/src/sync/peer-mutation-bundle.d.ts +26 -0
- package/build/src/sync/peer-mutation-bundle.d.ts.map +1 -1
- package/build/src/sync/peer-mutation-bundle.js +7 -1
- package/build/src/sync/sync-api-client.d.ts +3 -1
- package/build/src/sync/sync-api-client.d.ts.map +1 -1
- package/build/src/sync/sync-api-client.js +46 -8
- package/build/src/sync/sync-client-types.d.ts +24 -12
- package/build/src/sync/sync-client-types.d.ts.map +1 -1
- package/build/src/sync/sync-client-types.js +7 -5
- package/build/src/sync/sync-client.d.ts +101 -0
- package/build/src/sync/sync-client.d.ts.map +1 -1
- package/build/src/sync/sync-client.js +236 -24
- package/build/src/sync/sync-offline-session.d.ts +328 -0
- package/build/src/sync/sync-offline-session.d.ts.map +1 -0
- package/build/src/sync/sync-offline-session.js +617 -0
- package/build/src/sync/sync-resource-base.d.ts +26 -28
- package/build/src/sync/sync-resource-base.d.ts.map +1 -1
- package/build/src/sync/sync-resource-base.js +11 -45
- package/build/sync/local-mutation-log.js +10 -3
- package/build/sync/peer-mutation-bundle.js +6 -0
- package/build/sync/sync-api-client.js +53 -7
- package/build/sync/sync-client-types.js +6 -4
- package/build/sync/sync-client.js +264 -21
- package/build/sync/sync-offline-session.js +713 -0
- package/build/sync/sync-resource-base.js +10 -53
- package/package.json +1 -1
- package/src/configuration-types.js +73 -3
- package/src/configuration.js +113 -20
- package/src/frontend-model-resource/base-resource.js +150 -2
- package/src/frontend-models/resource-definition.js +47 -0
- package/src/sync/local-mutation-log.js +10 -3
- package/src/sync/peer-mutation-bundle.js +6 -0
- package/src/sync/sync-api-client.js +53 -7
- package/src/sync/sync-client-types.js +6 -4
- package/src/sync/sync-client.js +264 -21
- package/src/sync/sync-offline-session.js +713 -0
- package/src/sync/sync-resource-base.js +10 -53
|
@@ -17,6 +17,23 @@ export type ChangeDeliverableSyncEntry = Record<string, ReturnType<typeof JSON.p
|
|
|
17
17
|
resourceId: string;
|
|
18
18
|
resourceType: string;
|
|
19
19
|
};
|
|
20
|
+
/**
|
|
21
|
+
* Optional client-declared sync scope carried on a changes request.
|
|
22
|
+
* @typedef {object} SerializedChangesScope
|
|
23
|
+
* @property {Record<string, ReturnType<typeof JSON.parse>>} conditions - Plain attribute conditions from the client query.
|
|
24
|
+
* @property {string | null} resourceType - Client resource/model name the scope was declared for, or null for the all-types (user) scope: one scope covering every resource type this resource authorizes for the caller, so a sync authorizes once however many types it serves.
|
|
25
|
+
* @property {string[] | null} resourceTypes - For the all-types scope, the resource types the client can apply. A cheap delivery/type filter only - it narrows, never widens, what the app's authorization already allows. Null for a type-declared scope.
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* One published sync entry as delivered to the per-delivery access re-check
|
|
29
|
+
* ({@link SyncResourceBase#changeDeliverable}): the complete broadcast sync
|
|
30
|
+
* entry — including the immutable sync-row id, actor-specific metadata, and
|
|
31
|
+
* any other app fields the publisher put on it — with `resourceId` and
|
|
32
|
+
* `resourceType` normalized to strings. Apps authorizing by exact-row
|
|
33
|
+
* identity read the extra fields; overrides that only read
|
|
34
|
+
* `resourceId`/`resourceType` keep working unchanged.
|
|
35
|
+
* @typedef {Record<string, ReturnType<typeof JSON.parse>> & {resourceId: string, resourceType: string}} ChangeDeliverableSyncEntry
|
|
36
|
+
*/
|
|
20
37
|
/**
|
|
21
38
|
* Base resource for Velocious sync endpoints.
|
|
22
39
|
*
|
|
@@ -36,36 +53,17 @@ export default class SyncResourceBase<TModelClass extends typeof import("../data
|
|
|
36
53
|
*/
|
|
37
54
|
static ReplayServiceClass: typeof import("./sync-envelope-replay-service.js").default | undefined;
|
|
38
55
|
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* @
|
|
43
|
-
static quickSearchColumns: string[] | null;
|
|
44
|
-
/**
|
|
45
|
-
* Applies frontend-model index searches, expanding declared quick searches.
|
|
46
|
-
* @param {object} args - Search args.
|
|
47
|
-
* @param {import("../frontend-model-resource/base-resource.js").FrontendModelResourceController} args.controller - Controller handling the query.
|
|
48
|
-
* @param {import("../frontend-model-resource/base-resource.js").FrontendModelResourceAnyQuery} args.query - Query instance.
|
|
49
|
-
* @param {import("../frontend-model-resource/base-resource.js").FrontendModelResourceSearch} args.search - Search params.
|
|
50
|
-
* @returns {void}
|
|
56
|
+
* Keeps the sync resource's established public error contract for invalid
|
|
57
|
+
* quick-search payloads; the quick-search mechanism itself lives on
|
|
58
|
+
* FrontendModelBaseResource.
|
|
59
|
+
* @returns {string} - Error label.
|
|
51
60
|
*/
|
|
52
|
-
|
|
53
|
-
controller: import("../frontend-model-resource/base-resource.js").FrontendModelResourceController;
|
|
54
|
-
query: import("../frontend-model-resource/base-resource.js").FrontendModelResourceAnyQuery;
|
|
55
|
-
search: import("../frontend-model-resource/base-resource.js").FrontendModelResourceSearch;
|
|
56
|
-
}): void;
|
|
61
|
+
quickSearchErrorLabel(): string;
|
|
57
62
|
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
* @param {import("../frontend-model-resource/base-resource.js").FrontendModelResourceSearch} args.search - Search payload.
|
|
63
|
-
* @returns {boolean} Whether the search was handled as a quick search.
|
|
64
|
-
*/
|
|
65
|
-
applyQuickSearch({ query, search }: {
|
|
66
|
-
query: import("../frontend-model-resource/base-resource.js").FrontendModelResourceAnyQuery;
|
|
67
|
-
search: import("../frontend-model-resource/base-resource.js").FrontendModelResourceSearch;
|
|
68
|
-
}): boolean;
|
|
63
|
+
* Keeps the established public error code for invalid quick-search payloads.
|
|
64
|
+
* @returns {string} - Error code.
|
|
65
|
+
*/
|
|
66
|
+
quickSearchErrorCode(): string;
|
|
69
67
|
/**
|
|
70
68
|
* Returns a stable change-feed page after app authorization.
|
|
71
69
|
* @returns {Promise<Record<string, ReturnType<typeof JSON.parse>>>} Change-feed page result.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-resource-base.d.ts","sourceRoot":"","sources":["../../../src/sync/sync-resource-base.js"],"names":[],"mappings":"AAIA,OAAO,yBAAyB,MAAM,6CAA6C,CAAA;
|
|
1
|
+
{"version":3,"file":"sync-resource-base.d.ts","sourceRoot":"","sources":["../../../src/sync/sync-resource-base.js"],"names":[],"mappings":"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"}
|
|
@@ -4,7 +4,6 @@ import FrontendModelBaseResource from "../frontend-model-resource/base-resource.
|
|
|
4
4
|
import SyncEnvelopeReplayService from "./sync-envelope-replay-service.js";
|
|
5
5
|
import SyncModelChangeFeedService from "./sync-model-change-feed-service.js";
|
|
6
6
|
import { syncUpstreamImporterForConfiguration } from "./sync-upstream-importer.js";
|
|
7
|
-
import VelociousError from "../velocious-error.js";
|
|
8
7
|
/**
|
|
9
8
|
* Optional client-declared sync scope carried on a changes request.
|
|
10
9
|
* @typedef {object} SerializedChangesScope
|
|
@@ -22,7 +21,6 @@ import VelociousError from "../velocious-error.js";
|
|
|
22
21
|
* `resourceId`/`resourceType` keep working unchanged.
|
|
23
22
|
* @typedef {Record<string, ReturnType<typeof JSON.parse>> & {resourceId: string, resourceType: string}} ChangeDeliverableSyncEntry
|
|
24
23
|
*/
|
|
25
|
-
const QUICK_SEARCH_COLUMN = "quickSearch";
|
|
26
24
|
/**
|
|
27
25
|
* Base resource for Velocious sync endpoints.
|
|
28
26
|
*
|
|
@@ -42,52 +40,20 @@ export default class SyncResourceBase extends FrontendModelBaseResource {
|
|
|
42
40
|
*/
|
|
43
41
|
static ReplayServiceClass = undefined;
|
|
44
42
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* @
|
|
49
|
-
static quickSearchColumns = null;
|
|
50
|
-
/**
|
|
51
|
-
* Applies frontend-model index searches, expanding declared quick searches.
|
|
52
|
-
* @param {object} args - Search args.
|
|
53
|
-
* @param {import("../frontend-model-resource/base-resource.js").FrontendModelResourceController} args.controller - Controller handling the query.
|
|
54
|
-
* @param {import("../frontend-model-resource/base-resource.js").FrontendModelResourceAnyQuery} args.query - Query instance.
|
|
55
|
-
* @param {import("../frontend-model-resource/base-resource.js").FrontendModelResourceSearch} args.search - Search params.
|
|
56
|
-
* @returns {void}
|
|
43
|
+
* Keeps the sync resource's established public error contract for invalid
|
|
44
|
+
* quick-search payloads; the quick-search mechanism itself lives on
|
|
45
|
+
* FrontendModelBaseResource.
|
|
46
|
+
* @returns {string} - Error label.
|
|
57
47
|
*/
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
return;
|
|
61
|
-
super.applyFrontendModelIndexSearch({ controller, query, search });
|
|
48
|
+
quickSearchErrorLabel() {
|
|
49
|
+
return "Sync quick search";
|
|
62
50
|
}
|
|
63
51
|
/**
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
* @param {object} args - Search args.
|
|
67
|
-
* @param {import("../frontend-model-resource/base-resource.js").FrontendModelResourceAnyQuery} args.query - Query to filter.
|
|
68
|
-
* @param {import("../frontend-model-resource/base-resource.js").FrontendModelResourceSearch} args.search - Search payload.
|
|
69
|
-
* @returns {boolean} Whether the search was handled as a quick search.
|
|
52
|
+
* Keeps the established public error code for invalid quick-search payloads.
|
|
53
|
+
* @returns {string} - Error code.
|
|
70
54
|
*/
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (!quickSearchColumns || quickSearchColumns.length === 0)
|
|
74
|
-
return false;
|
|
75
|
-
if (search.path.length > 0 || search.column !== QUICK_SEARCH_COLUMN)
|
|
76
|
-
return false;
|
|
77
|
-
if (search.operator !== "like") {
|
|
78
|
-
throw VelociousError.safe("Sync quick search must use the like operator.", { code: "sync-invalid-quick-search" });
|
|
79
|
-
}
|
|
80
|
-
if (typeof search.value !== "string") {
|
|
81
|
-
throw VelociousError.safe("Sync quick search must be a string.", { code: "sync-invalid-quick-search" });
|
|
82
|
-
}
|
|
83
|
-
const trimmedValue = search.value.trim();
|
|
84
|
-
if (!trimmedValue)
|
|
85
|
-
return true;
|
|
86
|
-
const tableSql = query.driver.quoteTable(query.getTableReferenceForJoin());
|
|
87
|
-
const likeValue = `%${trimmedValue}%`;
|
|
88
|
-
const conditions = quickSearchColumns.map((columnName) => (`${tableSql}.${query.driver.quoteColumn(columnName)} LIKE ${query.driver.quote(likeValue)}`));
|
|
89
|
-
query.where(`(${conditions.join(" OR ")})`);
|
|
90
|
-
return true;
|
|
55
|
+
quickSearchErrorCode() {
|
|
56
|
+
return "sync-invalid-quick-search";
|
|
91
57
|
}
|
|
92
58
|
// The declarative `static writableAttributes` permit list lives on
|
|
93
59
|
// FrontendModelBaseResource so every frontend-model resource can declare
|
|
@@ -259,4 +225,4 @@ export default class SyncResourceBase extends FrontendModelBaseResource {
|
|
|
259
225
|
return ResourceClass.ReplayServiceClass ?? SharedResource?.ReplayServiceClass ?? SyncEnvelopeReplayService;
|
|
260
226
|
}
|
|
261
227
|
}
|
|
262
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1yZXNvdXJjZS1iYXNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3N5bmMvc3luYy1yZXNvdXJjZS1iYXNlLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLEVBQUMsb0JBQW9CLEVBQUMsTUFBTSxTQUFTLENBQUE7QUFFNUMsT0FBTyx5QkFBeUIsTUFBTSw2Q0FBNkMsQ0FBQTtBQUNuRixPQUFPLHlCQUF5QixNQUFNLG1DQUFtQyxDQUFBO0FBQ3pFLE9BQU8sMEJBQTBCLE1BQU0scUNBQXFDLENBQUE7QUFDNUUsT0FBTyxFQUFDLG9DQUFvQyxFQUFDLE1BQU0sNkJBQTZCLENBQUE7QUFDaEYsT0FBTyxjQUFjLE1BQU0sdUJBQXVCLENBQUE7QUFFbEQ7Ozs7OztHQU1HO0FBRUg7Ozs7Ozs7OztHQVNHO0FBQ0gsTUFBTSxtQkFBbUIsR0FBRyxhQUFhLENBQUE7QUFFekM7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLENBQUMsT0FBTyxPQUFPLGdCQUFpQixTQUFRLHlCQUF5QjtJQUNyRSwrRUFBK0U7SUFDL0UsTUFBTSxDQUFDLFVBQVUsR0FBRyxTQUFTLENBQUE7SUFFN0I7Ozs7T0FJRztJQUNILE1BQU0sQ0FBQyxrQkFBa0IsR0FBRyxTQUFTLENBQUE7SUFFckM7Ozs7aUNBSTZCO0lBQzdCLE1BQU0sQ0FBQyxrQkFBa0IsR0FBRyxJQUFJLENBQUE7SUFFaEM7Ozs7Ozs7T0FPRztJQUNILDZCQUE2QixDQUFDLEVBQUMsVUFBVSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUM7UUFDdkQsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsRUFBQyxLQUFLLEVBQUUsTUFBTSxFQUFDLENBQUM7WUFBRSxPQUFNO1FBRWxELEtBQUssQ0FBQyw2QkFBNkIsQ0FBQyxFQUFDLFVBQVUsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFDLENBQUMsQ0FBQTtJQUNsRSxDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNI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QTtJQUNyQyxDQUFDO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDSCxrQkFBa0I7UUFDaEIsTUFBTSxhQUFhLEdBQUcsc0NBQXNDLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUE7UUFDL0UsTUFBTSxjQUFjLEdBQUcsNkNBQTZDLENBQUMsQ0FBQyxhQUFhLENBQUMsbUJBQW1CLEVBQUUsSUFBSSxJQUFJLENBQUMsQ0FBQTtRQUVsSCxPQUFPLGFBQWEsQ0FBQyxrQkFBa0IsSUFBSSxjQUFjLEVBQUUsa0JBQWtCLElBQUkseUJBQXlCLENBQUE7SUFDNUcsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCB7Zm9yY2VkTm9uQmxhbmtTdHJpbmd9IGZyb20gXCJ0eXBhbmljXCJcblxuaW1wb3J0IEZyb250ZW5kTW9kZWxCYXNlUmVzb3VyY2UgZnJvbSBcIi4uL2Zyb250ZW5kLW1vZGVsLXJlc291cmNlL2Jhc2UtcmVzb3VyY2UuanNcIlxuaW1wb3J0IFN5bmNFbnZlbG9wZVJlcGxheVNlcnZpY2UgZnJvbSBcIi4vc3luYy1lbnZlbG9wZS1yZXBsYXktc2VydmljZS5qc1wiXG5pbXBvcnQgU3luY01vZGVsQ2hhbmdlRmVlZFNlcnZpY2UgZnJvbSBcIi4vc3luYy1tb2RlbC1jaGFuZ2UtZmVlZC1zZXJ2aWNlLmpzXCJcbmltcG9ydCB7c3luY1Vwc3RyZWFtSW1wb3J0ZXJGb3JDb25maWd1cmF0aW9ufSBmcm9tIFwiLi9zeW5jLXVwc3RyZWFtLWltcG9ydGVyLmpzXCJcbmltcG9ydCBWZWxvY2lvdXNFcnJvciBmcm9tIFwiLi4vdmVsb2Npb3VzLWVycm9yLmpzXCJcblxuLyoqXG4gKiBPcHRpb25hbCBjbGllbnQtZGVjbGFyZWQgc3luYyBzY29wZSBjYXJyaWVkIG9uIGEgY2hhbmdlcyByZXF1ZXN0LlxuICogQHR5cGVkZWYge29iamVjdH0gU2VyaWFsaXplZENoYW5nZXNTY29wZVxuICogQHByb3BlcnR5IHtSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj59IGNvbmRpdGlvbnMgLSBQbGFpbiBhdHRyaWJ1dGUgY29uZGl0aW9ucyBmcm9tIHRoZSBjbGllbnQgcXVlcnkuXG4gKiBAcHJvcGVydHkge3N0cmluZyB8IG51bGx9IHJlc291cmNlVHlwZSAtIENsaWVudCByZXNvdXJjZS9tb2RlbCBuYW1lIHRoZSBzY29wZSB3YXMgZGVjbGFyZWQgZm9yLCBvciBudWxsIGZvciB0aGUgYWxsLXR5cGVzICh1c2VyKSBzY29wZTogb25lIHNjb3BlIGNvdmVyaW5nIGV2ZXJ5IHJlc291cmNlIHR5cGUgdGhpcyByZXNvdXJjZSBhdXRob3JpemVzIGZvciB0aGUgY2FsbGVyLCBzbyBhIHN5bmMgYXV0aG9yaXplcyBvbmNlIGhvd2V2ZXIgbWFueSB0eXBlcyBpdCBzZXJ2ZXMuXG4gKiBAcHJvcGVydHkge3N0cmluZ1tdIHwgbnVsbH0gcmVzb3VyY2VUeXBlcyAtIEZvciB0aGUgYWxsLXR5cGVzIHNjb3BlLCB0aGUgcmVzb3VyY2UgdHlwZXMgdGhlIGNsaWVudCBjYW4gYXBwbHkuIEEgY2hlYXAgZGVsaXZlcnkvdHlwZSBmaWx0ZXIgb25seSAtIGl0IG5hcnJvd3MsIG5ldmVyIHdpZGVucywgd2hhdCB0aGUgYXBwJ3MgYXV0aG9yaXphdGlvbiBhbHJlYWR5IGFsbG93cy4gTnVsbCBmb3IgYSB0eXBlLWRlY2xhcmVkIHNjb3BlLlxuICovXG5cbi8qKlxuICogT25lIHB1Ymxpc2hlZCBzeW5jIGVudHJ5IGFzIGRlbGl2ZXJlZCB0byB0aGUgcGVyLWRlbGl2ZXJ5IGFjY2VzcyByZS1jaGVja1xuICogKHtAbGluayBTeW5jUmVzb3VyY2VCYXNlI2NoYW5nZURlbGl2ZXJhYmxlfSk6IHRoZSBjb21wbGV0ZSBicm9hZGNhc3Qgc3luY1xuICogZW50cnkg4oCUIGluY2x1ZGluZyB0aGUgaW1tdXRhYmxlIHN5bmMtcm93IGlkLCBhY3Rvci1zcGVjaWZpYyBtZXRhZGF0YSwgYW5kXG4gKiBhbnkgb3RoZXIgYXBwIGZpZWxkcyB0aGUgcHVibGlzaGVyIHB1dCBvbiBpdCDigJQgd2l0aCBgcmVzb3VyY2VJZGAgYW5kXG4gKiBgcmVzb3VyY2VUeXBlYCBub3JtYWxpemVkIHRvIHN0cmluZ3MuIEFwcHMgYXV0aG9yaXppbmcgYnkgZXhhY3Qtcm93XG4gKiBpZGVudGl0eSByZWFkIHRoZSBleHRyYSBmaWVsZHM7IG92ZXJyaWRlcyB0aGF0IG9ubHkgcmVhZFxuICogYHJlc291cmNlSWRgL2ByZXNvdXJjZVR5cGVgIGtlZXAgd29ya2luZyB1bmNoYW5nZWQuXG4gKiBAdHlwZWRlZiB7UmVjb3JkPHN0cmluZywgUmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4+ICYge3Jlc291cmNlSWQ6IHN0cmluZywgcmVzb3VyY2VUeXBlOiBzdHJpbmd9fSBDaGFuZ2VEZWxpdmVyYWJsZVN5bmNFbnRyeVxuICovXG5jb25zdCBRVUlDS19TRUFSQ0hfQ09MVU1OID0gXCJxdWlja1NlYXJjaFwiXG5cbi8qKlxuICogQmFzZSByZXNvdXJjZSBmb3IgVmVsb2Npb3VzIHN5bmMgZW5kcG9pbnRzLlxuICpcbiAqIFZlbG9jaW91cyBvd25zIHRoZSBjaGFuZ2VzL3JlcGxheSBvcmNoZXN0cmF0aW9uIChzY29wZSBwYXJzaW5nLCBmZWVkIHBhZ2luZyxcbiAqIHJlcGxheSBkZWxlZ2F0aW9uLCByZXNwb25zZSBzaGFwZSkgd2hpbGUgYXBwcyBzdWJjbGFzcyBhbmQgb25seSBkZWNsYXJlXG4gKiBhdXRob3JpemF0aW9uLCBmZWVkIHNjb3BpbmcsIGFuZCB0aGVpciByZXBsYXkgc2VydmljZS5cbiAqIEB0ZW1wbGF0ZSB7dHlwZW9mIGltcG9ydChcIi4uL2RhdGFiYXNlL3JlY29yZC9pbmRleC5qc1wiKS5kZWZhdWx0fSBbVE1vZGVsQ2xhc3M9dHlwZW9mIGltcG9ydChcIi4uL2RhdGFiYXNlL3JlY29yZC9pbmRleC5qc1wiKS5kZWZhdWx0XVxuICogQGF1Z21lbnRzIHtGcm9udGVuZE1vZGVsQmFzZVJlc291cmNlPFRNb2RlbENsYXNzPn1cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU3luY1Jlc291cmNlQmFzZSBleHRlbmRzIEZyb250ZW5kTW9kZWxCYXNlUmVzb3VyY2Uge1xuICAvKiogQHR5cGUge3R5cGVvZiBpbXBvcnQoXCIuLi9kYXRhYmFzZS9yZWNvcmQvaW5kZXguanNcIikuZGVmYXVsdCB8IHVuZGVmaW5lZH0gKi9cbiAgc3RhdGljIE1vZGVsQ2xhc3MgPSB1bmRlZmluZWRcblxuICAvKipcbiAgICogUmVwbGF5IHNlcnZpY2UgY2xhc3MgaGFuZGxpbmcgcmVwbGF5IG11dGF0aW9ucyBmb3IgdGhpcyByZXNvdXJjZSxcbiAgICogZGVjbGFyZWQgaW5zdGVhZCBvZiBvdmVycmlkaW5nIHtAbGluayBTeW5jUmVzb3VyY2VCYXNlI3JlcGxheVNlcnZpY2VDbGFzc30uXG4gICAqIEB0eXBlIHt0eXBlb2YgaW1wb3J0KFwiLi9zeW5jLWVudmVsb3BlLXJlcGxheS1zZXJ2aWNlLmpzXCIpLmRlZmF1bHQgfCB1bmRlZmluZWR9XG4gICAqL1xuICBzdGF0aWMgUmVwbGF5U2VydmljZUNsYXNzID0gdW5kZWZpbmVkXG5cbiAgLyoqXG4gICAqIERlY2xhcmF0aXZlIHF1aWNrLXNlYXJjaCB0ZXh0IGNvbHVtbnMuIFdoZW4gZGVjbGFyZWQsIGFuIGluZGV4IHNlYXJjaCBvblxuICAgKiB0aGUgcHNldWRvLWNvbHVtbiBgcXVpY2tTZWFyY2hgIGV4cGFuZHMgdG8gYW4gT1Igb2YgTElLRSBjb25kaXRpb25zIG92ZXJcbiAgICogdGhlc2Ugcm9vdC10YWJsZSBjb2x1bW5zIGluc3RlYWQgb2YgaGl0dGluZyB0aGUgY29udHJvbGxlciBkZWZhdWx0LlxuICAgKiBAdHlwZSB7c3RyaW5nW10gfCBudWxsfSAqL1xuICBzdGF0aWMgcXVpY2tTZWFyY2hDb2x1bW5zID0gbnVsbFxuXG4gIC8qKlxuICAgKiBBcHBsaWVzIGZyb250ZW5kLW1vZGVsIGluZGV4IHNlYXJjaGVzLCBleHBhbmRpbmcgZGVjbGFyZWQgcXVpY2sgc2VhcmNoZXMuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gU2VhcmNoIGFyZ3MuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZnJvbnRlbmQtbW9kZWwtcmVzb3VyY2UvYmFzZS1yZXNvdXJjZS5qc1wiKS5Gcm9udGVuZE1vZGVsUmVzb3VyY2VDb250cm9sbGVyfSBhcmdzLmNvbnRyb2xsZXIgLSBDb250cm9sbGVyIGhhbmRsaW5nIHRoZSBxdWVyeS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9mcm9udGVuZC1tb2RlbC1yZXNvdXJjZS9iYXNlLXJlc291cmNlLmpzXCIpLkZyb250ZW5kTW9kZWxSZXNvdXJjZUFueVF1ZXJ5fSBhcmdzLnF1ZXJ5IC0gUXVlcnkgaW5zdGFuY2UuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZnJvbnRlbmQtbW9kZWwtcmVzb3VyY2UvYmFzZS1yZXNvdXJjZS5qc1wiKS5Gcm9udGVuZE1vZGVsUmVzb3VyY2VTZWFyY2h9IGFyZ3Muc2VhcmNoIC0gU2VhcmNoIHBhcmFtcy5cbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICBhcHBseUZyb250ZW5kTW9kZWxJbmRleFNlYXJjaCh7Y29udHJvbGxlciwgcXVlcnksIHNlYXJjaH0pIHtcbiAgICBpZiAodGhpcy5hcHBseVF1aWNrU2VhcmNoKHtxdWVyeSwgc2VhcmNofSkpIHJldHVyblxuXG4gICAgc3VwZXIuYXBwbHlGcm9udGVuZE1vZGVsSW5kZXhTZWFyY2goe2NvbnRyb2xsZXIsIHF1ZXJ5LCBzZWFyY2h9KVxuICB9XG5cbiAgLyoqXG4gICAqIEV4cGFuZHMgYSBgcXVpY2tTZWFyY2hgIHBzZXVkby1jb2x1bW4gc2VhcmNoIGludG8gYW4gT1Igb2YgTElLRSBjb25kaXRpb25zXG4gICAqIG92ZXIgdGhlIGRlY2xhcmVkIHtAbGluayBTeW5jUmVzb3VyY2VCYXNlLnF1aWNrU2VhcmNoQ29sdW1uc30uXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gU2VhcmNoIGFyZ3MuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZnJvbnRlbmQtbW9kZWwtcmVzb3VyY2UvYmFzZS1yZXNvdXJjZS5qc1wiKS5Gcm9udGVuZE1vZGVsUmVzb3VyY2VBbnlRdWVyeX0gYXJncy5xdWVyeSAtIFF1ZXJ5IHRvIGZpbHRlci5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9mcm9udGVuZC1tb2RlbC1yZXNvdXJjZS9iYXNlLXJlc291cmNlLmpzXCIpLkZyb250ZW5kTW9kZWxSZXNvdXJjZVNlYXJjaH0gYXJncy5zZWFyY2ggLSBTZWFyY2ggcGF5bG9hZC5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IFdoZXRoZXIgdGhlIHNlYXJjaCB3YXMgaGFuZGxlZCBhcyBhIHF1aWNrIHNlYXJjaC5cbiAgICovXG4gIGFwcGx5UXVpY2tTZWFyY2goe3F1ZXJ5LCBzZWFyY2h9KSB7XG4gICAgY29uc3QgcXVpY2tTZWFyY2hDb2x1bW5zID0gLyoqIEB0eXBlIHt0eXBlb2YgU3luY1Jlc291cmNlQmFzZX0gKi8gKHRoaXMuY29uc3RydWN0b3IpLnF1aWNrU2VhcmNoQ29sdW1uc1xuXG4gICAgaWYgKCFxdWlja1NlYXJjaENvbHVtbnMgfHwgcXVpY2tTZWFyY2hDb2x1bW5zLmxlbmd0aCA9PT0gMCkgcmV0dXJuIGZhbHNlXG4gICAgaWYgKHNlYXJjaC5wYXRoLmxlbmd0aCA+IDAgfHwgc2VhcmNoLmNvbHVtbiAhPT0gUVVJQ0tfU0VBUkNIX0NPTFVNTikgcmV0dXJuIGZhbHNlXG5cbiAgICBpZiAoc2VhcmNoLm9wZXJhdG9yICE9PSBcImxpa2VcIikge1xuICAgICAgdGhyb3cgVmVsb2Npb3VzRXJyb3Iuc2FmZShcIlN5bmMgcXVpY2sgc2VhcmNoIG11c3QgdXNlIHRoZSBsaWtlIG9wZXJhdG9yLlwiLCB7Y29kZTogXCJzeW5jLWludmFsaWQtcXVpY2stc2VhcmNoXCJ9KVxuICAgIH1cblxuICAgIGlmICh0eXBlb2Ygc2VhcmNoLnZhbHVlICE9PSBcInN0cmluZ1wiKSB7XG4gICAgICB0aHJvdyBWZWxvY2lvdXNFcnJvci5zYWZlKFwiU3luYyBxdWljayBzZWFyY2ggbXVzdCBiZSBhIHN0cmluZy5cIiwge2NvZGU6IFwic3luYy1pbnZhbGlkLXF1aWNrLXNlYXJjaFwifSlcbiAgICB9XG5cbiAgICBjb25zdCB0cmltbWVkVmFsdWUgPSBzZWFyY2gudmFsdWUudHJpbSgpXG5cbiAgICBpZiAoIXRyaW1tZWRWYWx1ZSkgcmV0dXJuIHRydWVcblxuICAgIGNvbnN0IHRhYmxlU3FsID0gcXVlcnkuZHJpdmVyLnF1b3RlVGFibGUocXVlcnkuZ2V0VGFibGVSZWZlcmVuY2VGb3JKb2luKCkpXG4gICAgY29uc3QgbGlrZVZhbHVlID0gYCUke3RyaW1tZWRWYWx1ZX0lYFxuICAgIGNvbnN0IGNvbmRpdGlvbnMgPSBxdWlja1NlYXJjaENvbHVtbnMubWFwKChjb2x1bW5OYW1lKSA9PiAoXG4gICAgICBgJHt0YWJsZVNxbH0uJHtxdWVyeS5kcml2ZXIucXVvdGVDb2x1bW4oY29sdW1uTmFtZSl9IExJS0UgJHtxdWVyeS5kcml2ZXIucXVvdGUobGlrZVZhbHVlKX1gXG4gICAgKSlcblxuICAgIHF1ZXJ5LndoZXJlKGAoJHtjb25kaXRpb25zLmpvaW4oXCIgT1IgXCIpfSlgKVxuXG4gICAgcmV0dXJuIHRydWVcbiAgfVxuXG4gIC8vIFRoZSBkZWNsYXJhdGl2ZSBgc3RhdGljIHdyaXRhYmxlQXR0cmlidXRlc2AgcGVybWl0IGxpc3QgbGl2ZXMgb25cbiAgLy8gRnJvbnRlbmRNb2RlbEJhc2VSZXNvdXJjZSBzbyBldmVyeSBmcm9udGVuZC1tb2RlbCByZXNvdXJjZSBjYW4gZGVjbGFyZVxuICAvLyBvbmU7IHN5bmMgcmVzb3VyY2VzIGluaGVyaXQgaXQgdW5jaGFuZ2VkLlxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgc3RhYmxlIGNoYW5nZS1mZWVkIHBhZ2UgYWZ0ZXIgYXBwIGF1dGhvcml6YXRpb24uXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pj59IENoYW5nZS1mZWVkIHBhZ2UgcmVzdWx0LlxuICAgKi9cbiAgYXN5bmMgY2hhbmdlcygpIHtcbiAgICBjb25zdCBwYXJhbXMgPSB0aGlzLnBhcmFtcygpXG4gICAgY29uc3Qgc2NvcGUgPSB0aGlzLmNoYW5nZXNTY29wZShwYXJhbXMpXG5cbiAgICBhd2FpdCB0aGlzLmF1dGhvcml6ZUNoYW5nZXMoe3BhcmFtcywgc2NvcGV9KVxuXG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuY2hhbmdlRmVlZFNlcnZpY2Uoe3BhcmFtcywgc2NvcGV9KS5jaGFuZ2VzKClcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXBsYXlzIGNsaWVudCBzeW5jIGVudmVsb3BlcyB0aHJvdWdoIHRoZSBhcHAgcmVwbGF5IHNlcnZpY2UuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pj59IFJlcGxheSByZXN1bHQgd2l0aCBwZXItc3luYyBzdGF0ZXMuXG4gICAqL1xuICBhc3luYyByZXBsYXkoKSB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5idWlsZFJlcGxheVNlcnZpY2UoKS5yZXBsYXkodGhpcy5wYXJhbXMoKSlcblxuICAgIGlmIChyZXN1bHQuc3RhdHVzID09PSBcImVycm9yXCIpIHJldHVybiByZXN1bHRcblxuICAgIHJldHVybiB7c3RhdHVzOiBcInN1Y2Nlc3NcIiwgc3luY3M6IHJlc3VsdC5zeW5jc31cbiAgfVxuXG4gIC8qKlxuICAgKiBQYXJzZXMgdGhlIG9wdGlvbmFsIGNsaWVudC1kZWNsYXJlZCBzY29wZSBmcm9tIHJlcXVlc3QgcGFyYW1zLlxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pn0gcGFyYW1zIC0gUmVxdWVzdCBwYXJhbXMuXG4gICAqIEByZXR1cm5zIHtTZXJpYWxpemVkQ2hhbmdlc1Njb3BlIHwgbnVsbH0gUGFyc2VkIHNjb3BlLCBvciBudWxsIHdoZW4gdGhlIGNsaWVudCBzZW50IG5vbmUuXG4gICAqL1xuICBjaGFuZ2VzU2NvcGUocGFyYW1zKSB7XG4gICAgY29uc3Qgc2NvcGUgPSBwYXJhbXMuc2NvcGVcblxuICAgIGlmIChzY29wZSA9PT0gdW5kZWZpbmVkIHx8IHNjb3BlID09PSBudWxsKSByZXR1cm4gbnVsbFxuXG4gICAgaWYgKHR5cGVvZiBzY29wZSAhPT0gXCJvYmplY3RcIiB8fCBBcnJheS5pc0FycmF5KHNjb3BlKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBTeW5jIGNoYW5nZXMgc2NvcGUgbXVzdCBiZSBhbiBvYmplY3QsIGdvdDogJHtTdHJpbmcoc2NvcGUpfWApXG4gICAgfVxuXG4gICAgY29uc3Qgc2NvcGVQYXJhbXMgPSAvKiogQHR5cGUge1JlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pn0gKi8gKHNjb3BlKVxuICAgIGNvbnN0IHJlc291cmNlVHlwZSA9IHNjb3BlUGFyYW1zLnJlc291cmNlVHlwZSA9PT0gbnVsbCB8fCBzY29wZVBhcmFtcy5yZXNvdXJjZVR5cGUgPT09IHVuZGVmaW5lZFxuICAgICAgPyBudWxsXG4gICAgICA6IGZvcmNlZE5vbkJsYW5rU3RyaW5nKHNjb3BlUGFyYW1zLnJlc291cmNlVHlwZSwgXCJyZXNvdXJjZVR5cGVcIilcbiAgICBjb25zdCByZXNvdXJjZVR5cGVzID0gdGhpcy5jaGFuZ2VzU2NvcGVSZXNvdXJjZVR5cGVzKHNjb3BlUGFyYW1zLnJlc291cmNlVHlwZXMpXG4gICAgY29uc3QgY29uZGl0aW9ucyA9IHNjb3BlUGFyYW1zLmNvbmRpdGlvbnNcblxuICAgIGlmICghY29uZGl0aW9ucyB8fCB0eXBlb2YgY29uZGl0aW9ucyAhPT0gXCJvYmplY3RcIiB8fCBBcnJheS5pc0FycmF5KGNvbmRpdGlvbnMpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFN5bmMgY2hhbmdlcyBzY29wZS5jb25kaXRpb25zIG11c3QgYmUgYW4gb2JqZWN0LCBnb3Q6ICR7U3RyaW5nKGNvbmRpdGlvbnMpfWApXG4gICAgfVxuXG4gICAgcmV0dXJuIHtjb25kaXRpb25zOiAvKiogQHR5cGUge1JlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pn0gKi8gKGNvbmRpdGlvbnMpLCByZXNvdXJjZVR5cGUsIHJlc291cmNlVHlwZXN9XG4gIH1cblxuICAvKipcbiAgICogUGFyc2VzIHRoZSBvcHRpb25hbCByZXNvdXJjZS10eXBlIGxpc3QgYW4gYWxsLXR5cGVzIHNjb3BlIGRlY2xhcmVzLlxuICAgKiBAcGFyYW0ge1JldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+fSB2YWx1ZSAtIFJhdyBgc2NvcGUucmVzb3VyY2VUeXBlc2AgcGFyYW0uXG4gICAqIEByZXR1cm5zIHtzdHJpbmdbXSB8IG51bGx9IERlY2xhcmVkIHJlc291cmNlIHR5cGVzLCBvciBudWxsIHdoZW4gdGhlIGNsaWVudCBzZW50IG5vbmUuXG4gICAqL1xuICBjaGFuZ2VzU2NvcGVSZXNvdXJjZVR5cGVzKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQgfHwgdmFsdWUgPT09IG51bGwpIHJldHVybiBudWxsXG5cbiAgICBpZiAoIUFycmF5LmlzQXJyYXkodmFsdWUpKSB0aHJvdyBuZXcgRXJyb3IoYFN5bmMgY2hhbmdlcyBzY29wZS5yZXNvdXJjZVR5cGVzIG11c3QgYmUgYW4gYXJyYXksIGdvdDogJHtTdHJpbmcodmFsdWUpfWApXG5cbiAgICByZXR1cm4gdmFsdWUubWFwKChyZXNvdXJjZVR5cGUpID0+IGZvcmNlZE5vbkJsYW5rU3RyaW5nKHJlc291cmNlVHlwZSwgXCJyZXNvdXJjZVR5cGVzXCIpKVxuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkcyB0aGUgY2hhbmdlLWZlZWQgc2VydmljZSBzZXJ2aW5nIHRoaXMgY2hhbmdlcyByZXF1ZXN0LlxuICAgKiBAcGFyYW0ge3twYXJhbXM6IFJlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Piwgc2NvcGU6IFNlcmlhbGl6ZWRDaGFuZ2VzU2NvcGUgfCBudWxsfX0gYXJncyAtIFJlcXVlc3QgcGFyYW1zIGFuZCBwYXJzZWQgc2NvcGUuXG4gICAqIEByZXR1cm5zIHt7Y2hhbmdlczogKCkgPT4gUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj4+fX0gQ2hhbmdlLWZlZWQgc2VydmljZS5cbiAgICovXG4gIGNoYW5nZUZlZWRTZXJ2aWNlKHtwYXJhbXMsIHNjb3BlfSkge1xuICAgIHJldHVybiBuZXcgU3luY01vZGVsQ2hhbmdlRmVlZFNlcnZpY2Uoe1xuICAgICAgbW9kZWxDbGFzczogdGhpcy5zeW5jTW9kZWxDbGFzcygpLFxuICAgICAgcGFyYW1zLFxuICAgICAgc2NvcGVRdWVyeTogKHtxdWVyeX0pID0+IHRoaXMuc2NvcGVDaGFuZ2VzUXVlcnkoe3BhcmFtcywgcXVlcnksIHNjb3BlfSlcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkcyB0aGUgYXBwIHJlcGxheSBzZXJ2aWNlIGhhbmRsaW5nIHRoaXMgcmVwbGF5IHJlcXVlc3QuIFRoZSByZXNvdXJjZVxuICAgKiBhYmlsaXR5LCBjb250ZXh0LCBjb25maWd1cmF0aW9uLCBhbmQgbG9jYWxzIGFyZSBwbHVtYmVkIGluIHVuZGVyIHRoZVxuICAgKiBhcHAtZGVjbGFyZWQge0BsaW5rIFN5bmNSZXNvdXJjZUJhc2UjcmVwbGF5U2VydmljZUFyZ3N9IChhcHAgYXJncyB3aW4pIHNvXG4gICAqIHRoZSBkZWZhdWx0IHJlc291cmNlLXJvdXRlZCByZXBsYXkgd29ya3Mgd2l0aG91dCB3aXJpbmcuXG4gICAqIEByZXR1cm5zIHtpbXBvcnQoXCIuL3N5bmMtZW52ZWxvcGUtcmVwbGF5LXNlcnZpY2UuanNcIikuZGVmYXVsdH0gUmVwbGF5IHNlcnZpY2UgaW5zdGFuY2UuXG4gICAqL1xuICBidWlsZFJlcGxheVNlcnZpY2UoKSB7XG4gICAgY29uc3QgUmVwbGF5U2VydmljZUNsYXNzID0gdGhpcy5yZXBsYXlTZXJ2aWNlQ2xhc3MoKVxuXG4gICAgcmV0dXJuIG5ldyBSZXBsYXlTZXJ2aWNlQ2xhc3Moe1xuICAgICAgYWJpbGl0eTogdGhpcy5hYmlsaXR5LFxuICAgICAgYWJpbGl0eUNvbnRleHQ6IHRoaXMuZ2V0Q29udGV4dCgpLFxuICAgICAgY29uZmlndXJhdGlvbjogdGhpcy5jb250cm9sbGVyID8gdGhpcy5jb250cm9sbGVySW5zdGFuY2UoKS5nZXRDb25maWd1cmF0aW9uKCkgOiB1bmRlZmluZWQsXG4gICAgICBsb2NhbHM6IHRoaXMuZ2V0TG9jYWxzKCksXG4gICAgICAuLi50aGlzLnJlcGxheVNlcnZpY2VBcmdzKClcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgY29uc3RydWN0b3IgYXJncyBmb3IgdGhlIGFwcCByZXBsYXkgc2VydmljZS5cbiAgICogQHJldHVybnMge1JlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pn0gUmVwbGF5IHNlcnZpY2UgY29uc3RydWN0b3IgYXJncy5cbiAgICovXG4gIHJlcGxheVNlcnZpY2VBcmdzKCkge1xuICAgIHJldHVybiB7fVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHN5bmMgbW9kZWwgY2xhc3MgYmFja2luZyB0aGUgY2hhbmdlIGZlZWQuXG4gICAqIEByZXR1cm5zIHt0eXBlb2YgaW1wb3J0KFwiLi4vZGF0YWJhc2UvcmVjb3JkL2luZGV4LmpzXCIpLmRlZmF1bHR9IFN5bmMgbW9kZWwgY2xhc3MuXG4gICAqL1xuICBzeW5jTW9kZWxDbGFzcygpIHtcbiAgICBjb25zdCBtb2RlbENsYXNzID0gLyoqIEB0eXBlIHt0eXBlb2YgU3luY1Jlc291cmNlQmFzZX0gKi8gKHRoaXMuY29uc3RydWN0b3IpLk1vZGVsQ2xhc3NcblxuICAgIGlmICghbW9kZWxDbGFzcykgdGhyb3cgbmV3IEVycm9yKGAke3RoaXMuY29uc3RydWN0b3IubmFtZX0gbXVzdCBkZWZpbmUgc3RhdGljIE1vZGVsQ2xhc3NgKVxuXG4gICAgcmV0dXJuIG1vZGVsQ2xhc3NcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBzaGFyZWQgdXBzdHJlYW0gaW1wb3J0ZXIgZm9yIHRoaXMgcmVzb3VyY2UncyBjb25maWd1cmF0aW9uLiBBcHBzXG4gICAqIHVzZSBpdCBpbnNpZGUge0BsaW5rIFN5bmNSZXNvdXJjZUJhc2UjYXV0aG9yaXplQ2hhbmdlc30gKG9yIGEgbGVnYWN5IHRyaWdnZXJcbiAgICogZW5kcG9pbnQpIHRvIHJ1biB0aGUgdXBzdHJlYW0gaW1wb3J0IHRoYXQga2VlcHMgdGhlIGZlZWQgc2VsZi1zdXN0YWluaW5nLFxuICAgKiB3aXRoIGNvYWxlc2NpbmcgYW5kIHRocm90dGxpbmcgb3duZWQgYnkgdGhlIGZyYW1ld29yay5cbiAgICogQHJldHVybnMge2ltcG9ydChcIi4vc3luYy11cHN0cmVhbS1pbXBvcnRlci5qc1wiKS5kZWZhdWx0fSBTaGFyZWQgaW1wb3J0ZXIgZm9yIHRoZSBjdXJyZW50IGNvbmZpZ3VyYXRpb24uXG4gICAqL1xuICBzeW5jVXBzdHJlYW1JbXBvcnRlcigpIHtcbiAgICByZXR1cm4gc3luY1Vwc3RyZWFtSW1wb3J0ZXJGb3JDb25maWd1cmF0aW9uKHRoaXMuY29uZmlndXJhdGlvbigpKVxuICB9XG5cbiAgLyoqXG4gICAqIEF1dGhvcml6ZXMgdGhlIGN1cnJlbnQgY29udGV4dCBmb3IgcmVhZGluZyB0aGUgcmVxdWVzdGVkIGNoYW5nZXMuXG4gICAqIEBwYXJhbSB7e3BhcmFtczogUmVjb3JkPHN0cmluZywgUmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4+LCBzY29wZTogU2VyaWFsaXplZENoYW5nZXNTY29wZSB8IG51bGx9fSBfYXJncyAtIFJlcXVlc3QgcGFyYW1zIGFuZCBwYXJzZWQgc2NvcGUuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBSZXNvbHZlcyB3aGVuIGFjY2VzcyBpcyBhbGxvd2VkOyB0aHJvd3Mgb3RoZXJ3aXNlLlxuICAgKi9cbiAgYXN5bmMgYXV0aG9yaXplQ2hhbmdlcyhfYXJncykge1xuICAgIHRocm93IG5ldyBFcnJvcihcIlN5bmNSZXNvdXJjZUJhc2UjYXV0aG9yaXplQ2hhbmdlcyBtdXN0IGJlIGltcGxlbWVudGVkXCIpXG4gIH1cblxuICAvKipcbiAgICogQXBwbGllcyBhcHAgdmlzaWJpbGl0eSBzY29waW5nIG9udG8gdGhlIGNoYW5nZS1mZWVkIHF1ZXJ5LlxuICAgKiBAcGFyYW0ge3twYXJhbXM6IFJlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+PiwgcXVlcnk6IGltcG9ydChcIi4uL2RhdGFiYXNlL3F1ZXJ5L21vZGVsLWNsYXNzLXF1ZXJ5LmpzXCIpLmRlZmF1bHQsIHNjb3BlOiBTZXJpYWxpemVkQ2hhbmdlc1Njb3BlIHwgbnVsbH19IF9hcmdzIC0gUmVxdWVzdCBwYXJhbXMsIGZlZWQgcXVlcnksIGFuZCBwYXJzZWQgc2NvcGUuXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgc2NvcGVDaGFuZ2VzUXVlcnkoX2FyZ3MpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJTeW5jUmVzb3VyY2VCYXNlI3Njb3BlQ2hhbmdlc1F1ZXJ5IG11c3QgYmUgaW1wbGVtZW50ZWRcIilcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWNpZGVzIHdoZXRoZXIgb25lIHB1Ymxpc2hlZCBjaGFuZ2UgaXMgZGVsaXZlcmFibGUgdG8gYSB1c2VyLXNjb3BlXG4gICAqIHN1YnNjcmlwdGlvbiAodGhlIGZyYW1ld29yayBzeW5jIGNoYW5uZWwncyBwZXItZGVsaXZlcnkgYWNjZXNzIHJlLWNoZWNrKS5cbiAgICogVGhlIGRlZmF1bHQgcmV1c2VzIHRoZSBhcHAncyBhYmlsaXR5IHNjb3Bpbmc6IGl0IGFwcGxpZXNcbiAgICoge0BsaW5rIFN5bmNSZXNvdXJjZUJhc2Ujc2NvcGVDaGFuZ2VzUXVlcnl9IHRvIHRoZSBjaGFuZ2UtZmVlZCBtb2RlbCDigJQgd2hpY2hcbiAgICogZm9yIGFuIGVtcHR5LWNvbmRpdGlvbnMgdXNlciBzY29wZSBmYWxscyBiYWNrIHRvIGFiaWxpdHkgc2NvcGluZyDigJQgYW5kXG4gICAqIGNoZWNrcyB3aGV0aGVyIHRoZSBwdWJsaXNoZWQgY2hhbmdlJ3MgZmVlZCByb3cgaXMgdmlzaWJsZSB3aXRoaW4gdGhhdFxuICAgKiBzY29wZS4gQXBwcyBnZXQgdGhpcyBmb3IgZnJlZSBmcm9tIHRoZSBzY29waW5nIHRoZXkgYWxyZWFkeSBkZWNsYXJlZDtcbiAgICogb3ZlcnJpZGUgb25seSBmb3IgY3VzdG9tIHBlci1kZWxpdmVyeSBydWxlcy5cbiAgICpcbiAgICogVGhlIGBzeW5jYCBhcmd1bWVudCBpcyB0aGUgY29tcGxldGUgYnJvYWRjYXN0IHN5bmMgZW50cnkg4oCUIGltbXV0YWJsZVxuICAgKiBzeW5jLXJvdyBpZCwgYWN0b3Itc3BlY2lmaWMgbWV0YWRhdGEsIGFuZCBhbnkgb3RoZXIgcHVibGlzaGVyIGZpZWxkcyDigJRcbiAgICogd2l0aCBgcmVzb3VyY2VJZGAvYHJlc291cmNlVHlwZWAgbm9ybWFsaXplZCB0byBzdHJpbmdzLCBzbyBhbiBvdmVycmlkZVxuICAgKiBjYW4gYXV0aG9yaXplIGNvbmN1cnJlbnQgdGFyZ2V0ZWQgYW5kIHNoYXJlZCBicm9hZGNhc3RzIGZvciB0aGUgc2FtZVxuICAgKiByZXNvdXJjZSBpZGVudGl0eSBpbmRlcGVuZGVudGx5IGJ5IHRoZWlyIGV4YWN0LXJvdyBpZGVudGl0eS4gVGhlIGNoYW5uZWxcbiAgICogbmV2ZXIgbXV0YXRlcyB0aGUgcHVibGlzaGVkIGVudHJ5OyBub3JtYWxpemF0aW9uIGhhcHBlbnMgb24gYSBjb3B5LlxuICAgKiBAcGFyYW0ge3twYXJhbXM6IFJlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Piwgc2NvcGU6IFNlcmlhbGl6ZWRDaGFuZ2VzU2NvcGUgfCBudWxsLCBzeW5jOiBDaGFuZ2VEZWxpdmVyYWJsZVN5bmNFbnRyeX19IGFyZ3MgLSBSZXF1ZXN0IHBhcmFtcywgc3Vic2NyaXB0aW9uIHNjb3BlLCBhbmQgdGhlIHB1Ymxpc2hlZCBzeW5jIGVudHJ5LlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxib29sZWFuPn0gV2hldGhlciB0aGUgY2hhbmdlIG1heSBiZSBkZWxpdmVyZWQgdG8gdGhpcyBzdWJzY3JpcHRpb24uXG4gICAqL1xuICBhc3luYyBjaGFuZ2VEZWxpdmVyYWJsZSh7cGFyYW1zLCBzY29wZSwgc3luY30pIHtcbiAgICBjb25zdCBxdWVyeSA9IHRoaXMuc3luY01vZGVsQ2xhc3MoKS53aGVyZSh7fSlcblxuICAgIHRoaXMuc2NvcGVDaGFuZ2VzUXVlcnkoe3BhcmFtcywgcXVlcnksIHNjb3BlfSlcbiAgICBxdWVyeS53aGVyZSh7cmVzb3VyY2VfaWQ6IFN0cmluZyhzeW5jLnJlc291cmNlSWQpLCByZXNvdXJjZV90eXBlOiBTdHJpbmcoc3luYy5yZXNvdXJjZVR5cGUpfSlcblxuICAgIHJldHVybiBCb29sZWFuKGF3YWl0IHF1ZXJ5LmZpcnN0KCkpXG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZXMgdGhlIHJlcGxheSBzZXJ2aWNlIGNsYXNzIGhhbmRsaW5nIHJlcGxheSBtdXRhdGlvbnM6IHRoZVxuICAgKiBkZWNsYXJhdGl2ZSB7QGxpbmsgU3luY1Jlc291cmNlQmFzZS5SZXBsYXlTZXJ2aWNlQ2xhc3N9IHN0YXRpYyAoc2hhcmVkXG4gICAqIHJlc291cmNlcyBpbmNsdWRlZCkgd2hlbiBkZWNsYXJlZCwgb3RoZXJ3aXNlXG4gICAqIHtAbGluayBTeW5jRW52ZWxvcGVSZXBsYXlTZXJ2aWNlfSwgd2hpY2ggcmVzb3VyY2Utcm91dGVzIG11dGF0aW9ucyB0aHJvdWdoXG4gICAqIHRoZSBwbHVtYmVkIGNvbmZpZ3VyYXRpb24gcmVnaXN0cnkuIEFwcHMgZGVjbGFyZSB0aGUgc3RhdGljIGluc3RlYWQgb2ZcbiAgICogb3ZlcnJpZGluZyB0aGlzIG1ldGhvZC5cbiAgICogQHJldHVybnMge3R5cGVvZiBpbXBvcnQoXCIuL3N5bmMtZW52ZWxvcGUtcmVwbGF5LXNlcnZpY2UuanNcIikuZGVmYXVsdH0gUmVwbGF5IHNlcnZpY2UgY2xhc3MuXG4gICAqL1xuICByZXBsYXlTZXJ2aWNlQ2xhc3MoKSB7XG4gICAgY29uc3QgUmVzb3VyY2VDbGFzcyA9IC8qKiBAdHlwZSB7dHlwZW9mIFN5bmNSZXNvdXJjZUJhc2V9ICovICh0aGlzLmNvbnN0cnVjdG9yKVxuICAgIGNvbnN0IFNoYXJlZFJlc291cmNlID0gLyoqIEB0eXBlIHt0eXBlb2YgU3luY1Jlc291cmNlQmFzZSB8IG51bGx9ICovIChSZXNvdXJjZUNsYXNzLnNoYXJlZFJlc291cmNlQ2xhc3MoKSA/PyBudWxsKVxuXG4gICAgcmV0dXJuIFJlc291cmNlQ2xhc3MuUmVwbGF5U2VydmljZUNsYXNzID8/IFNoYXJlZFJlc291cmNlPy5SZXBsYXlTZXJ2aWNlQ2xhc3MgPz8gU3luY0VudmVsb3BlUmVwbGF5U2VydmljZVxuICB9XG59XG4iXX0=
|
|
228
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1yZXNvdXJjZS1iYXNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3N5bmMvc3luYy1yZXNvdXJjZS1iYXNlLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLEVBQUMsb0JBQW9CLEVBQUMsTUFBTSxTQUFTLENBQUE7QUFFNUMsT0FBTyx5QkFBeUIsTUFBTSw2Q0FBNkMsQ0FBQTtBQUNuRixPQUFPLHlCQUF5QixNQUFNLG1DQUFtQyxDQUFBO0FBQ3pFLE9BQU8sMEJBQTBCLE1BQU0scUNBQXFDLENBQUE7QUFDNUUsT0FBTyxFQUFDLG9DQUFvQyxFQUFDLE1BQU0sNkJBQTZCLENBQUE7QUFFaEY7Ozs7OztHQU1HO0FBRUg7Ozs7Ozs7OztHQVNHO0FBQ0g7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLENBQUMsT0FBTyxPQUFPLGdCQUFpQixTQUFRLHlCQUF5QjtJQUNyRSwrRUFBK0U7SUFDL0UsTUFBTSxDQUFDLFVBQVUsR0FBRyxTQUFTLENBQUE7SUFFN0I7Ozs7T0FJRztJQUNILE1BQU0sQ0FBQyxrQkFBa0IsR0FBRyxTQUFTLENBQUE7SUFFckM7Ozs7O09BS0c7SUFDSCxxQkFBcUI7UUFDbkIsT0FBTyxtQkFBbUIsQ0FBQTtJQUM1QixDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsb0JBQW9CO1FBQ2xCLE9BQU8sMkJBQTJCLENBQUE7SUFDcEMsQ0FBQztJQUVELG1FQUFtRTtJQUNuRSx5RUFBeUU7SUFDekUsNENBQTRDO0lBRTVDOzs7T0FHRztJQUNILEtBQUssQ0FBQyxPQUFPO1FBQ1gsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFBO1FBQzVCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUE7UUFFdkMsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsRUFBQyxNQUFNLEVBQUUsS0FBSyxFQUFDLENBQUMsQ0FBQTtRQUU1QyxP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QUFNLElBQUksS0FBSyxDQUFDLHdEQUF3RCxDQUFDLENBQUE7SUFDM0UsQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7T0FrQkc7SUFDSCxLQUFLLENBQUMsaUJBQWlCLENBQUMsRUFBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBQztRQUMzQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFBO1FBRTdDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxFQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFDLENBQUMsQ0FBQTtRQUM5QyxLQUFLLENBQUMsS0FBSyxDQUFDLEVBQUMsV0FBVyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUUsYUFBYSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLEVBQUMsQ0FBQyxDQUFBO1FBRTdGLE9BQU8sT0FBTyxDQUFDLE1BQU0sS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUE7SUFDckMsQ0FBQztJQUVEOzs7Ozs7OztPQVFHO0lBQ0gsa0JBQWtCO1FBQ2hCLE1BQU0sYUFBYSxHQUFHLHNDQUFzQyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFBO1FBQy9FLE1BQU0sY0FBYyxHQUFHLDZDQUE2QyxDQUFDLENBQUMsYUFBYSxDQUFDLG1CQUFtQixFQUFFLElBQUksSUFBSSxDQUFDLENBQUE7UUFFbEgsT0FBTyxhQUFhLENBQUMsa0JBQWtCLElBQUksY0FBYyxFQUFFLGtCQUFrQixJQUFJLHlCQUF5QixDQUFBO0lBQzVHLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQge2ZvcmNlZE5vbkJsYW5rU3RyaW5nfSBmcm9tIFwidHlwYW5pY1wiXG5cbmltcG9ydCBGcm9udGVuZE1vZGVsQmFzZVJlc291cmNlIGZyb20gXCIuLi9mcm9udGVuZC1tb2RlbC1yZXNvdXJjZS9iYXNlLXJlc291cmNlLmpzXCJcbmltcG9ydCBTeW5jRW52ZWxvcGVSZXBsYXlTZXJ2aWNlIGZyb20gXCIuL3N5bmMtZW52ZWxvcGUtcmVwbGF5LXNlcnZpY2UuanNcIlxuaW1wb3J0IFN5bmNNb2RlbENoYW5nZUZlZWRTZXJ2aWNlIGZyb20gXCIuL3N5bmMtbW9kZWwtY2hhbmdlLWZlZWQtc2VydmljZS5qc1wiXG5pbXBvcnQge3N5bmNVcHN0cmVhbUltcG9ydGVyRm9yQ29uZmlndXJhdGlvbn0gZnJvbSBcIi4vc3luYy11cHN0cmVhbS1pbXBvcnRlci5qc1wiXG5cbi8qKlxuICogT3B0aW9uYWwgY2xpZW50LWRlY2xhcmVkIHN5bmMgc2NvcGUgY2FycmllZCBvbiBhIGNoYW5nZXMgcmVxdWVzdC5cbiAqIEB0eXBlZGVmIHtvYmplY3R9IFNlcmlhbGl6ZWRDaGFuZ2VzU2NvcGVcbiAqIEBwcm9wZXJ0eSB7UmVjb3JkPHN0cmluZywgUmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4+fSBjb25kaXRpb25zIC0gUGxhaW4gYXR0cmlidXRlIGNvbmRpdGlvbnMgZnJvbSB0aGUgY2xpZW50IHF1ZXJ5LlxuICogQHByb3BlcnR5IHtzdHJpbmcgfCBudWxsfSByZXNvdXJjZVR5cGUgLSBDbGllbnQgcmVzb3VyY2UvbW9kZWwgbmFtZSB0aGUgc2NvcGUgd2FzIGRlY2xhcmVkIGZvciwgb3IgbnVsbCBmb3IgdGhlIGFsbC10eXBlcyAodXNlcikgc2NvcGU6IG9uZSBzY29wZSBjb3ZlcmluZyBldmVyeSByZXNvdXJjZSB0eXBlIHRoaXMgcmVzb3VyY2UgYXV0aG9yaXplcyBmb3IgdGhlIGNhbGxlciwgc28gYSBzeW5jIGF1dGhvcml6ZXMgb25jZSBob3dldmVyIG1hbnkgdHlwZXMgaXQgc2VydmVzLlxuICogQHByb3BlcnR5IHtzdHJpbmdbXSB8IG51bGx9IHJlc291cmNlVHlwZXMgLSBGb3IgdGhlIGFsbC10eXBlcyBzY29wZSwgdGhlIHJlc291cmNlIHR5cGVzIHRoZSBjbGllbnQgY2FuIGFwcGx5LiBBIGNoZWFwIGRlbGl2ZXJ5L3R5cGUgZmlsdGVyIG9ubHkgLSBpdCBuYXJyb3dzLCBuZXZlciB3aWRlbnMsIHdoYXQgdGhlIGFwcCdzIGF1dGhvcml6YXRpb24gYWxyZWFkeSBhbGxvd3MuIE51bGwgZm9yIGEgdHlwZS1kZWNsYXJlZCBzY29wZS5cbiAqL1xuXG4vKipcbiAqIE9uZSBwdWJsaXNoZWQgc3luYyBlbnRyeSBhcyBkZWxpdmVyZWQgdG8gdGhlIHBlci1kZWxpdmVyeSBhY2Nlc3MgcmUtY2hlY2tcbiAqICh7QGxpbmsgU3luY1Jlc291cmNlQmFzZSNjaGFuZ2VEZWxpdmVyYWJsZX0pOiB0aGUgY29tcGxldGUgYnJvYWRjYXN0IHN5bmNcbiAqIGVudHJ5IOKAlCBpbmNsdWRpbmcgdGhlIGltbXV0YWJsZSBzeW5jLXJvdyBpZCwgYWN0b3Itc3BlY2lmaWMgbWV0YWRhdGEsIGFuZFxuICogYW55IG90aGVyIGFwcCBmaWVsZHMgdGhlIHB1Ymxpc2hlciBwdXQgb24gaXQg4oCUIHdpdGggYHJlc291cmNlSWRgIGFuZFxuICogYHJlc291cmNlVHlwZWAgbm9ybWFsaXplZCB0byBzdHJpbmdzLiBBcHBzIGF1dGhvcml6aW5nIGJ5IGV4YWN0LXJvd1xuICogaWRlbnRpdHkgcmVhZCB0aGUgZXh0cmEgZmllbGRzOyBvdmVycmlkZXMgdGhhdCBvbmx5IHJlYWRcbiAqIGByZXNvdXJjZUlkYC9gcmVzb3VyY2VUeXBlYCBrZWVwIHdvcmtpbmcgdW5jaGFuZ2VkLlxuICogQHR5cGVkZWYge1JlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+PiAmIHtyZXNvdXJjZUlkOiBzdHJpbmcsIHJlc291cmNlVHlwZTogc3RyaW5nfX0gQ2hhbmdlRGVsaXZlcmFibGVTeW5jRW50cnlcbiAqL1xuLyoqXG4gKiBCYXNlIHJlc291cmNlIGZvciBWZWxvY2lvdXMgc3luYyBlbmRwb2ludHMuXG4gKlxuICogVmVsb2Npb3VzIG93bnMgdGhlIGNoYW5nZXMvcmVwbGF5IG9yY2hlc3RyYXRpb24gKHNjb3BlIHBhcnNpbmcsIGZlZWQgcGFnaW5nLFxuICogcmVwbGF5IGRlbGVnYXRpb24sIHJlc3BvbnNlIHNoYXBlKSB3aGlsZSBhcHBzIHN1YmNsYXNzIGFuZCBvbmx5IGRlY2xhcmVcbiAqIGF1dGhvcml6YXRpb24sIGZlZWQgc2NvcGluZywgYW5kIHRoZWlyIHJlcGxheSBzZXJ2aWNlLlxuICogQHRlbXBsYXRlIHt0eXBlb2YgaW1wb3J0KFwiLi4vZGF0YWJhc2UvcmVjb3JkL2luZGV4LmpzXCIpLmRlZmF1bHR9IFtUTW9kZWxDbGFzcz10eXBlb2YgaW1wb3J0KFwiLi4vZGF0YWJhc2UvcmVjb3JkL2luZGV4LmpzXCIpLmRlZmF1bHRdXG4gKiBAYXVnbWVudHMge0Zyb250ZW5kTW9kZWxCYXNlUmVzb3VyY2U8VE1vZGVsQ2xhc3M+fVxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTeW5jUmVzb3VyY2VCYXNlIGV4dGVuZHMgRnJvbnRlbmRNb2RlbEJhc2VSZXNvdXJjZSB7XG4gIC8qKiBAdHlwZSB7dHlwZW9mIGltcG9ydChcIi4uL2RhdGFiYXNlL3JlY29yZC9pbmRleC5qc1wiKS5kZWZhdWx0IHwgdW5kZWZpbmVkfSAqL1xuICBzdGF0aWMgTW9kZWxDbGFzcyA9IHVuZGVmaW5lZFxuXG4gIC8qKlxuICAgKiBSZXBsYXkgc2VydmljZSBjbGFzcyBoYW5kbGluZyByZXBsYXkgbXV0YXRpb25zIGZvciB0aGlzIHJlc291cmNlLFxuICAgKiBkZWNsYXJlZCBpbnN0ZWFkIG9mIG92ZXJyaWRpbmcge0BsaW5rIFN5bmNSZXNvdXJjZUJhc2UjcmVwbGF5U2VydmljZUNsYXNzfS5cbiAgICogQHR5cGUge3R5cGVvZiBpbXBvcnQoXCIuL3N5bmMtZW52ZWxvcGUtcmVwbGF5LXNlcnZpY2UuanNcIikuZGVmYXVsdCB8IHVuZGVmaW5lZH1cbiAgICovXG4gIHN0YXRpYyBSZXBsYXlTZXJ2aWNlQ2xhc3MgPSB1bmRlZmluZWRcblxuICAvKipcbiAgICogS2VlcHMgdGhlIHN5bmMgcmVzb3VyY2UncyBlc3RhYmxpc2hlZCBwdWJsaWMgZXJyb3IgY29udHJhY3QgZm9yIGludmFsaWRcbiAgICogcXVpY2stc2VhcmNoIHBheWxvYWRzOyB0aGUgcXVpY2stc2VhcmNoIG1lY2hhbmlzbSBpdHNlbGYgbGl2ZXMgb25cbiAgICogRnJvbnRlbmRNb2RlbEJhc2VSZXNvdXJjZS5cbiAgICogQHJldHVybnMge3N0cmluZ30gLSBFcnJvciBsYWJlbC5cbiAgICovXG4gIHF1aWNrU2VhcmNoRXJyb3JMYWJlbCgpIHtcbiAgICByZXR1cm4gXCJTeW5jIHF1aWNrIHNlYXJjaFwiXG4gIH1cblxuICAvKipcbiAgICogS2VlcHMgdGhlIGVzdGFibGlzaGVkIHB1YmxpYyBlcnJvciBjb2RlIGZvciBpbnZhbGlkIHF1aWNrLXNlYXJjaCBwYXlsb2Fkcy5cbiAgICogQHJldHVybnMge3N0cmluZ30gLSBFcnJvciBjb2RlLlxuICAgKi9cbiAgcXVpY2tTZWFyY2hFcnJvckNvZGUoKSB7XG4gICAgcmV0dXJuIFwic3luYy1pbnZhbGlkLXF1aWNrLXNlYXJjaFwiXG4gIH1cblxuICAvLyBUaGUgZGVjbGFyYXRpdmUgYHN0YXRpYyB3cml0YWJsZUF0dHJpYnV0ZXNgIHBlcm1pdCBsaXN0IGxpdmVzIG9uXG4gIC8vIEZyb250ZW5kTW9kZWxCYXNlUmVzb3VyY2Ugc28gZXZlcnkgZnJvbnRlbmQtbW9kZWwgcmVzb3VyY2UgY2FuIGRlY2xhcmVcbiAgLy8gb25lOyBzeW5jIHJlc291cmNlcyBpbmhlcml0IGl0IHVuY2hhbmdlZC5cblxuICAvKipcbiAgICogUmV0dXJucyBhIHN0YWJsZSBjaGFuZ2UtZmVlZCBwYWdlIGFmdGVyIGFwcCBhdXRob3JpemF0aW9uLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj4+fSBDaGFuZ2UtZmVlZCBwYWdlIHJlc3VsdC5cbiAgICovXG4gIGFzeW5jIGNoYW5nZXMoKSB7XG4gICAgY29uc3QgcGFyYW1zID0gdGhpcy5wYXJhbXMoKVxuICAgIGNvbnN0IHNjb3BlID0gdGhpcy5jaGFuZ2VzU2NvcGUocGFyYW1zKVxuXG4gICAgYXdhaXQgdGhpcy5hdXRob3JpemVDaGFuZ2VzKHtwYXJhbXMsIHNjb3BlfSlcblxuICAgIHJldHVybiBhd2FpdCB0aGlzLmNoYW5nZUZlZWRTZXJ2aWNlKHtwYXJhbXMsIHNjb3BlfSkuY2hhbmdlcygpXG4gIH1cblxuICAvKipcbiAgICogUmVwbGF5cyBjbGllbnQgc3luYyBlbnZlbG9wZXMgdGhyb3VnaCB0aGUgYXBwIHJlcGxheSBzZXJ2aWNlLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj4+fSBSZXBsYXkgcmVzdWx0IHdpdGggcGVyLXN5bmMgc3RhdGVzLlxuICAgKi9cbiAgYXN5bmMgcmVwbGF5KCkge1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuYnVpbGRSZXBsYXlTZXJ2aWNlKCkucmVwbGF5KHRoaXMucGFyYW1zKCkpXG5cbiAgICBpZiAocmVzdWx0LnN0YXR1cyA9PT0gXCJlcnJvclwiKSByZXR1cm4gcmVzdWx0XG5cbiAgICByZXR1cm4ge3N0YXR1czogXCJzdWNjZXNzXCIsIHN5bmNzOiByZXN1bHQuc3luY3N9XG4gIH1cblxuICAvKipcbiAgICogUGFyc2VzIHRoZSBvcHRpb25hbCBjbGllbnQtZGVjbGFyZWQgc2NvcGUgZnJvbSByZXF1ZXN0IHBhcmFtcy5cbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj59IHBhcmFtcyAtIFJlcXVlc3QgcGFyYW1zLlxuICAgKiBAcmV0dXJucyB7U2VyaWFsaXplZENoYW5nZXNTY29wZSB8IG51bGx9IFBhcnNlZCBzY29wZSwgb3IgbnVsbCB3aGVuIHRoZSBjbGllbnQgc2VudCBub25lLlxuICAgKi9cbiAgY2hhbmdlc1Njb3BlKHBhcmFtcykge1xuICAgIGNvbnN0IHNjb3BlID0gcGFyYW1zLnNjb3BlXG5cbiAgICBpZiAoc2NvcGUgPT09IHVuZGVmaW5lZCB8fCBzY29wZSA9PT0gbnVsbCkgcmV0dXJuIG51bGxcblxuICAgIGlmICh0eXBlb2Ygc2NvcGUgIT09IFwib2JqZWN0XCIgfHwgQXJyYXkuaXNBcnJheShzY29wZSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgU3luYyBjaGFuZ2VzIHNjb3BlIG11c3QgYmUgYW4gb2JqZWN0LCBnb3Q6ICR7U3RyaW5nKHNjb3BlKX1gKVxuICAgIH1cblxuICAgIGNvbnN0IHNjb3BlUGFyYW1zID0gLyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj59ICovIChzY29wZSlcbiAgICBjb25zdCByZXNvdXJjZVR5cGUgPSBzY29wZVBhcmFtcy5yZXNvdXJjZVR5cGUgPT09IG51bGwgfHwgc2NvcGVQYXJhbXMucmVzb3VyY2VUeXBlID09PSB1bmRlZmluZWRcbiAgICAgID8gbnVsbFxuICAgICAgOiBmb3JjZWROb25CbGFua1N0cmluZyhzY29wZVBhcmFtcy5yZXNvdXJjZVR5cGUsIFwicmVzb3VyY2VUeXBlXCIpXG4gICAgY29uc3QgcmVzb3VyY2VUeXBlcyA9IHRoaXMuY2hhbmdlc1Njb3BlUmVzb3VyY2VUeXBlcyhzY29wZVBhcmFtcy5yZXNvdXJjZVR5cGVzKVxuICAgIGNvbnN0IGNvbmRpdGlvbnMgPSBzY29wZVBhcmFtcy5jb25kaXRpb25zXG5cbiAgICBpZiAoIWNvbmRpdGlvbnMgfHwgdHlwZW9mIGNvbmRpdGlvbnMgIT09IFwib2JqZWN0XCIgfHwgQXJyYXkuaXNBcnJheShjb25kaXRpb25zKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBTeW5jIGNoYW5nZXMgc2NvcGUuY29uZGl0aW9ucyBtdXN0IGJlIGFuIG9iamVjdCwgZ290OiAke1N0cmluZyhjb25kaXRpb25zKX1gKVxuICAgIH1cblxuICAgIHJldHVybiB7Y29uZGl0aW9uczogLyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj59ICovIChjb25kaXRpb25zKSwgcmVzb3VyY2VUeXBlLCByZXNvdXJjZVR5cGVzfVxuICB9XG5cbiAgLyoqXG4gICAqIFBhcnNlcyB0aGUgb3B0aW9uYWwgcmVzb3VyY2UtdHlwZSBsaXN0IGFuIGFsbC10eXBlcyBzY29wZSBkZWNsYXJlcy5cbiAgICogQHBhcmFtIHtSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPn0gdmFsdWUgLSBSYXcgYHNjb3BlLnJlc291cmNlVHlwZXNgIHBhcmFtLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nW10gfCBudWxsfSBEZWNsYXJlZCByZXNvdXJjZSB0eXBlcywgb3IgbnVsbCB3aGVuIHRoZSBjbGllbnQgc2VudCBub25lLlxuICAgKi9cbiAgY2hhbmdlc1Njb3BlUmVzb3VyY2VUeXBlcyh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHZhbHVlID09PSBudWxsKSByZXR1cm4gbnVsbFxuXG4gICAgaWYgKCFBcnJheS5pc0FycmF5KHZhbHVlKSkgdGhyb3cgbmV3IEVycm9yKGBTeW5jIGNoYW5nZXMgc2NvcGUucmVzb3VyY2VUeXBlcyBtdXN0IGJlIGFuIGFycmF5LCBnb3Q6ICR7U3RyaW5nKHZhbHVlKX1gKVxuXG4gICAgcmV0dXJuIHZhbHVlLm1hcCgocmVzb3VyY2VUeXBlKSA9PiBmb3JjZWROb25CbGFua1N0cmluZyhyZXNvdXJjZVR5cGUsIFwicmVzb3VyY2VUeXBlc1wiKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZHMgdGhlIGNoYW5nZS1mZWVkIHNlcnZpY2Ugc2VydmluZyB0aGlzIGNoYW5nZXMgcmVxdWVzdC5cbiAgICogQHBhcmFtIHt7cGFyYW1zOiBSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj4sIHNjb3BlOiBTZXJpYWxpemVkQ2hhbmdlc1Njb3BlIHwgbnVsbH19IGFyZ3MgLSBSZXF1ZXN0IHBhcmFtcyBhbmQgcGFyc2VkIHNjb3BlLlxuICAgKiBAcmV0dXJucyB7e2NoYW5nZXM6ICgpID0+IFByb21pc2U8UmVjb3JkPHN0cmluZywgUmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4+Pn19IENoYW5nZS1mZWVkIHNlcnZpY2UuXG4gICAqL1xuICBjaGFuZ2VGZWVkU2VydmljZSh7cGFyYW1zLCBzY29wZX0pIHtcbiAgICByZXR1cm4gbmV3IFN5bmNNb2RlbENoYW5nZUZlZWRTZXJ2aWNlKHtcbiAgICAgIG1vZGVsQ2xhc3M6IHRoaXMuc3luY01vZGVsQ2xhc3MoKSxcbiAgICAgIHBhcmFtcyxcbiAgICAgIHNjb3BlUXVlcnk6ICh7cXVlcnl9KSA9PiB0aGlzLnNjb3BlQ2hhbmdlc1F1ZXJ5KHtwYXJhbXMsIHF1ZXJ5LCBzY29wZX0pXG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZHMgdGhlIGFwcCByZXBsYXkgc2VydmljZSBoYW5kbGluZyB0aGlzIHJlcGxheSByZXF1ZXN0LiBUaGUgcmVzb3VyY2VcbiAgICogYWJpbGl0eSwgY29udGV4dCwgY29uZmlndXJhdGlvbiwgYW5kIGxvY2FscyBhcmUgcGx1bWJlZCBpbiB1bmRlciB0aGVcbiAgICogYXBwLWRlY2xhcmVkIHtAbGluayBTeW5jUmVzb3VyY2VCYXNlI3JlcGxheVNlcnZpY2VBcmdzfSAoYXBwIGFyZ3Mgd2luKSBzb1xuICAgKiB0aGUgZGVmYXVsdCByZXNvdXJjZS1yb3V0ZWQgcmVwbGF5IHdvcmtzIHdpdGhvdXQgd2lyaW5nLlxuICAgKiBAcmV0dXJucyB7aW1wb3J0KFwiLi9zeW5jLWVudmVsb3BlLXJlcGxheS1zZXJ2aWNlLmpzXCIpLmRlZmF1bHR9IFJlcGxheSBzZXJ2aWNlIGluc3RhbmNlLlxuICAgKi9cbiAgYnVpbGRSZXBsYXlTZXJ2aWNlKCkge1xuICAgIGNvbnN0IFJlcGxheVNlcnZpY2VDbGFzcyA9IHRoaXMucmVwbGF5U2VydmljZUNsYXNzKClcblxuICAgIHJldHVybiBuZXcgUmVwbGF5U2VydmljZUNsYXNzKHtcbiAgICAgIGFiaWxpdHk6IHRoaXMuYWJpbGl0eSxcbiAgICAgIGFiaWxpdHlDb250ZXh0OiB0aGlzLmdldENvbnRleHQoKSxcbiAgICAgIGNvbmZpZ3VyYXRpb246IHRoaXMuY29udHJvbGxlciA/IHRoaXMuY29udHJvbGxlckluc3RhbmNlKCkuZ2V0Q29uZmlndXJhdGlvbigpIDogdW5kZWZpbmVkLFxuICAgICAgbG9jYWxzOiB0aGlzLmdldExvY2FscygpLFxuICAgICAgLi4udGhpcy5yZXBsYXlTZXJ2aWNlQXJncygpXG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGNvbnN0cnVjdG9yIGFyZ3MgZm9yIHRoZSBhcHAgcmVwbGF5IHNlcnZpY2UuXG4gICAqIEByZXR1cm5zIHtSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj59IFJlcGxheSBzZXJ2aWNlIGNvbnN0cnVjdG9yIGFyZ3MuXG4gICAqL1xuICByZXBsYXlTZXJ2aWNlQXJncygpIHtcbiAgICByZXR1cm4ge31cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBzeW5jIG1vZGVsIGNsYXNzIGJhY2tpbmcgdGhlIGNoYW5nZSBmZWVkLlxuICAgKiBAcmV0dXJucyB7dHlwZW9mIGltcG9ydChcIi4uL2RhdGFiYXNlL3JlY29yZC9pbmRleC5qc1wiKS5kZWZhdWx0fSBTeW5jIG1vZGVsIGNsYXNzLlxuICAgKi9cbiAgc3luY01vZGVsQ2xhc3MoKSB7XG4gICAgY29uc3QgbW9kZWxDbGFzcyA9IC8qKiBAdHlwZSB7dHlwZW9mIFN5bmNSZXNvdXJjZUJhc2V9ICovICh0aGlzLmNvbnN0cnVjdG9yKS5Nb2RlbENsYXNzXG5cbiAgICBpZiAoIW1vZGVsQ2xhc3MpIHRocm93IG5ldyBFcnJvcihgJHt0aGlzLmNvbnN0cnVjdG9yLm5hbWV9IG11c3QgZGVmaW5lIHN0YXRpYyBNb2RlbENsYXNzYClcblxuICAgIHJldHVybiBtb2RlbENsYXNzXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgc2hhcmVkIHVwc3RyZWFtIGltcG9ydGVyIGZvciB0aGlzIHJlc291cmNlJ3MgY29uZmlndXJhdGlvbi4gQXBwc1xuICAgKiB1c2UgaXQgaW5zaWRlIHtAbGluayBTeW5jUmVzb3VyY2VCYXNlI2F1dGhvcml6ZUNoYW5nZXN9IChvciBhIGxlZ2FjeSB0cmlnZ2VyXG4gICAqIGVuZHBvaW50KSB0byBydW4gdGhlIHVwc3RyZWFtIGltcG9ydCB0aGF0IGtlZXBzIHRoZSBmZWVkIHNlbGYtc3VzdGFpbmluZyxcbiAgICogd2l0aCBjb2FsZXNjaW5nIGFuZCB0aHJvdHRsaW5nIG93bmVkIGJ5IHRoZSBmcmFtZXdvcmsuXG4gICAqIEByZXR1cm5zIHtpbXBvcnQoXCIuL3N5bmMtdXBzdHJlYW0taW1wb3J0ZXIuanNcIikuZGVmYXVsdH0gU2hhcmVkIGltcG9ydGVyIGZvciB0aGUgY3VycmVudCBjb25maWd1cmF0aW9uLlxuICAgKi9cbiAgc3luY1Vwc3RyZWFtSW1wb3J0ZXIoKSB7XG4gICAgcmV0dXJuIHN5bmNVcHN0cmVhbUltcG9ydGVyRm9yQ29uZmlndXJhdGlvbih0aGlzLmNvbmZpZ3VyYXRpb24oKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBBdXRob3JpemVzIHRoZSBjdXJyZW50IGNvbnRleHQgZm9yIHJlYWRpbmcgdGhlIHJlcXVlc3RlZCBjaGFuZ2VzLlxuICAgKiBAcGFyYW0ge3twYXJhbXM6IFJlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Piwgc2NvcGU6IFNlcmlhbGl6ZWRDaGFuZ2VzU2NvcGUgfCBudWxsfX0gX2FyZ3MgLSBSZXF1ZXN0IHBhcmFtcyBhbmQgcGFyc2VkIHNjb3BlLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gUmVzb2x2ZXMgd2hlbiBhY2Nlc3MgaXMgYWxsb3dlZDsgdGhyb3dzIG90aGVyd2lzZS5cbiAgICovXG4gIGFzeW5jIGF1dGhvcml6ZUNoYW5nZXMoX2FyZ3MpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJTeW5jUmVzb3VyY2VCYXNlI2F1dGhvcml6ZUNoYW5nZXMgbXVzdCBiZSBpbXBsZW1lbnRlZFwiKVxuICB9XG5cbiAgLyoqXG4gICAqIEFwcGxpZXMgYXBwIHZpc2liaWxpdHkgc2NvcGluZyBvbnRvIHRoZSBjaGFuZ2UtZmVlZCBxdWVyeS5cbiAgICogQHBhcmFtIHt7cGFyYW1zOiBSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj4sIHF1ZXJ5OiBpbXBvcnQoXCIuLi9kYXRhYmFzZS9xdWVyeS9tb2RlbC1jbGFzcy1xdWVyeS5qc1wiKS5kZWZhdWx0LCBzY29wZTogU2VyaWFsaXplZENoYW5nZXNTY29wZSB8IG51bGx9fSBfYXJncyAtIFJlcXVlc3QgcGFyYW1zLCBmZWVkIHF1ZXJ5LCBhbmQgcGFyc2VkIHNjb3BlLlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIHNjb3BlQ2hhbmdlc1F1ZXJ5KF9hcmdzKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiU3luY1Jlc291cmNlQmFzZSNzY29wZUNoYW5nZXNRdWVyeSBtdXN0IGJlIGltcGxlbWVudGVkXCIpXG4gIH1cblxuICAvKipcbiAgICogRGVjaWRlcyB3aGV0aGVyIG9uZSBwdWJsaXNoZWQgY2hhbmdlIGlzIGRlbGl2ZXJhYmxlIHRvIGEgdXNlci1zY29wZVxuICAgKiBzdWJzY3JpcHRpb24gKHRoZSBmcmFtZXdvcmsgc3luYyBjaGFubmVsJ3MgcGVyLWRlbGl2ZXJ5IGFjY2VzcyByZS1jaGVjaykuXG4gICAqIFRoZSBkZWZhdWx0IHJldXNlcyB0aGUgYXBwJ3MgYWJpbGl0eSBzY29waW5nOiBpdCBhcHBsaWVzXG4gICAqIHtAbGluayBTeW5jUmVzb3VyY2VCYXNlI3Njb3BlQ2hhbmdlc1F1ZXJ5fSB0byB0aGUgY2hhbmdlLWZlZWQgbW9kZWwg4oCUIHdoaWNoXG4gICAqIGZvciBhbiBlbXB0eS1jb25kaXRpb25zIHVzZXIgc2NvcGUgZmFsbHMgYmFjayB0byBhYmlsaXR5IHNjb3Bpbmcg4oCUIGFuZFxuICAgKiBjaGVja3Mgd2hldGhlciB0aGUgcHVibGlzaGVkIGNoYW5nZSdzIGZlZWQgcm93IGlzIHZpc2libGUgd2l0aGluIHRoYXRcbiAgICogc2NvcGUuIEFwcHMgZ2V0IHRoaXMgZm9yIGZyZWUgZnJvbSB0aGUgc2NvcGluZyB0aGV5IGFscmVhZHkgZGVjbGFyZWQ7XG4gICAqIG92ZXJyaWRlIG9ubHkgZm9yIGN1c3RvbSBwZXItZGVsaXZlcnkgcnVsZXMuXG4gICAqXG4gICAqIFRoZSBgc3luY2AgYXJndW1lbnQgaXMgdGhlIGNvbXBsZXRlIGJyb2FkY2FzdCBzeW5jIGVudHJ5IOKAlCBpbW11dGFibGVcbiAgICogc3luYy1yb3cgaWQsIGFjdG9yLXNwZWNpZmljIG1ldGFkYXRhLCBhbmQgYW55IG90aGVyIHB1Ymxpc2hlciBmaWVsZHMg4oCUXG4gICAqIHdpdGggYHJlc291cmNlSWRgL2ByZXNvdXJjZVR5cGVgIG5vcm1hbGl6ZWQgdG8gc3RyaW5ncywgc28gYW4gb3ZlcnJpZGVcbiAgICogY2FuIGF1dGhvcml6ZSBjb25jdXJyZW50IHRhcmdldGVkIGFuZCBzaGFyZWQgYnJvYWRjYXN0cyBmb3IgdGhlIHNhbWVcbiAgICogcmVzb3VyY2UgaWRlbnRpdHkgaW5kZXBlbmRlbnRseSBieSB0aGVpciBleGFjdC1yb3cgaWRlbnRpdHkuIFRoZSBjaGFubmVsXG4gICAqIG5ldmVyIG11dGF0ZXMgdGhlIHB1Ymxpc2hlZCBlbnRyeTsgbm9ybWFsaXphdGlvbiBoYXBwZW5zIG9uIGEgY29weS5cbiAgICogQHBhcmFtIHt7cGFyYW1zOiBSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj4sIHNjb3BlOiBTZXJpYWxpemVkQ2hhbmdlc1Njb3BlIHwgbnVsbCwgc3luYzogQ2hhbmdlRGVsaXZlcmFibGVTeW5jRW50cnl9fSBhcmdzIC0gUmVxdWVzdCBwYXJhbXMsIHN1YnNjcmlwdGlvbiBzY29wZSwgYW5kIHRoZSBwdWJsaXNoZWQgc3luYyBlbnRyeS5cbiAgICogQHJldHVybnMge1Byb21pc2U8Ym9vbGVhbj59IFdoZXRoZXIgdGhlIGNoYW5nZSBtYXkgYmUgZGVsaXZlcmVkIHRvIHRoaXMgc3Vic2NyaXB0aW9uLlxuICAgKi9cbiAgYXN5bmMgY2hhbmdlRGVsaXZlcmFibGUoe3BhcmFtcywgc2NvcGUsIHN5bmN9KSB7XG4gICAgY29uc3QgcXVlcnkgPSB0aGlzLnN5bmNNb2RlbENsYXNzKCkud2hlcmUoe30pXG5cbiAgICB0aGlzLnNjb3BlQ2hhbmdlc1F1ZXJ5KHtwYXJhbXMsIHF1ZXJ5LCBzY29wZX0pXG4gICAgcXVlcnkud2hlcmUoe3Jlc291cmNlX2lkOiBTdHJpbmcoc3luYy5yZXNvdXJjZUlkKSwgcmVzb3VyY2VfdHlwZTogU3RyaW5nKHN5bmMucmVzb3VyY2VUeXBlKX0pXG5cbiAgICByZXR1cm4gQm9vbGVhbihhd2FpdCBxdWVyeS5maXJzdCgpKVxuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmVzIHRoZSByZXBsYXkgc2VydmljZSBjbGFzcyBoYW5kbGluZyByZXBsYXkgbXV0YXRpb25zOiB0aGVcbiAgICogZGVjbGFyYXRpdmUge0BsaW5rIFN5bmNSZXNvdXJjZUJhc2UuUmVwbGF5U2VydmljZUNsYXNzfSBzdGF0aWMgKHNoYXJlZFxuICAgKiByZXNvdXJjZXMgaW5jbHVkZWQpIHdoZW4gZGVjbGFyZWQsIG90aGVyd2lzZVxuICAgKiB7QGxpbmsgU3luY0VudmVsb3BlUmVwbGF5U2VydmljZX0sIHdoaWNoIHJlc291cmNlLXJvdXRlcyBtdXRhdGlvbnMgdGhyb3VnaFxuICAgKiB0aGUgcGx1bWJlZCBjb25maWd1cmF0aW9uIHJlZ2lzdHJ5LiBBcHBzIGRlY2xhcmUgdGhlIHN0YXRpYyBpbnN0ZWFkIG9mXG4gICAqIG92ZXJyaWRpbmcgdGhpcyBtZXRob2QuXG4gICAqIEByZXR1cm5zIHt0eXBlb2YgaW1wb3J0KFwiLi9zeW5jLWVudmVsb3BlLXJlcGxheS1zZXJ2aWNlLmpzXCIpLmRlZmF1bHR9IFJlcGxheSBzZXJ2aWNlIGNsYXNzLlxuICAgKi9cbiAgcmVwbGF5U2VydmljZUNsYXNzKCkge1xuICAgIGNvbnN0IFJlc291cmNlQ2xhc3MgPSAvKiogQHR5cGUge3R5cGVvZiBTeW5jUmVzb3VyY2VCYXNlfSAqLyAodGhpcy5jb25zdHJ1Y3RvcilcbiAgICBjb25zdCBTaGFyZWRSZXNvdXJjZSA9IC8qKiBAdHlwZSB7dHlwZW9mIFN5bmNSZXNvdXJjZUJhc2UgfCBudWxsfSAqLyAoUmVzb3VyY2VDbGFzcy5zaGFyZWRSZXNvdXJjZUNsYXNzKCkgPz8gbnVsbClcblxuICAgIHJldHVybiBSZXNvdXJjZUNsYXNzLlJlcGxheVNlcnZpY2VDbGFzcyA/PyBTaGFyZWRSZXNvdXJjZT8uUmVwbGF5U2VydmljZUNsYXNzID8/IFN5bmNFbnZlbG9wZVJlcGxheVNlcnZpY2VcbiAgfVxufVxuIl19
|
|
@@ -173,11 +173,17 @@ export default class LocalMutationLog {
|
|
|
173
173
|
|
|
174
174
|
/**
|
|
175
175
|
* Replaces the mutation payload of a still-pending record. Used when an
|
|
176
|
-
* acknowledged predecessor supplies the authoritative base for its successor
|
|
177
|
-
*
|
|
176
|
+
* acknowledged predecessor supplies the authoritative base for its successor
|
|
177
|
+
* and when an offline session re-signs a pending record under a refreshed
|
|
178
|
+
* grant (pass the new `signedMutation` envelope together with the mutation).
|
|
179
|
+
* @param {{id: string, mutation: import("./device-identity.js").SyncMutation, signedMutation?: import("./device-identity.js").SignedSyncMutation}} args - Record and replacement mutation.
|
|
178
180
|
* @returns {Promise<LocalMutationLogRecord>} Updated record.
|
|
179
181
|
*/
|
|
180
|
-
async updateMutation({id, mutation}) {
|
|
182
|
+
async updateMutation({id, mutation, signedMutation}) {
|
|
183
|
+
if (signedMutation !== undefined && stableJsonStringify(signedMutation.mutation) !== stableJsonStringify(mutation)) {
|
|
184
|
+
throw new Error("signedMutation must match the mutation payload it signs")
|
|
185
|
+
}
|
|
186
|
+
|
|
181
187
|
return await withStorageKeyLock(this.storageKey, async () => {
|
|
182
188
|
const rawRecord = await this.storage.record(this.storageKey, id)
|
|
183
189
|
|
|
@@ -188,6 +194,7 @@ export default class LocalMutationLog {
|
|
|
188
194
|
if (!PENDING_STATUSES.has(record.status)) throw new Error(`Cannot update mutation for ${record.status} local mutation '${id}'`)
|
|
189
195
|
|
|
190
196
|
record.mutation = normalizeMutation(mutation)
|
|
197
|
+
if (signedMutation !== undefined) record.signedMutation = /** @type {import("./device-identity.js").SignedSyncMutation} */ (JSON.parse(JSON.stringify(signedMutation)))
|
|
191
198
|
record.updatedAt = this.currentTimestamp()
|
|
192
199
|
await this.storage.updateRecord(this.storageKey, cloneRecord(record))
|
|
193
200
|
|
|
@@ -11,6 +11,12 @@ import {createSignedMutation, mutationIdempotencyKey, verifySignedMutation} from
|
|
|
11
11
|
*/
|
|
12
12
|
/**
|
|
13
13
|
* One peer mutation bundle entry.
|
|
14
|
+
* @typedef {object} PeerMutationBundleImportResult
|
|
15
|
+
* @property {Array<{clientMutationId: string, idempotencyKey: string, localRecordId: string}>} imported - Entries appended to the local log.
|
|
16
|
+
* @property {Array<{errorMessage: string, index: number}>} rejected - Entries that failed verification.
|
|
17
|
+
* @property {Array<{clientMutationId: string, idempotencyKey: string, localRecordId: string, reason: "duplicate"}>} skipped - Entries already present by idempotency key.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
14
20
|
* @typedef {object} PeerMutationBundleEntry
|
|
15
21
|
* @property {string} [localRecordId] - Exporting device's local mutation record id.
|
|
16
22
|
* @property {number} [localSequence] - Exporting device's local mutation sequence.
|
|
@@ -29,13 +29,14 @@ export default class SyncApiClient {
|
|
|
29
29
|
* @param {string | number | null} args.baseVersion - Authoritative version observed before the local mutation.
|
|
30
30
|
* @param {import("./sync-client-types.js").SyncClientConflictTrackingConfig} args.conflictTracking - Durable tracking configuration.
|
|
31
31
|
* @param {Record<string, unknown>} args.data - Backend-safe mutation attributes.
|
|
32
|
+
* @param {import("./sync-offline-session.js").default} [args.offlineSession] - Active long-offline session: the mutation identity (actor ids, grant id, policy hash) is supplied by the session and the appended record carries the device-signed envelope.
|
|
32
33
|
* @param {"create" | "update" | "destroy"} args.operation - Local operation.
|
|
33
34
|
* @param {ReturnType<typeof JSON.parse>} args.resource - Local resource.
|
|
34
35
|
* @param {string} args.resourceType - Resource type.
|
|
35
36
|
* @param {string} args.syncType - Wire operation.
|
|
36
37
|
* @returns {Promise<import("./local-mutation-log.js").LocalMutationLogRecord>} Appended intent.
|
|
37
38
|
*/
|
|
38
|
-
static async queueConflictTrackedSync({baseVersion, conflictTracking, data, operation, resource, resourceType, syncType}) {
|
|
39
|
+
static async queueConflictTrackedSync({baseVersion, conflictTracking, data, offlineSession, operation, resource, resourceType, syncType}) {
|
|
39
40
|
const resourceId = String(scalarModelPrimaryKeyValue(resource.id(), `Conflict-tracked sync for ${resourceType}`))
|
|
40
41
|
const records = await conflictTracking.mutationLog.records()
|
|
41
42
|
const predecessor = records
|
|
@@ -46,20 +47,40 @@ export default class SyncApiClient {
|
|
|
46
47
|
const predecessorTime = predecessor ? new Date(predecessor.mutation.occurredAt).getTime() : Number.NEGATIVE_INFINITY
|
|
47
48
|
const occurredAt = new Date(Math.max(now.getTime(), predecessorTime + 1)).toISOString()
|
|
48
49
|
|
|
50
|
+
const dependencies = predecessor ? [{clientMutationId: predecessor.mutation.clientMutationId, model: resourceType}] : []
|
|
51
|
+
const attributes = /** @type {Record<string, import("../configuration-types.js").FrontendModelSyncJsonValue>} */ (data)
|
|
52
|
+
|
|
53
|
+
if (offlineSession) {
|
|
54
|
+
// Long-offline queueing: the session supplies the rotating identity
|
|
55
|
+
// (actor ids, live grant id, current policy hash) and signs the intent
|
|
56
|
+
// with the device key so it can replay without a live session.
|
|
57
|
+
const signedMutation = await offlineSession.signMutation({
|
|
58
|
+
attributes,
|
|
59
|
+
baseVersion,
|
|
60
|
+
clientMutationId,
|
|
61
|
+
model: resourceType,
|
|
62
|
+
occurredAt,
|
|
63
|
+
operation,
|
|
64
|
+
payload: {resourceId, syncType}
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
return await conflictTracking.mutationLog.append({dependencies, mutation: signedMutation.mutation, signedMutation})
|
|
68
|
+
}
|
|
69
|
+
|
|
49
70
|
return await conflictTracking.mutationLog.append({
|
|
50
|
-
dependencies
|
|
71
|
+
dependencies,
|
|
51
72
|
mutation: {
|
|
52
|
-
actorDeviceId: conflictTracking
|
|
53
|
-
actorUserId: conflictTracking
|
|
54
|
-
attributes
|
|
73
|
+
actorDeviceId: await resolveConflictTrackingIdentityValue({conflictTracking, key: "actorDeviceId", resourceType}),
|
|
74
|
+
actorUserId: await resolveConflictTrackingIdentityValue({conflictTracking, key: "actorUserId", resourceType}),
|
|
75
|
+
attributes,
|
|
55
76
|
baseVersion,
|
|
56
77
|
clientMutationId,
|
|
57
78
|
model: resourceType,
|
|
58
79
|
occurredAt,
|
|
59
|
-
offlineGrantId: conflictTracking
|
|
80
|
+
offlineGrantId: await resolveConflictTrackingIdentityValue({conflictTracking, key: "offlineGrantId", resourceType}),
|
|
60
81
|
operation,
|
|
61
82
|
payload: {resourceId, syncType},
|
|
62
|
-
policyHash: conflictTracking
|
|
83
|
+
policyHash: await resolveConflictTrackingIdentityValue({conflictTracking, key: "policyHash", resourceType})
|
|
63
84
|
}
|
|
64
85
|
})
|
|
65
86
|
}
|
|
@@ -938,3 +959,28 @@ function throwIfSyncAborted(signal) {
|
|
|
938
959
|
|
|
939
960
|
throw signal.reason instanceof Error ? signal.reason : new Error("Sync operation aborted")
|
|
940
961
|
}
|
|
962
|
+
|
|
963
|
+
/**
|
|
964
|
+
* Resolves one conflict-tracking identity field at queue time: a static string
|
|
965
|
+
* or a function (sync or async) resolving the current value. Grants and policy
|
|
966
|
+
* hashes rotate at runtime, so declarations may resolve them per mutation.
|
|
967
|
+
* @param {{conflictTracking: import("./sync-client-types.js").SyncClientConflictTrackingConfig, key: "actorDeviceId" | "actorUserId" | "offlineGrantId" | "policyHash", resourceType: string}} args - Resolution args.
|
|
968
|
+
* @returns {Promise<string>} - Resolved non-empty identity value.
|
|
969
|
+
*/
|
|
970
|
+
async function resolveConflictTrackingIdentityValue({conflictTracking, key, resourceType}) {
|
|
971
|
+
const value = conflictTracking[key]
|
|
972
|
+
|
|
973
|
+
if (typeof value === "function") {
|
|
974
|
+
const resolved = await value()
|
|
975
|
+
|
|
976
|
+
if (typeof resolved !== "string" || resolved.length === 0) {
|
|
977
|
+
throw new Error(`${resourceType} conflictTracking.${key} resolved to an empty value`)
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
return resolved
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
if (typeof value === "string" && value.length > 0) return value
|
|
984
|
+
|
|
985
|
+
throw new Error(`${resourceType} conflictTracking.${key} must be a non-empty string or a function resolving one (or start an offline session)`)
|
|
986
|
+
}
|
|
@@ -21,13 +21,13 @@
|
|
|
21
21
|
* Durable optimistic-version tracking configuration. Identity/grant fields are
|
|
22
22
|
* retained in the shared LocalMutationLog mutation shape used by offline sync.
|
|
23
23
|
* @typedef {object} SyncClientConflictTrackingConfig
|
|
24
|
-
* @property {string} actorDeviceId - Stable device identity.
|
|
25
|
-
* @property {string} actorUserId - Stable user identity.
|
|
24
|
+
* @property {string | (() => string | Promise<string>)} [actorDeviceId] - Stable device identity, or a function resolving it at queue time. When a `sync.client.offline` session is configured, the session supplies it and the declaration may omit it.
|
|
25
|
+
* @property {string | (() => string | Promise<string>)} [actorUserId] - Stable user identity, or a function resolving it at queue time. When a `sync.client.offline` session is configured, the session supplies it and the declaration may omit it.
|
|
26
26
|
* @property {() => string} clientMutationId - Durable idempotency-id generator.
|
|
27
27
|
* @property {import("./local-mutation-log.js").default} mutationLog - Existing durable mutation log.
|
|
28
28
|
* @property {() => Date} [now] - Mutation clock.
|
|
29
|
-
* @property {string} offlineGrantId - Grant identifier retained with intent.
|
|
30
|
-
* @property {string} policyHash - Policy hash retained with intent.
|
|
29
|
+
* @property {string | (() => string | Promise<string>)} [offlineGrantId] - Grant identifier retained with intent, or a function resolving it at queue time (grants rotate at runtime). When a `sync.client.offline` session is configured, the session supplies it and the declaration may omit it.
|
|
30
|
+
* @property {string | (() => string | Promise<string>)} [policyHash] - Policy hash retained with intent, or a function resolving it at queue time (policy hashes rotate with the server policy). When a `sync.client.offline` session is configured, the session supplies it and the declaration may omit it.
|
|
31
31
|
* @property {string} [versionAttribute] - Authoritative version attribute; defaults to updatedAt when present.
|
|
32
32
|
*/
|
|
33
33
|
|
|
@@ -128,6 +128,8 @@
|
|
|
128
128
|
* @property {(args: {scope: SerializedSyncScope}) => string | null | Promise<string | null>} [legacyCursor] - Seeds a newly declared scope's cursor (e.g. from a pre-scope cursor store) so devices don't re-pull everything.
|
|
129
129
|
* @property {(error: Error) => void} [onError] - Reports background replay/pull failures. Defaults to rethrowing.
|
|
130
130
|
* @property {(payload: import("./sync-api-client-types.js").SyncChangesRequest & {scope: SerializedSyncScope}, options?: {signal?: AbortSignal}) => Promise<import("./sync-api-client-types.js").SyncChangesResponse>} postChanges - Posts one changes request.
|
|
131
|
+
* @property {import("../configuration-types.js").NormalizedVelociousSyncClientOfflineConfiguration} [offline] - Normalized long-offline session configuration from `sync.client.offline`.
|
|
132
|
+
* @property {(path: string, payload: Record<string, ReturnType<typeof JSON.parse>>, options?: {signal?: AbortSignal}) => Promise<ReturnType<typeof JSON.parse>>} offlinePost - Path-selecting POSTer over the configured transport for the offline session's bootstrap/replay endpoints.
|
|
131
133
|
* @property {(payload: {authenticationToken: string, syncs: Array<Record<string, ReturnType<typeof JSON.parse>>>}, options?: {signal?: AbortSignal}) => Promise<import("./sync-api-client-types.js").SyncReplayResponse>} postReplay - Posts one replay request.
|
|
132
134
|
* @property {import("../configuration-types.js").VelociousSyncClientRealtimeConfiguration} [realtime] - Realtime push configuration consumed by `subscribeRealtime(...)`.
|
|
133
135
|
* @property {import("../remote-request-context.js").RemoteRequestContext} requestContext - Immutable scalar context captured for this client.
|