velocious 1.0.672 → 1.0.673
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 -1
- package/build/database/drivers/base.js +52 -18
- package/build/database/drivers/mssql/index.js +48 -3
- package/build/src/database/drivers/base.d.ts +23 -0
- package/build/src/database/drivers/base.d.ts.map +1 -1
- package/build/src/database/drivers/base.js +51 -21
- package/build/src/database/drivers/mssql/index.d.ts +22 -0
- package/build/src/database/drivers/mssql/index.d.ts.map +1 -1
- package/build/src/database/drivers/mssql/index.js +45 -4
- package/build/src/sync/local-mutation-log.d.ts +12 -0
- package/build/src/sync/local-mutation-log.d.ts.map +1 -1
- package/build/src/sync/local-mutation-log.js +45 -1
- package/build/src/sync/sync-api-client.d.ts +6 -1
- package/build/src/sync/sync-api-client.d.ts.map +1 -1
- package/build/src/sync/sync-api-client.js +7 -2
- package/build/src/sync/sync-client.d.ts +60 -0
- package/build/src/sync/sync-client.d.ts.map +1 -1
- package/build/src/sync/sync-client.js +172 -3
- package/build/src/sync/sync-coordinator-types.d.ts +190 -0
- package/build/src/sync/sync-coordinator-types.d.ts.map +1 -0
- package/build/src/sync/sync-coordinator-types.js +65 -0
- package/build/src/sync/sync-coordinator.d.ts +246 -0
- package/build/src/sync/sync-coordinator.d.ts.map +1 -0
- package/build/src/sync/sync-coordinator.js +683 -0
- package/build/src/sync/sync-envelope-replay-service.d.ts +90 -2
- package/build/src/sync/sync-envelope-replay-service.d.ts.map +1 -1
- package/build/src/sync/sync-envelope-replay-service.js +101 -9
- package/build/src/sync/sync-realtime-bridge.d.ts.map +1 -1
- package/build/src/sync/sync-realtime-bridge.js +8 -1
- package/build/sync/local-mutation-log.js +53 -0
- package/build/sync/sync-api-client.js +7 -1
- package/build/sync/sync-client.js +190 -2
- package/build/sync/sync-coordinator-types.js +73 -0
- package/build/sync/sync-coordinator.js +738 -0
- package/build/sync/sync-envelope-replay-service.js +107 -8
- package/build/sync/sync-realtime-bridge.js +9 -0
- package/package.json +1 -1
- package/src/database/drivers/base.js +52 -18
- package/src/database/drivers/mssql/index.js +48 -3
- package/src/sync/local-mutation-log.js +53 -0
- package/src/sync/sync-api-client.js +7 -1
- package/src/sync/sync-client.js +190 -2
- package/src/sync/sync-coordinator-types.js +73 -0
- package/src/sync/sync-coordinator.js +738 -0
- package/src/sync/sync-envelope-replay-service.js +107 -8
- package/src/sync/sync-realtime-bridge.js +9 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-realtime-bridge.d.ts","sourceRoot":"","sources":["../../../src/sync/sync-realtime-bridge.js"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"sync-realtime-bridge.d.ts","sourceRoot":"","sources":["../../../src/sync/sync-realtime-bridge.js"],"names":[],"mappings":"AAQI,YAAsF,sCAAsC,GAAlH,OAAO,2BAA2B,EAAE,sCAAsC,CAAwC;AAC5H,YAAoF,oCAAoC,GAA9G,OAAO,2BAA2B,EAAE,oCAAoC,CAAsC;AAD5H,mIAAmI;AACnI,+HAA+H;AAE/H;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,OAAO,OAAO,kBAAkB;IAM9B,UAAU;IACf,yJAAyJ;IACpJ,SAAS,EADH,KAAK,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,YAAY,EAAE,OAAO,2BAA2B,EAAE,iCAAiC,CAAA;KAAC,CAAC;IAErJ,0DAA0D;IACrD,OAAO,EADD,oCAAoC,GAAG,IAAI;IAEtD,uKAAuK;IAClK,WAAW,EADL,OAAO;IAElB,4BAA4B;IACvB,aAAa,EADP,OAAO,CAAC,IAAI,CAAC;IAExB,uHAAuH;IAClH,WAAW,EADL,MAAM;IAEjB,mCAAmC;IAC9B,cAAc,EADR,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAE/B,mCAAmC;IAC9B,iBAAiB,EADX,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAE/B,4DAA4D;IACvD,MAAM,EADA,YAAY,GAAG,aAAa,GAAG,cAAc;IApB1D;;;OAGG;IACH,YAAY,EAAC,UAAU,EAAC,EAFb;QAAC,UAAU,EAAE,OAAO,kBAAkB,EAAE,OAAO,CAAA;KAElC,EAkBvB;IAED;;;;;;;OAOG;IACG,SAAS,CAAC,OAAO,AAJpB,CACA,EADQ,UAAU,CAAC,OAAO,IAAI,CAAC,KAAK,CAIhB,EAAE,EAAC,MAAM,EAAC,AAH9B,CACA,EADQ;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAGM,GAFzB,OAAO,CAAC,IAAI,CAAC,CAYzB;IAED;;;;;;;;;;OAUG;IACG,UAAU,CAAC,OAAO,EAJb,UAAU,CAAC,OAAO,IAAI,CAAC,KAAK,CAIf,EAAE,MAAM,EAHrB,WAAW,GAAG,SAGO,GAFnB,OAAO,CAAC,IAAI,CAAC,CA2GzB;IAED;;;;;;;;OAQG;IACG,WAAW,IAFJ,OAAO,CAAC,IAAI,CAAC,CAmBzB;IAED;;;OAGG;IACH,MAAM,IAFO;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;IACG,cAAc,IAFP,OAAO,CAAC,IAAI,CAAC,CAKzB;IAED;;;;OAIG;IACH,qBAAqB,IAFR,OAAO,2BAA2B,EAAE,wCAAwC,GAAG,IAAI,CAI/F;IAED;;;;;;OAMG;IACH,mBAAmB,CAAC,YAAY,EAHrB,OAAO,2BAA2B,EAAE,oCAAoC,GAAG,IAGtD,GAFnB,OAAO,2BAA2B,EAAE,wCAAwC,GAAG,IAAI,CAU/F;IAED;;;;;;;;OAQG;IACG,kBAAkB,CAAC,OAAO,EAHrB,UAAU,CAAC,OAAO,IAAI,CAAC,KAAK,CAGP,GAFnB,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC,CAkClE;IAED;;;;;;;;;;;;;;;OAeG;IACH,wBAAwB,CAAC,QAAQ,EAHtB;QAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;KAGjE,GAFpB,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAoBzD;IAED;;;;;OAKG;IACH,YAAY,CAAC,EAAC,IAAI,EAAE,UAA6B,EAAE,YAAY,EAAC,EAHrD;QAAC,IAAI,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;KAGjC,GAFnD,IAAI,CAYhB;IAED;;;;;;OAMG;IACG,YAAY,CAAC,EAAC,IAAI,EAAE,YAAY,EAAC,EAH5B;QAAC,IAAI,EAAE,UAAU,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;KAGrC,GAF1B,OAAO,CAAC,IAAI,CAAC,CA0BzB;IAED;;;;;;OAMG;IACH,YAAY,CAAC,UAAU,AAHpB,CACA,EADQ,MAG+B,GAF7B,IAAI,CA0BhB;CACF"}
|
|
@@ -352,6 +352,13 @@ export default class SyncRealtimeBridge {
|
|
|
352
352
|
return;
|
|
353
353
|
if (this.realtimeConfiguration()?.pullOnReconnect === false)
|
|
354
354
|
return;
|
|
355
|
+
const coordinatorRun = this.syncClient.requestCoordinatorSync("realtime");
|
|
356
|
+
if (coordinatorRun) {
|
|
357
|
+
this._scheduledPull ||= coordinatorRun.finally(() => {
|
|
358
|
+
this._scheduledPull = null;
|
|
359
|
+
});
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
355
362
|
this._scheduledPull ||= (async () => {
|
|
356
363
|
try {
|
|
357
364
|
await this.syncClient.pull();
|
|
@@ -377,4 +384,4 @@ function throwIfAborted(signal) {
|
|
|
377
384
|
return;
|
|
378
385
|
throw signal.reason instanceof Error ? signal.reason : new Error("Sync realtime subscription was aborted");
|
|
379
386
|
}
|
|
380
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1yZWFsdGltZS1icmlkZ2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc3luYy9zeW5jLXJlYWx0aW1lLWJyaWRnZS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxhQUFhLE1BQU0sK0JBQStCLENBQUE7QUFDekQsT0FBTyxFQUFDLHlCQUF5QixFQUFDLE1BQU0sOEJBQThCLENBQUE7QUFFdEUsT0FBTyxhQUFhLE1BQU0sc0JBQXNCLENBQUE7QUFDaEQsT0FBTyxFQUFDLHNCQUFzQixFQUFDLE1BQU0sd0JBQXdCLENBQUE7QUFFN0QsbUlBQW1JO0FBQ25JLCtIQUErSDtBQUUvSDs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSCxNQUFNLENBQUMsT0FBTyxPQUFPLGtCQUFrQjtJQUNyQzs7O09BR0c7SUFDSCxZQUFZLEVBQUMsVUFBVSxFQUFDO1FBQ3RCLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFBO1FBQzVCLHlKQUF5SjtRQUN6SixJQUFJLENBQUMsU0FBUyxHQUFHLEVBQUUsQ0FBQTtRQUNuQiwwREFBMEQ7UUFDMUQsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUE7UUFDbkIsdUtBQXVLO1FBQ3ZLLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFBO1FBQ3hCLDRCQUE0QjtRQUM1QixJQUFJLENBQUMsYUFBYSxHQUFHLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQTtRQUN0Qyx1SEFBdUg7UUFDdkgsSUFBSSxDQUFDLFdBQVcsR0FBRyxDQUFDLENBQUE7UUFDcEIsbUNBQW1DO1FBQ25DLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFBO1FBQzFCLG1DQUFtQztRQUNuQyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxDQUFBO1FBQzdCLDREQUE0RDtRQUM1RCxJQUFJLENBQUMsTUFBTSxHQUFHLGNBQWMsQ0FBQTtJQUM5QixDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNI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Q0FBQztnQkFDVCxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQTtZQUM1QixDQUFDO1FBQ0gsQ0FBQyxDQUFDLEVBQUUsQ0FBQTtJQUNOLENBQUM7Q0FDRjtBQUVEOzs7O0dBSUc7QUFDSCxTQUFTLGNBQWMsQ0FBQyxNQUFNO0lBQzVCLElBQUksQ0FBQyxNQUFNLEVBQUUsT0FBTztRQUFFLE9BQU07SUFFNUIsTUFBTSxNQUFNLENBQUMsTUFBTSxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLENBQUMsd0NBQXdDLENBQUMsQ0FBQTtBQUM1RyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCByZWNvcmRDaGFuZ2VzIGZyb20gXCIuLi9kYXRhYmFzZS9yZWNvcmQtY2hhbmdlcy5qc1wiXG5pbXBvcnQge21lcmdlUmVtb3RlUmVxdWVzdENvbnRleHR9IGZyb20gXCIuLi9yZW1vdGUtcmVxdWVzdC1jb250ZXh0LmpzXCJcblxuaW1wb3J0IFN5bmNBcGlDbGllbnQgZnJvbSBcIi4vc3luYy1hcGktY2xpZW50LmpzXCJcbmltcG9ydCB7VkVMT0NJT1VTX1NZTkNfQ0hBTk5FTH0gZnJvbSBcIi4vc3luYy1jaGFubmVsLW5hbWUuanNcIlxuXG4vKiogQHR5cGVkZWYge2ltcG9ydChcIi4uL2NvbmZpZ3VyYXRpb24tdHlwZXMuanNcIikuVmVsb2Npb3VzU3luY1JlYWx0aW1lQ2hhbm5lbERlc2NyaXB0b3J9IFZlbG9jaW91c1N5bmNSZWFsdGltZUNoYW5uZWxEZXNjcmlwdG9yICovXG4vKiogQHR5cGVkZWYge2ltcG9ydChcIi4uL2NvbmZpZ3VyYXRpb24tdHlwZXMuanNcIikuVmVsb2Npb3VzU3luY1JlYWx0aW1lV2Vic29ja2V0Q2xpZW50fSBWZWxvY2lvdXNTeW5jUmVhbHRpbWVXZWJzb2NrZXRDbGllbnQgKi9cblxuLyoqXG4gKiBEZXJpdmVkIHJlYWx0aW1lIHB1c2ggYnJpZGdlIGZvciB0aGUgc3luYyBjbGllbnQuIFN1YnNjcmliZXMgZXZlcnkgZGVjbGFyZWRcbiAqIHB1bGwgc2NvcGUgdG8gdGhlIGZyYW1ld29yayBzeW5jIGNoYW5uZWwgKHtAbGluayBWRUxPQ0lPVVNfU1lOQ19DSEFOTkVMfSlcbiAqIGF1dG9tYXRpY2FsbHkg4oCUIHRoZSBzdWJzY3JpYmUgcGFyYW1zIG1pcnJvciB0aGUgc2NvcGUnc1xuICogYHtyZXNvdXJjZVR5cGUsIGNvbmRpdGlvbnN9YCBzbyB0aGUgc2VydmVyIGF1dGhvcml6ZXMgdGhlbSB0aHJvdWdoIHRoZSBzYW1lXG4gKiBzeW5jIHJlc291cmNlIGF1dGhvcml6YXRpb24gYXMgcHVsbHMg4oCUIHBsdXMgYW55IGRlcHJlY2F0ZWQgbGVnYWN5IGNoYW5uZWxzXG4gKiAoY29uZmlnIGBzeW5jLmNsaWVudC5yZWFsdGltZS5jaGFubmVsc2AgY2FsbGJhY2sgYW5kIG1vZGVsLWxldmVsXG4gKiBgc3RhdGljIHN5bmMgPSB7cmVhbHRpbWU6IHtjaGFubmVsfX1gIGRlY2xhcmF0aW9ucykuIFB1c2hlZCBjaGFuZ2VzIGFwcGx5XG4gKiB0aHJvdWdoIHRoZSBzYW1lIGRlcml2ZWQgcmVzb3VyY2UgYXBwbGllciBhcyBwdWxscyAod2l0aCBlY2hvIHN1cHByZXNzaW9uXG4gKiBhZ2FpbnN0IHRyYWNrZWQgcmUtcXVldWVpbmcpLCBvd24tZGV2aWNlIG1lc3NhZ2VzIGFyZSBkcm9wcGVkIGJ5IGVjaG9cbiAqIG9yaWdpbiwgYW5kIGEgY29hbGVzY2VkIGBwdWxsKClgIGZpcmVzIHdoZW4gc3Vic2NyaXB0aW9ucyBiZWNvbWUgcmVhZHkgb3JcbiAqIHJlc3VtZSBzbyBvZmZsaW5lIGdhcHMgY2xvc2UuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFN5bmNSZWFsdGltZUJyaWRnZSB7XG4gIC8qKlxuICAgKiBCdWlsZHMgdGhlIGJyaWRnZSBmb3IgYSBzeW5jIGNsaWVudC5cbiAgICogQHBhcmFtIHt7c3luY0NsaWVudDogaW1wb3J0KFwiLi9zeW5jLWNsaWVudC5qc1wiKS5kZWZhdWx0fX0gYXJncyAtIEJyaWRnZSBhcmdzLlxuICAgKi9cbiAgY29uc3RydWN0b3Ioe3N5bmNDbGllbnR9KSB7XG4gICAgdGhpcy5zeW5jQ2xpZW50ID0gc3luY0NsaWVudFxuICAgIC8qKiBAdHlwZSB7QXJyYXk8e2NoYW5uZWw6IHN0cmluZywgcmVzb3VyY2VUeXBlOiBzdHJpbmcgfCBudWxsLCBzdWJzY3JpcHRpb246IGltcG9ydChcIi4uL2NvbmZpZ3VyYXRpb24tdHlwZXMuanNcIikuVmVsb2Npb3VzU3luY1JlYWx0aW1lU3Vic2NyaXB0aW9ufT59ICovXG4gICAgdGhpcy5fY2hhbm5lbHMgPSBbXVxuICAgIC8qKiBAdHlwZSB7VmVsb2Npb3VzU3luY1JlYWx0aW1lV2Vic29ja2V0Q2xpZW50IHwgbnVsbH0gKi9cbiAgICB0aGlzLl9jbGllbnQgPSBudWxsXG4gICAgLyoqIEB0eXBlIHtib29sZWFufSBXaGV0aGVyIHRoZSBicmlkZ2UgY3JlYXRlZCBpdHMgb3duIGNsaWVudCAoZGVwcmVjYXRlZCBwZXItY3ljbGUgcGF0aCkgYW5kIG11c3QgZGlzY29ubmVjdCBpdCBvbiB1bnN1YnNjcmliZS4gQSBzaGFyZWQgY29ubmVjdGlvbiBpcyBuZXZlciBvd25lZC4gKi9cbiAgICB0aGlzLl9vd25zQ2xpZW50ID0gZmFsc2VcbiAgICAvKiogQHR5cGUge1Byb21pc2U8dm9pZD59ICovXG4gICAgdGhpcy5fYXBwbHlQcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKClcbiAgICAvKiogQHR5cGUge251bWJlcn0gU3Vic2NyaXB0aW9uIGdlbmVyYXRpb24gLSBidW1wZWQgYnkgdW5zdWJzY3JpYmUgc28gaW4tZmxpZ2h0IHN1YnNjcmliZXMgZGV0ZWN0IHRoZXkgYmVjYW1lIHN0YWxlLiAqL1xuICAgIHRoaXMuX2dlbmVyYXRpb24gPSAwXG4gICAgLyoqIEB0eXBlIHtQcm9taXNlPHZvaWQ+IHwgbnVsbH0gKi9cbiAgICB0aGlzLl9zY2hlZHVsZWRQdWxsID0gbnVsbFxuICAgIC8qKiBAdHlwZSB7UHJvbWlzZTx2b2lkPiB8IG51bGx9ICovXG4gICAgdGhpcy5fc3Vic2NyaWJlUHJvbWlzZSA9IG51bGxcbiAgICAvKiogQHR5cGUge1wic3Vic2NyaWJlZFwiIHwgXCJzdWJzY3JpYmluZ1wiIHwgXCJ1bnN1YnNjcmliZWRcIn0gKi9cbiAgICB0aGlzLl9zdGF0ZSA9IFwidW5zdWJzY3JpYmVkXCJcbiAgfVxuXG4gIC8qKlxuICAgKiBTdWJzY3JpYmVzIHRoZSBkZXJpdmVkIHJlYWx0aW1lIGNoYW5uZWxzIChpZGVtcG90ZW50IGFuZCBzaW5nbGUtZmxpZ2h0ZWQpOlxuICAgKiBhbiBhY3RpdmUgc3Vic2NyaXB0aW9uIGlzIGtlcHQgYXMtaXMgYW5kIGEgY29uY3VycmVudCBzdWJzY3JpYmUgYXdhaXRzIHRoZVxuICAgKiBpbi1mbGlnaHQgYXR0ZW1wdC4gQ2FsbCBgdW5zdWJzY3JpYmUoKWAgZmlyc3QgdG8gY2hhbmdlIHRoZSBjb250ZXh0LlxuICAgKiBAcGFyYW0ge1JldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+fSBbY29udGV4dF0gLSBBcHAgY29udGV4dCBwYXNzZWQgdG8gdGhlIGRlcHJlY2F0ZWQgYHN5bmMuY2xpZW50LnJlYWx0aW1lLmNoYW5uZWxzYCBjYWxsYmFjayAocnVudGltZSBzY29wZSB2YWx1ZXMpLlxuICAgKiBAcGFyYW0ge3tzaWduYWw/OiBBYm9ydFNpZ25hbH19IFtvcHRpb25zXSAtIFN1YnNjcmlwdGlvbiBsaWZlY3ljbGUgb3B0aW9ucy5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAqL1xuICBhc3luYyBzdWJzY3JpYmUoY29udGV4dCwge3NpZ25hbH0gPSB7fSkge1xuICAgIGlmICh0aGlzLl9zdGF0ZSA9PT0gXCJzdWJzY3JpYmVkXCIpIHJldHVyblxuXG4gICAgaWYgKCF0aGlzLl9zdWJzY3JpYmVQcm9taXNlKSB7XG4gICAgICB0aGlzLl9zdWJzY3JpYmVQcm9taXNlID0gdGhpcy5fc3Vic2NyaWJlKGNvbnRleHQsIHNpZ25hbCkuZmluYWxseSgoKSA9PiB7XG4gICAgICAgIHRoaXMuX3N1YnNjcmliZVByb21pc2UgPSBudWxsXG4gICAgICB9KVxuICAgIH1cblxuICAgIGF3YWl0IHRoaXMuX3N1YnNjcmliZVByb21pc2VcbiAgfVxuXG4gIC8qKlxuICAgKiBDb25uZWN0cyB0aGUgd2Vic29ja2V0IGNsaWVudCwgc3Vic2NyaWJlcyBldmVyeSBkZXJpdmVkIGNoYW5uZWwsIGFuZCB3YWl0c1xuICAgKiBmb3IgZWFjaCBzdWJzY3JpcHRpb24ncyBzZXJ2ZXIgYWNrbm93bGVkZ2VtZW50IGJlZm9yZSB0aGUgZ2FwLWNsb3NpbmcgcHVsbCxcbiAgICogc28gbm8gY2hhbmdlIGNhbiBsYW5kIGJldHdlZW4gdGhlIHB1bGwgYW5kIHRoZSBzdWJzY3JpcHRpb25zIGdvaW5nIGxpdmUuXG4gICAqIExvY2FsbHkgY3JlYXRlZCByZXNvdXJjZXMgYXJlIG9ubHkgcHJvbW90ZWQgdG8gdGhlIGJyaWRnZSBvbmNlIGV2ZXJ5dGhpbmdcbiAgICogaXMgbGl2ZTsgYW4gdW5zdWJzY3JpYmUgYXJyaXZpbmcgZHVyaW5nIGFueSBhd2FpdCBtYXJrcyB0aGlzIGF0dGVtcHQgc3RhbGVcbiAgICogYW5kIGl0IHRlYXJzIGl0cyBvd24gcmVzb3VyY2VzIGRvd24gaW5zdGVhZCBvZiByZXN1YnNjcmliaW5nLlxuICAgKiBAcGFyYW0ge1JldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+fSBjb250ZXh0IC0gQXBwIGNvbnRleHQgcGFzc2VkIHRvIHRoZSBjaGFubmVscyBjYWxsYmFjay5cbiAgICogQHBhcmFtIHtBYm9ydFNpZ25hbCB8IHVuZGVmaW5lZH0gc2lnbmFsIC0gU3Vic2NyaXB0aW9uIGxpZmVjeWNsZSBzaWduYWwuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgYXN5bmMgX3N1YnNjcmliZShjb250ZXh0LCBzaWduYWwpIHtcbiAgICBjb25zdCBnZW5lcmF0aW9uID0gdGhpcy5fZ2VuZXJhdGlvblxuXG4gICAgdGhpcy5fc3RhdGUgPSBcInN1YnNjcmliaW5nXCJcblxuICAgIC8qKiBAdHlwZSB7QXJyYXk8e2NoYW5uZWw6IHN0cmluZywgcmVzb3VyY2VUeXBlOiBzdHJpbmcgfCBudWxsLCBzdWJzY3JpcHRpb246IGltcG9ydChcIi4uL2NvbmZpZ3VyYXRpb24tdHlwZXMuanNcIikuVmVsb2Npb3VzU3luY1JlYWx0aW1lU3Vic2NyaXB0aW9ufT59ICovXG4gICAgY29uc3QgY2hhbm5lbHMgPSBbXVxuICAgIC8qKiBAdHlwZSB7VmVsb2Npb3VzU3luY1JlYWx0aW1lV2Vic29ja2V0Q2xpZW50IHwgbnVsbH0gKi9cbiAgICBsZXQgY2xpZW50ID0gbnVsbFxuICAgIC8qKiBAdHlwZSB7Ym9vbGVhbn0gV2hldGhlciB0aGlzIGF0dGVtcHQgY3JlYXRlZCBpdHMgb3duIGNsaWVudCBhbmQgbXVzdCBkaXNjb25uZWN0IGl0IG9uIHRlYXJkb3duLiAqL1xuICAgIGxldCBvd25zQ2xpZW50ID0gZmFsc2VcbiAgICAvKipcbiAgICAgKiBUZWFycyBkb3duIGV2ZXJ5dGhpbmcgdGhpcyBzdGFsZS9mYWlsZWQgc3Vic2NyaWJlIGF0dGVtcHQgY3JlYXRlZCBpdHNlbGY6XG4gICAgICogYWx3YXlzIGNsb3NlcyBpdHMgY2hhbm5lbCBzdWJzY3JpcHRpb25zLCBhbmQgZGlzY29ubmVjdHMgdGhlIHdlYnNvY2tldFxuICAgICAqIG9ubHkgd2hlbiB0aGUgYnJpZGdlIG93bnMgaXQgKGRlcHJlY2F0ZWQgcGVyLWN5Y2xlIHBhdGgpOyBhIHNoYXJlZFxuICAgICAqIGNvbm5lY3Rpb24gc3RheXMgb3Blbi5cbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICAgKi9cbiAgICBjb25zdCB0ZWFyZG93biA9IGFzeW5jICgpID0+IHtcbiAgICAgIGZvciAoY29uc3Qge3N1YnNjcmlwdGlvbn0gb2YgY2hhbm5lbHMpIHtcbiAgICAgICAgc3Vic2NyaXB0aW9uLmNsb3NlKClcbiAgICAgIH1cblxuICAgICAgaWYgKGNsaWVudCAmJiBvd25zQ2xpZW50KSBhd2FpdCBjbGllbnQuZGlzY29ubmVjdEFuZFN0b3BSZWNvbm5lY3QoKVxuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICB0aHJvd0lmQWJvcnRlZChzaWduYWwpXG5cbiAgICAgIGNvbnN0IHNoYXJlZENsaWVudCA9IHRoaXMuc3luY0NsaWVudC5zeW5jQ29ubmVjdGlvbigpXG4gICAgICBjb25zdCByZWFsdGltZSA9IHRoaXMucmVxdWlyZUNsaWVudFNvdXJjZShzaGFyZWRDbGllbnQpXG4gICAgICBjb25zdCBjaGFubmVsRGVzY3JpcHRvcnMgPSBhd2FpdCB0aGlzLmNoYW5uZWxEZXNjcmlwdG9ycyhjb250ZXh0KVxuXG4gICAgICB0aHJvd0lmQWJvcnRlZChzaWduYWwpXG4gICAgICBpZiAoZ2VuZXJhdGlvbiAhPT0gdGhpcy5fZ2VuZXJhdGlvbikgcmV0dXJuXG5cbiAgICAgIGlmIChzaGFyZWRDbGllbnQpIHtcbiAgICAgICAgY2xpZW50ID0gc2hhcmVkQ2xpZW50XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyByZXF1aXJlQ2xpZW50U291cmNlIGd1YXJhbnRlZWQgcmVhbHRpbWUuY3JlYXRlQ2xpZW50IHdoZW4gdGhlcmUgaXMgbm8gc2hhcmVkIGNvbm5lY3Rpb24uXG4gICAgICAgIGNsaWVudCA9IGF3YWl0IC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vY29uZmlndXJhdGlvbi10eXBlcy5qc1wiKS5WZWxvY2lvdXNTeW5jQ2xpZW50UmVhbHRpbWVDb25maWd1cmF0aW9ufSAqLyAocmVhbHRpbWUpLmNyZWF0ZUNsaWVudCgpXG4gICAgICAgIG93bnNDbGllbnQgPSB0cnVlXG4gICAgICB9XG5cbiAgICAgIGlmIChnZW5lcmF0aW9uICE9PSB0aGlzLl9nZW5lcmF0aW9uKSB7XG4gICAgICAgIGF3YWl0IHRlYXJkb3duKClcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG5cbiAgICAgIGF3YWl0IGNsaWVudC5jb25uZWN0KHtzaWduYWx9KVxuXG4gICAgICB0aHJvd0lmQWJvcnRlZChzaWduYWwpXG4gICAgICBpZiAoZ2VuZXJhdGlvbiAhPT0gdGhpcy5fZ2VuZXJhdGlvbikge1xuICAgICAgICBhd2FpdCB0ZWFyZG93bigpXG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICBjb25zdCBhdXRoZW50aWNhdGlvblRva2VuID0gYXdhaXQgdGhpcy5zeW5jQ2xpZW50LmNvbmZpZy5hdXRoZW50aWNhdGlvblRva2VuKClcblxuICAgICAgdGhyb3dJZkFib3J0ZWQoc2lnbmFsKVxuICAgICAgaWYgKGdlbmVyYXRpb24gIT09IHRoaXMuX2dlbmVyYXRpb24pIHtcbiAgICAgICAgYXdhaXQgdGVhcmRvd24oKVxuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgZm9yIChjb25zdCBjaGFubmVsRGVzY3JpcHRvciBvZiBjaGFubmVsRGVzY3JpcHRvcnMpIHtcbiAgICAgICAgaWYgKGNoYW5uZWxEZXNjcmlwdG9yLnBhcmFtcyAmJiBcImF1dGhlbnRpY2F0aW9uVG9rZW5cIiBpbiBjaGFubmVsRGVzY3JpcHRvci5wYXJhbXMpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFJlYWx0aW1lIGNoYW5uZWwgXCIke2NoYW5uZWxEZXNjcmlwdG9yLmNoYW5uZWx9XCIgcGFyYW1zIG11c3Qgbm90IGluY2x1ZGUgYXV0aGVudGljYXRpb25Ub2tlbiAtIHRoZSBmcmFtZXdvcmsgaW5qZWN0cyB0aGUgc3luYy5jbGllbnQgYXV0aGVudGljYXRpb25Ub2tlbiBhdXRvbWF0aWNhbGx5YClcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJlc291cmNlVHlwZSA9IGNoYW5uZWxEZXNjcmlwdG9yLnJlc291cmNlVHlwZSA/PyBudWxsXG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IG1lcmdlUmVtb3RlUmVxdWVzdENvbnRleHQoe1xuICAgICAgICAgIGNvbnRleHQ6IHRoaXMuc3luY0NsaWVudC5jb25maWcucmVxdWVzdENvbnRleHQsXG4gICAgICAgICAgbGFiZWw6IFwiU3luYyBjbGllbnQgcmVxdWVzdCBjb250ZXh0XCIsXG4gICAgICAgICAgcGFyYW1zOiB7Li4uY2hhbm5lbERlc2NyaXB0b3IucGFyYW1zLCBhdXRoZW50aWNhdGlvblRva2VufVxuICAgICAgICB9KVxuICAgICAgICBjb25zdCBzdWJzY3JpcHRpb24gPSBjbGllbnQuc3Vic2NyaWJlQ2hhbm5lbChjaGFubmVsRGVzY3JpcHRvci5jaGFubmVsLCB7XG4gICAgICAgICAgb25NZXNzYWdlOiAoYm9keSkgPT4gdGhpcy5lbnF1ZXVlQXBwbHkoe2JvZHksIGdlbmVyYXRpb24sIHJlc291cmNlVHlwZX0pLFxuICAgICAgICAgIG9uUmVzdW1lOiAoKSA9PiB0aGlzLnNjaGVkdWxlUHVsbChnZW5lcmF0aW9uKSxcbiAgICAgICAgICBwYXJhbXNcbiAgICAgICAgfSlcblxuICAgICAgICBjaGFubmVscy5wdXNoKHtjaGFubmVsOiBjaGFubmVsRGVzY3JpcHRvci5jaGFubmVsLCByZXNvdXJjZVR5cGUsIHN1YnNjcmlwdGlvbn0pXG4gICAgICB9XG5cbiAgICAgIGF3YWl0IFByb21pc2UuYWxsKGNoYW5uZWxzLm1hcCgoe3N1YnNjcmlwdGlvbn0pID0+IHN1YnNjcmlwdGlvbi53YWl0Rm9yUmVhZHkoe3NpZ25hbH0pKSlcblxuICAgICAgdGhyb3dJZkFib3J0ZWQoc2lnbmFsKVxuICAgICAgaWYgKGdlbmVyYXRpb24gIT09IHRoaXMuX2dlbmVyYXRpb24pIHtcbiAgICAgICAgYXdhaXQgdGVhcmRvd24oKVxuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgdGhpcy5fY2hhbm5lbHMgPSBjaGFubmVsc1xuICAgICAgdGhpcy5fY2xpZW50ID0gY2xpZW50XG4gICAgICB0aGlzLl9vd25zQ2xpZW50ID0gb3duc0NsaWVudFxuICAgICAgdGhpcy5fc3RhdGUgPSBcInN1YnNjcmliZWRcIlxuICAgICAgdGhpcy5zY2hlZHVsZVB1bGwoZ2VuZXJhdGlvbilcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgYXdhaXQgdGVhcmRvd24oKVxuXG4gICAgICBpZiAoZ2VuZXJhdGlvbiA9PT0gdGhpcy5fZ2VuZXJhdGlvbikgdGhpcy5fc3RhdGUgPSBcInVuc3Vic2NyaWJlZFwiXG5cbiAgICAgIHRocm93IGVycm9yXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlcyBldmVyeSBjaGFubmVsIHN1YnNjcmlwdGlvbiAoaWRlbXBvdGVudCkuIFRoZSB3ZWJzb2NrZXQgaXNcbiAgICogZGlzY29ubmVjdGVkIG9ubHkgd2hlbiB0aGUgYnJpZGdlIG93bnMgaXQgKGRlcHJlY2F0ZWQgcGVyLWN5Y2xlXG4gICAqIGByZWFsdGltZS5jcmVhdGVDbGllbnRgIHBhdGgpOyBhIHNoYXJlZCBhcHAtbGlmZXRpbWUgY29ubmVjdGlvbiBzdGF5cyBvcGVuXG4gICAqIHNvIHVuc3Vic2NyaWJpbmcgZHJvcHMgc3Vic2NyaXB0aW9ucyB3aXRob3V0IHRlYXJpbmcgZG93biB0aGUgc29ja2V0LiBBbHNvXG4gICAqIG1hcmtzIGFueSBpbi1mbGlnaHQgc3Vic2NyaWJlIGF0dGVtcHQgc3RhbGUgc28gaXQgdGVhcnMgaXRzZWxmIGRvd24gaW5zdGVhZFxuICAgKiBvZiBmaW5pc2hpbmcgdGhlIHN1YnNjcmlwdGlvbiBhZnRlcndhcmRzLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIGFzeW5jIHVuc3Vic2NyaWJlKCkge1xuICAgIHRoaXMuX2dlbmVyYXRpb24gKz0gMVxuXG4gICAgY29uc3QgY2hhbm5lbHMgPSB0aGlzLl9jaGFubmVsc1xuICAgIGNvbnN0IGNsaWVudCA9IHRoaXMuX2NsaWVudFxuICAgIGNvbnN0IG93bnNDbGllbnQgPSB0aGlzLl9vd25zQ2xpZW50XG5cbiAgICB0aGlzLl9jaGFubmVscyA9IFtdXG4gICAgdGhpcy5fY2xpZW50ID0gbnVsbFxuICAgIHRoaXMuX293bnNDbGllbnQgPSBmYWxzZVxuICAgIHRoaXMuX3N0YXRlID0gXCJ1bnN1YnNjcmliZWRcIlxuXG4gICAgZm9yIChjb25zdCB7c3Vic2NyaXB0aW9ufSBvZiBjaGFubmVscykge1xuICAgICAgc3Vic2NyaXB0aW9uLmNsb3NlKClcbiAgICB9XG5cbiAgICBpZiAoY2xpZW50ICYmIG93bnNDbGllbnQpIGF3YWl0IGNsaWVudC5kaXNjb25uZWN0QW5kU3RvcFJlY29ubmVjdCgpXG4gIH1cblxuICAvKipcbiAgICogUmVwb3J0cyB0aGUgYnJpZGdlIHN1YnNjcmlwdGlvbiBzdGF0ZSBhbmQgcGVyLWNoYW5uZWwgcmVhZGluZXNzLlxuICAgKiBAcmV0dXJucyB7e2NoYW5uZWxzOiBBcnJheTx7Y2hhbm5lbDogc3RyaW5nLCByZWFkeTogYm9vbGVhbiwgcmVzb3VyY2VUeXBlOiBzdHJpbmcgfCBudWxsfT4sIHN0YXRlOiBcInN1YnNjcmliZWRcIiB8IFwic3Vic2NyaWJpbmdcIiB8IFwidW5zdWJzY3JpYmVkXCJ9fSBSZWFsdGltZSBzdGF0dXMuXG4gICAqL1xuICBzdGF0dXMoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNoYW5uZWxzOiB0aGlzLl9jaGFubmVscy5tYXAoKHtjaGFubmVsLCByZXNvdXJjZVR5cGUsIHN1YnNjcmlwdGlvbn0pID0+ICh7Y2hhbm5lbCwgcmVhZHk6IHN1YnNjcmlwdGlvbi5pc1JlYWR5KCksIHJlc291cmNlVHlwZX0pKSxcbiAgICAgIHN0YXRlOiB0aGlzLl9zdGF0ZVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBd2FpdHMgYWxsIGVucXVldWVkIG1lc3NhZ2UgYXBwbGllcyBhbmQgYW55IHNjaGVkdWxlZCBwdWxsICh0ZXN0cywgc2h1dGRvd24gZmxvd3MpLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIGFzeW5jIHdhaXRGb3JBcHBsaWVkKCkge1xuICAgIGF3YWl0IHRoaXMuX2FwcGx5UHJvbWlzZVxuICAgIGlmICh0aGlzLl9zY2hlZHVsZWRQdWxsKSBhd2FpdCB0aGlzLl9zY2hlZHVsZWRQdWxsXG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZXMgdGhlIHJlYWx0aW1lIGNvbmZpZ3VyYXRpb24gYmxvY2ssIG9yIG51bGwgd2hlbiB0aGUgYXBwIGRlY2xhcmVkXG4gICAqIG5vbmUgKHZhbGlkIHdoZW4gYSBzaGFyZWQgY29ubmVjdGlvbiBpcyBjb25maWd1cmVkKS5cbiAgICogQHJldHVybnMge2ltcG9ydChcIi4uL2NvbmZpZ3VyYXRpb24tdHlwZXMuanNcIikuVmVsb2Npb3VzU3luY0NsaWVudFJlYWx0aW1lQ29uZmlndXJhdGlvbiB8IG51bGx9IFJlYWx0aW1lIGNvbmZpZ3VyYXRpb24sIG9yIG51bGwuXG4gICAqL1xuICByZWFsdGltZUNvbmZpZ3VyYXRpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuc3luY0NsaWVudC5jb25maWcucmVhbHRpbWUgfHwgbnVsbFxuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmVzIHRoZSByZWFsdGltZSBjb25maWd1cmF0aW9uIGFuZCBhc3NlcnRzIGEgd2Vic29ja2V0IGNsaWVudCBzb3VyY2VcbiAgICogZXhpc3RzOiBhIHNoYXJlZCBjb25uZWN0aW9uIHJpZGVzIGl0cyBvd24gbGlmZWN5Y2xlLCBvdGhlcndpc2UgdGhlXG4gICAqIGRlcHJlY2F0ZWQgcGVyLWN5Y2xlIGByZWFsdGltZS5jcmVhdGVDbGllbnRgIG11c3QgYmUgY29uZmlndXJlZC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLXR5cGVzLmpzXCIpLlZlbG9jaW91c1N5bmNSZWFsdGltZVdlYnNvY2tldENsaWVudCB8IG51bGx9IHNoYXJlZENsaWVudCAtIFNoYXJlZCBjb25uZWN0aW9uLCBvciBudWxsLlxuICAgKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vY29uZmlndXJhdGlvbi10eXBlcy5qc1wiKS5WZWxvY2lvdXNTeW5jQ2xpZW50UmVhbHRpbWVDb25maWd1cmF0aW9uIHwgbnVsbH0gUmVhbHRpbWUgY29uZmlndXJhdGlvbiwgb3IgbnVsbC5cbiAgICovXG4gIHJlcXVpcmVDbGllbnRTb3VyY2Uoc2hhcmVkQ2xpZW50KSB7XG4gICAgY29uc3QgcmVhbHRpbWUgPSB0aGlzLnJlYWx0aW1lQ29uZmlndXJhdGlvbigpXG5cbiAgICBpZiAoIXNoYXJlZENsaWVudCAmJiB0eXBlb2YgcmVhbHRpbWU/LmNyZWF0ZUNsaWVudCAhPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJzdWJzY3JpYmVSZWFsdGltZSByZXF1aXJlcyBhIHNoYXJlZCBjb25uZWN0aW9uIChzeW5jLmNsaWVudC53ZWJzb2NrZXRVcmwgb3Igc3luYy5jbGllbnQud2Vic29ja2V0Q2xpZW50KSBvciB0aGUgZGVwcmVjYXRlZCBzeW5jLmNsaWVudC5yZWFsdGltZS5jcmVhdGVDbGllbnQgY2FsbGJhY2tcIilcbiAgICB9XG5cbiAgICByZXR1cm4gcmVhbHRpbWVcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXJpdmVzIHRoZSBjaGFubmVsIGRlc2NyaXB0b3JzIHRvIHN1YnNjcmliZTogb25lIGZyYW1ld29yayBzeW5jIGNoYW5uZWxcbiAgICogc3Vic2NyaXB0aW9uIHBlciBkZWNsYXJlZCBwdWxsIHNjb3BlICh0aGUgcGFyYW1zIG1pcnJvciB0aGUgc2NvcGUnc1xuICAgKiBge3Jlc291cmNlVHlwZSwgY29uZGl0aW9uc31gKSwgcGx1cyB0aGUgZGVwcmVjYXRlZCBsZWdhY3kgcGF0aHMg4oCUXG4gICAqIG1vZGVsLWxldmVsIHN0YXRpYyByZWFsdGltZSBkZWNsYXJhdGlvbnMgYW5kIHRoZSBjb25maWcgY2hhbm5lbHMgY2FsbGJhY2suXG4gICAqIEZhaWxzIGxvdWRseSB3aGVuIG5vdGhpbmcgaXMgc3Vic2NyaWJhYmxlLlxuICAgKiBAcGFyYW0ge1JldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+fSBjb250ZXh0IC0gQXBwIGNvbnRleHQgcGFzc2VkIHRvIHRoZSBkZXByZWNhdGVkIGNoYW5uZWxzIGNhbGxiYWNrLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxBcnJheTxWZWxvY2lvdXNTeW5jUmVhbHRpbWVDaGFubmVsRGVzY3JpcHRvcj4+fSBDaGFubmVsIGRlc2NyaXB0b3JzLlxuICAgKi9cbiAgYXN5bmMgY2hhbm5lbERlc2NyaXB0b3JzKGNvbnRleHQpIHtcbiAgICBjb25zdCByZWFsdGltZSA9IHRoaXMucmVhbHRpbWVDb25maWd1cmF0aW9uKClcbiAgICAvKiogQHR5cGUge0FycmF5PFZlbG9jaW91c1N5bmNSZWFsdGltZUNoYW5uZWxEZXNjcmlwdG9yPn0gKi9cbiAgICBjb25zdCBjaGFubmVsRGVzY3JpcHRvcnMgPSBbXVxuXG4gICAgZm9yIChjb25zdCBzY29wZVJvdyBvZiBhd2FpdCB0aGlzLnN5bmNDbGllbnQuc2NvcGVTdG9yZSgpLmFjdGl2ZVNjb3BlcygpKSB7XG4gICAgICBjaGFubmVsRGVzY3JpcHRvcnMucHVzaCh7XG4gICAgICAgIGNoYW5uZWw6IFZFTE9DSU9VU19TWU5DX0NIQU5ORUwsXG4gICAgICAgIHBhcmFtczoge1xuICAgICAgICAgIGNvbmRpdGlvbnM6IHRoaXMuYXR0cmlidXRlTmFtZWRDb25kaXRpb25zKHNjb3BlUm93KSxcbiAgICAgICAgICByZXNvdXJjZVR5cGU6IHNjb3BlUm93LnJlc291cmNlVHlwZSxcbiAgICAgICAgICAvLyBPbmx5IHRoZSBhbGwtdHlwZXMgc2NvcGUgY2FycmllcyB0aGUgdHlwZSBsaXN0OyBhIHR5cGUtZGVjbGFyZWQgc2NvcGUgbmVlZHMgbm9uZS5cbiAgICAgICAgICAuLi4oc2NvcGVSb3cucmVzb3VyY2VUeXBlID09PSBudWxsID8ge3Jlc291cmNlVHlwZXM6IHRoaXMuc3luY0NsaWVudC51c2VyU2NvcGVSZXNvdXJjZVR5cGVzKCl9IDoge30pXG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBbcmVzb3VyY2VUeXBlLCByZXNvdXJjZUNvbmZpZ10gb2YgT2JqZWN0LmVudHJpZXModGhpcy5zeW5jQ2xpZW50LmNvbmZpZy5yZXNvdXJjZXMpKSB7XG4gICAgICBpZiAoIXJlc291cmNlQ29uZmlnLnJlYWx0aW1lKSBjb250aW51ZVxuXG4gICAgICBjaGFubmVsRGVzY3JpcHRvcnMucHVzaCh7Y2hhbm5lbDogcmVzb3VyY2VDb25maWcucmVhbHRpbWUuY2hhbm5lbCwgcGFyYW1zOiByZXNvdXJjZUNvbmZpZy5yZWFsdGltZS5wYXJhbXMsIHJlc291cmNlVHlwZX0pXG4gICAgfVxuXG4gICAgaWYgKHJlYWx0aW1lPy5jaGFubmVscykge1xuICAgICAgY2hhbm5lbERlc2NyaXB0b3JzLnB1c2goLi4uYXdhaXQgcmVhbHRpbWUuY2hhbm5lbHMoY29udGV4dCkpXG4gICAgfVxuXG4gICAgaWYgKGNoYW5uZWxEZXNjcmlwdG9ycy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcInN1YnNjcmliZVJlYWx0aW1lIGZvdW5kIG5vIGNoYW5uZWxzIHRvIHN1YnNjcmliZSAtIGRlY2xhcmUgYSBzeW5jIHNjb3BlIChzeW5jQ2xpZW50KCkuc3luYyhxdWVyeSkpIHNvIGl0cyBmcmFtZXdvcmsgc3luYyBjaGFubmVsIHN1YnNjcmlwdGlvbiBjYW4gYmUgZGVyaXZlZCwgb3IgdGhlIGRlcHJlY2F0ZWQgc3luYy5jbGllbnQucmVhbHRpbWUuY2hhbm5lbHMgY2FsbGJhY2tcIilcbiAgICB9XG5cbiAgICByZXR1cm4gY2hhbm5lbERlc2NyaXB0b3JzXG4gIH1cblxuICAvKipcbiAgICogVHJhbnNsYXRlcyBhIHBlcnNpc3RlZCBzY29wZSdzIGNvbmRpdGlvbiBrZXlzIHRvIHRoZSBtb2RlbCdzIGF0dHJpYnV0ZVxuICAgKiBuYW1lcyBzbyB0aGUgZnJhbWV3b3JrIGNoYW5uZWwgc3Vic2NyaXB0aW9uIG1hdGNoZXMgdGhlIHB1Ymxpc2hlcidzXG4gICAqIGF0dHJpYnV0ZS1uYW1lZCBzY29waW5nIHBhcmFtczogYHNlcmlhbGl6ZWRTY29wZUZyb21RdWVyeWAgcGVyc2lzdHMgdGhlXG4gICAqIHF1ZXJ5J3MgbW9kZWwtbm9ybWFsaXplZCBjb2x1bW4gbmFtZXMgKGZvciBleGFtcGxlIGBwcm9qZWN0X2lkYCksIHdoaWxlXG4gICAqIHNjb3BlLXBhcnRpdGlvbiBicm9hZGNhc3RzIGNhcnJ5IGF0dHJpYnV0ZSBuYW1lcyAoYHByb2plY3RJZGApLiBLZXlzXG4gICAqIHdpdGhvdXQgYSBjb2x1bW4gbWFwcGluZyBhcmUgYWxyZWFkeSBhdHRyaWJ1dGUgbmFtZXMgYW5kIHBhc3MgdGhyb3VnaDtcbiAgICogc2NvcGVzIG9uIG1vZGVscyB3aXRob3V0IGEgZGVjbGFyZWQgc3luYyByZXNvdXJjZSBmYWlsIGxvdWRseSBiZWNhdXNlIG5vXG4gICAqIGF0dHJpYnV0ZSBtYXBwaW5nIGV4aXN0cyBmb3IgdGhlbS5cbiAgICpcbiAgICogVGhlIGFsbC10eXBlcyAodXNlcikgc2NvcGUgaGFzIG5vIHJlc291cmNlIHR5cGUgYW5kIG5vIGNvbmRpdGlvbnMgLSBpdFxuICAgKiBjb3ZlcnMgZXZlcnl0aGluZyB0aGUgc2VydmVyIGF1dGhvcml6ZXMgZm9yIHRoZSBjYWxsZXIgLSBzbyB0aGVyZSBpc1xuICAgKiBub3RoaW5nIHRvIG1hcC5cbiAgICogQHBhcmFtIHt7Y29uZGl0aW9uczogUmVjb3JkPHN0cmluZywgUmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4+LCByZXNvdXJjZVR5cGU6IHN0cmluZyB8IG51bGx9fSBzY29wZVJvdyAtIEFjdGl2ZSBzY29wZSByb3cuXG4gICAqIEByZXR1cm5zIHtSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj59IEF0dHJpYnV0ZS1uYW1lZCBzY29wZSBjb25kaXRpb25zLlxuICAgKi9cbiAgYXR0cmlidXRlTmFtZWRDb25kaXRpb25zKHNjb3BlUm93KSB7XG4gICAgaWYgKHNjb3BlUm93LnJlc291cmNlVHlwZSA9PT0gbnVsbCkgcmV0dXJuIHt9XG5cbiAgICBjb25zdCByZXNvdXJjZUNvbmZpZyA9IHRoaXMuc3luY0NsaWVudC5jb25maWcucmVzb3VyY2VzW3Njb3BlUm93LnJlc291cmNlVHlwZV1cblxuICAgIGlmICghcmVzb3VyY2VDb25maWcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgc3Vic2NyaWJlUmVhbHRpbWUgY2FuJ3QgZGVyaXZlIGF0dHJpYnV0ZSBuYW1lcyBmb3IgdGhlIHN5bmMgc2NvcGUgZGVjbGFyZWQgb24gJHtzY29wZVJvdy5yZXNvdXJjZVR5cGV9IC0gZGVjbGFyZSBzdGF0aWMgc3luYyBvbiB0aGF0IG1vZGVsIHNvIGl0cyByZXNvdXJjZSBpcyByZWdpc3RlcmVkYClcbiAgICB9XG5cbiAgICBjb25zdCBjb2x1bW5OYW1lVG9BdHRyaWJ1dGVOYW1lID0gcmVzb3VyY2VDb25maWcubWV0YWRhdGFNb2RlbENsYXNzLmdldENvbHVtbk5hbWVUb0F0dHJpYnV0ZU5hbWVNYXAoKVxuICAgIC8qKiBAdHlwZSB7UmVjb3JkPHN0cmluZywgUmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4+fSAqL1xuICAgIGNvbnN0IGNvbmRpdGlvbnMgPSB7fVxuXG4gICAgZm9yIChjb25zdCBbY29uZGl0aW9uTmFtZSwgY29uZGl0aW9uVmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKHNjb3BlUm93LmNvbmRpdGlvbnMpKSB7XG4gICAgICBjb25kaXRpb25zW2NvbHVtbk5hbWVUb0F0dHJpYnV0ZU5hbWVbY29uZGl0aW9uTmFtZV0gfHwgY29uZGl0aW9uTmFtZV0gPSBjb25kaXRpb25WYWx1ZVxuICAgIH1cblxuICAgIHJldHVybiBjb25kaXRpb25zXG4gIH1cblxuICAvKipcbiAgICogQ2hhaW5zIG9uZSBwdXNoZWQgbWVzc2FnZSBvbnRvIHRoZSBzZXJpYWxpemVkIGFwcGx5IHF1ZXVlIHNvIGNoYW5nZXMgYXBwbHlcbiAgICogaW4gYXJyaXZhbCBvcmRlcjsgZmFpbHVyZXMgZ28gdG8gdGhlIHN5bmMgY2xpZW50J3MgZXJyb3IgcmVwb3J0aW5nLlxuICAgKiBAcGFyYW0ge3tib2R5OiBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPiwgZ2VuZXJhdGlvbj86IG51bWJlciwgcmVzb3VyY2VUeXBlOiBzdHJpbmcgfCBudWxsfX0gYXJncyAtIE1lc3NhZ2UgYXJncy5cbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICBlbnF1ZXVlQXBwbHkoe2JvZHksIGdlbmVyYXRpb24gPSB0aGlzLl9nZW5lcmF0aW9uLCByZXNvdXJjZVR5cGV9KSB7XG4gICAgdGhpcy5fYXBwbHlQcm9taXNlID0gdGhpcy5fYXBwbHlQcm9taXNlLnRoZW4oYXN5bmMgKCkgPT4ge1xuICAgICAgaWYgKGdlbmVyYXRpb24gIT09IHRoaXMuX2dlbmVyYXRpb24pIHJldHVyblxuXG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB0aGlzLmFwcGx5TWVzc2FnZSh7Ym9keSwgcmVzb3VyY2VUeXBlfSlcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHRoaXMuc3luY0NsaWVudC5yZXBvcnRFcnJvcigvKiogQHR5cGUge0Vycm9yfSAqLyAoZXJyb3IpKVxuICAgICAgfVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogQXBwbGllcyBvbmUgcHVzaGVkIG1lc3NhZ2UgdGhyb3VnaCB0aGUgZGVyaXZlZCByZXNvdXJjZSBhcHBsaWVyOiBkcm9wc1xuICAgKiBvd24tZGV2aWNlIG1lc3NhZ2VzIGJ5IGVjaG8gb3JpZ2luLCBkZWZhdWx0cyB0aGUgY2hhbm5lbCdzIHJlc291cmNlVHlwZSBvbnRvXG4gICAqIGVudmVsb3BlcyB3aXRob3V0IG9uZSwgYW5kIGZhaWxzIGxvdWRseSBvbiB1bmtub3duIHJlc291cmNlIHR5cGVzLlxuICAgKiBAcGFyYW0ge3tib2R5OiBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPiwgcmVzb3VyY2VUeXBlOiBzdHJpbmcgfCBudWxsfX0gYXJncyAtIE1lc3NhZ2UgYXJncy5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAqL1xuICBhc3luYyBhcHBseU1lc3NhZ2Uoe2JvZHksIHJlc291cmNlVHlwZX0pIHtcbiAgICBpZiAoIWJvZHkgfHwgdHlwZW9mIGJvZHkgIT09IFwib2JqZWN0XCIgfHwgQXJyYXkuaXNBcnJheShib2R5KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBSZWFsdGltZSBzeW5jIG1lc3NhZ2VzIG11c3QgYmUgZW52ZWxvcGUgb2JqZWN0cywgZ290OiAke0pTT04uc3RyaW5naWZ5KGJvZHkpfWApXG4gICAgfVxuXG4gICAgY29uc3QgcmVhbHRpbWUgPSB0aGlzLnJlYWx0aW1lQ29uZmlndXJhdGlvbigpXG5cbiAgICBpZiAocmVhbHRpbWU/LmxvY2FsT3JpZ2luICYmIGJvZHkuZWNob09yaWdpbiAhPT0gdW5kZWZpbmVkICYmIGJvZHkuZWNob09yaWdpbiAhPT0gbnVsbCkge1xuICAgICAgY29uc3QgbG9jYWxPcmlnaW4gPSBTdHJpbmcoYXdhaXQgcmVhbHRpbWUubG9jYWxPcmlnaW4oKSlcblxuICAgICAgaWYgKFN0cmluZyhib2R5LmVjaG9PcmlnaW4pID09PSBsb2NhbE9yaWdpbikgcmV0dXJuXG4gICAgfVxuXG4gICAgY29uc3Qgc3luY1BheWxvYWRzID0gQXJyYXkuaXNBcnJheShib2R5LnN5bmNzKSA/IGJvZHkuc3luY3MgOiBbYm9keV1cbiAgICBjb25zdCBhcHBseVN5bmMgPSB0aGlzLnN5bmNDbGllbnQucmVtb3RlQXBwbHlTeW5jKHtzb3VyY2U6IFwicmVtb3RlIGNoYW5nZVwifSlcblxuICAgIC8vIENvYWxlc2NlIHJlY29yZC1jaGFuZ2UgZXZlbnRzIGFjcm9zcyB0aGUgcHVzaGVkIGJhdGNoIHNvIGl0IHRyaWdnZXJzIG9uZSBsaXZlLXF1ZXJ5IHJlLXJ1bi5cbiAgICBhd2FpdCByZWNvcmRDaGFuZ2VzLmJhdGNoKGFzeW5jICgpID0+IHtcbiAgICAgIGZvciAoY29uc3Qgc3luY1BheWxvYWQgb2Ygc3luY1BheWxvYWRzKSB7XG4gICAgICAgIGNvbnN0IHN5bmMgPSBTeW5jQXBpQ2xpZW50LnN5bmNFbnZlbG9wZUZyb21QYXlsb2FkKHtyZXNvdXJjZVR5cGUsIC4uLnN5bmNQYXlsb2FkfSlcblxuICAgICAgICBhd2FpdCBhcHBseVN5bmMoc3luYylcbiAgICAgIH1cbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIFNjaGVkdWxlcyBhIGNvYWxlc2NlZCBiYWNrZ3JvdW5kIHB1bGwgY2xvc2luZyBvZmZsaW5lIGdhcHMgYWZ0ZXJcbiAgICogKHJlKXN1YnNjcmlwdGlvbiByZWFkaW5lc3MuIFJlc3VtZXMgYXJyaXZpbmcgd2hpbGUgYSBwdWxsIGlzIGFscmVhZHlcbiAgICogc2NoZWR1bGVkIG9yIGluIGZsaWdodCBjb2FsZXNjZSBpbnRvIHRoYXQgcHVsbCBpbnN0ZWFkIG9mIHN0YWNraW5nLlxuICAgKiBAcGFyYW0ge251bWJlcn0gW2dlbmVyYXRpb25dIC0gU3Vic2NyaXB0aW9uIGdlbmVyYXRpb24gb3duaW5nIHRoZSByZXN1bWUvcmVhZGluZXNzIGNhbGxiYWNrLlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIHNjaGVkdWxlUHVsbChnZW5lcmF0aW9uID0gdGhpcy5fZ2VuZXJhdGlvbikge1xuICAgIGlmIChnZW5lcmF0aW9uICE9PSB0aGlzLl9nZW5lcmF0aW9uKSByZXR1cm5cbiAgICBpZiAodGhpcy5yZWFsdGltZUNvbmZpZ3VyYXRpb24oKT8ucHVsbE9uUmVjb25uZWN0ID09PSBmYWxzZSkgcmV0dXJuXG5cbiAgICB0aGlzLl9zY2hlZHVsZWRQdWxsIHx8PSAoYXN5bmMgKCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgdGhpcy5zeW5jQ2xpZW50LnB1bGwoKVxuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgaWYgKCF0aGlzLnN5bmNDbGllbnQuaXNMaWZlY3ljbGVBYm9ydChlcnJvcikpIHtcbiAgICAgICAgICB0aGlzLnN5bmNDbGllbnQucmVwb3J0RXJyb3IoLyoqIEB0eXBlIHtFcnJvcn0gKi8gKGVycm9yKSlcbiAgICAgICAgfVxuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgdGhpcy5fc2NoZWR1bGVkUHVsbCA9IG51bGxcbiAgICAgIH1cbiAgICB9KSgpXG4gIH1cbn1cblxuLyoqXG4gKiBUaHJvd3MgdGhlIGxpZmVjeWNsZSBhYm9ydCByZWFzb24gd2hlbiB0aGUgc3Vic2NyaXB0aW9uIGlzIG5vIGxvbmdlciBvd25lZC5cbiAqIEBwYXJhbSB7QWJvcnRTaWduYWwgfCB1bmRlZmluZWR9IHNpZ25hbCAtIFN1YnNjcmlwdGlvbiBsaWZlY3ljbGUgc2lnbmFsLlxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIHRocm93SWZBYm9ydGVkKHNpZ25hbCkge1xuICBpZiAoIXNpZ25hbD8uYWJvcnRlZCkgcmV0dXJuXG5cbiAgdGhyb3cgc2lnbmFsLnJlYXNvbiBpbnN0YW5jZW9mIEVycm9yID8gc2lnbmFsLnJlYXNvbiA6IG5ldyBFcnJvcihcIlN5bmMgcmVhbHRpbWUgc3Vic2NyaXB0aW9uIHdhcyBhYm9ydGVkXCIpXG59XG4iXX0=
|
|
387
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1yZWFsdGltZS1icmlkZ2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc3luYy9zeW5jLXJlYWx0aW1lLWJyaWRnZS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxhQUFhLE1BQU0sK0JBQStCLENBQUE7QUFDekQsT0FBTyxFQUFDLHlCQUF5QixFQUFDLE1BQU0sOEJBQThCLENBQUE7QUFFdEUsT0FBTyxhQUFhLE1BQU0sc0JBQXNCLENBQUE7QUFDaEQsT0FBTyxFQUFDLHNCQUFzQixFQUFDLE1BQU0sd0JBQXdCLENBQUE7QUFFN0QsbUlBQW1JO0FBQ25JLCtIQUErSDtBQUUvSDs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSCxNQUFNLENBQUMsT0FBTyxPQUFPLGtCQUFrQjtJQUNyQzs7O09BR0c7SUFDSCxZQUFZLEVBQUMsVUFBVSxFQUFDO1FBQ3RCLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFBO1FBQzVCLHlKQUF5SjtRQUN6SixJQUFJLENBQUMsU0FBUyxHQUFHLEVBQUUsQ0FBQTtRQUNuQiwwREFBMEQ7UUFDMUQsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUE7UUFDbkIsdUtBQXVLO1FBQ3ZLLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFBO1FBQ3hCLDRCQUE0QjtRQUM1QixJQUFJLENBQUMsYUFBYSxHQUFHLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQTtRQUN0Qyx1SEFBdUg7UUFDdkgsSUFBSSxDQUFDLFdBQVcsR0FBRyxDQUFDLENBQUE7UUFDcEIsbUNBQW1DO1FBQ25DLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFBO1FBQzFCLG1DQUFtQztRQUNuQyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxDQUFBO1FBQzdCLDREQUE0RDtRQUM1RCxJQUFJLENBQUMsTUFBTSxHQUFHLGNBQWMsQ0FBQTtJQUM5QixDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNI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LENBQUMsSUFBSSxFQUFFLENBQUE7WUFDOUIsQ0FBQztZQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7Z0JBQ2YsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztvQkFDN0MsSUFBSSxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsb0JBQW9CLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFBO2dCQUMzRCxDQUFDO1lBQ0gsQ0FBQztvQkFBUyxDQUFDO2dCQUNULElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFBO1lBQzVCLENBQUM7UUFDSCxDQUFDLENBQUMsRUFBRSxDQUFBO0lBQ04sQ0FBQztDQUNGO0FBRUQ7Ozs7R0FJRztBQUNILFNBQVMsY0FBYyxDQUFDLE1BQU07SUFDNUIsSUFBSSxDQUFDLE1BQU0sRUFBRSxPQUFPO1FBQUUsT0FBTTtJQUU1QixNQUFNLE1BQU0sQ0FBQyxNQUFNLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssQ0FBQyx3Q0FBd0MsQ0FBQyxDQUFBO0FBQzVHLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IHJlY29yZENoYW5nZXMgZnJvbSBcIi4uL2RhdGFiYXNlL3JlY29yZC1jaGFuZ2VzLmpzXCJcbmltcG9ydCB7bWVyZ2VSZW1vdGVSZXF1ZXN0Q29udGV4dH0gZnJvbSBcIi4uL3JlbW90ZS1yZXF1ZXN0LWNvbnRleHQuanNcIlxuXG5pbXBvcnQgU3luY0FwaUNsaWVudCBmcm9tIFwiLi9zeW5jLWFwaS1jbGllbnQuanNcIlxuaW1wb3J0IHtWRUxPQ0lPVVNfU1lOQ19DSEFOTkVMfSBmcm9tIFwiLi9zeW5jLWNoYW5uZWwtbmFtZS5qc1wiXG5cbi8qKiBAdHlwZWRlZiB7aW1wb3J0KFwiLi4vY29uZmlndXJhdGlvbi10eXBlcy5qc1wiKS5WZWxvY2lvdXNTeW5jUmVhbHRpbWVDaGFubmVsRGVzY3JpcHRvcn0gVmVsb2Npb3VzU3luY1JlYWx0aW1lQ2hhbm5lbERlc2NyaXB0b3IgKi9cbi8qKiBAdHlwZWRlZiB7aW1wb3J0KFwiLi4vY29uZmlndXJhdGlvbi10eXBlcy5qc1wiKS5WZWxvY2lvdXNTeW5jUmVhbHRpbWVXZWJzb2NrZXRDbGllbnR9IFZlbG9jaW91c1N5bmNSZWFsdGltZVdlYnNvY2tldENsaWVudCAqL1xuXG4vKipcbiAqIERlcml2ZWQgcmVhbHRpbWUgcHVzaCBicmlkZ2UgZm9yIHRoZSBzeW5jIGNsaWVudC4gU3Vic2NyaWJlcyBldmVyeSBkZWNsYXJlZFxuICogcHVsbCBzY29wZSB0byB0aGUgZnJhbWV3b3JrIHN5bmMgY2hhbm5lbCAoe0BsaW5rIFZFTE9DSU9VU19TWU5DX0NIQU5ORUx9KVxuICogYXV0b21hdGljYWxseSDigJQgdGhlIHN1YnNjcmliZSBwYXJhbXMgbWlycm9yIHRoZSBzY29wZSdzXG4gKiBge3Jlc291cmNlVHlwZSwgY29uZGl0aW9uc31gIHNvIHRoZSBzZXJ2ZXIgYXV0aG9yaXplcyB0aGVtIHRocm91Z2ggdGhlIHNhbWVcbiAqIHN5bmMgcmVzb3VyY2UgYXV0aG9yaXphdGlvbiBhcyBwdWxscyDigJQgcGx1cyBhbnkgZGVwcmVjYXRlZCBsZWdhY3kgY2hhbm5lbHNcbiAqIChjb25maWcgYHN5bmMuY2xpZW50LnJlYWx0aW1lLmNoYW5uZWxzYCBjYWxsYmFjayBhbmQgbW9kZWwtbGV2ZWxcbiAqIGBzdGF0aWMgc3luYyA9IHtyZWFsdGltZToge2NoYW5uZWx9fWAgZGVjbGFyYXRpb25zKS4gUHVzaGVkIGNoYW5nZXMgYXBwbHlcbiAqIHRocm91Z2ggdGhlIHNhbWUgZGVyaXZlZCByZXNvdXJjZSBhcHBsaWVyIGFzIHB1bGxzICh3aXRoIGVjaG8gc3VwcHJlc3Npb25cbiAqIGFnYWluc3QgdHJhY2tlZCByZS1xdWV1ZWluZyksIG93bi1kZXZpY2UgbWVzc2FnZXMgYXJlIGRyb3BwZWQgYnkgZWNob1xuICogb3JpZ2luLCBhbmQgYSBjb2FsZXNjZWQgYHB1bGwoKWAgZmlyZXMgd2hlbiBzdWJzY3JpcHRpb25zIGJlY29tZSByZWFkeSBvclxuICogcmVzdW1lIHNvIG9mZmxpbmUgZ2FwcyBjbG9zZS5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU3luY1JlYWx0aW1lQnJpZGdlIHtcbiAgLyoqXG4gICAqIEJ1aWxkcyB0aGUgYnJpZGdlIGZvciBhIHN5bmMgY2xpZW50LlxuICAgKiBAcGFyYW0ge3tzeW5jQ2xpZW50OiBpbXBvcnQoXCIuL3N5bmMtY2xpZW50LmpzXCIpLmRlZmF1bHR9fSBhcmdzIC0gQnJpZGdlIGFyZ3MuXG4gICAqL1xuICBjb25zdHJ1Y3Rvcih7c3luY0NsaWVudH0pIHtcbiAgICB0aGlzLnN5bmNDbGllbnQgPSBzeW5jQ2xpZW50XG4gICAgLyoqIEB0eXBlIHtBcnJheTx7Y2hhbm5lbDogc3RyaW5nLCByZXNvdXJjZVR5cGU6IHN0cmluZyB8IG51bGwsIHN1YnNjcmlwdGlvbjogaW1wb3J0KFwiLi4vY29uZmlndXJhdGlvbi10eXBlcy5qc1wiKS5WZWxvY2lvdXNTeW5jUmVhbHRpbWVTdWJzY3JpcHRpb259Pn0gKi9cbiAgICB0aGlzLl9jaGFubmVscyA9IFtdXG4gICAgLyoqIEB0eXBlIHtWZWxvY2lvdXNTeW5jUmVhbHRpbWVXZWJzb2NrZXRDbGllbnQgfCBudWxsfSAqL1xuICAgIHRoaXMuX2NsaWVudCA9IG51bGxcbiAgICAvKiogQHR5cGUge2Jvb2xlYW59IFdoZXRoZXIgdGhlIGJyaWRnZSBjcmVhdGVkIGl0cyBvd24gY2xpZW50IChkZXByZWNhdGVkIHBlci1jeWNsZSBwYXRoKSBhbmQgbXVzdCBkaXNjb25uZWN0IGl0IG9uIHVuc3Vic2NyaWJlLiBBIHNoYXJlZCBjb25uZWN0aW9uIGlzIG5ldmVyIG93bmVkLiAqL1xuICAgIHRoaXMuX293bnNDbGllbnQgPSBmYWxzZVxuICAgIC8qKiBAdHlwZSB7UHJvbWlzZTx2b2lkPn0gKi9cbiAgICB0aGlzLl9hcHBseVByb21pc2UgPSBQcm9taXNlLnJlc29sdmUoKVxuICAgIC8qKiBAdHlwZSB7bnVtYmVyfSBTdWJzY3JpcHRpb24gZ2VuZXJhdGlvbiAtIGJ1bXBlZCBieSB1bnN1YnNjcmliZSBzbyBpbi1mbGlnaHQgc3Vic2NyaWJlcyBkZXRlY3QgdGhleSBiZWNhbWUgc3RhbGUuICovXG4gICAgdGhpcy5fZ2VuZXJhdGlvbiA9IDBcbiAgICAvKiogQHR5cGUge1Byb21pc2U8dm9pZD4gfCBudWxsfSAqL1xuICAgIHRoaXMuX3NjaGVkdWxlZFB1bGwgPSBudWxsXG4gICAgLyoqIEB0eXBlIHtQcm9taXNlPHZvaWQ+IHwgbnVsbH0gKi9cbiAgICB0aGlzLl9zdWJzY3JpYmVQcm9taXNlID0gbnVsbFxuICAgIC8qKiBAdHlwZSB7XCJzdWJzY3JpYmVkXCIgfCBcInN1YnNjcmliaW5nXCIgfCBcInVuc3Vic2NyaWJlZFwifSAqL1xuICAgIHRoaXMuX3N0YXRlID0gXCJ1bnN1YnNjcmliZWRcIlxuICB9XG5cbiAgLyoqXG4gICAqIFN1YnNjcmliZXMgdGhlIGRlcml2ZWQgcmVhbHRpbWUgY2hhbm5lbHMgKGlkZW1wb3RlbnQgYW5kIHNpbmdsZS1mbGlnaHRlZCk6XG4gICAqIGFuIGFjdGl2ZSBzdWJzY3JpcHRpb24gaXMga2VwdCBhcy1pcyBhbmQgYSBjb25jdXJyZW50IHN1YnNjcmliZSBhd2FpdHMgdGhlXG4gICAqIGluLWZsaWdodCBhdHRlbXB0LiBDYWxsIGB1bnN1YnNjcmliZSgpYCBmaXJzdCB0byBjaGFuZ2UgdGhlIGNvbnRleHQuXG4gICAqIEBwYXJhbSB7UmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT59IFtjb250ZXh0XSAtIEFwcCBjb250ZXh0IHBhc3NlZCB0byB0aGUgZGVwcmVjYXRlZCBgc3luYy5jbGllbnQucmVhbHRpbWUuY2hhbm5lbHNgIGNhbGxiYWNrIChydW50aW1lIHNjb3BlIHZhbHVlcykuXG4gICAqIEBwYXJhbSB7e3NpZ25hbD86IEFib3J0U2lnbmFsfX0gW29wdGlvbnNdIC0gU3Vic2NyaXB0aW9uIGxpZmVjeWNsZSBvcHRpb25zLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIGFzeW5jIHN1YnNjcmliZShjb250ZXh0LCB7c2lnbmFsfSA9IHt9KSB7XG4gICAgaWYgKHRoaXMuX3N0YXRlID09PSBcInN1YnNjcmliZWRcIikgcmV0dXJuXG5cbiAgICBpZiAoIXRoaXMuX3N1YnNjcmliZVByb21pc2UpIHtcbiAgICAgIHRoaXMuX3N1YnNjcmliZVByb21pc2UgPSB0aGlzLl9zdWJzY3JpYmUoY29udGV4dCwgc2lnbmFsKS5maW5hbGx5KCgpID0+IHtcbiAgICAgICAgdGhpcy5fc3Vic2NyaWJlUHJvbWlzZSA9IG51bGxcbiAgICAgIH0pXG4gICAgfVxuXG4gICAgYXdhaXQgdGhpcy5fc3Vic2NyaWJlUHJvbWlzZVxuICB9XG5cbiAgLyoqXG4gICAqIENvbm5lY3RzIHRoZSB3ZWJzb2NrZXQgY2xpZW50LCBzdWJzY3JpYmVzIGV2ZXJ5IGRlcml2ZWQgY2hhbm5lbCwgYW5kIHdhaXRzXG4gICAqIGZvciBlYWNoIHN1YnNjcmlwdGlvbidzIHNlcnZlciBhY2tub3dsZWRnZW1lbnQgYmVmb3JlIHRoZSBnYXAtY2xvc2luZyBwdWxsLFxuICAgKiBzbyBubyBjaGFuZ2UgY2FuIGxhbmQgYmV0d2VlbiB0aGUgcHVsbCBhbmQgdGhlIHN1YnNjcmlwdGlvbnMgZ29pbmcgbGl2ZS5cbiAgICogTG9jYWxseSBjcmVhdGVkIHJlc291cmNlcyBhcmUgb25seSBwcm9tb3RlZCB0byB0aGUgYnJpZGdlIG9uY2UgZXZlcnl0aGluZ1xuICAgKiBpcyBsaXZlOyBhbiB1bnN1YnNjcmliZSBhcnJpdmluZyBkdXJpbmcgYW55IGF3YWl0IG1hcmtzIHRoaXMgYXR0ZW1wdCBzdGFsZVxuICAgKiBhbmQgaXQgdGVhcnMgaXRzIG93biByZXNvdXJjZXMgZG93biBpbnN0ZWFkIG9mIHJlc3Vic2NyaWJpbmcuXG4gICAqIEBwYXJhbSB7UmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT59IGNvbnRleHQgLSBBcHAgY29udGV4dCBwYXNzZWQgdG8gdGhlIGNoYW5uZWxzIGNhbGxiYWNrLlxuICAgKiBAcGFyYW0ge0Fib3J0U2lnbmFsIHwgdW5kZWZpbmVkfSBzaWduYWwgLSBTdWJzY3JpcHRpb24gbGlmZWN5Y2xlIHNpZ25hbC5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAqL1xuICBhc3luYyBfc3Vic2NyaWJlKGNvbnRleHQsIHNpZ25hbCkge1xuICAgIGNvbnN0IGdlbmVyYXRpb24gPSB0aGlzLl9nZW5lcmF0aW9uXG5cbiAgICB0aGlzLl9zdGF0ZSA9IFwic3Vic2NyaWJpbmdcIlxuXG4gICAgLyoqIEB0eXBlIHtBcnJheTx7Y2hhbm5lbDogc3RyaW5nLCByZXNvdXJjZVR5cGU6IHN0cmluZyB8IG51bGwsIHN1YnNjcmlwdGlvbjogaW1wb3J0KFwiLi4vY29uZmlndXJhdGlvbi10eXBlcy5qc1wiKS5WZWxvY2lvdXNTeW5jUmVhbHRpbWVTdWJzY3JpcHRpb259Pn0gKi9cbiAgICBjb25zdCBjaGFubmVscyA9IFtdXG4gICAgLyoqIEB0eXBlIHtWZWxvY2lvdXNTeW5jUmVhbHRpbWVXZWJzb2NrZXRDbGllbnQgfCBudWxsfSAqL1xuICAgIGxldCBjbGllbnQgPSBudWxsXG4gICAgLyoqIEB0eXBlIHtib29sZWFufSBXaGV0aGVyIHRoaXMgYXR0ZW1wdCBjcmVhdGVkIGl0cyBvd24gY2xpZW50IGFuZCBtdXN0IGRpc2Nvbm5lY3QgaXQgb24gdGVhcmRvd24uICovXG4gICAgbGV0IG93bnNDbGllbnQgPSBmYWxzZVxuICAgIC8qKlxuICAgICAqIFRlYXJzIGRvd24gZXZlcnl0aGluZyB0aGlzIHN0YWxlL2ZhaWxlZCBzdWJzY3JpYmUgYXR0ZW1wdCBjcmVhdGVkIGl0c2VsZjpcbiAgICAgKiBhbHdheXMgY2xvc2VzIGl0cyBjaGFubmVsIHN1YnNjcmlwdGlvbnMsIGFuZCBkaXNjb25uZWN0cyB0aGUgd2Vic29ja2V0XG4gICAgICogb25seSB3aGVuIHRoZSBicmlkZ2Ugb3ducyBpdCAoZGVwcmVjYXRlZCBwZXItY3ljbGUgcGF0aCk7IGEgc2hhcmVkXG4gICAgICogY29ubmVjdGlvbiBzdGF5cyBvcGVuLlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgICAqL1xuICAgIGNvbnN0IHRlYXJkb3duID0gYXN5bmMgKCkgPT4ge1xuICAgICAgZm9yIChjb25zdCB7c3Vic2NyaXB0aW9ufSBvZiBjaGFubmVscykge1xuICAgICAgICBzdWJzY3JpcHRpb24uY2xvc2UoKVxuICAgICAgfVxuXG4gICAgICBpZiAoY2xpZW50ICYmIG93bnNDbGllbnQpIGF3YWl0IGNsaWVudC5kaXNjb25uZWN0QW5kU3RvcFJlY29ubmVjdCgpXG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIHRocm93SWZBYm9ydGVkKHNpZ25hbClcblxuICAgICAgY29uc3Qgc2hhcmVkQ2xpZW50ID0gdGhpcy5zeW5jQ2xpZW50LnN5bmNDb25uZWN0aW9uKClcbiAgICAgIGNvbnN0IHJlYWx0aW1lID0gdGhpcy5yZXF1aXJlQ2xpZW50U291cmNlKHNoYXJlZENsaWVudClcbiAgICAgIGNvbnN0IGNoYW5uZWxEZXNjcmlwdG9ycyA9IGF3YWl0IHRoaXMuY2hhbm5lbERlc2NyaXB0b3JzKGNvbnRleHQpXG5cbiAgICAgIHRocm93SWZBYm9ydGVkKHNpZ25hbClcbiAgICAgIGlmIChnZW5lcmF0aW9uICE9PSB0aGlzLl9nZW5lcmF0aW9uKSByZXR1cm5cblxuICAgICAgaWYgKHNoYXJlZENsaWVudCkge1xuICAgICAgICBjbGllbnQgPSBzaGFyZWRDbGllbnRcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHJlcXVpcmVDbGllbnRTb3VyY2UgZ3VhcmFudGVlZCByZWFsdGltZS5jcmVhdGVDbGllbnQgd2hlbiB0aGVyZSBpcyBubyBzaGFyZWQgY29ubmVjdGlvbi5cbiAgICAgICAgY2xpZW50ID0gYXdhaXQgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLXR5cGVzLmpzXCIpLlZlbG9jaW91c1N5bmNDbGllbnRSZWFsdGltZUNvbmZpZ3VyYXRpb259ICovIChyZWFsdGltZSkuY3JlYXRlQ2xpZW50KClcbiAgICAgICAgb3duc0NsaWVudCA9IHRydWVcbiAgICAgIH1cblxuICAgICAgaWYgKGdlbmVyYXRpb24gIT09IHRoaXMuX2dlbmVyYXRpb24pIHtcbiAgICAgICAgYXdhaXQgdGVhcmRvd24oKVxuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgYXdhaXQgY2xpZW50LmNvbm5lY3Qoe3NpZ25hbH0pXG5cbiAgICAgIHRocm93SWZBYm9ydGVkKHNpZ25hbClcbiAgICAgIGlmIChnZW5lcmF0aW9uICE9PSB0aGlzLl9nZW5lcmF0aW9uKSB7XG4gICAgICAgIGF3YWl0IHRlYXJkb3duKClcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGF1dGhlbnRpY2F0aW9uVG9rZW4gPSBhd2FpdCB0aGlzLnN5bmNDbGllbnQuY29uZmlnLmF1dGhlbnRpY2F0aW9uVG9rZW4oKVxuXG4gICAgICB0aHJvd0lmQWJvcnRlZChzaWduYWwpXG4gICAgICBpZiAoZ2VuZXJhdGlvbiAhPT0gdGhpcy5fZ2VuZXJhdGlvbikge1xuICAgICAgICBhd2FpdCB0ZWFyZG93bigpXG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICBmb3IgKGNvbnN0IGNoYW5uZWxEZXNjcmlwdG9yIG9mIGNoYW5uZWxEZXNjcmlwdG9ycykge1xuICAgICAgICBpZiAoY2hhbm5lbERlc2NyaXB0b3IucGFyYW1zICYmIFwiYXV0aGVudGljYXRpb25Ub2tlblwiIGluIGNoYW5uZWxEZXNjcmlwdG9yLnBhcmFtcykge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgUmVhbHRpbWUgY2hhbm5lbCBcIiR7Y2hhbm5lbERlc2NyaXB0b3IuY2hhbm5lbH1cIiBwYXJhbXMgbXVzdCBub3QgaW5jbHVkZSBhdXRoZW50aWNhdGlvblRva2VuIC0gdGhlIGZyYW1ld29yayBpbmplY3RzIHRoZSBzeW5jLmNsaWVudCBhdXRoZW50aWNhdGlvblRva2VuIGF1dG9tYXRpY2FsbHlgKVxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVzb3VyY2VUeXBlID0gY2hhbm5lbERlc2NyaXB0b3IucmVzb3VyY2VUeXBlID8/IG51bGxcbiAgICAgICAgY29uc3QgcGFyYW1zID0gbWVyZ2VSZW1vdGVSZXF1ZXN0Q29udGV4dCh7XG4gICAgICAgICAgY29udGV4dDogdGhpcy5zeW5jQ2xpZW50LmNvbmZpZy5yZXF1ZXN0Q29udGV4dCxcbiAgICAgICAgICBsYWJlbDogXCJTeW5jIGNsaWVudCByZXF1ZXN0IGNvbnRleHRcIixcbiAgICAgICAgICBwYXJhbXM6IHsuLi5jaGFubmVsRGVzY3JpcHRvci5wYXJhbXMsIGF1dGhlbnRpY2F0aW9uVG9rZW59XG4gICAgICAgIH0pXG4gICAgICAgIGNvbnN0IHN1YnNjcmlwdGlvbiA9IGNsaWVudC5zdWJzY3JpYmVDaGFubmVsKGNoYW5uZWxEZXNjcmlwdG9yLmNoYW5uZWwsIHtcbiAgICAgICAgICBvbk1lc3NhZ2U6IChib2R5KSA9PiB0aGlzLmVucXVldWVBcHBseSh7Ym9keSwgZ2VuZXJhdGlvbiwgcmVzb3VyY2VUeXBlfSksXG4gICAgICAgICAgb25SZXN1bWU6ICgpID0+IHRoaXMuc2NoZWR1bGVQdWxsKGdlbmVyYXRpb24pLFxuICAgICAgICAgIHBhcmFtc1xuICAgICAgICB9KVxuXG4gICAgICAgIGNoYW5uZWxzLnB1c2goe2NoYW5uZWw6IGNoYW5uZWxEZXNjcmlwdG9yLmNoYW5uZWwsIHJlc291cmNlVHlwZSwgc3Vic2NyaXB0aW9ufSlcbiAgICAgIH1cblxuICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoY2hhbm5lbHMubWFwKCh7c3Vic2NyaXB0aW9ufSkgPT4gc3Vic2NyaXB0aW9uLndhaXRGb3JSZWFkeSh7c2lnbmFsfSkpKVxuXG4gICAgICB0aHJvd0lmQWJvcnRlZChzaWduYWwpXG4gICAgICBpZiAoZ2VuZXJhdGlvbiAhPT0gdGhpcy5fZ2VuZXJhdGlvbikge1xuICAgICAgICBhd2FpdCB0ZWFyZG93bigpXG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICB0aGlzLl9jaGFubmVscyA9IGNoYW5uZWxzXG4gICAgICB0aGlzLl9jbGllbnQgPSBjbGllbnRcbiAgICAgIHRoaXMuX293bnNDbGllbnQgPSBvd25zQ2xpZW50XG4gICAgICB0aGlzLl9zdGF0ZSA9IFwic3Vic2NyaWJlZFwiXG4gICAgICB0aGlzLnNjaGVkdWxlUHVsbChnZW5lcmF0aW9uKVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBhd2FpdCB0ZWFyZG93bigpXG5cbiAgICAgIGlmIChnZW5lcmF0aW9uID09PSB0aGlzLl9nZW5lcmF0aW9uKSB0aGlzLl9zdGF0ZSA9IFwidW5zdWJzY3JpYmVkXCJcblxuICAgICAgdGhyb3cgZXJyb3JcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2xvc2VzIGV2ZXJ5IGNoYW5uZWwgc3Vic2NyaXB0aW9uIChpZGVtcG90ZW50KS4gVGhlIHdlYnNvY2tldCBpc1xuICAgKiBkaXNjb25uZWN0ZWQgb25seSB3aGVuIHRoZSBicmlkZ2Ugb3ducyBpdCAoZGVwcmVjYXRlZCBwZXItY3ljbGVcbiAgICogYHJlYWx0aW1lLmNyZWF0ZUNsaWVudGAgcGF0aCk7IGEgc2hhcmVkIGFwcC1saWZldGltZSBjb25uZWN0aW9uIHN0YXlzIG9wZW5cbiAgICogc28gdW5zdWJzY3JpYmluZyBkcm9wcyBzdWJzY3JpcHRpb25zIHdpdGhvdXQgdGVhcmluZyBkb3duIHRoZSBzb2NrZXQuIEFsc29cbiAgICogbWFya3MgYW55IGluLWZsaWdodCBzdWJzY3JpYmUgYXR0ZW1wdCBzdGFsZSBzbyBpdCB0ZWFycyBpdHNlbGYgZG93biBpbnN0ZWFkXG4gICAqIG9mIGZpbmlzaGluZyB0aGUgc3Vic2NyaXB0aW9uIGFmdGVyd2FyZHMuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgYXN5bmMgdW5zdWJzY3JpYmUoKSB7XG4gICAgdGhpcy5fZ2VuZXJhdGlvbiArPSAxXG5cbiAgICBjb25zdCBjaGFubmVscyA9IHRoaXMuX2NoYW5uZWxzXG4gICAgY29uc3QgY2xpZW50ID0gdGhpcy5fY2xpZW50XG4gICAgY29uc3Qgb3duc0NsaWVudCA9IHRoaXMuX293bnNDbGllbnRcblxuICAgIHRoaXMuX2NoYW5uZWxzID0gW11cbiAgICB0aGlzLl9jbGllbnQgPSBudWxsXG4gICAgdGhpcy5fb3duc0NsaWVudCA9IGZhbHNlXG4gICAgdGhpcy5fc3RhdGUgPSBcInVuc3Vic2NyaWJlZFwiXG5cbiAgICBmb3IgKGNvbnN0IHtzdWJzY3JpcHRpb259IG9mIGNoYW5uZWxzKSB7XG4gICAgICBzdWJzY3JpcHRpb24uY2xvc2UoKVxuICAgIH1cblxuICAgIGlmIChjbGllbnQgJiYgb3duc0NsaWVudCkgYXdhaXQgY2xpZW50LmRpc2Nvbm5lY3RBbmRTdG9wUmVjb25uZWN0KClcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXBvcnRzIHRoZSBicmlkZ2Ugc3Vic2NyaXB0aW9uIHN0YXRlIGFuZCBwZXItY2hhbm5lbCByZWFkaW5lc3MuXG4gICAqIEByZXR1cm5zIHt7Y2hhbm5lbHM6IEFycmF5PHtjaGFubmVsOiBzdHJpbmcsIHJlYWR5OiBib29sZWFuLCByZXNvdXJjZVR5cGU6IHN0cmluZyB8IG51bGx9Piwgc3RhdGU6IFwic3Vic2NyaWJlZFwiIHwgXCJzdWJzY3JpYmluZ1wiIHwgXCJ1bnN1YnNjcmliZWRcIn19IFJlYWx0aW1lIHN0YXR1cy5cbiAgICovXG4gIHN0YXR1cygpIHtcbiAgICByZXR1cm4ge1xuICAgICAgY2hhbm5lbHM6IHRoaXMuX2NoYW5uZWxzLm1hcCgoe2NoYW5uZWwsIHJlc291cmNlVHlwZSwgc3Vic2NyaXB0aW9ufSkgPT4gKHtjaGFubmVsLCByZWFkeTogc3Vic2NyaXB0aW9uLmlzUmVhZHkoKSwgcmVzb3VyY2VUeXBlfSkpLFxuICAgICAgc3RhdGU6IHRoaXMuX3N0YXRlXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEF3YWl0cyBhbGwgZW5xdWV1ZWQgbWVzc2FnZSBhcHBsaWVzIGFuZCBhbnkgc2NoZWR1bGVkIHB1bGwgKHRlc3RzLCBzaHV0ZG93biBmbG93cykuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgYXN5bmMgd2FpdEZvckFwcGxpZWQoKSB7XG4gICAgYXdhaXQgdGhpcy5fYXBwbHlQcm9taXNlXG4gICAgaWYgKHRoaXMuX3NjaGVkdWxlZFB1bGwpIGF3YWl0IHRoaXMuX3NjaGVkdWxlZFB1bGxcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNvbHZlcyB0aGUgcmVhbHRpbWUgY29uZmlndXJhdGlvbiBibG9jaywgb3IgbnVsbCB3aGVuIHRoZSBhcHAgZGVjbGFyZWRcbiAgICogbm9uZSAodmFsaWQgd2hlbiBhIHNoYXJlZCBjb25uZWN0aW9uIGlzIGNvbmZpZ3VyZWQpLlxuICAgKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vY29uZmlndXJhdGlvbi10eXBlcy5qc1wiKS5WZWxvY2lvdXNTeW5jQ2xpZW50UmVhbHRpbWVDb25maWd1cmF0aW9uIHwgbnVsbH0gUmVhbHRpbWUgY29uZmlndXJhdGlvbiwgb3IgbnVsbC5cbiAgICovXG4gIHJlYWx0aW1lQ29uZmlndXJhdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5zeW5jQ2xpZW50LmNvbmZpZy5yZWFsdGltZSB8fCBudWxsXG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZXMgdGhlIHJlYWx0aW1lIGNvbmZpZ3VyYXRpb24gYW5kIGFzc2VydHMgYSB3ZWJzb2NrZXQgY2xpZW50IHNvdXJjZVxuICAgKiBleGlzdHM6IGEgc2hhcmVkIGNvbm5lY3Rpb24gcmlkZXMgaXRzIG93biBsaWZlY3ljbGUsIG90aGVyd2lzZSB0aGVcbiAgICogZGVwcmVjYXRlZCBwZXItY3ljbGUgYHJlYWx0aW1lLmNyZWF0ZUNsaWVudGAgbXVzdCBiZSBjb25maWd1cmVkLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2NvbmZpZ3VyYXRpb24tdHlwZXMuanNcIikuVmVsb2Npb3VzU3luY1JlYWx0aW1lV2Vic29ja2V0Q2xpZW50IHwgbnVsbH0gc2hhcmVkQ2xpZW50IC0gU2hhcmVkIGNvbm5lY3Rpb24sIG9yIG51bGwuXG4gICAqIEByZXR1cm5zIHtpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLXR5cGVzLmpzXCIpLlZlbG9jaW91c1N5bmNDbGllbnRSZWFsdGltZUNvbmZpZ3VyYXRpb24gfCBudWxsfSBSZWFsdGltZSBjb25maWd1cmF0aW9uLCBvciBudWxsLlxuICAgKi9cbiAgcmVxdWlyZUNsaWVudFNvdXJjZShzaGFyZWRDbGllbnQpIHtcbiAgICBjb25zdCByZWFsdGltZSA9IHRoaXMucmVhbHRpbWVDb25maWd1cmF0aW9uKClcblxuICAgIGlmICghc2hhcmVkQ2xpZW50ICYmIHR5cGVvZiByZWFsdGltZT8uY3JlYXRlQ2xpZW50ICE9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcInN1YnNjcmliZVJlYWx0aW1lIHJlcXVpcmVzIGEgc2hhcmVkIGNvbm5lY3Rpb24gKHN5bmMuY2xpZW50LndlYnNvY2tldFVybCBvciBzeW5jLmNsaWVudC53ZWJzb2NrZXRDbGllbnQpIG9yIHRoZSBkZXByZWNhdGVkIHN5bmMuY2xpZW50LnJlYWx0aW1lLmNyZWF0ZUNsaWVudCBjYWxsYmFja1wiKVxuICAgIH1cblxuICAgIHJldHVybiByZWFsdGltZVxuICB9XG5cbiAgLyoqXG4gICAqIERlcml2ZXMgdGhlIGNoYW5uZWwgZGVzY3JpcHRvcnMgdG8gc3Vic2NyaWJlOiBvbmUgZnJhbWV3b3JrIHN5bmMgY2hhbm5lbFxuICAgKiBzdWJzY3JpcHRpb24gcGVyIGRlY2xhcmVkIHB1bGwgc2NvcGUgKHRoZSBwYXJhbXMgbWlycm9yIHRoZSBzY29wZSdzXG4gICAqIGB7cmVzb3VyY2VUeXBlLCBjb25kaXRpb25zfWApLCBwbHVzIHRoZSBkZXByZWNhdGVkIGxlZ2FjeSBwYXRocyDigJRcbiAgICogbW9kZWwtbGV2ZWwgc3RhdGljIHJlYWx0aW1lIGRlY2xhcmF0aW9ucyBhbmQgdGhlIGNvbmZpZyBjaGFubmVscyBjYWxsYmFjay5cbiAgICogRmFpbHMgbG91ZGx5IHdoZW4gbm90aGluZyBpcyBzdWJzY3JpYmFibGUuXG4gICAqIEBwYXJhbSB7UmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT59IGNvbnRleHQgLSBBcHAgY29udGV4dCBwYXNzZWQgdG8gdGhlIGRlcHJlY2F0ZWQgY2hhbm5lbHMgY2FsbGJhY2suXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPEFycmF5PFZlbG9jaW91c1N5bmNSZWFsdGltZUNoYW5uZWxEZXNjcmlwdG9yPj59IENoYW5uZWwgZGVzY3JpcHRvcnMuXG4gICAqL1xuICBhc3luYyBjaGFubmVsRGVzY3JpcHRvcnMoY29udGV4dCkge1xuICAgIGNvbnN0IHJlYWx0aW1lID0gdGhpcy5yZWFsdGltZUNvbmZpZ3VyYXRpb24oKVxuICAgIC8qKiBAdHlwZSB7QXJyYXk8VmVsb2Npb3VzU3luY1JlYWx0aW1lQ2hhbm5lbERlc2NyaXB0b3I+fSAqL1xuICAgIGNvbnN0IGNoYW5uZWxEZXNjcmlwdG9ycyA9IFtdXG5cbiAgICBmb3IgKGNvbnN0IHNjb3BlUm93IG9mIGF3YWl0IHRoaXMuc3luY0NsaWVudC5zY29wZVN0b3JlKCkuYWN0aXZlU2NvcGVzKCkpIHtcbiAgICAgIGNoYW5uZWxEZXNjcmlwdG9ycy5wdXNoKHtcbiAgICAgICAgY2hhbm5lbDogVkVMT0NJT1VTX1NZTkNfQ0hBTk5FTCxcbiAgICAgICAgcGFyYW1zOiB7XG4gICAgICAgICAgY29uZGl0aW9uczogdGhpcy5hdHRyaWJ1dGVOYW1lZENvbmRpdGlvbnMoc2NvcGVSb3cpLFxuICAgICAgICAgIHJlc291cmNlVHlwZTogc2NvcGVSb3cucmVzb3VyY2VUeXBlLFxuICAgICAgICAgIC8vIE9ubHkgdGhlIGFsbC10eXBlcyBzY29wZSBjYXJyaWVzIHRoZSB0eXBlIGxpc3Q7IGEgdHlwZS1kZWNsYXJlZCBzY29wZSBuZWVkcyBub25lLlxuICAgICAgICAgIC4uLihzY29wZVJvdy5yZXNvdXJjZVR5cGUgPT09IG51bGwgPyB7cmVzb3VyY2VUeXBlczogdGhpcy5zeW5jQ2xpZW50LnVzZXJTY29wZVJlc291cmNlVHlwZXMoKX0gOiB7fSlcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IFtyZXNvdXJjZVR5cGUsIHJlc291cmNlQ29uZmlnXSBvZiBPYmplY3QuZW50cmllcyh0aGlzLnN5bmNDbGllbnQuY29uZmlnLnJlc291cmNlcykpIHtcbiAgICAgIGlmICghcmVzb3VyY2VDb25maWcucmVhbHRpbWUpIGNvbnRpbnVlXG5cbiAgICAgIGNoYW5uZWxEZXNjcmlwdG9ycy5wdXNoKHtjaGFubmVsOiByZXNvdXJjZUNvbmZpZy5yZWFsdGltZS5jaGFubmVsLCBwYXJhbXM6IHJlc291cmNlQ29uZmlnLnJlYWx0aW1lLnBhcmFtcywgcmVzb3VyY2VUeXBlfSlcbiAgICB9XG5cbiAgICBpZiAocmVhbHRpbWU/LmNoYW5uZWxzKSB7XG4gICAgICBjaGFubmVsRGVzY3JpcHRvcnMucHVzaCguLi5hd2FpdCByZWFsdGltZS5jaGFubmVscyhjb250ZXh0KSlcbiAgICB9XG5cbiAgICBpZiAoY2hhbm5lbERlc2NyaXB0b3JzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwic3Vic2NyaWJlUmVhbHRpbWUgZm91bmQgbm8gY2hhbm5lbHMgdG8gc3Vic2NyaWJlIC0gZGVjbGFyZSBhIHN5bmMgc2NvcGUgKHN5bmNDbGllbnQoKS5zeW5jKHF1ZXJ5KSkgc28gaXRzIGZyYW1ld29yayBzeW5jIGNoYW5uZWwgc3Vic2NyaXB0aW9uIGNhbiBiZSBkZXJpdmVkLCBvciB0aGUgZGVwcmVjYXRlZCBzeW5jLmNsaWVudC5yZWFsdGltZS5jaGFubmVscyBjYWxsYmFja1wiKVxuICAgIH1cblxuICAgIHJldHVybiBjaGFubmVsRGVzY3JpcHRvcnNcbiAgfVxuXG4gIC8qKlxuICAgKiBUcmFuc2xhdGVzIGEgcGVyc2lzdGVkIHNjb3BlJ3MgY29uZGl0aW9uIGtleXMgdG8gdGhlIG1vZGVsJ3MgYXR0cmlidXRlXG4gICAqIG5hbWVzIHNvIHRoZSBmcmFtZXdvcmsgY2hhbm5lbCBzdWJzY3JpcHRpb24gbWF0Y2hlcyB0aGUgcHVibGlzaGVyJ3NcbiAgICogYXR0cmlidXRlLW5hbWVkIHNjb3BpbmcgcGFyYW1zOiBgc2VyaWFsaXplZFNjb3BlRnJvbVF1ZXJ5YCBwZXJzaXN0cyB0aGVcbiAgICogcXVlcnkncyBtb2RlbC1ub3JtYWxpemVkIGNvbHVtbiBuYW1lcyAoZm9yIGV4YW1wbGUgYHByb2plY3RfaWRgKSwgd2hpbGVcbiAgICogc2NvcGUtcGFydGl0aW9uIGJyb2FkY2FzdHMgY2FycnkgYXR0cmlidXRlIG5hbWVzIChgcHJvamVjdElkYCkuIEtleXNcbiAgICogd2l0aG91dCBhIGNvbHVtbiBtYXBwaW5nIGFyZSBhbHJlYWR5IGF0dHJpYnV0ZSBuYW1lcyBhbmQgcGFzcyB0aHJvdWdoO1xuICAgKiBzY29wZXMgb24gbW9kZWxzIHdpdGhvdXQgYSBkZWNsYXJlZCBzeW5jIHJlc291cmNlIGZhaWwgbG91ZGx5IGJlY2F1c2Ugbm9cbiAgICogYXR0cmlidXRlIG1hcHBpbmcgZXhpc3RzIGZvciB0aGVtLlxuICAgKlxuICAgKiBUaGUgYWxsLXR5cGVzICh1c2VyKSBzY29wZSBoYXMgbm8gcmVzb3VyY2UgdHlwZSBhbmQgbm8gY29uZGl0aW9ucyAtIGl0XG4gICAqIGNvdmVycyBldmVyeXRoaW5nIHRoZSBzZXJ2ZXIgYXV0aG9yaXplcyBmb3IgdGhlIGNhbGxlciAtIHNvIHRoZXJlIGlzXG4gICAqIG5vdGhpbmcgdG8gbWFwLlxuICAgKiBAcGFyYW0ge3tjb25kaXRpb25zOiBSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj4sIHJlc291cmNlVHlwZTogc3RyaW5nIHwgbnVsbH19IHNjb3BlUm93IC0gQWN0aXZlIHNjb3BlIHJvdy5cbiAgICogQHJldHVybnMge1JlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pn0gQXR0cmlidXRlLW5hbWVkIHNjb3BlIGNvbmRpdGlvbnMuXG4gICAqL1xuICBhdHRyaWJ1dGVOYW1lZENvbmRpdGlvbnMoc2NvcGVSb3cpIHtcbiAgICBpZiAoc2NvcGVSb3cucmVzb3VyY2VUeXBlID09PSBudWxsKSByZXR1cm4ge31cblxuICAgIGNvbnN0IHJlc291cmNlQ29uZmlnID0gdGhpcy5zeW5jQ2xpZW50LmNvbmZpZy5yZXNvdXJjZXNbc2NvcGVSb3cucmVzb3VyY2VUeXBlXVxuXG4gICAgaWYgKCFyZXNvdXJjZUNvbmZpZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBzdWJzY3JpYmVSZWFsdGltZSBjYW4ndCBkZXJpdmUgYXR0cmlidXRlIG5hbWVzIGZvciB0aGUgc3luYyBzY29wZSBkZWNsYXJlZCBvbiAke3Njb3BlUm93LnJlc291cmNlVHlwZX0gLSBkZWNsYXJlIHN0YXRpYyBzeW5jIG9uIHRoYXQgbW9kZWwgc28gaXRzIHJlc291cmNlIGlzIHJlZ2lzdGVyZWRgKVxuICAgIH1cblxuICAgIGNvbnN0IGNvbHVtbk5hbWVUb0F0dHJpYnV0ZU5hbWUgPSByZXNvdXJjZUNvbmZpZy5tZXRhZGF0YU1vZGVsQ2xhc3MuZ2V0Q29sdW1uTmFtZVRvQXR0cmlidXRlTmFtZU1hcCgpXG4gICAgLyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj59ICovXG4gICAgY29uc3QgY29uZGl0aW9ucyA9IHt9XG5cbiAgICBmb3IgKGNvbnN0IFtjb25kaXRpb25OYW1lLCBjb25kaXRpb25WYWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMoc2NvcGVSb3cuY29uZGl0aW9ucykpIHtcbiAgICAgIGNvbmRpdGlvbnNbY29sdW1uTmFtZVRvQXR0cmlidXRlTmFtZVtjb25kaXRpb25OYW1lXSB8fCBjb25kaXRpb25OYW1lXSA9IGNvbmRpdGlvblZhbHVlXG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbmRpdGlvbnNcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGFpbnMgb25lIHB1c2hlZCBtZXNzYWdlIG9udG8gdGhlIHNlcmlhbGl6ZWQgYXBwbHkgcXVldWUgc28gY2hhbmdlcyBhcHBseVxuICAgKiBpbiBhcnJpdmFsIG9yZGVyOyBmYWlsdXJlcyBnbyB0byB0aGUgc3luYyBjbGllbnQncyBlcnJvciByZXBvcnRpbmcuXG4gICAqIEBwYXJhbSB7e2JvZHk6IFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+LCBnZW5lcmF0aW9uPzogbnVtYmVyLCByZXNvdXJjZVR5cGU6IHN0cmluZyB8IG51bGx9fSBhcmdzIC0gTWVzc2FnZSBhcmdzLlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIGVucXVldWVBcHBseSh7Ym9keSwgZ2VuZXJhdGlvbiA9IHRoaXMuX2dlbmVyYXRpb24sIHJlc291cmNlVHlwZX0pIHtcbiAgICB0aGlzLl9hcHBseVByb21pc2UgPSB0aGlzLl9hcHBseVByb21pc2UudGhlbihhc3luYyAoKSA9PiB7XG4gICAgICBpZiAoZ2VuZXJhdGlvbiAhPT0gdGhpcy5fZ2VuZXJhdGlvbikgcmV0dXJuXG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHRoaXMuYXBwbHlNZXNzYWdlKHtib2R5LCByZXNvdXJjZVR5cGV9KVxuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgdGhpcy5zeW5jQ2xpZW50LnJlcG9ydEVycm9yKC8qKiBAdHlwZSB7RXJyb3J9ICovIChlcnJvcikpXG4gICAgICB9XG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBsaWVzIG9uZSBwdXNoZWQgbWVzc2FnZSB0aHJvdWdoIHRoZSBkZXJpdmVkIHJlc291cmNlIGFwcGxpZXI6IGRyb3BzXG4gICAqIG93bi1kZXZpY2UgbWVzc2FnZXMgYnkgZWNobyBvcmlnaW4sIGRlZmF1bHRzIHRoZSBjaGFubmVsJ3MgcmVzb3VyY2VUeXBlIG9udG9cbiAgICogZW52ZWxvcGVzIHdpdGhvdXQgb25lLCBhbmQgZmFpbHMgbG91ZGx5IG9uIHVua25vd24gcmVzb3VyY2UgdHlwZXMuXG4gICAqIEBwYXJhbSB7e2JvZHk6IFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+LCByZXNvdXJjZVR5cGU6IHN0cmluZyB8IG51bGx9fSBhcmdzIC0gTWVzc2FnZSBhcmdzLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIGFzeW5jIGFwcGx5TWVzc2FnZSh7Ym9keSwgcmVzb3VyY2VUeXBlfSkge1xuICAgIGlmICghYm9keSB8fCB0eXBlb2YgYm9keSAhPT0gXCJvYmplY3RcIiB8fCBBcnJheS5pc0FycmF5KGJvZHkpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFJlYWx0aW1lIHN5bmMgbWVzc2FnZXMgbXVzdCBiZSBlbnZlbG9wZSBvYmplY3RzLCBnb3Q6ICR7SlNPTi5zdHJpbmdpZnkoYm9keSl9YClcbiAgICB9XG5cbiAgICBjb25zdCByZWFsdGltZSA9IHRoaXMucmVhbHRpbWVDb25maWd1cmF0aW9uKClcblxuICAgIGlmIChyZWFsdGltZT8ubG9jYWxPcmlnaW4gJiYgYm9keS5lY2hvT3JpZ2luICE9PSB1bmRlZmluZWQgJiYgYm9keS5lY2hvT3JpZ2luICE9PSBudWxsKSB7XG4gICAgICBjb25zdCBsb2NhbE9yaWdpbiA9IFN0cmluZyhhd2FpdCByZWFsdGltZS5sb2NhbE9yaWdpbigpKVxuXG4gICAgICBpZiAoU3RyaW5nKGJvZHkuZWNob09yaWdpbikgPT09IGxvY2FsT3JpZ2luKSByZXR1cm5cbiAgICB9XG5cbiAgICBjb25zdCBzeW5jUGF5bG9hZHMgPSBBcnJheS5pc0FycmF5KGJvZHkuc3luY3MpID8gYm9keS5zeW5jcyA6IFtib2R5XVxuICAgIGNvbnN0IGFwcGx5U3luYyA9IHRoaXMuc3luY0NsaWVudC5yZW1vdGVBcHBseVN5bmMoe3NvdXJjZTogXCJyZW1vdGUgY2hhbmdlXCJ9KVxuXG4gICAgLy8gQ29hbGVzY2UgcmVjb3JkLWNoYW5nZSBldmVudHMgYWNyb3NzIHRoZSBwdXNoZWQgYmF0Y2ggc28gaXQgdHJpZ2dlcnMgb25lIGxpdmUtcXVlcnkgcmUtcnVuLlxuICAgIGF3YWl0IHJlY29yZENoYW5nZXMuYmF0Y2goYXN5bmMgKCkgPT4ge1xuICAgICAgZm9yIChjb25zdCBzeW5jUGF5bG9hZCBvZiBzeW5jUGF5bG9hZHMpIHtcbiAgICAgICAgY29uc3Qgc3luYyA9IFN5bmNBcGlDbGllbnQuc3luY0VudmVsb3BlRnJvbVBheWxvYWQoe3Jlc291cmNlVHlwZSwgLi4uc3luY1BheWxvYWR9KVxuXG4gICAgICAgIGF3YWl0IGFwcGx5U3luYyhzeW5jKVxuICAgICAgfVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogU2NoZWR1bGVzIGEgY29hbGVzY2VkIGJhY2tncm91bmQgcHVsbCBjbG9zaW5nIG9mZmxpbmUgZ2FwcyBhZnRlclxuICAgKiAocmUpc3Vic2NyaXB0aW9uIHJlYWRpbmVzcy4gUmVzdW1lcyBhcnJpdmluZyB3aGlsZSBhIHB1bGwgaXMgYWxyZWFkeVxuICAgKiBzY2hlZHVsZWQgb3IgaW4gZmxpZ2h0IGNvYWxlc2NlIGludG8gdGhhdCBwdWxsIGluc3RlYWQgb2Ygc3RhY2tpbmcuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbZ2VuZXJhdGlvbl0gLSBTdWJzY3JpcHRpb24gZ2VuZXJhdGlvbiBvd25pbmcgdGhlIHJlc3VtZS9yZWFkaW5lc3MgY2FsbGJhY2suXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgc2NoZWR1bGVQdWxsKGdlbmVyYXRpb24gPSB0aGlzLl9nZW5lcmF0aW9uKSB7XG4gICAgaWYgKGdlbmVyYXRpb24gIT09IHRoaXMuX2dlbmVyYXRpb24pIHJldHVyblxuICAgIGlmICh0aGlzLnJlYWx0aW1lQ29uZmlndXJhdGlvbigpPy5wdWxsT25SZWNvbm5lY3QgPT09IGZhbHNlKSByZXR1cm5cblxuICAgIGNvbnN0IGNvb3JkaW5hdG9yUnVuID0gdGhpcy5zeW5jQ2xpZW50LnJlcXVlc3RDb29yZGluYXRvclN5bmMoXCJyZWFsdGltZVwiKVxuXG4gICAgaWYgKGNvb3JkaW5hdG9yUnVuKSB7XG4gICAgICB0aGlzLl9zY2hlZHVsZWRQdWxsIHx8PSBjb29yZGluYXRvclJ1bi5maW5hbGx5KCgpID0+IHtcbiAgICAgICAgdGhpcy5fc2NoZWR1bGVkUHVsbCA9IG51bGxcbiAgICAgIH0pXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICB0aGlzLl9zY2hlZHVsZWRQdWxsIHx8PSAoYXN5bmMgKCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgdGhpcy5zeW5jQ2xpZW50LnB1bGwoKVxuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgaWYgKCF0aGlzLnN5bmNDbGllbnQuaXNMaWZlY3ljbGVBYm9ydChlcnJvcikpIHtcbiAgICAgICAgICB0aGlzLnN5bmNDbGllbnQucmVwb3J0RXJyb3IoLyoqIEB0eXBlIHtFcnJvcn0gKi8gKGVycm9yKSlcbiAgICAgICAgfVxuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgdGhpcy5fc2NoZWR1bGVkUHVsbCA9IG51bGxcbiAgICAgIH1cbiAgICB9KSgpXG4gIH1cbn1cblxuLyoqXG4gKiBUaHJvd3MgdGhlIGxpZmVjeWNsZSBhYm9ydCByZWFzb24gd2hlbiB0aGUgc3Vic2NyaXB0aW9uIGlzIG5vIGxvbmdlciBvd25lZC5cbiAqIEBwYXJhbSB7QWJvcnRTaWduYWwgfCB1bmRlZmluZWR9IHNpZ25hbCAtIFN1YnNjcmlwdGlvbiBsaWZlY3ljbGUgc2lnbmFsLlxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIHRocm93SWZBYm9ydGVkKHNpZ25hbCkge1xuICBpZiAoIXNpZ25hbD8uYWJvcnRlZCkgcmV0dXJuXG5cbiAgdGhyb3cgc2lnbmFsLnJlYXNvbiBpbnN0YW5jZW9mIEVycm9yID8gc2lnbmFsLnJlYXNvbiA6IG5ldyBFcnJvcihcIlN5bmMgcmVhbHRpbWUgc3Vic2NyaXB0aW9uIHdhcyBhYm9ydGVkXCIpXG59XG4iXX0=
|
|
@@ -195,6 +195,42 @@ export default class LocalMutationLog {
|
|
|
195
195
|
})
|
|
196
196
|
}
|
|
197
197
|
|
|
198
|
+
/**
|
|
199
|
+
* Resolves a durable conflict explicitly. Keeping the server acknowledges the
|
|
200
|
+
* preserved local intent without replaying it; retrying local intent rebases
|
|
201
|
+
* it onto the conflict's authoritative serverVersion and returns it to the
|
|
202
|
+
* pending queue. The prior conflict result stays attached as audit metadata.
|
|
203
|
+
* @param {{id: string, resolution: "keep-server" | "retry-local"}} args - Resolution.
|
|
204
|
+
* @returns {Promise<LocalMutationLogRecord>} Resolved record.
|
|
205
|
+
*/
|
|
206
|
+
async resolveConflict({id, resolution}) {
|
|
207
|
+
if (!["keep-server", "retry-local"].includes(resolution)) throw new Error(`Unknown local mutation conflict resolution '${resolution}'`)
|
|
208
|
+
|
|
209
|
+
return await withStorageKeyLock(this.storageKey, async () => {
|
|
210
|
+
const rawRecord = await this.storage.record(this.storageKey, id)
|
|
211
|
+
|
|
212
|
+
if (!rawRecord) throw new Error(`No local mutation log record '${id}'`)
|
|
213
|
+
|
|
214
|
+
const record = normalizeRecord(rawRecord)
|
|
215
|
+
|
|
216
|
+
if (record.status !== "conflict") throw new Error(`Cannot resolve ${record.status} local mutation '${id}' as a conflict`)
|
|
217
|
+
|
|
218
|
+
if (resolution === "keep-server") {
|
|
219
|
+
record.status = "synced"
|
|
220
|
+
} else {
|
|
221
|
+
const serverVersion = conflictServerVersion(record)
|
|
222
|
+
|
|
223
|
+
record.mutation = {...record.mutation, baseVersion: serverVersion}
|
|
224
|
+
record.status = "pending"
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
record.updatedAt = this.currentTimestamp()
|
|
228
|
+
await this.storage.updateRecord(this.storageKey, cloneRecord(record))
|
|
229
|
+
|
|
230
|
+
return restoreSyncResultTypes(cloneRecord(record))
|
|
231
|
+
})
|
|
232
|
+
}
|
|
233
|
+
|
|
198
234
|
/**
|
|
199
235
|
* Prunes terminal records that are no longer needed for replay dependencies.
|
|
200
236
|
* @param {object} [args] - Compaction options.
|
|
@@ -267,6 +303,23 @@ function validStorage(storage) {
|
|
|
267
303
|
&& typeof storageObject.updateRecord === "function"
|
|
268
304
|
}
|
|
269
305
|
|
|
306
|
+
/**
|
|
307
|
+
* Reads the authoritative version from a conflicted mutation.
|
|
308
|
+
* @param {LocalMutationLogRecord} record - Conflicted record.
|
|
309
|
+
* @returns {string | number | null} - Authoritative version.
|
|
310
|
+
*/
|
|
311
|
+
function conflictServerVersion(record) {
|
|
312
|
+
const conflict = record.syncResult?.conflict
|
|
313
|
+
|
|
314
|
+
if (!conflict || conflict instanceof Date || typeof conflict !== "object" || Array.isArray(conflict) || !Object.hasOwn(conflict, "serverVersion")) {
|
|
315
|
+
throw new Error(`Cannot retry local mutation '${record.id}' without a conflict serverVersion`)
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const conflictMetadata = /** @type {Record<string, unknown>} */ (conflict)
|
|
319
|
+
|
|
320
|
+
return cloneBaseVersion(conflictMetadata.serverVersion)
|
|
321
|
+
}
|
|
322
|
+
|
|
270
323
|
/**
|
|
271
324
|
* Sorts records by newest update/sequence first.
|
|
272
325
|
* @param {LocalMutationLogRecord} left - Left record.
|
|
@@ -72,12 +72,13 @@ export default class SyncApiClient {
|
|
|
72
72
|
* @param {number} [args.batchSize] - Batch size.
|
|
73
73
|
* @param {import("./sync-client-types.js").SyncClientConflictTrackingConfig} args.conflictTracking - Tracking configuration.
|
|
74
74
|
* @param {(payload: {authenticationToken: string, syncs: Array<Record<string, ReturnType<typeof JSON.parse>>>}, options?: {signal?: AbortSignal}) => Promise<SyncReplayResponse>} args.postReplay - Transport boundary.
|
|
75
|
+
* @param {(args: {record: import("./local-mutation-log.js").LocalMutationLogRecord, result: SyncReplayItem}) => Promise<void>} [args.applyConflict] - Applies authoritative conflict state to the local replica before preserving the rejected intent.
|
|
75
76
|
* @param {(identity: string) => number} args.remoteGeneration - Current remote generation.
|
|
76
77
|
* @param {string} args.resourceType - Resource whose log records should drain.
|
|
77
78
|
* @param {AbortSignal} [args.signal] - Lifecycle cancellation signal.
|
|
78
79
|
* @returns {Promise<void>} Resolves when no ready intent remains.
|
|
79
80
|
*/
|
|
80
|
-
static async replayConflictTrackedSyncs({authenticationToken, batchSize, conflictTracking, postReplay, remoteGeneration, resourceType, signal}) {
|
|
81
|
+
static async replayConflictTrackedSyncs({applyConflict, authenticationToken, batchSize, conflictTracking, postReplay, remoteGeneration, resourceType, signal}) {
|
|
81
82
|
const maxBatchSize = this.normalizedBatchSize(batchSize)
|
|
82
83
|
|
|
83
84
|
while (true) {
|
|
@@ -111,6 +112,11 @@ export default class SyncApiClient {
|
|
|
111
112
|
throw new Error(`Invalid sync state returned for mutation ${group[0].mutation.clientMutationId}: ${result.syncState}`)
|
|
112
113
|
}
|
|
113
114
|
|
|
115
|
+
if (result.syncState === "conflict" && applyConflict) {
|
|
116
|
+
await applyConflict({record: group[0], result})
|
|
117
|
+
throwIfSyncAborted(signal)
|
|
118
|
+
}
|
|
119
|
+
|
|
114
120
|
for (const record of group) {
|
|
115
121
|
await applySyncReplayResultToLocalMutationLog({mutationLog: conflictTracking.mutationLog, record, result: /** @type {Record<string, ReturnType<typeof JSON.parse>>} */ (result)})
|
|
116
122
|
throwIfSyncAborted(signal)
|
|
@@ -180,6 +180,8 @@ export default class SyncClient {
|
|
|
180
180
|
this._scopeStore = scopeStore || null
|
|
181
181
|
/** @type {Promise<void> | null} */
|
|
182
182
|
this._scheduledReplay = null
|
|
183
|
+
/** @type {((reason: "mutation" | "realtime") => Promise<void>) | null} */
|
|
184
|
+
this._coordinatorTrigger = null
|
|
183
185
|
/** @type {Record<string, import("./sync-api-client-types.js").SyncResourceConfig> | null} */
|
|
184
186
|
this._pullResourceConfigs = null
|
|
185
187
|
/** @type {Array<{callback: (record: ReturnType<typeof JSON.parse>) => Promise<void> | void, callbackName: "afterCreate" | "afterUpdate" | "afterDestroy" | "beforeUpdate" | "beforeDestroy", modelClass: ReturnType<typeof JSON.parse>}>} */
|
|
@@ -200,6 +202,7 @@ export default class SyncClient {
|
|
|
200
202
|
this._lifecycleTransitionCount = 0
|
|
201
203
|
/** @type {Promise<void>} */
|
|
202
204
|
this._lifecycleTransitionPromise = Promise.resolve()
|
|
205
|
+
this._trackingGeneration = 0
|
|
203
206
|
this._started = false
|
|
204
207
|
}
|
|
205
208
|
|
|
@@ -212,7 +215,10 @@ export default class SyncClient {
|
|
|
212
215
|
* @returns {Promise<void>}
|
|
213
216
|
*/
|
|
214
217
|
async start() {
|
|
218
|
+
const trackingGeneration = this._trackingGeneration
|
|
219
|
+
|
|
215
220
|
await this._lifecycleTransitionPromise
|
|
221
|
+
if (trackingGeneration !== this._trackingGeneration) return
|
|
216
222
|
this.assertTenantReady()
|
|
217
223
|
if (this._started) return
|
|
218
224
|
|
|
@@ -257,6 +263,8 @@ export default class SyncClient {
|
|
|
257
263
|
* @returns {Promise<void>}
|
|
258
264
|
*/
|
|
259
265
|
stop(options = {}) {
|
|
266
|
+
this._trackingGeneration += 1
|
|
267
|
+
|
|
260
268
|
for (const {callback, callbackName, modelClass} of this._trackedCallbacks) {
|
|
261
269
|
modelClass.unregisterLifecycleCallback(callbackName, callback)
|
|
262
270
|
}
|
|
@@ -639,6 +647,33 @@ export default class SyncClient {
|
|
|
639
647
|
setCurrentSyncClient(this)
|
|
640
648
|
}
|
|
641
649
|
|
|
650
|
+
/**
|
|
651
|
+
* Attaches the one reusable coordinator that owns mutation and reconnect
|
|
652
|
+
* cycles for this client. The returned detach only removes the same owner.
|
|
653
|
+
* @param {(reason: "mutation" | "realtime") => Promise<void>} trigger - Coordinator trigger.
|
|
654
|
+
* @returns {() => void} Idempotent detach callback.
|
|
655
|
+
*/
|
|
656
|
+
attachCoordinator(trigger) {
|
|
657
|
+
if (typeof trigger !== "function") throw new Error("SyncClient coordinator trigger must be a function")
|
|
658
|
+
if (this._coordinatorTrigger) throw new Error("SyncClient already has an attached coordinator")
|
|
659
|
+
|
|
660
|
+
this._coordinatorTrigger = trigger
|
|
661
|
+
|
|
662
|
+
return () => {
|
|
663
|
+
if (this._coordinatorTrigger === trigger) this._coordinatorTrigger = null
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
/**
|
|
668
|
+
* Routes framework-owned work through the attached coordinator, or returns
|
|
669
|
+
* null so the legacy direct scheduling owner may run.
|
|
670
|
+
* @param {"mutation" | "realtime"} reason - Trigger reason.
|
|
671
|
+
* @returns {Promise<void> | null} Coordinator flight, or null without an owner.
|
|
672
|
+
*/
|
|
673
|
+
requestCoordinatorSync(reason) {
|
|
674
|
+
return this._coordinatorTrigger ? this._coordinatorTrigger(reason) : null
|
|
675
|
+
}
|
|
676
|
+
|
|
642
677
|
/**
|
|
643
678
|
* Returns the app's current sync client.
|
|
644
679
|
* @returns {SyncClient} Current sync client.
|
|
@@ -892,6 +927,26 @@ export default class SyncClient {
|
|
|
892
927
|
await this._subscribeUserScopePromise
|
|
893
928
|
}
|
|
894
929
|
|
|
930
|
+
/**
|
|
931
|
+
* Declares and activates the server-enumerated user scope without starting
|
|
932
|
+
* realtime or pulling. Use this from SyncCoordinator.prepare() so the
|
|
933
|
+
* coordinator remains the sole network ordering owner.
|
|
934
|
+
* @returns {Promise<void>}
|
|
935
|
+
*/
|
|
936
|
+
async activateUserScope() {
|
|
937
|
+
await this._runLifecycleWork(async (signal) => await this._activateUserScope(signal))
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
/**
|
|
941
|
+
* Activates the user scope under the current lifecycle generation.
|
|
942
|
+
* @param {AbortSignal} signal - Lifecycle cancellation signal.
|
|
943
|
+
* @returns {Promise<void>} - Resolves after the scope is durable.
|
|
944
|
+
*/
|
|
945
|
+
async _activateUserScope(signal) {
|
|
946
|
+
await this.scopeStore().findOrCreateScope(await this.userScope())
|
|
947
|
+
this._throwIfLifecycleAborted(signal)
|
|
948
|
+
}
|
|
949
|
+
|
|
895
950
|
/**
|
|
896
951
|
* Declares and activates the user scope for every pullable resource, then
|
|
897
952
|
* subscribes realtime and pulls.
|
|
@@ -902,8 +957,7 @@ export default class SyncClient {
|
|
|
902
957
|
this._userScopeState = "subscribing"
|
|
903
958
|
|
|
904
959
|
try {
|
|
905
|
-
await this.
|
|
906
|
-
this._throwIfLifecycleAborted(signal)
|
|
960
|
+
await this._activateUserScope(signal)
|
|
907
961
|
|
|
908
962
|
await this.subscribeRealtime()
|
|
909
963
|
this._throwIfLifecycleAborted(signal)
|
|
@@ -1087,6 +1141,7 @@ export default class SyncClient {
|
|
|
1087
1141
|
if (!resourceConfig.conflictTracking) continue
|
|
1088
1142
|
|
|
1089
1143
|
await SyncApiClient.replayConflictTrackedSyncs({
|
|
1144
|
+
applyConflict: async ({record, result}) => await this.applyConflictReplayResult({record, result, resourceType}),
|
|
1090
1145
|
authenticationToken: await this.config.authenticationToken(),
|
|
1091
1146
|
batchSize: this.config.batchSize,
|
|
1092
1147
|
conflictTracking: resourceConfig.conflictTracking,
|
|
@@ -1110,6 +1165,97 @@ export default class SyncClient {
|
|
|
1110
1165
|
this._throwIfLifecycleAborted(signal)
|
|
1111
1166
|
}
|
|
1112
1167
|
|
|
1168
|
+
/**
|
|
1169
|
+
* Applies an authoritative serverModel returned by a conflict through the
|
|
1170
|
+
* same tenant-bound, tracking-suppressed applier used by pull/realtime.
|
|
1171
|
+
* A conflict result without serverModel has no authoritative state to apply
|
|
1172
|
+
* and remains diagnostic-only.
|
|
1173
|
+
* @param {{record: import("./local-mutation-log.js").LocalMutationLogRecord, resourceType: string, result: import("./sync-api-client-types.js").SyncReplayItem}} args - Conflict result.
|
|
1174
|
+
* @returns {Promise<void>}
|
|
1175
|
+
*/
|
|
1176
|
+
async applyConflictReplayResult({record, resourceType, result}) {
|
|
1177
|
+
const conflict = result.conflict
|
|
1178
|
+
|
|
1179
|
+
if (!conflict || !Object.hasOwn(conflict, "serverModel")) return
|
|
1180
|
+
|
|
1181
|
+
const serverModel = conflict.serverModel
|
|
1182
|
+
|
|
1183
|
+
if (serverModel !== null && (typeof serverModel !== "object" || Array.isArray(serverModel))) {
|
|
1184
|
+
throw new Error(`Sync conflict serverModel for ${resourceType} must be an object or null`)
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
const resourceId = record.mutation.payload?.resourceId
|
|
1188
|
+
|
|
1189
|
+
if (typeof resourceId !== "string" || resourceId.length === 0) throw new Error(`Sync conflict for ${resourceType} is missing resourceId`)
|
|
1190
|
+
|
|
1191
|
+
const sync = SyncApiClient.syncEnvelopeFromPayload({
|
|
1192
|
+
data: serverModel,
|
|
1193
|
+
resourceId,
|
|
1194
|
+
resourceType,
|
|
1195
|
+
syncType: serverModel === null ? "delete" : "update"
|
|
1196
|
+
})
|
|
1197
|
+
|
|
1198
|
+
await this.remoteApplySync({source: "conflict server version"})(sync)
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
/**
|
|
1202
|
+
* Returns queue counts and privacy-safe conflicts for coordinator/UI status.
|
|
1203
|
+
* Full local/server payloads remain only in the durable mutation log.
|
|
1204
|
+
* @returns {Promise<import("./sync-coordinator-types.js").SyncClientInspection>} Durable sync state.
|
|
1205
|
+
*/
|
|
1206
|
+
async inspectSyncState() {
|
|
1207
|
+
return await this._runLifecycleWork(async (signal) => {
|
|
1208
|
+
this._throwIfLifecycleAborted(signal)
|
|
1209
|
+
let pendingCount = 0
|
|
1210
|
+
let rejectedCount = 0
|
|
1211
|
+
/** @type {import("./sync-coordinator-types.js").SyncConflictDiagnostic[]} */
|
|
1212
|
+
const conflicts = []
|
|
1213
|
+
|
|
1214
|
+
for (const [resourceType, resourceConfig] of Object.entries(this.config.resources)) {
|
|
1215
|
+
if (!resourceConfig.conflictTracking) continue
|
|
1216
|
+
|
|
1217
|
+
for (const record of await resourceConfig.conflictTracking.mutationLog.records()) {
|
|
1218
|
+
if (record.mutation.model !== resourceType) continue
|
|
1219
|
+
if (["pending", "applied-locally", "peer-applied"].includes(record.status)) pendingCount += 1
|
|
1220
|
+
if (record.status === "rejected") rejectedCount += 1
|
|
1221
|
+
if (record.status === "conflict") conflicts.push(syncConflictDiagnostic(record))
|
|
1222
|
+
}
|
|
1223
|
+
this._throwIfLifecycleAborted(signal)
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
pendingCount += await this.withTenantOperation(async (operation) => {
|
|
1227
|
+
const syncModel = operation ? operation.modelClass(this.config.syncModel) : this.config.syncModel
|
|
1228
|
+
const pendingRows = await syncModel.preload({resource: true}).where({state: "pending"}).order("created_at").toArray()
|
|
1229
|
+
|
|
1230
|
+
return pendingRows.length
|
|
1231
|
+
})
|
|
1232
|
+
this._throwIfLifecycleAborted(signal)
|
|
1233
|
+
|
|
1234
|
+
return {conflicts, pendingCount, rejectedCount}
|
|
1235
|
+
})
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
/**
|
|
1239
|
+
* Resolves a durable conflict on its declared resource log. Retry-local is
|
|
1240
|
+
* scheduled through the current coordinator when attached.
|
|
1241
|
+
* @param {{recordId: string, resolution: "keep-server" | "retry-local", resourceType: string}} args - Resolution.
|
|
1242
|
+
* @returns {Promise<import("./local-mutation-log.js").LocalMutationLogRecord>} - Resolved durable record.
|
|
1243
|
+
*/
|
|
1244
|
+
async resolveConflict({recordId, resolution, resourceType}) {
|
|
1245
|
+
return await this._runLifecycleWork(async (signal) => {
|
|
1246
|
+
const conflictTracking = this.config.resources[resourceType]?.conflictTracking
|
|
1247
|
+
|
|
1248
|
+
if (!conflictTracking) throw new Error(`No conflict-tracked sync resource configured for: ${resourceType}`)
|
|
1249
|
+
|
|
1250
|
+
const record = await conflictTracking.mutationLog.resolveConflict({id: recordId, resolution})
|
|
1251
|
+
|
|
1252
|
+
this._throwIfLifecycleAborted(signal)
|
|
1253
|
+
if (resolution === "retry-local") this.scheduleReplay()
|
|
1254
|
+
|
|
1255
|
+
return record
|
|
1256
|
+
})
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1113
1259
|
/**
|
|
1114
1260
|
* Records an authoritative remote observation so an in-flight acknowledgement
|
|
1115
1261
|
* cannot rebase a successor across that observation.
|
|
@@ -1192,6 +1338,13 @@ export default class SyncClient {
|
|
|
1192
1338
|
* @returns {void}
|
|
1193
1339
|
*/
|
|
1194
1340
|
scheduleReplay() {
|
|
1341
|
+
const coordinatorRun = this.requestCoordinatorSync("mutation")
|
|
1342
|
+
|
|
1343
|
+
if (coordinatorRun) {
|
|
1344
|
+
this._scheduledReplay = coordinatorRun
|
|
1345
|
+
return
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1195
1348
|
this._scheduledReplay = (async () => {
|
|
1196
1349
|
try {
|
|
1197
1350
|
await this.replayPending()
|
|
@@ -1414,6 +1567,41 @@ export default class SyncClient {
|
|
|
1414
1567
|
}
|
|
1415
1568
|
}
|
|
1416
1569
|
|
|
1570
|
+
/**
|
|
1571
|
+
* Builds privacy-safe conflict metadata from a durable record.
|
|
1572
|
+
* @param {import("./local-mutation-log.js").LocalMutationLogRecord} record - Durable conflict record.
|
|
1573
|
+
* @returns {import("./sync-coordinator-types.js").SyncConflictDiagnostic} - Safe diagnostic.
|
|
1574
|
+
*/
|
|
1575
|
+
function syncConflictDiagnostic(record) {
|
|
1576
|
+
const conflict = record.syncResult?.conflict
|
|
1577
|
+
const conflictObject = conflict && !(conflict instanceof Date) && typeof conflict === "object" && !Array.isArray(conflict)
|
|
1578
|
+
? /** @type {Record<string, unknown>} */ (conflict)
|
|
1579
|
+
: {}
|
|
1580
|
+
const resourceId = record.mutation.payload?.resourceId
|
|
1581
|
+
|
|
1582
|
+
if (typeof resourceId !== "string" || resourceId.length === 0) throw new Error(`Sync conflict ${record.id} is missing a safe resourceId`)
|
|
1583
|
+
|
|
1584
|
+
return {
|
|
1585
|
+
baseVersion: safeConflictVersion(conflictObject.baseVersion ?? record.mutation.baseVersion ?? null),
|
|
1586
|
+
clientMutationId: record.mutation.clientMutationId,
|
|
1587
|
+
localVersion: safeConflictVersion(conflictObject.localVersion ?? null),
|
|
1588
|
+
recordId: record.id,
|
|
1589
|
+
resourceId,
|
|
1590
|
+
resourceType: record.mutation.model,
|
|
1591
|
+
serverVersion: safeConflictVersion(conflictObject.serverVersion ?? null),
|
|
1592
|
+
versionAttribute: typeof conflictObject.versionAttribute === "string" ? conflictObject.versionAttribute : null
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1596
|
+
/**
|
|
1597
|
+
* Restricts diagnostic versions to safe scalar values.
|
|
1598
|
+
* @param {unknown} value - Version candidate.
|
|
1599
|
+
* @returns {string | number | null} - Safe scalar version.
|
|
1600
|
+
*/
|
|
1601
|
+
function safeConflictVersion(value) {
|
|
1602
|
+
return value === null || typeof value === "string" || typeof value === "number" ? value : null
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1417
1605
|
/**
|
|
1418
1606
|
* Builds one resource config from a model's `static sync` declaration plus its
|
|
1419
1607
|
* derived column metadata.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/* eslint-disable jsdoc/no-undefined-types -- ReadonlyArray is a TypeScript utility type used by checkJs. */
|
|
3
|
+
|
|
4
|
+
/** @typedef {"backoff" | "conflicted" | "failed" | "idle" | "offline" | "pending" | "stopped" | "syncing"} SyncCoordinatorState */
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Privacy-safe conflict metadata for status surfaces. Mutation attributes,
|
|
8
|
+
* authoritative record data, credentials, and rejection reasons are excluded.
|
|
9
|
+
* @typedef {object} SyncConflictDiagnostic
|
|
10
|
+
* @property {string | number | null} baseVersion - Version the local mutation was based on.
|
|
11
|
+
* @property {string} clientMutationId - Durable client idempotency identifier.
|
|
12
|
+
* @property {string | number | null} localVersion - Optional client version returned by the conflict contract.
|
|
13
|
+
* @property {string} recordId - Durable local mutation-log record id.
|
|
14
|
+
* @property {string} resourceId - Stable resource identifier.
|
|
15
|
+
* @property {string} resourceType - Stable resource/model type.
|
|
16
|
+
* @property {string | number | null} serverVersion - Authoritative server version.
|
|
17
|
+
* @property {string | null} versionAttribute - Authoritative version attribute name.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Safe classified failure metadata. Applications own the classifier and must
|
|
22
|
+
* return only user-safe codes/messages; the original Error is never persisted.
|
|
23
|
+
* @typedef {object} SyncCoordinatorFailure
|
|
24
|
+
* @property {number} attempt - Consecutive cycle attempt number.
|
|
25
|
+
* @property {string} at - ISO timestamp of the failure.
|
|
26
|
+
* @property {string} code - Stable safe error code.
|
|
27
|
+
* @property {string} [message] - Optional safe display message.
|
|
28
|
+
* @property {boolean} retryable - Whether automatic retry is allowed.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Immutable coordinator status snapshot.
|
|
33
|
+
* @typedef {object} SyncCoordinatorStatus
|
|
34
|
+
* @property {ReadonlyArray<SyncConflictDiagnostic>} conflicts - Privacy-safe unresolved conflicts.
|
|
35
|
+
* @property {SyncCoordinatorFailure | null} failure - Last unresolved cycle failure.
|
|
36
|
+
* @property {string | null} lastSuccessAt - Last successful online cycle timestamp.
|
|
37
|
+
* @property {string | null} nextRetryAt - Scheduled automatic retry timestamp.
|
|
38
|
+
* @property {number} pendingCount - Durable pending mutation count.
|
|
39
|
+
* @property {number} rejectedCount - Durable permanently rejected mutation count.
|
|
40
|
+
* @property {SyncCoordinatorState} state - Observable lifecycle state.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Durable sync state reported by SyncClient.
|
|
45
|
+
* @typedef {object} SyncClientInspection
|
|
46
|
+
* @property {ReadonlyArray<SyncConflictDiagnostic>} conflicts - Privacy-safe conflict diagnostics.
|
|
47
|
+
* @property {number} pendingCount - Durable pending mutation count.
|
|
48
|
+
* @property {number} rejectedCount - Durable rejected mutation count.
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Application connectivity signal adapter. SyncClient remains the authority
|
|
53
|
+
* for the current online check; this adapter only notifies the coordinator.
|
|
54
|
+
* @typedef {object} SyncCoordinatorConnectivity
|
|
55
|
+
* @property {(listener: (online: boolean) => void) => (() => void)} subscribe - Subscribes to connectivity changes.
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Injected timer ownership for deterministic retry tests and teardown.
|
|
60
|
+
* @typedef {object} SyncCoordinatorScheduler
|
|
61
|
+
* @property {(timer: unknown) => void} clearTimeout - Clears a scheduled retry.
|
|
62
|
+
* @property {(callback: () => void, delayMs: number) => unknown} setTimeout - Schedules a retry.
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Optional durable status metadata store. Conflict payloads remain owned by
|
|
67
|
+
* LocalMutationLog; this store receives only privacy-safe snapshots.
|
|
68
|
+
* @typedef {object} SyncCoordinatorStatusStore
|
|
69
|
+
* @property {() => Promise<SyncCoordinatorStatus | null> | SyncCoordinatorStatus | null} load - Loads the last safe snapshot.
|
|
70
|
+
* @property {(status: SyncCoordinatorStatus) => Promise<void> | void} save - Persists one safe snapshot.
|
|
71
|
+
*/
|
|
72
|
+
|
|
73
|
+
export {}
|