@rljson/io 0.0.61 → 0.0.63
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/dist/conformance-tests/goldens/tableCfgs-1.json +3 -157
- package/dist/conformance-tests/io-conformance.spec.ts +5 -4
- package/dist/index.d.ts +4 -0
- package/dist/io-multi.d.ts +117 -0
- package/dist/io-peer-bridge.d.ts +75 -0
- package/dist/io.js +779 -16
- package/dist/io.js.map +1 -0
- package/dist/peer-socket-mock.d.ts +13 -0
- package/dist/socket.d.ts +3 -1
- package/package.json +10 -10
package/dist/io.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { hip, hsh } from "@rljson/hash";
|
|
2
2
|
import { IsReady } from "@rljson/is-ready";
|
|
3
|
-
import { copy, equals } from "@rljson/json";
|
|
3
|
+
import { copy, equals, merge } from "@rljson/json";
|
|
4
4
|
import { iterateTables, throwOnInvalidTableCfg, validateRljsonAgainstTableCfg, iterateTablesSync } from "@rljson/rljson";
|
|
5
5
|
class IoDbNameMapping {
|
|
6
6
|
// The primary key column is always named '_hash'
|
|
@@ -600,20 +600,6 @@ class IoMem {
|
|
|
600
600
|
});
|
|
601
601
|
}
|
|
602
602
|
}
|
|
603
|
-
const exampleTestSetup = () => {
|
|
604
|
-
return {
|
|
605
|
-
io: new IoMem(),
|
|
606
|
-
beforeAll: async () => {
|
|
607
|
-
},
|
|
608
|
-
beforeEach: async () => {
|
|
609
|
-
},
|
|
610
|
-
afterEach: async () => {
|
|
611
|
-
},
|
|
612
|
-
afterAll: async () => {
|
|
613
|
-
}
|
|
614
|
-
};
|
|
615
|
-
};
|
|
616
|
-
const exampleIo = "Checkout @rljson/io-mem for an example implementation";
|
|
617
603
|
class PeerSocketMock {
|
|
618
604
|
constructor(_io) {
|
|
619
605
|
this._io = _io;
|
|
@@ -622,6 +608,36 @@ class PeerSocketMock {
|
|
|
622
608
|
connected = false;
|
|
623
609
|
disconnected = true;
|
|
624
610
|
// ............................................................................
|
|
611
|
+
/**
|
|
612
|
+
* Removes a specific listener for the specified event.
|
|
613
|
+
* @param eventName - The name of the event.
|
|
614
|
+
* @param listener - The callback function to remove.
|
|
615
|
+
* @returns The PeerSocketMock instance for chaining.
|
|
616
|
+
*/
|
|
617
|
+
off(eventName, listener) {
|
|
618
|
+
const listeners = this._listenersMap.get(eventName) || [];
|
|
619
|
+
const index = listeners.indexOf(listener);
|
|
620
|
+
if (index !== -1) {
|
|
621
|
+
listeners.splice(index, 1);
|
|
622
|
+
this._listenersMap.set(eventName, listeners);
|
|
623
|
+
}
|
|
624
|
+
return this;
|
|
625
|
+
}
|
|
626
|
+
// ............................................................................
|
|
627
|
+
/**
|
|
628
|
+
* Removes all listeners for the specified event, or all listeners if no event is specified.
|
|
629
|
+
* @param eventName - (Optional) The name of the event.
|
|
630
|
+
* @returns The PeerSocketMock instance for chaining.
|
|
631
|
+
*/
|
|
632
|
+
removeAllListeners(eventName) {
|
|
633
|
+
if (eventName) {
|
|
634
|
+
this._listenersMap.delete(eventName);
|
|
635
|
+
} else {
|
|
636
|
+
this._listenersMap.clear();
|
|
637
|
+
}
|
|
638
|
+
return this;
|
|
639
|
+
}
|
|
640
|
+
// ............................................................................
|
|
625
641
|
/**
|
|
626
642
|
* Registers an event listener for the specified event.
|
|
627
643
|
* @param eventName - The name of the event to listen for.
|
|
@@ -684,6 +700,741 @@ class PeerSocketMock {
|
|
|
684
700
|
return true;
|
|
685
701
|
}
|
|
686
702
|
}
|
|
703
|
+
class IoPeer {
|
|
704
|
+
constructor(_socket) {
|
|
705
|
+
this._socket = _socket;
|
|
706
|
+
}
|
|
707
|
+
isOpen = false;
|
|
708
|
+
// ...........................................................................
|
|
709
|
+
/**
|
|
710
|
+
*
|
|
711
|
+
* Initializes the Peer connection.
|
|
712
|
+
* @returns
|
|
713
|
+
*/
|
|
714
|
+
async init() {
|
|
715
|
+
this._socket.on("connect", () => {
|
|
716
|
+
this.isOpen = true;
|
|
717
|
+
});
|
|
718
|
+
this._socket.on("disconnect", () => {
|
|
719
|
+
this.isOpen = false;
|
|
720
|
+
});
|
|
721
|
+
this._socket.connect();
|
|
722
|
+
return new Promise((resolve) => {
|
|
723
|
+
if (this._socket.connected) {
|
|
724
|
+
this.isOpen = true;
|
|
725
|
+
resolve();
|
|
726
|
+
} else {
|
|
727
|
+
this._socket.on("connect", () => {
|
|
728
|
+
resolve();
|
|
729
|
+
});
|
|
730
|
+
}
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
// ...........................................................................
|
|
734
|
+
/**
|
|
735
|
+
* Closes the Peer connection.
|
|
736
|
+
* @returns
|
|
737
|
+
*/
|
|
738
|
+
async close() {
|
|
739
|
+
if (!this._socket.connected) return;
|
|
740
|
+
return new Promise((resolve) => {
|
|
741
|
+
this._socket.on("disconnect", () => {
|
|
742
|
+
resolve();
|
|
743
|
+
});
|
|
744
|
+
this._socket.disconnect();
|
|
745
|
+
});
|
|
746
|
+
}
|
|
747
|
+
// ...........................................................................
|
|
748
|
+
/**
|
|
749
|
+
* Returns a promise that resolves once the Peer connection is ready.
|
|
750
|
+
* @returns
|
|
751
|
+
*/
|
|
752
|
+
async isReady() {
|
|
753
|
+
if (!!this._socket && this._socket.connected === true) this.isOpen = true;
|
|
754
|
+
else this.isOpen = false;
|
|
755
|
+
return !!this.isOpen ? Promise.resolve() : Promise.reject();
|
|
756
|
+
}
|
|
757
|
+
// ...........................................................................
|
|
758
|
+
/**
|
|
759
|
+
* Dumps the entire database content.
|
|
760
|
+
* @returns A promise that resolves to the dumped database content.
|
|
761
|
+
*/
|
|
762
|
+
async dump() {
|
|
763
|
+
return new Promise((resolve) => {
|
|
764
|
+
this._socket.emit("dump", (data) => {
|
|
765
|
+
resolve(data);
|
|
766
|
+
});
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
// ...........................................................................
|
|
770
|
+
/**
|
|
771
|
+
* Dumps a specific table from the database.
|
|
772
|
+
* @param request An object containing the table name to dump.
|
|
773
|
+
* @returns A promise that resolves to the dumped table data.
|
|
774
|
+
*/
|
|
775
|
+
dumpTable(request) {
|
|
776
|
+
return new Promise((resolve, reject) => {
|
|
777
|
+
this._socket.emit("dumpTable", request, (data, error) => {
|
|
778
|
+
if (error) reject(error);
|
|
779
|
+
resolve(data);
|
|
780
|
+
});
|
|
781
|
+
});
|
|
782
|
+
}
|
|
783
|
+
// ...........................................................................
|
|
784
|
+
/**
|
|
785
|
+
* Gets the content type of a specific table.
|
|
786
|
+
* @param request An object containing the table name to get the content type for.
|
|
787
|
+
* @returns A promise that resolves to the content type of the specified table.
|
|
788
|
+
*/
|
|
789
|
+
contentType(request) {
|
|
790
|
+
return new Promise((resolve, reject) => {
|
|
791
|
+
this._socket.emit(
|
|
792
|
+
"contentType",
|
|
793
|
+
request,
|
|
794
|
+
(data, error) => {
|
|
795
|
+
if (error) reject(error);
|
|
796
|
+
resolve(data);
|
|
797
|
+
}
|
|
798
|
+
);
|
|
799
|
+
});
|
|
800
|
+
}
|
|
801
|
+
// ...........................................................................
|
|
802
|
+
/**
|
|
803
|
+
* Checks if a specific table exists in the database.
|
|
804
|
+
* @param tableKey The key of the table to check for existence.
|
|
805
|
+
* @returns A promise that resolves to true if the table exists, false otherwise.
|
|
806
|
+
*/
|
|
807
|
+
tableExists(tableKey) {
|
|
808
|
+
return new Promise((resolve) => {
|
|
809
|
+
this._socket.emit("tableExists", tableKey, (exists) => {
|
|
810
|
+
resolve(exists);
|
|
811
|
+
});
|
|
812
|
+
});
|
|
813
|
+
}
|
|
814
|
+
// ...........................................................................
|
|
815
|
+
/**
|
|
816
|
+
* Creates or extends a table with the given configuration.
|
|
817
|
+
* @param request An object containing the table configuration.
|
|
818
|
+
* @returns A promise that resolves once the table is created or extended.
|
|
819
|
+
*/
|
|
820
|
+
createOrExtendTable(request) {
|
|
821
|
+
return new Promise((resolve, reject) => {
|
|
822
|
+
this._socket.emit(
|
|
823
|
+
"createOrExtendTable",
|
|
824
|
+
request,
|
|
825
|
+
(_, error) => {
|
|
826
|
+
if (error) reject(error);
|
|
827
|
+
resolve();
|
|
828
|
+
}
|
|
829
|
+
);
|
|
830
|
+
});
|
|
831
|
+
}
|
|
832
|
+
// ...........................................................................
|
|
833
|
+
/**
|
|
834
|
+
* Retrieves the raw table configurations from the database.
|
|
835
|
+
* @returns A promise that resolves to an array of table configurations.
|
|
836
|
+
*/
|
|
837
|
+
rawTableCfgs() {
|
|
838
|
+
return new Promise((resolve) => {
|
|
839
|
+
this._socket.emit("rawTableCfgs", (data) => {
|
|
840
|
+
resolve(data);
|
|
841
|
+
});
|
|
842
|
+
});
|
|
843
|
+
}
|
|
844
|
+
// ...........................................................................
|
|
845
|
+
/**
|
|
846
|
+
* Writes data to the database.
|
|
847
|
+
* @param request An object containing the data to write.
|
|
848
|
+
* @returns A promise that resolves once the data is written.
|
|
849
|
+
*/
|
|
850
|
+
write(request) {
|
|
851
|
+
return new Promise((resolve, reject) => {
|
|
852
|
+
this._socket.emit("write", request, (_, error) => {
|
|
853
|
+
if (error) reject(error);
|
|
854
|
+
resolve();
|
|
855
|
+
});
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
// ...........................................................................
|
|
859
|
+
/**
|
|
860
|
+
* Reads rows from a specific table that match the given criteria.
|
|
861
|
+
* @param request An object containing the table name and the criteria for selecting rows.
|
|
862
|
+
* @returns A promise that resolves to the selected rows.
|
|
863
|
+
*/
|
|
864
|
+
readRows(request) {
|
|
865
|
+
return new Promise((resolve, reject) => {
|
|
866
|
+
this._socket.emit(
|
|
867
|
+
"readRows",
|
|
868
|
+
request,
|
|
869
|
+
(result, error) => {
|
|
870
|
+
if (error) reject(error);
|
|
871
|
+
resolve(result);
|
|
872
|
+
}
|
|
873
|
+
);
|
|
874
|
+
});
|
|
875
|
+
}
|
|
876
|
+
// ...........................................................................
|
|
877
|
+
/**
|
|
878
|
+
* Retrieves the number of rows in a specific table.
|
|
879
|
+
* @param table The name of the table to count rows in.
|
|
880
|
+
* @returns A promise that resolves to the number of rows in the specified table.
|
|
881
|
+
*/
|
|
882
|
+
rowCount(table) {
|
|
883
|
+
return new Promise((resolve, reject) => {
|
|
884
|
+
this._socket.emit("rowCount", table, (count, error) => {
|
|
885
|
+
if (error) reject(error);
|
|
886
|
+
resolve(count);
|
|
887
|
+
});
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
// ...........................................................................
|
|
891
|
+
static example = async () => {
|
|
892
|
+
const ioMem = await IoMem.example();
|
|
893
|
+
const socket = new PeerSocketMock(ioMem);
|
|
894
|
+
const io = new IoPeer(socket);
|
|
895
|
+
await io.init();
|
|
896
|
+
return io;
|
|
897
|
+
};
|
|
898
|
+
}
|
|
899
|
+
class IoMulti {
|
|
900
|
+
constructor(_ios) {
|
|
901
|
+
this._ios = _ios;
|
|
902
|
+
}
|
|
903
|
+
isOpen = false;
|
|
904
|
+
// ...........................................................................
|
|
905
|
+
/**
|
|
906
|
+
*
|
|
907
|
+
* Initializes all underlying Io instances.
|
|
908
|
+
* @returns
|
|
909
|
+
*/
|
|
910
|
+
async init() {
|
|
911
|
+
for (let idx = 0; idx < this._ios.length; idx++) {
|
|
912
|
+
const { io } = this._ios[idx];
|
|
913
|
+
if (io.isOpen === false) {
|
|
914
|
+
throw new Error(
|
|
915
|
+
"All underlying Io instances must be initialized before initializing IoMulti"
|
|
916
|
+
);
|
|
917
|
+
}
|
|
918
|
+
this._ios[idx] = { ...this._ios[idx], id: `io-${idx}` };
|
|
919
|
+
}
|
|
920
|
+
this.isOpen = true;
|
|
921
|
+
return Promise.resolve();
|
|
922
|
+
}
|
|
923
|
+
// ...........................................................................
|
|
924
|
+
/**
|
|
925
|
+
* Closes all underlying Io instances.
|
|
926
|
+
* @returns
|
|
927
|
+
*/
|
|
928
|
+
async close() {
|
|
929
|
+
await Promise.all(this._ios.map((ioMultiIo) => ioMultiIo.io.close()));
|
|
930
|
+
this.isOpen = false;
|
|
931
|
+
return Promise.resolve();
|
|
932
|
+
}
|
|
933
|
+
// ...........................................................................
|
|
934
|
+
/**
|
|
935
|
+
* Returns a promise that resolves once all underlying Io instances are ready.
|
|
936
|
+
* @returns
|
|
937
|
+
*/
|
|
938
|
+
isReady() {
|
|
939
|
+
return Promise.all(
|
|
940
|
+
this._ios.map((ioMultiIo) => ioMultiIo.io.isReady())
|
|
941
|
+
).then(() => Promise.resolve());
|
|
942
|
+
}
|
|
943
|
+
// ...........................................................................
|
|
944
|
+
/**
|
|
945
|
+
* Dumps the entire database content by merging dumps from all dumpable underlying Io instances.
|
|
946
|
+
* @returns
|
|
947
|
+
*/
|
|
948
|
+
async dump() {
|
|
949
|
+
if (this.dumpables.length === 0) {
|
|
950
|
+
throw new Error("No dumpable Io available");
|
|
951
|
+
}
|
|
952
|
+
const dumps = await Promise.all(
|
|
953
|
+
this.dumpables.map(({ io: dumpable }) => dumpable.dump())
|
|
954
|
+
);
|
|
955
|
+
return merge(...dumps);
|
|
956
|
+
}
|
|
957
|
+
// ...........................................................................
|
|
958
|
+
/**
|
|
959
|
+
* Dumps a specific table by merging dumps from all dumpable underlying Io instances that contain the table.
|
|
960
|
+
* @param request An object containing the table name to dump.
|
|
961
|
+
* @returns A promise that resolves to the dumped table data.
|
|
962
|
+
*/
|
|
963
|
+
async dumpTable(request) {
|
|
964
|
+
if (this.dumpables.length === 0) {
|
|
965
|
+
throw new Error("No dumpable Io available");
|
|
966
|
+
}
|
|
967
|
+
const dumps = [];
|
|
968
|
+
for (const { io: dumpable } of this.dumpables) {
|
|
969
|
+
try {
|
|
970
|
+
const dump = await dumpable.dumpTable(request);
|
|
971
|
+
dumps.push(dump);
|
|
972
|
+
} catch {
|
|
973
|
+
continue;
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
if (dumps.length === 0) {
|
|
977
|
+
throw new Error(`Table "${request.table}" not found`);
|
|
978
|
+
}
|
|
979
|
+
return merge(...dumps);
|
|
980
|
+
}
|
|
981
|
+
// ...........................................................................
|
|
982
|
+
/**
|
|
983
|
+
* Retrieves the content type of a specific table from the first underlying readable Io instance that contains the table.
|
|
984
|
+
* @param request An object containing the table name.
|
|
985
|
+
* @returns A promise that resolves to the content type of the table.
|
|
986
|
+
*/
|
|
987
|
+
async contentType(request) {
|
|
988
|
+
if (this.readables.length === 0) {
|
|
989
|
+
throw new Error("No readable Io available");
|
|
990
|
+
}
|
|
991
|
+
for (const { io: readable } of this.readables) {
|
|
992
|
+
return readable.contentType(request);
|
|
993
|
+
}
|
|
994
|
+
throw new Error(`Table "${request.table}" not found`);
|
|
995
|
+
}
|
|
996
|
+
// ...........................................................................
|
|
997
|
+
/**
|
|
998
|
+
* Checks if a specific table exists in any of the underlying readable Io instances.
|
|
999
|
+
* @param tableKey The key of the table to check.
|
|
1000
|
+
* @returns A promise that resolves to true if the table exists in any readable Io, false otherwise.
|
|
1001
|
+
*/
|
|
1002
|
+
async tableExists(tableKey) {
|
|
1003
|
+
if (this.readables.length === 0) {
|
|
1004
|
+
throw new Error("No readable Io available");
|
|
1005
|
+
}
|
|
1006
|
+
for (let i = 0; i < this.readables.length; i++) {
|
|
1007
|
+
const readable = this.readables[i].io;
|
|
1008
|
+
const exists = await readable.tableExists(tableKey);
|
|
1009
|
+
if (exists) {
|
|
1010
|
+
return true;
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
return false;
|
|
1014
|
+
}
|
|
1015
|
+
// ...........................................................................
|
|
1016
|
+
/**
|
|
1017
|
+
* Creates or extends a table in all underlying writable Io instances.
|
|
1018
|
+
* @param request An object containing the table configuration.
|
|
1019
|
+
* @returns A promise that resolves once the table has been created or extended in all writable Io instances.
|
|
1020
|
+
*/
|
|
1021
|
+
createOrExtendTable(request) {
|
|
1022
|
+
if (this.writables.length === 0) {
|
|
1023
|
+
throw new Error("No writable Io available");
|
|
1024
|
+
}
|
|
1025
|
+
const creations = this.writables.map(
|
|
1026
|
+
({ io: writable }) => writable.createOrExtendTable(request)
|
|
1027
|
+
);
|
|
1028
|
+
return Promise.all(creations).then(() => Promise.resolve());
|
|
1029
|
+
}
|
|
1030
|
+
// ...........................................................................
|
|
1031
|
+
/**
|
|
1032
|
+
* Retrieves the raw table configurations from the highest priority underlying readable Io instance.
|
|
1033
|
+
* @returns A promise that resolves to an array of table configurations.
|
|
1034
|
+
*/
|
|
1035
|
+
async rawTableCfgs() {
|
|
1036
|
+
if (this.readables.length === 0) {
|
|
1037
|
+
throw new Error("No readable Io available");
|
|
1038
|
+
}
|
|
1039
|
+
const rawTableCfgs = /* @__PURE__ */ new Map();
|
|
1040
|
+
for (const { io: readable } of this.readables) {
|
|
1041
|
+
const cfgs = await readable.rawTableCfgs();
|
|
1042
|
+
if (cfgs.length > 0) {
|
|
1043
|
+
for (const tableCfg of cfgs) {
|
|
1044
|
+
if (!rawTableCfgs.has(tableCfg.key)) {
|
|
1045
|
+
rawTableCfgs.set(tableCfg.key, tableCfg);
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
return Array.from(rawTableCfgs.values());
|
|
1051
|
+
}
|
|
1052
|
+
// ...........................................................................
|
|
1053
|
+
/**
|
|
1054
|
+
* Writes data to all underlying writable Io instances.
|
|
1055
|
+
* @param request - An object containing the data to write.
|
|
1056
|
+
* @returns A promise that resolves once the data has been written to all writable Io instances.
|
|
1057
|
+
*/
|
|
1058
|
+
write(request) {
|
|
1059
|
+
if (this.writables.length === 0) {
|
|
1060
|
+
throw new Error("No writable Io available");
|
|
1061
|
+
}
|
|
1062
|
+
const writes = this.writables.map(
|
|
1063
|
+
({ io: writable }) => writable.write(request)
|
|
1064
|
+
);
|
|
1065
|
+
return Promise.all(writes).then(() => Promise.resolve());
|
|
1066
|
+
}
|
|
1067
|
+
// ...........................................................................
|
|
1068
|
+
/**
|
|
1069
|
+
* Reads rows from a specific table by merging rows from all underlying readable Io instances.
|
|
1070
|
+
* @param request An object containing the table name and where clause.
|
|
1071
|
+
* @returns A promise that resolves to the read rows.
|
|
1072
|
+
*/
|
|
1073
|
+
async readRows(request) {
|
|
1074
|
+
if (this.readables.length === 0) {
|
|
1075
|
+
throw new Error("No readable Io available");
|
|
1076
|
+
}
|
|
1077
|
+
let tableExistsAny = false;
|
|
1078
|
+
const rows = /* @__PURE__ */ new Map();
|
|
1079
|
+
let type = void 0;
|
|
1080
|
+
let readFrom = "";
|
|
1081
|
+
const errors = [];
|
|
1082
|
+
for (const readable of this.readables) {
|
|
1083
|
+
let tableRows = [];
|
|
1084
|
+
let tableType;
|
|
1085
|
+
try {
|
|
1086
|
+
const { [request.table]: tableData } = await readable.io.readRows(
|
|
1087
|
+
request
|
|
1088
|
+
);
|
|
1089
|
+
tableRows = tableData._data;
|
|
1090
|
+
tableType = tableData._type;
|
|
1091
|
+
tableExistsAny = true;
|
|
1092
|
+
readFrom = readable.id ?? "";
|
|
1093
|
+
} catch (e) {
|
|
1094
|
+
errors.push(e);
|
|
1095
|
+
continue;
|
|
1096
|
+
}
|
|
1097
|
+
type ??= tableType;
|
|
1098
|
+
if (tableRows.length === 0) {
|
|
1099
|
+
continue;
|
|
1100
|
+
}
|
|
1101
|
+
for (const tableRow of tableRows) {
|
|
1102
|
+
const ref = tableRow._hash;
|
|
1103
|
+
rows.set(ref, tableRow);
|
|
1104
|
+
}
|
|
1105
|
+
break;
|
|
1106
|
+
}
|
|
1107
|
+
if (!tableExistsAny) {
|
|
1108
|
+
if (errors.length === 0) {
|
|
1109
|
+
throw new Error(`Table "${request.table}" not found`);
|
|
1110
|
+
} else {
|
|
1111
|
+
const preciseErrors = errors.filter(
|
|
1112
|
+
(err) => !err.message.includes(`Table "${request.table}" not found`)
|
|
1113
|
+
);
|
|
1114
|
+
if (preciseErrors.length > 0) {
|
|
1115
|
+
throw preciseErrors[0];
|
|
1116
|
+
} else {
|
|
1117
|
+
throw errors[0];
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
} else {
|
|
1121
|
+
const rljson = {
|
|
1122
|
+
[request.table]: hip({ _data: Array.from(rows.values()), _type: type })
|
|
1123
|
+
};
|
|
1124
|
+
if (this.writables.length > 0 && rows.size > 0) {
|
|
1125
|
+
for (const writeable of this.writables) {
|
|
1126
|
+
if (writeable.id === readFrom) {
|
|
1127
|
+
continue;
|
|
1128
|
+
}
|
|
1129
|
+
try {
|
|
1130
|
+
await writeable.io.write({
|
|
1131
|
+
data: rljson
|
|
1132
|
+
});
|
|
1133
|
+
} catch {
|
|
1134
|
+
continue;
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
return rljson;
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
// ...........................................................................
|
|
1142
|
+
/**
|
|
1143
|
+
* Retrieves the row count of a specific table by aggregating row counts from all dumpable underlying Io instances.
|
|
1144
|
+
* @param table The name of the table.
|
|
1145
|
+
* @returns A promise that resolves to the row count of the table.
|
|
1146
|
+
*/
|
|
1147
|
+
async rowCount(table) {
|
|
1148
|
+
if (this.dumpables.length === 0) {
|
|
1149
|
+
throw new Error("No dumpable Io available");
|
|
1150
|
+
}
|
|
1151
|
+
const dumpTable = await this.dumpTable({ table });
|
|
1152
|
+
const tableData = dumpTable[table];
|
|
1153
|
+
if (!tableData) {
|
|
1154
|
+
throw new Error(`Table "${table}" not found`);
|
|
1155
|
+
}
|
|
1156
|
+
return Promise.resolve(tableData._data.length);
|
|
1157
|
+
}
|
|
1158
|
+
// ...........................................................................
|
|
1159
|
+
/**
|
|
1160
|
+
* Gets the list of underlying readable Io instances, sorted by priority.
|
|
1161
|
+
*/
|
|
1162
|
+
get readables() {
|
|
1163
|
+
return this._ios.filter((ioMultiIo) => ioMultiIo.read).sort((a, b) => a.priority - b.priority);
|
|
1164
|
+
}
|
|
1165
|
+
// ...........................................................................
|
|
1166
|
+
/**
|
|
1167
|
+
* Gets the list of underlying writable Io instances, sorted by priority.
|
|
1168
|
+
*/
|
|
1169
|
+
get writables() {
|
|
1170
|
+
return this._ios.filter((ioMultiIo) => ioMultiIo.write).sort((a, b) => a.priority - b.priority);
|
|
1171
|
+
}
|
|
1172
|
+
// ...........................................................................
|
|
1173
|
+
/**
|
|
1174
|
+
* Gets the list of underlying dumpable Io instances, sorted by priority.
|
|
1175
|
+
*/
|
|
1176
|
+
get dumpables() {
|
|
1177
|
+
return this._ios.filter((ioMultiIo) => ioMultiIo.dump).sort((a, b) => a.priority - b.priority);
|
|
1178
|
+
}
|
|
1179
|
+
// ...........................................................................
|
|
1180
|
+
static example = async () => {
|
|
1181
|
+
const ioPeerMem = await IoMem.example();
|
|
1182
|
+
await ioPeerMem.init();
|
|
1183
|
+
const ioPeerSocket = new PeerSocketMock(ioPeerMem);
|
|
1184
|
+
const ioPeer = new IoPeer(ioPeerSocket);
|
|
1185
|
+
await ioPeer.init();
|
|
1186
|
+
const ioMem = await IoMem.example();
|
|
1187
|
+
await ioMem.init();
|
|
1188
|
+
const ios = [
|
|
1189
|
+
{ io: ioPeer, priority: 1, read: true, write: false, dump: false },
|
|
1190
|
+
{ io: ioMem, priority: 0, read: true, write: true, dump: true }
|
|
1191
|
+
];
|
|
1192
|
+
const ioMulti = new IoMulti(ios);
|
|
1193
|
+
await ioMulti.init();
|
|
1194
|
+
return ioMulti;
|
|
1195
|
+
};
|
|
1196
|
+
}
|
|
1197
|
+
class IoPeerBridge {
|
|
1198
|
+
constructor(_io, _socket) {
|
|
1199
|
+
this._io = _io;
|
|
1200
|
+
this._socket = _socket;
|
|
1201
|
+
}
|
|
1202
|
+
_eventHandlers = /* @__PURE__ */ new Map();
|
|
1203
|
+
/**
|
|
1204
|
+
* Starts the bridge by setting up connection event handlers and
|
|
1205
|
+
* automatically registering all Io methods.
|
|
1206
|
+
*/
|
|
1207
|
+
start() {
|
|
1208
|
+
this._socket.on("connect", () => this._handleConnect());
|
|
1209
|
+
this._socket.on("disconnect", () => this._handleDisconnect());
|
|
1210
|
+
this._registerIoMethods();
|
|
1211
|
+
}
|
|
1212
|
+
/**
|
|
1213
|
+
* Stops the bridge by removing all event handlers.
|
|
1214
|
+
*/
|
|
1215
|
+
stop() {
|
|
1216
|
+
this._socket.off("connect", () => this._handleConnect());
|
|
1217
|
+
this._socket.off("disconnect", () => this._handleDisconnect());
|
|
1218
|
+
for (const [eventName, handler] of this._eventHandlers) {
|
|
1219
|
+
this._socket.off(eventName, handler);
|
|
1220
|
+
}
|
|
1221
|
+
this._eventHandlers.clear();
|
|
1222
|
+
}
|
|
1223
|
+
/**
|
|
1224
|
+
* Automatically registers all Io interface methods as socket event handlers.
|
|
1225
|
+
*/
|
|
1226
|
+
_registerIoMethods() {
|
|
1227
|
+
const ioMethods = [
|
|
1228
|
+
"init",
|
|
1229
|
+
"isReady",
|
|
1230
|
+
"close",
|
|
1231
|
+
"tableExists",
|
|
1232
|
+
"createOrExtendTable",
|
|
1233
|
+
"write",
|
|
1234
|
+
"readRows",
|
|
1235
|
+
"rowCount",
|
|
1236
|
+
"dumpTable",
|
|
1237
|
+
"dump",
|
|
1238
|
+
"contentType",
|
|
1239
|
+
"rawTableCfgs"
|
|
1240
|
+
];
|
|
1241
|
+
for (const methodName of ioMethods) {
|
|
1242
|
+
this.registerEvent(methodName);
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
/**
|
|
1246
|
+
* Registers a socket event to be translated to an Io method call.
|
|
1247
|
+
*
|
|
1248
|
+
* @param eventName - The socket event name (should match an Io method name)
|
|
1249
|
+
* @param ioMethodName - (Optional) The Io method name if different from eventName
|
|
1250
|
+
*/
|
|
1251
|
+
registerEvent(eventName, ioMethodName) {
|
|
1252
|
+
const methodName = ioMethodName || eventName;
|
|
1253
|
+
const handler = (...args) => {
|
|
1254
|
+
const callback = args[args.length - 1];
|
|
1255
|
+
const methodArgs = args.slice(0, -1);
|
|
1256
|
+
const ioMethod = this._io[methodName];
|
|
1257
|
+
if (typeof ioMethod !== "function") {
|
|
1258
|
+
const error = new Error(
|
|
1259
|
+
`Method "${methodName}" not found on Io instance`
|
|
1260
|
+
);
|
|
1261
|
+
if (typeof callback === "function") {
|
|
1262
|
+
callback(null, error);
|
|
1263
|
+
}
|
|
1264
|
+
return;
|
|
1265
|
+
}
|
|
1266
|
+
ioMethod.apply(this._io, methodArgs).then((result) => {
|
|
1267
|
+
if (typeof callback === "function") {
|
|
1268
|
+
callback(result, null);
|
|
1269
|
+
}
|
|
1270
|
+
}).catch((error) => {
|
|
1271
|
+
if (typeof callback === "function") {
|
|
1272
|
+
callback(null, error);
|
|
1273
|
+
}
|
|
1274
|
+
});
|
|
1275
|
+
};
|
|
1276
|
+
this._eventHandlers.set(eventName, handler);
|
|
1277
|
+
this._socket.on(eventName, handler);
|
|
1278
|
+
}
|
|
1279
|
+
/**
|
|
1280
|
+
* Registers multiple socket events at once.
|
|
1281
|
+
*
|
|
1282
|
+
* @param eventNames - Array of event names to register
|
|
1283
|
+
*/
|
|
1284
|
+
registerEvents(eventNames) {
|
|
1285
|
+
for (const eventName of eventNames) {
|
|
1286
|
+
this.registerEvent(eventName);
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
/**
|
|
1290
|
+
* Unregisters a socket event handler.
|
|
1291
|
+
*
|
|
1292
|
+
* @param eventName - The event name to unregister
|
|
1293
|
+
*/
|
|
1294
|
+
unregisterEvent(eventName) {
|
|
1295
|
+
const handler = this._eventHandlers.get(eventName);
|
|
1296
|
+
if (handler) {
|
|
1297
|
+
this._socket.off(eventName, handler);
|
|
1298
|
+
this._eventHandlers.delete(eventName);
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
/**
|
|
1302
|
+
* Emits a result back through the socket.
|
|
1303
|
+
*
|
|
1304
|
+
* @param eventName - The event name to emit
|
|
1305
|
+
* @param data - The data to send
|
|
1306
|
+
*/
|
|
1307
|
+
emitToSocket(eventName, ...data) {
|
|
1308
|
+
this._socket.emit(eventName, ...data);
|
|
1309
|
+
}
|
|
1310
|
+
/**
|
|
1311
|
+
* Calls an Io method directly and emits the result through the socket.
|
|
1312
|
+
*
|
|
1313
|
+
* @param ioMethodName - The Io method to call
|
|
1314
|
+
* @param socketEventName - The socket event to emit with the result
|
|
1315
|
+
* @param args - Arguments to pass to the Io method
|
|
1316
|
+
*/
|
|
1317
|
+
async callIoAndEmit(ioMethodName, socketEventName, ...args) {
|
|
1318
|
+
try {
|
|
1319
|
+
const ioMethod = this._io[ioMethodName];
|
|
1320
|
+
if (typeof ioMethod !== "function") {
|
|
1321
|
+
throw new Error(`Method "${ioMethodName}" not found on Io instance`);
|
|
1322
|
+
}
|
|
1323
|
+
const result = await ioMethod.apply(this._io, args);
|
|
1324
|
+
this._socket.emit(socketEventName, result, null);
|
|
1325
|
+
} catch (error) {
|
|
1326
|
+
this._socket.emit(socketEventName, null, error);
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
/* v8 ignore next -- @preserve */
|
|
1330
|
+
_handleConnect() {
|
|
1331
|
+
}
|
|
1332
|
+
/* v8 ignore next -- @preserve */
|
|
1333
|
+
_handleDisconnect() {
|
|
1334
|
+
}
|
|
1335
|
+
/**
|
|
1336
|
+
* Gets the current socket instance.
|
|
1337
|
+
*/
|
|
1338
|
+
get socket() {
|
|
1339
|
+
return this._socket;
|
|
1340
|
+
}
|
|
1341
|
+
/**
|
|
1342
|
+
* Gets the current Io instance.
|
|
1343
|
+
*/
|
|
1344
|
+
get io() {
|
|
1345
|
+
return this._io;
|
|
1346
|
+
}
|
|
1347
|
+
/**
|
|
1348
|
+
* Returns whether the socket is currently connected.
|
|
1349
|
+
*/
|
|
1350
|
+
get isConnected() {
|
|
1351
|
+
return this._socket.connected;
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
class IoServer {
|
|
1355
|
+
constructor(_io) {
|
|
1356
|
+
this._io = _io;
|
|
1357
|
+
}
|
|
1358
|
+
_sockets = [];
|
|
1359
|
+
// ...........................................................................
|
|
1360
|
+
/**
|
|
1361
|
+
* Adds a socket to the IoServer instance.
|
|
1362
|
+
* @param socket - The socket to add.
|
|
1363
|
+
*/
|
|
1364
|
+
async addSocket(socket) {
|
|
1365
|
+
await this._addTransportLayer(socket);
|
|
1366
|
+
this._sockets.push(socket);
|
|
1367
|
+
}
|
|
1368
|
+
// ...........................................................................
|
|
1369
|
+
/**
|
|
1370
|
+
* Removes a transport layer from the given socket.
|
|
1371
|
+
* @param socket - The socket to remove the transport layer from.
|
|
1372
|
+
*/
|
|
1373
|
+
removeSocket(socket) {
|
|
1374
|
+
this._sockets = this._sockets.filter((s) => s !== socket);
|
|
1375
|
+
}
|
|
1376
|
+
// ...........................................................................
|
|
1377
|
+
/**
|
|
1378
|
+
* Adds a transport layer to the given socket.
|
|
1379
|
+
* @param socket - The socket to add the transport layer to.
|
|
1380
|
+
*/
|
|
1381
|
+
async _addTransportLayer(socket) {
|
|
1382
|
+
const crud = this._generateTransportLayerCRUD(this._io);
|
|
1383
|
+
for (const [key, fn] of Object.entries(crud)) {
|
|
1384
|
+
socket.on(key, (...args) => {
|
|
1385
|
+
const cb = args[args.length - 1];
|
|
1386
|
+
fn.apply(this, args.slice(0, -1)).then((result) => {
|
|
1387
|
+
cb(result, null);
|
|
1388
|
+
}).catch((err) => {
|
|
1389
|
+
cb(null, err);
|
|
1390
|
+
});
|
|
1391
|
+
});
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
// ...........................................................................
|
|
1395
|
+
/**
|
|
1396
|
+
* Creates or extends a table with the given configuration.
|
|
1397
|
+
* @param request - An object containing the table configuration.
|
|
1398
|
+
*/
|
|
1399
|
+
async createOrExtendTable(request) {
|
|
1400
|
+
return this._io.createOrExtendTable(request);
|
|
1401
|
+
}
|
|
1402
|
+
// ...........................................................................
|
|
1403
|
+
/**
|
|
1404
|
+
* Generates a transport layer object for the given Io instance.
|
|
1405
|
+
* @param io - The Io instance to generate the transport layer for.
|
|
1406
|
+
* @returns An object containing methods that correspond to the Io interface.
|
|
1407
|
+
*/
|
|
1408
|
+
_generateTransportLayerCRUD = (io) => ({
|
|
1409
|
+
init: () => io.init(),
|
|
1410
|
+
close: () => io.close(),
|
|
1411
|
+
isOpen: () => new Promise((resolve) => resolve(io.isOpen)),
|
|
1412
|
+
isReady: () => io.isReady(),
|
|
1413
|
+
dump: () => io.dump(),
|
|
1414
|
+
dumpTable: (request) => io.dumpTable(request),
|
|
1415
|
+
contentType: (request) => io.contentType(request),
|
|
1416
|
+
tableExists: (tableKey) => io.tableExists(tableKey),
|
|
1417
|
+
createOrExtendTable: (request) => this.createOrExtendTable(request),
|
|
1418
|
+
rawTableCfgs: () => io.rawTableCfgs(),
|
|
1419
|
+
write: (request) => io.write(request),
|
|
1420
|
+
readRows: (request) => io.readRows(request),
|
|
1421
|
+
rowCount: (table) => io.rowCount(table)
|
|
1422
|
+
});
|
|
1423
|
+
}
|
|
1424
|
+
const exampleTestSetup = () => {
|
|
1425
|
+
return {
|
|
1426
|
+
io: new IoMem(),
|
|
1427
|
+
beforeAll: async () => {
|
|
1428
|
+
},
|
|
1429
|
+
beforeEach: async () => {
|
|
1430
|
+
},
|
|
1431
|
+
afterEach: async () => {
|
|
1432
|
+
},
|
|
1433
|
+
afterAll: async () => {
|
|
1434
|
+
}
|
|
1435
|
+
};
|
|
1436
|
+
};
|
|
1437
|
+
const exampleIo = "Checkout @rljson/io-mem for an example implementation";
|
|
687
1438
|
const calcReverseRefs = (rljson) => {
|
|
688
1439
|
const result = {};
|
|
689
1440
|
iterateTablesSync(rljson, (childTableKey, table) => {
|
|
@@ -940,11 +1691,23 @@ const socketExample = () => ({
|
|
|
940
1691
|
/* v8 ignore next -- @preserve */
|
|
941
1692
|
emit() {
|
|
942
1693
|
return true;
|
|
1694
|
+
},
|
|
1695
|
+
/* v8 ignore next -- @preserve */
|
|
1696
|
+
off() {
|
|
1697
|
+
return this;
|
|
1698
|
+
},
|
|
1699
|
+
/* v8 ignore next -- @preserve */
|
|
1700
|
+
removeAllListeners() {
|
|
1701
|
+
return this;
|
|
943
1702
|
}
|
|
944
1703
|
});
|
|
945
1704
|
export {
|
|
946
1705
|
IoDbNameMapping,
|
|
947
1706
|
IoMem,
|
|
1707
|
+
IoMulti,
|
|
1708
|
+
IoPeer,
|
|
1709
|
+
IoPeerBridge,
|
|
1710
|
+
IoServer,
|
|
948
1711
|
IoTools,
|
|
949
1712
|
PeerSocketMock,
|
|
950
1713
|
SocketMock,
|
|
@@ -953,4 +1716,4 @@ export {
|
|
|
953
1716
|
exampleTestSetup,
|
|
954
1717
|
socketExample
|
|
955
1718
|
};
|
|
956
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW8uanMiLCJzb3VyY2VzIjpbIi4uL3NyYy9pby1kYi1uYW1lLW1hcHBpbmcudHMiLCIuLi9zcmMvaW8tdG9vbHMudHMiLCIuLi9zcmMvaW8tbWVtLnRzIiwiLi4vc3JjL2lvLXRlc3Qtc2V0dXAudHMiLCIuLi9zcmMvaW8udHMiLCIuLi9zcmMvcGVlci1zb2NrZXQtbW9jay50cyIsIi4uL3NyYy9yZXZlcnNlLXJlZi50cyIsIi4uL3NyYy9zb2NrZXQtbW9jay50cyIsIi4uL3NyYy9zb2NrZXQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gQGxpY2Vuc2Vcbi8vIENvcHlyaWdodCAoYykgMjAyNSBSbGpzb25cbi8vXG4vLyBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSB0ZXJtcyB0aGF0IGNhbiBiZVxuLy8gZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBvZiB0aGlzIHBhY2thZ2UuXG5cbmV4cG9ydCBjbGFzcyBJb0RiTmFtZU1hcHBpbmcge1xuICAvLyBUaGUgcHJpbWFyeSBrZXkgY29sdW1uIGlzIGFsd2F5cyBuYW1lZCAnX2hhc2gnXG4gIHB1YmxpYyBwcmltYXJ5S2V5Q29sdW1uOiBzdHJpbmcgPSAnX2hhc2gnO1xuICBwdWJsaWMgZGF0YVNlY3Rpb246IHN0cmluZyA9ICdfZGF0YSc7XG4gIHB1YmxpYyB0eXBlQ29sdW1uOiBzdHJpbmcgPSAndHlwZSc7XG4gIHB1YmxpYyBrZXlDb2x1bW46IHN0cmluZyA9ICdrZXknO1xuXG4gIC8vIE5hbWVzIGZvciB0aGUgbWFpbiB0YWJsZXMgaW4gdGhlIGRhdGFiYXNlXG4gIHB1YmxpYyB0YWJsZU5hbWVzOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0ge1xuICAgIG1haW46ICd0YWJsZUNmZ3MnLFxuICAgIHJldmlzaW9uOiAncmV2aXNpb25zJyxcbiAgfTtcblxuICAvLy8gU3VmZml4IGhhbmRsaW5nIGZvciB0aGUgZGF0YWJhc2VcbiAgcHJpdmF0ZSBfc3VmZml4OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0ge1xuICAgIGNvbDogJ19jb2wnLFxuICAgIHRibDogJ190YmwnLFxuICAgIHRtcDogJ190bXAnLFxuICB9O1xuXG4gIC8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gIC8vIGFkZCBhbmQgcmVtb3ZlIHN1ZmZpeGVzIGZvciB1c2UgaW4gU1FMIHN0YXRlbWVudHNcbiAgcHJpdmF0ZSBfYWRkRml4KG5hbWU6IHN0cmluZywgZml4OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBuYW1lLmVuZHNXaXRoKGZpeCkgPyBuYW1lIDogbmFtZSArIGZpeDtcbiAgfVxuXG4gIHB1YmxpYyBhZGRUYWJsZVN1ZmZpeChuYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLl9hZGRGaXgobmFtZSwgdGhpcy5fc3VmZml4LnRibCk7XG4gIH1cblxuICBwdWJsaWMgYWRkQ29sdW1uU3VmZml4KG5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX2FkZEZpeChuYW1lLCB0aGlzLl9zdWZmaXguY29sKTtcbiAgfVxuXG4gIHB1YmxpYyBhZGRUbXBTdWZmaXgobmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5fYWRkRml4KG5hbWUsIHRoaXMuX3N1ZmZpeC50bXApO1xuICB9XG5cbiAgcHJpdmF0ZSBfcmVtb3ZlRml4KG5hbWU6IHN0cmluZywgZml4OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBuYW1lLmVuZHNXaXRoKGZpeCkgPyBuYW1lLnNsaWNlKDAsIC1maXgubGVuZ3RoKSA6IG5hbWU7XG4gIH1cblxuICBwdWJsaWMgcmVtb3ZlVGFibGVTdWZmaXgobmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5fcmVtb3ZlRml4KG5hbWUsIHRoaXMuX3N1ZmZpeC50YmwpO1xuICB9XG5cbiAgcHVibGljIHJlbW92ZUNvbHVtblN1ZmZpeChuYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLl9yZW1vdmVGaXgobmFtZSwgdGhpcy5fc3VmZml4LmNvbCk7XG4gIH1cblxuICBwdWJsaWMgcmVtb3ZlVG1wU3VmZml4KG5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX3JlbW92ZUZpeChuYW1lLCB0aGlzLl9zdWZmaXgudG1wKTtcbiAgfVxufVxuIiwiLy8gQGxpY2Vuc2Vcbi8vIENvcHlyaWdodCAoYykgMjAyNSBSbGpzb25cbi8vXG4vLyBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSB0ZXJtcyB0aGF0IGNhbiBiZVxuLy8gZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBvZiB0aGlzIHBhY2thZ2UuXG5cbmltcG9ydCB7IGhpcCB9IGZyb20gJ0BybGpzb24vaGFzaCc7XG5pbXBvcnQge1xuICBpdGVyYXRlVGFibGVzLFxuICBSbGpzb24sXG4gIFRhYmxlQ2ZnLFxuICBUYWJsZUtleSxcbiAgVGFibGVUeXBlLFxuICB0aHJvd09uSW52YWxpZFRhYmxlQ2ZnLFxuICB2YWxpZGF0ZVJsanNvbkFnYWluc3RUYWJsZUNmZyxcbn0gZnJvbSAnQHJsanNvbi9ybGpzb24nO1xuXG5pbXBvcnQgeyBJb01lbSB9IGZyb20gJy4vaW8tbWVtLnRzJztcbmltcG9ydCB7IElvIH0gZnJvbSAnLi9pby50cyc7XG5cbmV4cG9ydCB0eXBlIElvT2JzZXJ2ZXIgPSAoZGF0YTogUmxqc29uKSA9PiB2b2lkO1xuXG4vKipcbiAqIFByb3ZpZGVzIHV0aWxpdHkgZnVuY3Rpb25zIGZvciB0aGUgSW8gaW50ZXJmYWNlLlxuICovXG5leHBvcnQgY2xhc3MgSW9Ub29scyB7XG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RvclxuICAgKiBAcGFyYW0gaW8gVGhlIElvIGludGVyZmFjZSB0byB1c2VcbiAgICovXG4gIGNvbnN0cnVjdG9yKHB1YmxpYyByZWFkb25seSBpbzogSW8pIHt9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHRhYmxlIGNvbmZpZ3VyYXRpb24gb2YgdGhlIHRhYmxlQ2ZncyB0YWJsZS5cbiAgICovXG4gIHN0YXRpYyBnZXQgdGFibGVDZmdzVGFibGVDZmcoKSB7XG4gICAgY29uc3QgdGFibGVDZmcgPSBoaXA8VGFibGVDZmc+KHtcbiAgICAgIF9oYXNoOiAnJyxcbiAgICAgIGtleTogJ3RhYmxlQ2ZncycsXG4gICAgICB0eXBlOiAndGFibGVDZmdzJyxcbiAgICAgIGlzSGVhZDogZmFsc2UsXG4gICAgICBpc1Jvb3Q6IGZhbHNlLFxuICAgICAgaXNTaGFyZWQ6IHRydWUsXG4gICAgICBwcmV2aW91czogJycsXG5cbiAgICAgIGNvbHVtbnM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGtleTogJ19oYXNoJyxcbiAgICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICB0aXRsZVNob3J0OiAnSGFzaCcsXG4gICAgICAgICAgdGl0bGVMb25nOiAnUm93IEhhc2gnLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAga2V5OiAna2V5JyxcbiAgICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICB0aXRsZVNob3J0OiAnS2V5JyxcbiAgICAgICAgICB0aXRsZUxvbmc6ICdUYWJsZSBLZXknLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAga2V5OiAndHlwZScsXG4gICAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgdGl0bGVTaG9ydDogJ1R5cGUnLFxuICAgICAgICAgIHRpdGxlTG9uZzogJ0NvbnRlbnQgVHlwZScsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBrZXk6ICdpc0hlYWQnLFxuICAgICAgICAgIHR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgICB0aXRsZVNob3J0OiAnSXMgSGVhZCcsXG4gICAgICAgICAgdGl0bGVMb25nOiAnSXMgSGVhZCBUYWJsZScsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBrZXk6ICdpc1Jvb3QnLFxuICAgICAgICAgIHR5cGU6ICdib29sZWFuJyxcbiAgICAgICAgICB0aXRsZVNob3J0OiAnSXMgUm9vdCcsXG4gICAgICAgICAgdGl0bGVMb25nOiAnSXMgUm9vdCBUYWJsZScsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBrZXk6ICdpc1NoYXJlZCcsXG4gICAgICAgICAgdHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICAgIHRpdGxlU2hvcnQ6ICdJcyBTaGFyZWQnLFxuICAgICAgICAgIHRpdGxlTG9uZzogJ0lzIFNoYXJlZCBUYWJsZScsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBrZXk6ICdwcmV2aW91cycsXG4gICAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgdGl0bGVTaG9ydDogJ1ByZXZpb3VzJyxcbiAgICAgICAgICB0aXRsZUxvbmc6ICdQcmV2aW91cyBUYWJsZSBDb25maWd1cmF0aW9uIEhhc2gnLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAga2V5OiAnY29sdW1ucycsXG4gICAgICAgICAgdHlwZTogJ2pzb25BcnJheScsXG4gICAgICAgICAgdGl0bGVTaG9ydDogJ0NvbHVtbnMnLFxuICAgICAgICAgIHRpdGxlTG9uZzogJ0NvbHVtbiBDb25maWd1cmF0aW9ucycsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHRhYmxlQ2ZnO1xuICB9XG5cbiAgLyoqXG4gICAqIEluaXRpYWxpemVzIHRoZSByZXZpc2lvbnMgdGFibGUuXG4gICAqL1xuICBpbml0UmV2aXNpb25zVGFibGUgPSBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgdGFibGVDZmc6IFRhYmxlQ2ZnID0ge1xuICAgICAga2V5OiAncmV2aXNpb25zJyxcbiAgICAgIHR5cGU6ICdyZXZpc2lvbnMnLFxuICAgICAgaXNIZWFkOiB0cnVlLFxuICAgICAgaXNSb290OiB0cnVlLFxuICAgICAgaXNTaGFyZWQ6IGZhbHNlLFxuXG4gICAgICBjb2x1bW5zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBrZXk6ICdfaGFzaCcsXG4gICAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgdGl0bGVTaG9ydDogJ0hhc2gnLFxuICAgICAgICAgIHRpdGxlTG9uZzogJ1JvdyBIYXNoJyxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGtleTogJ3RhYmxlJyxcbiAgICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICB0aXRsZVNob3J0OiAnVGFibGUnLFxuICAgICAgICAgIHRpdGxlTG9uZzogJ1RhYmxlIEtleScsXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBrZXk6ICdwcmVkZWNlc3NvcicsXG4gICAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgdGl0bGVTaG9ydDogJ1ByZWRlY2Vzc29yJyxcbiAgICAgICAgICB0aXRsZUxvbmc6ICdQcmVkZWNlc3NvciBSZXZpc2lvbiBIYXNoJyxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGtleTogJ3N1Y2Nlc3NvcicsXG4gICAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgdGl0bGVTaG9ydDogJ1N1Y2Nlc3NvcicsXG4gICAgICAgICAgdGl0bGVMb25nOiAnU3VjY2Vzc29yIFJldmlzaW9uIEhhc2gnLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAga2V5OiAndGltZXN0YW1wJyxcbiAgICAgICAgICB0eXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICB0aXRsZVNob3J0OiAnVGltZXN0YW1wJyxcbiAgICAgICAgICB0aXRsZUxvbmc6ICdSZXZpc2lvbiBUaW1lc3RhbXAnLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAga2V5OiAnaWQnLFxuICAgICAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgIHRpdGxlU2hvcnQ6ICdJRCcsXG4gICAgICAgICAgdGl0bGVMb25nOiAnUmV2aXNpb24gSUQnLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9O1xuXG4gICAgYXdhaXQgdGhpcy5pby5jcmVhdGVPckV4dGVuZFRhYmxlKHsgdGFibGVDZmcgfSk7XG4gIH07XG5cbiAgLyoqXG4gICAqIEV4YW1wbGUgb2JqZWN0IGZvciB0ZXN0IHB1cnBvc2VzXG4gICAqIEByZXR1cm5zIEFuIGluc3RhbmNlIG9mIGlvIHRvb2xzXG4gICAqL1xuICBzdGF0aWMgZXhhbXBsZSA9IGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBpbyA9IGF3YWl0IElvTWVtLmV4YW1wbGUoKTtcbiAgICBhd2FpdCBpby5pbml0KCk7XG4gICAgYXdhaXQgaW8uaXNSZWFkeSgpO1xuICAgIHJldHVybiBuZXcgSW9Ub29scyhpbyk7XG4gIH07XG5cbiAgLyoqXG4gICAqIFRocm93cyBpZiB0aGUgdGFibGUgZG9lcyBub3QgZXhpc3RcbiAgICovXG4gIGFzeW5jIHRocm93V2hlblRhYmxlRG9lc05vdEV4aXN0KHRhYmxlOiBUYWJsZUtleSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGV4aXN0cyA9IGF3YWl0IHRoaXMuaW8udGFibGVFeGlzdHModGFibGUpO1xuICAgIGlmICghZXhpc3RzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRhYmxlIFwiJHt0YWJsZX1cIiBub3QgZm91bmRgKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVGhyb3dzIGlmIGFueSBvZiB0aGUgdGFibGVzIGluIHJsanNvbiBkbyBub3QgZXhpc3RcbiAgICogQHBhcmFtIHJsanNvbiAtIFRoZSBSbGpzb24gb2JqZWN0IHRvIGNoZWNrXG4gICAqL1xuICBhc3luYyB0aHJvd1doZW5UYWJsZXNEb05vdEV4aXN0KHJsanNvbjogUmxqc29uKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGl0ZXJhdGVUYWJsZXMocmxqc29uLCBhc3luYyAodGFibGVLZXkpID0+IHtcbiAgICAgICAgY29uc3QgZXhpc3RzID0gYXdhaXQgdGhpcy5pby50YWJsZUV4aXN0cyh0YWJsZUtleSk7XG4gICAgICAgIGlmICghZXhpc3RzKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUYWJsZSBcIiR7dGFibGVLZXl9XCIgbm90IGZvdW5kYCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGNvbnN0IG1pc3NpbmdUYWJsZXMgPSAoZSBhcyBBcnJheTxhbnk+KS5tYXAoKGUpID0+IGUudGFibGVLZXkpO1xuXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBUaGUgZm9sbG93aW5nIHRhYmxlcyBkbyBub3QgZXhpc3Q6ICR7bWlzc2luZ1RhYmxlcy5qb2luKCcsICcpfWAsXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IHRhYmxlIGNmZ3Mgb2YgYWxsIHRhYmxlc1xuICAgKiBAcmV0dXJucyBUaGUgdGFibGUgY29uZmlndXJhdGlvbiBvZiBhbGwgdGFibGVzXG4gICAqL1xuICBhc3luYyB0YWJsZUNmZ3MoKTogUHJvbWlzZTxUYWJsZUNmZ1tdPiB7XG4gICAgY29uc3QgdGFibGVzID0gYXdhaXQgdGhpcy5pby5yYXdUYWJsZUNmZ3MoKTtcblxuICAgIC8vIFRha2UgdGhlIGxhdGVzdCB2ZXJzaW9uIG9mIGVhY2ggdHlwZSBrZXlcbiAgICBjb25zdCBuZXdlc3RWZXJzaW9uOiBSZWNvcmQ8VGFibGVLZXksIFRhYmxlQ2ZnPiA9IHt9O1xuICAgIGZvciAobGV0IGkgPSB0YWJsZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIGNvbnN0IHRhYmxlID0gdGFibGVzW2ldO1xuICAgICAgY29uc3QgZXhpc3RpbmcgPSBuZXdlc3RWZXJzaW9uW3RhYmxlLmtleV07XG4gICAgICBpZiAoIWV4aXN0aW5nIHx8IGV4aXN0aW5nLmNvbHVtbnMubGVuZ3RoIDwgdGFibGUuY29sdW1ucy5sZW5ndGgpIHtcbiAgICAgICAgbmV3ZXN0VmVyc2lvblt0YWJsZS5rZXldID0gdGFibGU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gU29ydCB0aGUgdGFibGVzIGJ5IGtleVxuICAgIC8qIHY4IGlnbm9yZSBuZXh0IC0tIEBwcmVzZXJ2ZSAqL1xuICAgIGNvbnN0IHJlc3VsdERhdGEgPSBPYmplY3QudmFsdWVzKG5ld2VzdFZlcnNpb24pLnNvcnQoKGEsIGIpID0+IHtcbiAgICAgIGlmIChhLmtleSA8IGIua2V5KSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cbiAgICAgIGlmIChhLmtleSA+IGIua2V5KSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gMDtcbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0RGF0YTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbGlzdCB3aXRoIGFsbCB0YWJsZSBuYW1lc1xuICAgKi9cbiAgYXN5bmMgYWxsVGFibGVLZXlzKCk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICBjb25zdCByZXN1bHQgPSAoYXdhaXQgdGhpcy50YWJsZUNmZ3MoKSkubWFwKChlKSA9PiBlLmtleSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBjb25maWd1cmF0aW9uIG9mIGEgZ2l2ZW4gdGFibGVcbiAgICovXG4gIGFzeW5jIHRhYmxlQ2ZnKHRhYmxlOiBUYWJsZUtleSk6IFByb21pc2U8VGFibGVDZmc+IHtcbiAgICBjb25zdCB0YWJsZUNmZyA9IGF3YWl0IHRoaXMudGFibGVDZmdPck51bGwodGFibGUpO1xuICAgIGlmICghdGFibGVDZmcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVGFibGUgXCIke3RhYmxlfVwiIG5vdCBmb3VuZGApO1xuICAgIH1cblxuICAgIHJldHVybiB0YWJsZUNmZyE7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgY29uZmlndXJhdGlvbiBvZiBhIGdpdmVuIHRhYmxlIG9yIG51bGwgaWYgaXQgZG9lcyBub3QgZXhpc3QuXG5cbiAgICovXG4gIGFzeW5jIHRhYmxlQ2ZnT3JOdWxsKHRhYmxlOiBUYWJsZUtleSk6IFByb21pc2U8VGFibGVDZmcgfCBudWxsPiB7XG4gICAgY29uc3QgdGFibGVDZmdzID0gYXdhaXQgdGhpcy50YWJsZUNmZ3MoKTtcbiAgICBjb25zdCB0YWJsZUNmZyA9IHRhYmxlQ2Zncy5maW5kKChlKSA9PiBlLmtleSA9PT0gdGFibGUpO1xuICAgIHJldHVybiB0YWJsZUNmZyA/PyBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBsaXN0IG9mIGFsbCBjb2x1bW4gbmFtZXMgb2YgYSBnaXZlbiB0YWJsZVxuICAgKi9cbiAgYXN5bmMgYWxsQ29sdW1uS2V5cyh0YWJsZTogVGFibGVLZXkpOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgY29uc3QgdGFibGVDZmcgPSBhd2FpdCB0aGlzLnRhYmxlQ2ZnKHRhYmxlKTtcbiAgICBjb25zdCByZXN1bHQgPSB0YWJsZUNmZy5jb2x1bW5zLm1hcCgoY29sdW1uKSA9PiBjb2x1bW4ua2V5KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIFRocm93cyB3aGVuIGEgY29sdW1uIGRvZXMgbm90IGV4aXN0IGluIGEgZ2l2ZW4gdGFibGVcbiAgICogQHBhcmFtIHRhYmxlIC0gVGhlIHRhYmxlIHRvIGNoZWNrXG4gICAqIEBwYXJhbSBjb2x1bW5zIC0gVGhlIGNvbHVtbiB0byBjaGVja1xuICAgKi9cbiAgYXN5bmMgdGhyb3dXaGVuQ29sdW1uRG9lc05vdEV4aXN0KFxuICAgIHRhYmxlOiBUYWJsZUtleSxcbiAgICBjb2x1bW5zOiBzdHJpbmdbXSxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgdGFibGVDZmcgPSBhd2FpdCB0aGlzLnRhYmxlQ2ZnKHRhYmxlKTtcbiAgICBjb25zdCBjb2x1bW5LZXlzID0gdGFibGVDZmcuY29sdW1ucy5tYXAoKGNvbHVtbikgPT4gY29sdW1uLmtleSk7XG4gICAgY29uc3QgbWlzc2luZ0NvbHVtbnMgPSBjb2x1bW5zLmZpbHRlcihcbiAgICAgIChjb2x1bW4pID0+ICFjb2x1bW5LZXlzLmluY2x1ZGVzKGNvbHVtbiksXG4gICAgKTtcbiAgICBpZiAobWlzc2luZ0NvbHVtbnMubGVuZ3RoID4gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgVGhlIGZvbGxvd2luZyBjb2x1bW5zIGRvIG5vdCBleGlzdCBpbiB0YWJsZSBcIiR7dGFibGV9XCI6ICR7bWlzc2luZ0NvbHVtbnMuam9pbihcbiAgICAgICAgICAnLCAnLFxuICAgICAgICApfS5gLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVGhyb3dzIHdoZW4gYSB0YWJsZSB1cGRhdGUgaXMgbm90IGNvbXBhdGlibGUgd2l0aCB0aGUgY3VycmVudCB0YWJsZVxuICAgKiBjb25maWd1cmF0aW9uLlxuICAgKi9cbiAgYXN5bmMgdGhyb3dXaGVuVGFibGVJc05vdENvbXBhdGlibGUodXBkYXRlOiBUYWJsZUNmZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHByZWZpeCA9IGBJbnZhbGlkIHVwZGF0ZSBvZiB0YWJsZSBhYmxlIFwiJHt1cGRhdGUua2V5fVwiYDtcblxuICAgIHRocm93T25JbnZhbGlkVGFibGVDZmcodXBkYXRlKTtcblxuICAgIC8vIENoZWNrIGNvbXBhdGliaWxpdHkgd2l0aCBleGlzdGluZyB0YWJsZVxuICAgIGNvbnN0IGV4aXN0aW5nID0gYXdhaXQgdGhpcy50YWJsZUNmZ09yTnVsbCh1cGRhdGUua2V5KTtcbiAgICBpZiAoZXhpc3RpbmcpIHtcbiAgICAgIC8vIEhhdmUgY29sdW1ucyBiZWVuIGRlbGV0ZWQ/XG4gICAgICBpZiAoZXhpc3RpbmcuY29sdW1ucy5sZW5ndGggPiB1cGRhdGUuY29sdW1ucy5sZW5ndGgpIHtcbiAgICAgICAgY29uc3QgZGVsZXRlZENvbHVtbktleXMgPSBleGlzdGluZy5jb2x1bW5zXG4gICAgICAgICAgLm1hcCgoY29sdW1uKSA9PiBjb2x1bW4ua2V5KVxuICAgICAgICAgIC5maWx0ZXIoXG4gICAgICAgICAgICAoa2V5KSA9PiAhdXBkYXRlLmNvbHVtbnMuc29tZSgoY29sdW1uKSA9PiBjb2x1bW4ua2V5ID09PSBrZXkpLFxuICAgICAgICAgICk7XG4gICAgICAgIC8qIHY4IGlnbm9yZSBuZXh0IC0tIEBwcmVzZXJ2ZSAqL1xuICAgICAgICBpZiAoZGVsZXRlZENvbHVtbktleXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGNvbnN0IGRlbGV0ZWRDb2x1bW5zID0gZGVsZXRlZENvbHVtbktleXMuam9pbignLCAnKTtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgJHtwcmVmaXh9OiBDb2x1bW5zIG11c3Qgbm90IGJlIGRlbGV0ZWQuIGAgK1xuICAgICAgICAgICAgICBgRGVsZXRlZCBjb2x1bW5zOiAke2RlbGV0ZWRDb2x1bW5zfX1gLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gSGF2ZSBjb2x1bW4ga2V5cyBjaGFuZ2VkP1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBleGlzdGluZy5jb2x1bW5zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGJlZm9yZSA9IGV4aXN0aW5nLmNvbHVtbnNbaV0ua2V5O1xuICAgICAgICBjb25zdCBhZnRlciA9IHVwZGF0ZS5jb2x1bW5zW2ldLmtleTtcbiAgICAgICAgaWYgKGJlZm9yZSAhPT0gYWZ0ZXIpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgJHtwcmVmaXh9OiBgICtcbiAgICAgICAgICAgICAgYENvbHVtbiBrZXlzIG11c3Qgbm90IGNoYW5nZSEgYCArXG4gICAgICAgICAgICAgIGBDb2x1bW4gXCIke2JlZm9yZX1cIiB3YXMgcmVuYW1lZCBpbnRvIFwiJHthZnRlcn1cIi5gLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gSGF2ZSBjb2x1bW4gdHlwZXMgY2hhbmdlZD9cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZXhpc3RpbmcuY29sdW1ucy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBjb2x1bW4gPSBleGlzdGluZy5jb2x1bW5zW2ldLmtleTtcbiAgICAgICAgY29uc3QgYmVmb3JlID0gZXhpc3RpbmcuY29sdW1uc1tpXS50eXBlO1xuICAgICAgICBjb25zdCBhZnRlciA9IHVwZGF0ZS5jb2x1bW5zW2ldLnR5cGU7XG4gICAgICAgIGlmIChiZWZvcmUgIT09IGFmdGVyKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYCR7cHJlZml4fTogYCArXG4gICAgICAgICAgICAgIGBDb2x1bW4gdHlwZXMgbXVzdCBub3QgY2hhbmdlISBgICtcbiAgICAgICAgICAgICAgYFR5cGUgb2YgY29sdW1uIFwiJHtjb2x1bW59XCIgd2FzIGNoYW5nZWQgZnJvbSBcIiR7YmVmb3JlfVwiIHRvICR7YWZ0ZXJ9LmAsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUaHJvd3MgaWYgdGhlIGRhdGEgaW4gdGhlIHRhYmxlIGRvIG5vdCBtYXRjaCB0aGUgdGFibGUgY29uZmlndXJhdGlvblxuICAgKi9cbiAgYXN5bmMgdGhyb3dXaGVuVGFibGVEYXRhRG9lc05vdE1hdGNoQ2ZnKGRhdGE6IFJsanNvbikge1xuICAgIGNvbnN0IGVycm9yczogc3RyaW5nW10gPSBbXTtcblxuICAgIGF3YWl0IGl0ZXJhdGVUYWJsZXMoZGF0YSwgYXN5bmMgKHRhYmxlS2V5KSA9PiB7XG4gICAgICBjb25zdCB0YWJsZUNmZyA9IGF3YWl0IHRoaXMudGFibGVDZmcodGFibGVLZXkpO1xuICAgICAgY29uc3QgdGFibGUgPSBkYXRhW3RhYmxlS2V5XTtcblxuICAgICAgLy8gSWdub3JlIHRhYmxlQ2ZncyB0YWJsZVxuICAgICAgLyogdjggaWdub3JlIG5leHQgLS0gQHByZXNlcnZlICovXG4gICAgICBpZiAodGFibGUuX3R5cGUgPT09ICd0YWJsZUNmZ3MnKSByZXR1cm47XG5cbiAgICAgIGVycm9ycy5wdXNoKC4uLnZhbGlkYXRlUmxqc29uQWdhaW5zdFRhYmxlQ2ZnKHRhYmxlLl9kYXRhLCB0YWJsZUNmZykpO1xuICAgIH0pO1xuXG4gICAgaWYgKGVycm9ycy5sZW5ndGggPiAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBUYWJsZSBkYXRhIGRvZXMgbm90IG1hdGNoIHRoZSBjb25maWd1cmF0aW9uLlxcblxcbkVycm9yczpcXG4ke2Vycm9yc1xuICAgICAgICAgIC5tYXAoKGUpID0+IGAtICR7ZX1gKVxuICAgICAgICAgIC5qb2luKCdcXG4nKX1gLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU29ydHMgdGhlIGRhdGEgb2YgYSB0YWJsZSBieSB0aGUgaGFzaCBhbmQgdXBkYXRlcyB0aGUgdGFibGUgaGFzaCBpbiBwbGFjZVxuICAgKi9cbiAgc29ydFRhYmxlRGF0YUFuZFVwZGF0ZUhhc2godGFibGU6IFRhYmxlVHlwZSk6IHZvaWQge1xuICAgIHRhYmxlLl9kYXRhLnNvcnQoKGEsIGIpID0+IHtcbiAgICAgIGNvbnN0IGhhc2hBID0gYS5faGFzaCBhcyBzdHJpbmc7XG4gICAgICBjb25zdCBoYXNoQiA9IGIuX2hhc2ggYXMgc3RyaW5nO1xuICAgICAgLyogdjggaWdub3JlIG5leHQgLS0gQHByZXNlcnZlICovXG4gICAgICBpZiAoaGFzaEEgPCBoYXNoQikge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG4gICAgICAvKiB2OCBpZ25vcmUgbmV4dCAtLSBAcHJlc2VydmUgKi9cbiAgICAgIGlmIChoYXNoQSA+IGhhc2hCKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuXG4gICAgICAvKiB2OCBpZ25vcmUgbmV4dCAtLSBAcHJlc2VydmUgKi9cbiAgICAgIHJldHVybiAwO1xuICAgIH0pO1xuXG4gICAgdGFibGUuX2hhc2ggPSAnJztcbiAgICBoaXAodGFibGUsIHtcbiAgICAgIHVwZGF0ZUV4aXN0aW5nSGFzaGVzOiBmYWxzZSxcbiAgICAgIHRocm93T25Xcm9uZ0hhc2hlczogZmFsc2UsXG4gICAgfSk7XG4gIH1cbn1cbiIsIi8vIEBsaWNlbnNlXG4vLyBDb3B5cmlnaHQgKGMpIDIwMjUgUmxqc29uXG4vL1xuLy8gVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgdGVybXMgdGhhdCBjYW4gYmVcbi8vIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3Qgb2YgdGhpcyBwYWNrYWdlLlxuXG5pbXBvcnQgeyBoaXAsIGhzaCB9IGZyb20gJ0BybGpzb24vaGFzaCc7XG5pbXBvcnQgeyBJc1JlYWR5IH0gZnJvbSAnQHJsanNvbi9pcy1yZWFkeSc7XG5pbXBvcnQgeyBjb3B5LCBlcXVhbHMsIEpzb25WYWx1ZSB9IGZyb20gJ0BybGpzb24vanNvbic7XG5pbXBvcnQge1xuICBDb250ZW50VHlwZSxcbiAgaXRlcmF0ZVRhYmxlc1N5bmMsXG4gIFJsanNvbixcbiAgVGFibGVDZmcsXG4gIFRhYmxlS2V5LFxuICBUYWJsZVR5cGUsXG59IGZyb20gJ0BybGpzb24vcmxqc29uJztcblxuaW1wb3J0IHsgSW9Ub29scyB9IGZyb20gJy4vaW8tdG9vbHMudHMnO1xuaW1wb3J0IHsgSW8gfSBmcm9tICcuL2lvLnRzJztcblxuLyoqXG4gKiBJbi1NZW1vcnkgaW1wbGVtZW50YXRpb24gb2YgdGhlIFJsanNvbiBJbyBpbnRlcmZhY2UuXG4gKi9cbmV4cG9ydCBjbGFzcyBJb01lbSBpbXBsZW1lbnRzIElvIHtcbiAgLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG4gIC8vIENvbnN0cnVjdG9yICYgZXhhbXBsZVxuXG4gIGluaXQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5faXNPcGVuID0gdHJ1ZTtcbiAgICByZXR1cm4gdGhpcy5faW5pdCgpO1xuICB9XG5cbiAgY2xvc2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5faXNPcGVuID0gZmFsc2U7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG5cbiAgZ2V0IGlzT3BlbigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5faXNPcGVuO1xuICB9XG5cbiAgc3RhdGljIGV4YW1wbGUgPSBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgaW8gPSBuZXcgSW9NZW0oKTtcbiAgICBhd2FpdCBpby5pbml0KCk7XG4gICAgcmV0dXJuIGlvO1xuICB9O1xuXG4gIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLlxuICAvLyBHZW5lcmFsXG4gIGlzUmVhZHkoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2lzUmVhZHkucHJvbWlzZTtcbiAgfVxuXG4gIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLlxuICAvLyBEdW1wXG5cbiAgZHVtcCgpOiBQcm9taXNlPFJsanNvbj4ge1xuICAgIHJldHVybiB0aGlzLl9kdW1wKCk7XG4gIH1cblxuICBhc3luYyBkdW1wVGFibGUocmVxdWVzdDogeyB0YWJsZTogc3RyaW5nIH0pOiBQcm9taXNlPFJsanNvbj4ge1xuICAgIHJldHVybiB0aGlzLl9kdW1wVGFibGUocmVxdWVzdCk7XG4gIH1cblxuICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbiAgLy8gTWV0YSBEYXRhXG5cbiAgYXN5bmMgY29udGVudFR5cGUocmVxdWVzdDogeyB0YWJsZTogc3RyaW5nIH0pOiBQcm9taXNlPENvbnRlbnRUeXBlPiB7XG4gICAgcmV0dXJuIHRoaXMuX2NvbnRlbnRUeXBlKHJlcXVlc3QpO1xuICB9XG5cbiAgLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG4gIC8vIFJvd3NcblxuICByZWFkUm93cyhyZXF1ZXN0OiB7XG4gICAgdGFibGU6IHN0cmluZztcbiAgICB3aGVyZTogeyBbY29sdW1uOiBzdHJpbmddOiBKc29uVmFsdWUgfTtcbiAgfSk6IFByb21pc2U8Umxqc29uPiB7XG4gICAgcmV0dXJuIHRoaXMuX3JlYWRSb3dzKHJlcXVlc3QpO1xuICB9XG5cbiAgYXN5bmMgcm93Q291bnQodGFibGU6IHN0cmluZyk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgY29uc3QgdGFibGVEYXRhID0gdGhpcy5fbWVtW3RhYmxlXSBhcyBUYWJsZVR5cGU7XG4gICAgaWYgKCF0YWJsZURhdGEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVGFibGUgXCIke3RhYmxlfVwiIG5vdCBmb3VuZGApO1xuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRhYmxlRGF0YS5fZGF0YS5sZW5ndGgpO1xuICB9XG5cbiAgLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG4gIC8vIFdyaXRlXG5cbiAgd3JpdGUocmVxdWVzdDogeyBkYXRhOiBSbGpzb24gfSk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLl93cml0ZShyZXF1ZXN0KTtcbiAgfVxuXG4gIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLlxuICAvLyBUYWJsZSBtYW5hZ2VtZW50XG4gIGFzeW5jIHRhYmxlRXhpc3RzKHRhYmxlS2V5OiBUYWJsZUtleSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IHRhYmxlID0gdGhpcy5fbWVtW3RhYmxlS2V5XSBhcyBUYWJsZVR5cGU7XG4gICAgcmV0dXJuIHRhYmxlID8gdHJ1ZSA6IGZhbHNlO1xuICB9XG5cbiAgY3JlYXRlT3JFeHRlbmRUYWJsZShyZXF1ZXN0OiB7IHRhYmxlQ2ZnOiBUYWJsZUNmZyB9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMuX2NyZWF0ZU9yRXh0ZW5kVGFibGUocmVxdWVzdCk7XG4gIH1cblxuICBhc3luYyByYXdUYWJsZUNmZ3MoKTogUHJvbWlzZTxUYWJsZUNmZ1tdPiB7XG4gICAgY29uc3QgdGFibGVzID0gdGhpcy5fbWVtLnRhYmxlQ2Zncy5fZGF0YSBhcyBUYWJsZUNmZ1tdO1xuICAgIHJldHVybiB0YWJsZXM7XG4gIH1cblxuICAvLyAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjXG4gIC8vIFByaXZhdGVcbiAgLy8gIyMjIyMjIyMjIyMjIyMjIyMjIyMjI1xuXG4gIHByaXZhdGUgX2lvVG9vbHMhOiBJb1Rvb2xzO1xuXG4gIHByaXZhdGUgX2lzUmVhZHkgPSBuZXcgSXNSZWFkeSgpO1xuICBwcml2YXRlIF9pc09wZW4gPSBmYWxzZTtcblxuICBwcml2YXRlIF9tZW06IFJsanNvbiA9IGhpcCh7fSBhcyBSbGpzb24pO1xuXG4gIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLlxuICBwcml2YXRlIGFzeW5jIF9pbml0KCkge1xuICAgIHRoaXMuX2lvVG9vbHMgPSBuZXcgSW9Ub29scyh0aGlzKTtcbiAgICB0aGlzLl9pbml0VGFibGVDZmdzKCk7XG4gICAgdGhpcy5fdXBkYXRlR2xvYmFsSGFzaCgpO1xuICAgIGF3YWl0IHRoaXMuX2lvVG9vbHMuaW5pdFJldmlzaW9uc1RhYmxlKCk7XG4gICAgaHNoKHRoaXMuX21lbSk7XG5cbiAgICB0aGlzLl9pc1JlYWR5LnJlc29sdmUoKTtcbiAgfVxuXG4gIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLlxuICBwcml2YXRlIF9pbml0VGFibGVDZmdzID0gKCkgPT4ge1xuICAgIGNvbnN0IHRhYmxlQ2ZnID0gSW9Ub29scy50YWJsZUNmZ3NUYWJsZUNmZztcblxuICAgIHRoaXMuX21lbS50YWJsZUNmZ3MgPSBoaXAoe1xuICAgICAgX3R5cGU6ICd0YWJsZUNmZ3MnLFxuICAgICAgX2RhdGE6IFt0YWJsZUNmZ10sXG4gICAgICBfdGFibGVDZmc6IHRhYmxlQ2ZnLl9oYXNoIGFzIHN0cmluZyxcbiAgICB9KTtcbiAgfTtcblxuICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbiAgcHJpdmF0ZSBfdXBkYXRlR2xvYmFsSGFzaCgpIHtcbiAgICAodGhpcy5fbWVtIGFzIGFueSkuX2hhc2ggPSAnJztcbiAgICBoaXAodGhpcy5fbWVtLCB7XG4gICAgICB1cGRhdGVFeGlzdGluZ0hhc2hlczogZmFsc2UsXG4gICAgfSk7XG4gIH1cblxuICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbiAgcHJpdmF0ZSBfdXBkYXRlVGFibGVIYXNoKHRhYmxlS2V5OiBUYWJsZUtleSkge1xuICAgIGNvbnN0IHRhYmxlID0gdGhpcy5fbWVtW3RhYmxlS2V5XSBhcyBUYWJsZVR5cGU7XG4gICAgdGFibGUuX2hhc2ggPSAnJztcbiAgICBoaXAodGFibGUsIHsgdXBkYXRlRXhpc3RpbmdIYXNoZXM6IGZhbHNlIH0pO1xuICB9XG5cbiAgLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG4gIHByaXZhdGUgYXN5bmMgX2NyZWF0ZU9yRXh0ZW5kVGFibGUocmVxdWVzdDoge1xuICAgIHRhYmxlQ2ZnOiBUYWJsZUNmZztcbiAgfSk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIE1ha2Ugc3VyZSB0aGF0IHRoZSB0YWJsZSBjb25maWcgaXMgY29tcGF0aWJsZVxuICAgIC8vIHdpdGggYW4gcG90ZW50aWFsIGV4aXN0aW5nIHRhYmxlXG4gICAgY29uc3QgdGFibGVDZmcgPSByZXF1ZXN0LnRhYmxlQ2ZnO1xuICAgIGF3YWl0IHRoaXMuX2lvVG9vbHMudGhyb3dXaGVuVGFibGVJc05vdENvbXBhdGlibGUodGFibGVDZmcpO1xuXG4gICAgY29uc3QgeyBrZXkgfSA9IHRhYmxlQ2ZnO1xuXG4gICAgLy8gUmVjcmVhdGUgaGFzaGVzIGluIHRoZSBjYXNlIHRoZSBleGlzdGluZyBoYXNoZXMgYXJlIHdyb25nXG4gICAgY29uc3QgbmV3Q29uZmlnID0gaHNoKHRhYmxlQ2ZnKTtcblxuICAgIC8vIEZpbmQgYW4gZXhpc3RpbmcgdGFibGUgY29uZmlnIHdpdGggdGhlIHNhbWUgaGFzaFxuICAgIGNvbnN0IGV4aXN0aW5nQ29uZmlnID0gYXdhaXQgdGhpcy5faW9Ub29scy50YWJsZUNmZ09yTnVsbChrZXkpO1xuXG4gICAgLy8gV3JpdGUgdGhlIG5ldyBjb25maWcgaW50byB0aGUgZGF0YWJhc2VcbiAgICBpZiAoIWV4aXN0aW5nQ29uZmlnKSB7XG4gICAgICB0aGlzLl9jcmVhdGVUYWJsZShuZXdDb25maWcsIGtleSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX2V4dGVuZFRhYmxlKGV4aXN0aW5nQ29uZmlnLCBuZXdDb25maWcpO1xuICAgIH1cbiAgfVxuXG4gIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLlxuICBwcml2YXRlIF9jcmVhdGVUYWJsZShuZXdDb25maWc6IFRhYmxlQ2ZnLCB0YWJsZUtleTogVGFibGVLZXkpIHtcbiAgICAvLyBXcml0ZSB0aGUgdGFibGUgY29uZmlnIGludG8gdGhlIGRhdGFiYXNlXG4gICAgbmV3Q29uZmlnID0gaHNoKG5ld0NvbmZpZyk7XG4gICAgdGhpcy5fbWVtLnRhYmxlQ2Zncy5fZGF0YS5wdXNoKG5ld0NvbmZpZyk7XG4gICAgdGhpcy5faW9Ub29scy5zb3J0VGFibGVEYXRhQW5kVXBkYXRlSGFzaCh0aGlzLl9tZW0udGFibGVDZmdzKTtcblxuICAgIC8vIENyZWF0ZSBhIHRhYmxlIGFuZCB3cml0ZSBpdCBpbnRvIHRoZSBkYXRhYmFzZVxuICAgIGNvbnN0IHRhYmxlOiBUYWJsZVR5cGUgPSB7XG4gICAgICBfdHlwZTogbmV3Q29uZmlnLnR5cGUsXG4gICAgICBfZGF0YTogW10sXG4gICAgICBfdGFibGVDZmc6IG5ld0NvbmZpZy5faGFzaCBhcyBzdHJpbmcsXG4gICAgfTtcblxuICAgIHRoaXMuX21lbVt0YWJsZUtleV0gPz89IGhpcCh0YWJsZSk7XG5cbiAgICAvLyBVcGRhdGUgaGFzaGVzXG4gICAgdGhpcy5fdXBkYXRlVGFibGVIYXNoKHRhYmxlS2V5KTtcbiAgICB0aGlzLl91cGRhdGVHbG9iYWxIYXNoKCk7XG4gIH1cblxuICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbiAgcHJpdmF0ZSBfZXh0ZW5kVGFibGUoZXhpc3RpbmdDb25maWc6IFRhYmxlQ2ZnLCBuZXdDb25maWc6IFRhYmxlQ2ZnKSB7XG4gICAgLy8gTm8gY29sdW1ucyBhZGRlZD8gUmV0dXJuLlxuICAgIGlmIChleGlzdGluZ0NvbmZpZy5jb2x1bW5zLmxlbmd0aCA9PT0gbmV3Q29uZmlnLmNvbHVtbnMubGVuZ3RoKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gV3JpdGUgdGhlIG5ldyB0YWJsZSBjb25maWcgaW50byB0aGUgZGF0YWJhc2VcbiAgICBuZXdDb25maWcgPSBoc2gobmV3Q29uZmlnKTtcbiAgICB0aGlzLl9tZW0udGFibGVDZmdzLl9kYXRhLnB1c2gobmV3Q29uZmlnKTtcbiAgICB0aGlzLl9pb1Rvb2xzLnNvcnRUYWJsZURhdGFBbmRVcGRhdGVIYXNoKHRoaXMuX21lbS50YWJsZUNmZ3MpO1xuXG4gICAgLy8gVXBkYXRlIHRoZSBjb25maWcgb2YgdGhlIGV4aXN0aW5nIHRhYmxlXG4gICAgY29uc3QgdGFibGUgPSB0aGlzLl9tZW1bbmV3Q29uZmlnLmtleV0gYXMgVGFibGVUeXBlO1xuICAgIHRhYmxlLl90YWJsZUNmZyA9IG5ld0NvbmZpZy5faGFzaCBhcyBzdHJpbmc7XG5cbiAgICAvLyBVcGRhdGUgdGhlIGhhc2hlc1xuICAgIHRoaXMuX3VwZGF0ZVRhYmxlSGFzaChuZXdDb25maWcua2V5KTtcbiAgICB0aGlzLl91cGRhdGVHbG9iYWxIYXNoKCk7XG4gIH1cblxuICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cblxuICBwcml2YXRlIGFzeW5jIF9kdW1wKCk6IFByb21pc2U8Umxqc29uPiB7XG4gICAgcmV0dXJuIGNvcHkodGhpcy5fbWVtKTtcbiAgfVxuXG4gIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLlxuICBwcml2YXRlIGFzeW5jIF9kdW1wVGFibGUocmVxdWVzdDogeyB0YWJsZTogc3RyaW5nIH0pOiBQcm9taXNlPFJsanNvbj4ge1xuICAgIGF3YWl0IHRoaXMuX2lvVG9vbHMudGhyb3dXaGVuVGFibGVEb2VzTm90RXhpc3QocmVxdWVzdC50YWJsZSk7XG5cbiAgICBjb25zdCB0YWJsZSA9IHRoaXMuX21lbVtyZXF1ZXN0LnRhYmxlXSBhcyBUYWJsZVR5cGU7XG5cbiAgICByZXR1cm4ge1xuICAgICAgW3JlcXVlc3QudGFibGVdOiBjb3B5KHRhYmxlKSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG4gIHByaXZhdGUgYXN5bmMgX2NvbnRlbnRUeXBlKHJlcXVlc3Q6IHsgdGFibGU6IHN0cmluZyB9KTogUHJvbWlzZTxDb250ZW50VHlwZT4ge1xuICAgIGF3YWl0IHRoaXMuX2lvVG9vbHMudGhyb3dXaGVuVGFibGVEb2VzTm90RXhpc3QocmVxdWVzdC50YWJsZSk7XG5cbiAgICByZXR1cm4gKHRoaXMuX21lbVtyZXF1ZXN0LnRhYmxlXSBhcyBUYWJsZVR5cGUpLl90eXBlO1xuICB9XG5cbiAgLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG4gIHByaXZhdGUgYXN5bmMgX3dyaXRlKHJlcXVlc3Q6IHsgZGF0YTogUmxqc29uIH0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBhZGRlZERhdGEgPSBoc2gocmVxdWVzdC5kYXRhKTtcbiAgICB0aGlzLl9yZW1vdmVOdWxsVmFsdWVzKGFkZGVkRGF0YSk7XG4gICAgY29uc3QgdGFibGVzID0gT2JqZWN0LmtleXMoYWRkZWREYXRhKTtcbiAgICBoc2goYWRkZWREYXRhKTtcblxuICAgIGF3YWl0IHRoaXMuX2lvVG9vbHMudGhyb3dXaGVuVGFibGVzRG9Ob3RFeGlzdChyZXF1ZXN0LmRhdGEpO1xuICAgIGF3YWl0IHRoaXMuX2lvVG9vbHMudGhyb3dXaGVuVGFibGVEYXRhRG9lc05vdE1hdGNoQ2ZnKHJlcXVlc3QuZGF0YSk7XG5cbiAgICBmb3IgKGNvbnN0IHRhYmxlIG9mIHRhYmxlcykge1xuICAgICAgaWYgKHRhYmxlLnN0YXJ0c1dpdGgoJ18nKSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgb2xkVGFibGUgPSB0aGlzLl9tZW1bdGFibGVdIGFzIFRhYmxlVHlwZTtcbiAgICAgIGNvbnN0IG5ld1RhYmxlID0gYWRkZWREYXRhW3RhYmxlXSBhcyBUYWJsZVR5cGU7XG5cbiAgICAgIC8vIFRhYmxlIGV4aXN0cy4gTWVyZ2UgZGF0YVxuICAgICAgZm9yIChjb25zdCBpdGVtIG9mIG5ld1RhYmxlLl9kYXRhKSB7XG4gICAgICAgIGNvbnN0IGhhc2ggPSBpdGVtLl9oYXNoO1xuICAgICAgICBjb25zdCBleGlzdHMgPSBvbGRUYWJsZS5fZGF0YS5maW5kKChpKSA9PiBpLl9oYXNoID09PSBoYXNoKTtcbiAgICAgICAgaWYgKCFleGlzdHMpIHtcbiAgICAgICAgICBvbGRUYWJsZS5fZGF0YS5wdXNoKGl0ZW0gYXMgYW55KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB0aGlzLl9pb1Rvb2xzLnNvcnRUYWJsZURhdGFBbmRVcGRhdGVIYXNoKG9sZFRhYmxlKTtcbiAgICB9XG5cbiAgICAvLyBSZWNhbGMgbWFpbiBoYXNoZXNcbiAgICB0aGlzLl91cGRhdGVHbG9iYWxIYXNoKCk7XG4gIH1cblxuICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbiAgcHJpdmF0ZSBhc3luYyBfcmVhZFJvd3MocmVxdWVzdDoge1xuICAgIHRhYmxlOiBzdHJpbmc7XG4gICAgd2hlcmU6IHsgW2NvbHVtbjogc3RyaW5nXTogSnNvblZhbHVlIH07XG4gIH0pOiBQcm9taXNlPFJsanNvbj4ge1xuICAgIGF3YWl0IHRoaXMuX2lvVG9vbHMudGhyb3dXaGVuVGFibGVEb2VzTm90RXhpc3QocmVxdWVzdC50YWJsZSk7XG4gICAgYXdhaXQgdGhpcy5faW9Ub29scy50aHJvd1doZW5Db2x1bW5Eb2VzTm90RXhpc3QoXG4gICAgICByZXF1ZXN0LnRhYmxlLFxuICAgICAgT2JqZWN0LmtleXMocmVxdWVzdC53aGVyZSksXG4gICAgKTtcblxuICAgIC8vIFJlYWQgdGFibGUgZnJvbSBkYXRhXG4gICAgY29uc3QgdGFibGUgPSB0aGlzLl9tZW1bcmVxdWVzdC50YWJsZV0gYXMgVGFibGVUeXBlO1xuXG4gICAgLy8gRmlsdGVyIHRhYmxlIGRhdGFcbiAgICBjb25zdCB0YWJsZURhdGFGaWx0ZXJlZCA9IHRhYmxlLl9kYXRhLmZpbHRlcigocm93KSA9PiB7XG4gICAgICBmb3IgKGNvbnN0IGNvbHVtbiBpbiByZXF1ZXN0LndoZXJlKSB7XG4gICAgICAgIGNvbnN0IGEgPSByb3dbY29sdW1uXTtcbiAgICAgICAgY29uc3QgYiA9IHJlcXVlc3Qud2hlcmVbY29sdW1uXTtcbiAgICAgICAgaWYgKGIgPT09IG51bGwgJiYgYSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWVxdWFscyhhLCBiKSkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSk7XG5cbiAgICAvLyBDcmVhdGUgYW4gdGFibGVcbiAgICBjb25zdCB0YWJsZUZpbHRlcmVkOiBUYWJsZVR5cGUgPSB7XG4gICAgICBfdHlwZTogdGFibGUuX3R5cGUsXG4gICAgICBfZGF0YTogdGFibGVEYXRhRmlsdGVyZWQsXG4gICAgfTtcblxuICAgIHRoaXMuX2lvVG9vbHMuc29ydFRhYmxlRGF0YUFuZFVwZGF0ZUhhc2godGFibGVGaWx0ZXJlZCk7XG5cbiAgICBjb25zdCByZXN1bHQ6IFJsanNvbiA9IHtcbiAgICAgIFtyZXF1ZXN0LnRhYmxlXTogdGFibGVGaWx0ZXJlZCxcbiAgICB9O1xuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIF9yZW1vdmVOdWxsVmFsdWVzKHJsanNvbjogUmxqc29uKSB7XG4gICAgaXRlcmF0ZVRhYmxlc1N5bmMocmxqc29uLCAodGFibGUpID0+IHtcbiAgICAgIGNvbnN0IGRhdGEgPSBybGpzb25bdGFibGVdLl9kYXRhO1xuXG4gICAgICBmb3IgKGNvbnN0IHJvdyBvZiBkYXRhKSB7XG4gICAgICAgIGZvciAoY29uc3Qga2V5IGluIHJvdykge1xuICAgICAgICAgIGlmIChyb3dba2V5XSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgZGVsZXRlIHJvd1trZXldO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9XG59XG4iLCIvLyBAbGljZW5zZVxuLy8gQ29weXJpZ2h0IChjKSAyMDI1IFJsanNvblxuLy9cbi8vIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IHRlcm1zIHRoYXQgY2FuIGJlXG4vLyBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGluIHRoZSByb290IG9mIHRoaXMgcGFja2FnZS5cblxuaW1wb3J0IHsgSW8sIElvTWVtIH0gZnJvbSAnLi9pbmRleC50cyc7XG5cbi8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG4vKipcbiAqIElvIGltcGxlbWVudGF0aW9uIG5lZWQgdG8gaW1wbGVtZW50IHRoaXMgaW50ZXJmYWNlIHRvIGJlIHVzZWQgaW5cbiAqIGNvbmZvcm1hbmNlIHRlc3RzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIElvVGVzdFNldHVwIHtcbiAgLyoqIHNldHVwIGJlZm9yZSB0aGUgc2luZ2xlIHNldHVwcyAqL1xuICBiZWZvcmVBbGw6ICgpID0+IFByb21pc2U8dm9pZD47XG5cbiAgLyoqXG4gICAqIEluaXRpYWxpemVzIHRoZSBpbyBpbXBsZW1lbnRhdGlvbi5cbiAgICogQHJldHVybnMgVGhlIGlvIGltcGxlbWVudGF0aW9uLlxuICAgKi9cbiAgYmVmb3JlRWFjaDogKCkgPT4gUHJvbWlzZTx2b2lkPjtcblxuICAvKipcbiAgICogVGVhcnMgZG93biB0aGUgaW8gaW1wbGVtZW50YXRpb24uXG4gICAqIEByZXR1cm5zIFRoZSBpbyBpbXBsZW1lbnRhdGlvbi5cbiAgICovXG4gIGFmdGVyRWFjaDogKCkgPT4gUHJvbWlzZTx2b2lkPjtcblxuICAvKiogY2xlYW51cCBhZnRlciBhbGwgdGVzdHMgKi9cbiAgYWZ0ZXJBbGw6ICgpID0+IFByb21pc2U8dm9pZD47XG5cbiAgLyoqXG4gICAqIFRoZSBpbyBpbXBsZW1lbnRhdGlvbiB0byBiZSB1c2VkIGluIHRoZSBjb25mb3JtYW5jZSB0ZXN0cy5cbiAgICovXG4gIGlvOiBJbztcbn1cblxuLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbi8vIEV4YW1wbGUgaW1wbGVtZW50YXRpb24gb2YgdGhlIElvVGVzdFNldHVwIGludGVyZmFjZVxuZXhwb3J0IGNvbnN0IGV4YW1wbGVUZXN0U2V0dXAgPSAoKTogSW9UZXN0U2V0dXAgPT4ge1xuICByZXR1cm4ge1xuICAgIGlvOiBuZXcgSW9NZW0oKSxcbiAgICBiZWZvcmVBbGw6IGFzeW5jICgpID0+IHtcbiAgICAgIC8vIFRoaXMgbWV0aG9kIGNhbiBiZSB1c2VkIGZvciBhbnkgYWRkaXRpb25hbCBzZXR1cCByZXF1aXJlZCBiZWZvcmUgaW5pdC5cbiAgICAgIC8vIEN1cnJlbnRseSwgaXQgZG9lcyBub3RoaW5nLlxuICAgIH0sXG5cbiAgICBiZWZvcmVFYWNoOiBhc3luYyAoKSA9PiB7XG4gICAgICAvLyBJbml0aWFsaXplIHRoZSBpbyBpbXBsZW1lbnRhdGlvblxuICAgIH0sXG4gICAgYWZ0ZXJFYWNoOiBhc3luYyAoKSA9PiB7XG4gICAgICAvLyBUZWFyIGRvd24gdGhlIGlvIGltcGxlbWVudGF0aW9uXG4gICAgfSxcblxuICAgIGFmdGVyQWxsOiBhc3luYyAoKSA9PiB7XG4gICAgICAvLyBUaGlzIG1ldGhvZCBjYW4gYmUgdXNlZCBmb3IgYW55IGFkZGl0aW9uYWwgY2xlYW51cCBhZnRlciB0ZWFyRG93bi5cbiAgICB9LFxuICB9O1xufTtcbiIsIi8vIEBsaWNlbnNlXG4vLyBDb3B5cmlnaHQgKGMpIDIwMjUgUmxqc29uXG4vL1xuLy8gVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgdGVybXMgdGhhdCBjYW4gYmVcbi8vIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3Qgb2YgdGhpcyBwYWNrYWdlLlxuXG5pbXBvcnQgeyBKc29uVmFsdWUgfSBmcm9tICdAcmxqc29uL2pzb24nO1xuaW1wb3J0IHsgQ29udGVudFR5cGUsIFJsanNvbiwgVGFibGVDZmcsIFRhYmxlS2V5IH0gZnJvbSAnQHJsanNvbi9ybGpzb24nO1xuXG5cbi8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG5leHBvcnQgaW50ZXJmYWNlIElvIHtcbiAgLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG4gIC8vIEdlbmVyYWxcblxuICAvKiogU3RhcnRzIHRoZSBpbml0aWFsaXphdGlvbiAqL1xuICBpbml0KCk6IFByb21pc2U8dm9pZD47XG5cbiAgLyoqIENsb3NlcyB0aGUgaW8gKi9cbiAgY2xvc2UoKTogUHJvbWlzZTx2b2lkPjtcblxuICAvKiogUmV0dXJucyB0cnVlIGlmIGlvIGlzIG9wZW5lZCAqL1xuICBpc09wZW46IGJvb2xlYW47XG5cbiAgLyoqIEEgcHJvbWlzZSByZXNvbHZpbmcgb25jZSB0aGUgSW8gaW50ZXJmYWNlIGlzIHJlYWR5XG4gICAqXG4gICAqIPCfkqEgVXNlIEBybGpzb24vaXMtcmVhZHlcbiAgICovXG4gIGlzUmVhZHkoKTogUHJvbWlzZTx2b2lkPjtcblxuICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbiAgLy8gRHVtcFxuXG4gIC8qKiBSZXR1cm5zIHRoZSBjb21wbGV0ZSBkYiBjb250ZW50IGFzIFJsanNvbiAqL1xuICBkdW1wKCk6IFByb21pc2U8Umxqc29uPjtcblxuICAvKiogUmV0dXJucyB0aGUgZHVtcCBvZiBhIGNvbXBsZXRlIHRhYmxlICovXG4gIGR1bXBUYWJsZShyZXF1ZXN0OiB7IHRhYmxlOiBzdHJpbmcgfSk6IFByb21pc2U8Umxqc29uPjtcblxuICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbiAgLy8gTWV0YSBEYXRhXG4gIGNvbnRlbnRUeXBlKHJlcXVlc3Q6IHsgdGFibGU6IHN0cmluZyB9KTogUHJvbWlzZTxDb250ZW50VHlwZT47XG5cbiAgLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG4gIC8vIFRhYmxlc1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlIHRhYmxlIGV4aXN0c1xuICAgKi9cbiAgdGFibGVFeGlzdHModGFibGVLZXk6IFRhYmxlS2V5KTogUHJvbWlzZTxib29sZWFuPjtcblxuICAvKipcbiAgICogQ3JlYXRlcyBhIHRhYmxlIHdpdGggYSBnaXZlbiBjb25maWcuXG4gICAqIElmIHRoZSB0YWJsZSBhbHJlYWR5IGV4aXN0cywgbmV3IGNvbHVtbnMgYXJlIGFkZGVkIHRvIHRoZSBleGlzdGluZyB0YWJsZS5cbiAgICogSWYgdGhlIHRhYmxlIGRvZXMgbm90IGV4aXN0LCBpdCBpcyBjcmVhdGVkIHdpdGggdGhlIGdpdmVuIGNvbmZpZy5cbiAgICogSWYgdGhlIHRhYmxlIGV4aXN0cyBhbmQgY29sdW1ucyBhcmUgcmVtb3ZlZCwgYW4gZXJyb3IgaXMgdGhyb3duLlxuICAgKiBJZiB0aGUgdGFibGUgZXhpc3RzIGFuZCB0aGUgY29sdW1uIHR5cGUgaXMgY2hhbmdlZCwgYW4gZXJyb3IgaXMgdGhyb3duLlxuICAgKi9cbiAgY3JlYXRlT3JFeHRlbmRUYWJsZShyZXF1ZXN0OiB7IHRhYmxlQ2ZnOiBUYWJsZUNmZyB9KTogUHJvbWlzZTx2b2lkPjtcblxuICAvKipcbiAgICogUmV0dXJucyBhIGpzb24gc3RydWN0dXJlIHJldHVybmluZyBjdXJyZW50IHRhYmxlIGNvbmZpZ3VyYXRpb25zXG4gICAqL1xuICByYXdUYWJsZUNmZ3MoKTogUHJvbWlzZTxUYWJsZUNmZ1tdPjtcblxuICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbiAgLy8gV3JpdGVcblxuICAvKiogV3JpdGVzIFJsanNvbiBkYXRhIGludG8gdGhlIGRhdGFiYXNlICovXG4gIHdyaXRlKHJlcXVlc3Q6IHsgZGF0YTogUmxqc29uIH0pOiBQcm9taXNlPHZvaWQ+O1xuXG4gIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLlxuICAvLyBSZWFkIHJvd3NcblxuICAvKiogUXVlcmllcyBhIGxpc3Qgb2Ygcm93cyAqL1xuICByZWFkUm93cyhyZXF1ZXN0OiB7XG4gICAgdGFibGU6IHN0cmluZztcbiAgICB3aGVyZTogeyBbY29sdW1uOiBzdHJpbmddOiBKc29uVmFsdWUgfCBudWxsIH07XG4gIH0pOiBQcm9taXNlPFJsanNvbj47XG5cbiAgLyoqIFJldHVybnMgdGhlIG51bWJlciBvZiByb3dzIGluIHRoZSBnaXZlbiB0YWJsZSAqL1xuICByb3dDb3VudCh0YWJsZTogc3RyaW5nKTogUHJvbWlzZTxudW1iZXI+O1xufVxuXG4vLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLlxuZXhwb3J0IGNvbnN0IGV4YW1wbGVJbyA9XG4gICdDaGVja291dCBAcmxqc29uL2lvLW1lbSBmb3IgYW4gZXhhbXBsZSBpbXBsZW1lbnRhdGlvbic7XG4iLCIvLyBAbGljZW5zZVxuLy8gQ29weXJpZ2h0IChjKSAyMDI1IFJsanNvblxuLy9cbi8vIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IHRlcm1zIHRoYXQgY2FuIGJlXG4vLyBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGluIHRoZSByb290IG9mIHRoaXMgcGFja2FnZS5cblxuaW1wb3J0IHsgSW8gfSBmcm9tICcuL2lvLnRzJztcbmltcG9ydCB7IFNvY2tldCB9IGZyb20gJy4vc29ja2V0LnRzJztcblxuXG5leHBvcnQgY2xhc3MgUGVlclNvY2tldE1vY2sgaW1wbGVtZW50cyBTb2NrZXQge1xuICBwcml2YXRlIF9saXN0ZW5lcnNNYXA6IE1hcDxzdHJpbmcgfCBzeW1ib2wsIEFycmF5PCguLi5hcmdzOiBhbnlbXSkgPT4gdm9pZD4+ID1cbiAgICBuZXcgTWFwKCk7XG5cbiAgY29ubmVjdGVkOiBib29sZWFuID0gZmFsc2U7XG4gIGRpc2Nvbm5lY3RlZDogYm9vbGVhbiA9IHRydWU7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBfaW86IElvKSB7fVxuXG4gIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbiAgLyoqXG4gICAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lciBmb3IgdGhlIHNwZWNpZmllZCBldmVudC5cbiAgICogQHBhcmFtIGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byBsaXN0ZW4gZm9yLlxuICAgKiBAcGFyYW0gbGlzdGVuZXIgLSBUaGUgY2FsbGJhY2sgZnVuY3Rpb24gdG8gaW52b2tlIHdoZW4gdGhlIGV2ZW50IGlzIGVtaXR0ZWQuXG4gICAqIEByZXR1cm5zIFRoZSBQZWVyU29ja2V0TW9jayBpbnN0YW5jZSBmb3IgY2hhaW5pbmcuXG4gICAqL1xuICBvbihldmVudE5hbWU6IHN0cmluZyB8IHN5bWJvbCwgbGlzdGVuZXI6ICguLi5hcmdzOiBhbnlbXSkgPT4gdm9pZCk6IHRoaXMge1xuICAgIGlmICghdGhpcy5fbGlzdGVuZXJzTWFwLmhhcyhldmVudE5hbWUpKSB7XG4gICAgICB0aGlzLl9saXN0ZW5lcnNNYXAuc2V0KGV2ZW50TmFtZSwgW10pO1xuICAgIH1cbiAgICB0aGlzLl9saXN0ZW5lcnNNYXAuZ2V0KGV2ZW50TmFtZSkhLnB1c2gobGlzdGVuZXIpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG4gIC8qKlxuICAgKiBTaW11bGF0ZXMgYSBjb25uZWN0aW9uIGV2ZW50LlxuICAgKlxuICAgKiBFbWl0cyB0aGUgJ2Nvbm5lY3QnIGV2ZW50IHRvIGFsbCByZWdpc3RlcmVkIGxpc3RlbmVycy5cbiAgICovXG4gIGNvbm5lY3QoKTogdm9pZCB7XG4gICAgdGhpcy5jb25uZWN0ZWQgPSB0cnVlO1xuICAgIHRoaXMuZGlzY29ubmVjdGVkID0gZmFsc2U7XG5cbiAgICBjb25zdCBsaXN0ZW5lcnMgPSB0aGlzLl9saXN0ZW5lcnNNYXAuZ2V0KCdjb25uZWN0JykgfHwgW107XG4gICAgZm9yIChjb25zdCBjYiBvZiBsaXN0ZW5lcnMpIHtcbiAgICAgIGNiKHt9KTtcbiAgICB9XG4gIH1cblxuICAvLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbiAgLyoqXG4gICAqIFNpbXVsYXRlcyBhIGRpc2Nvbm5lY3Rpb24gZXZlbnQuXG4gICAqXG4gICAqIEVtaXRzIHRoZSAnZGlzY29ubmVjdCcgZXZlbnQgdG8gYWxsIHJlZ2lzdGVyZWQgbGlzdGVuZXJzLlxuICAgKi9cbiAgZGlzY29ubmVjdCgpOiB2b2lkIHtcbiAgICB0aGlzLmNvbm5lY3RlZCA9IGZhbHNlO1xuICAgIHRoaXMuZGlzY29ubmVjdGVkID0gdHJ1ZTtcblxuICAgIGNvbnN0IGxpc3RlbmVycyA9IHRoaXMuX2xpc3RlbmVyc01hcC5nZXQoJ2Rpc2Nvbm5lY3QnKSB8fCBbXTtcbiAgICBmb3IgKGNvbnN0IGNiIG9mIGxpc3RlbmVycykge1xuICAgICAgY2Ioe30pO1xuICAgIH1cbiAgfVxuXG4gIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbiAgLyoqXG4gICAqIEVtaXRzIGFuIGV2ZW50LCBpbnZva2luZyB0aGUgY29ycmVzcG9uZGluZyBtZXRob2Qgb24gdGhlIElvIGluc3RhbmNlLlxuICAgKiBAcGFyYW0gZXZlbnROYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIGVtaXQuXG4gICAqIEBwYXJhbSBhcmdzIC0gVGhlIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBldmVudCBsaXN0ZW5lci5cbiAgICogQHJldHVybnNcbiAgICovXG4gIGVtaXQoZXZlbnROYW1lOiBzdHJpbmcgfCBzeW1ib2wsIC4uLmFyZ3M6IGFueVtdKTogYm9vbGVhbiB7XG4gICAgY29uc3QgZm4gPSAodGhpcy5faW8gYXMgYW55KVtldmVudE5hbWVdIGFzICguLi5hcmdzOiBhbnlbXSkgPT4gUHJvbWlzZTxhbnk+O1xuICAgIGlmICh0eXBlb2YgZm4gIT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXZlbnQgJHtldmVudE5hbWUudG9TdHJpbmcoKX0gbm90IHN1cHBvcnRlZGApO1xuICAgIH1cbiAgICBjb25zdCBjYiA9IGFyZ3NbYXJncy5sZW5ndGggLSAxXTtcbiAgICBmbi5hcHBseSh0aGlzLl9pbywgYXJncy5zbGljZSgwLCAtMSkpXG4gICAgICAudGhlbigocmVzdWx0KSA9PiB7XG4gICAgICAgIGNiKHJlc3VsdCwgbnVsbCk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnIpID0+IHtcbiAgICAgICAgY2IobnVsbCwgZXJyKTtcbiAgICAgIH0pO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbn1cbiIsIi8qIHY4IGlnbm9yZSBmaWxlIC0tIEBwcmVzZXJ2ZSAqL1xuLy8gQGxpY2Vuc2Vcbi8vIENvcHlyaWdodCAoYykgMjAyNSBSbGpzb25cbi8vXG4vLyBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSB0ZXJtcyB0aGF0IGNhbiBiZVxuLy8gZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBvZiB0aGlzIHBhY2thZ2UuXG5cbmltcG9ydCB7IEpzb24gfSBmcm9tICdAcmxqc29uL2pzb24nO1xuaW1wb3J0IHtcbiAgQnVmZmV0LFxuICBDYWtlLFxuICBpdGVyYXRlVGFibGVzU3luYyxcbiAgTGF5ZXIsXG4gIFJlZixcbiAgUmxqc29uLFxuICBUYWJsZUtleSxcbn0gZnJvbSAnQHJsanNvbi9ybGpzb24nO1xuXG4vLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLlxuLyoqXG4gKiBEZXNjcmliZXMgYSByb3cgdGhhdCByZWZlcmVuY2VzIGEgY2hpbGQgdGFibGUgcm93XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUGFyZW50UmVmIHtcbiAgLyoqXG4gICAqIFRoZSBwYXJlbnQgdGFibGUgdGhhdCByZWZlcmVuY2VzIHRoZSBjaGlsZCB0YWJsZVxuICAgKi9cbiAgW3BhcmVudFRhYmxlOiBUYWJsZUtleV06IHtcbiAgICAvKipcbiAgICAgKiBUaGUgcGFyZW50IHJvdyB0aGF0IHJlZmVyZW5jZXMgdGhlIGNoaWxkIHJvd1xuICAgICAqL1xuICAgIFtwYXJlbnRSb3c6IFJlZl06IHtcbiAgICAgIC8qKlxuICAgICAgICogRGV0YWlscyBhYm91dCB0aGUgcmVmZXJlbmNlLCBlLmcuIGFuIGFycmF5IGluZGV4IGV0Yy5cbiAgICAgICAqL1xuICAgICAgZGV0YWlscz86IEpzb247XG4gICAgfTtcbiAgfTtcbn1cblxuLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbi8qKlxuICogRGVzY3JpYmVzIHRoZSBwYXJlbnQgdGFibGUgcm93cyByZWZlcmVuY2luZyBhIGNoaWxkIHRhYmxlIHJvd1xuICovXG5leHBvcnQgaW50ZXJmYWNlIFJldmVyc2VSZWZzIHtcbiAgLyoqXG4gICAqIFRoZSBjaGlsZCB0YWJsZSB3ZSBuZWVkIHRoZSByZWZlcmVuY2luZyByb3dzIGZvclxuICAgKi9cbiAgW2NoaWxkVGFibGU6IFRhYmxlS2V5XToge1xuICAgIC8qKlxuICAgICAqIFRoZSByb3cgaGFzaHdlIG5lZWQgdGhlIHJlZmVyZW5jaW5nIHJvd3MgZm9yXG4gICAgICovXG4gICAgW2NoaWxkUm93OiBSZWZdOiBQYXJlbnRSZWY7XG4gIH07XG59XG5cbi8qIHY4IGlnbm9yZSBzdGFydCAqL1xuXG4vLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLlxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSByZXZlcnNlIHJlZmVyZW5jZXMgZm9yIGEgZ2l2ZW4gcmxqc29uIG9iamVjdFxuICovXG5leHBvcnQgY29uc3QgY2FsY1JldmVyc2VSZWZzID0gKHJsanNvbjogUmxqc29uKTogUmV2ZXJzZVJlZnMgPT4ge1xuICBjb25zdCByZXN1bHQ6IFJldmVyc2VSZWZzID0ge307XG5cbiAgLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLlxuICAvLyBQcmVwYXJlIGRhdGEgc3RydWN0dXJlXG4gIGl0ZXJhdGVUYWJsZXNTeW5jKHJsanNvbiwgKGNoaWxkVGFibGVLZXksIHRhYmxlKSA9PiB7XG4gICAgY29uc3QgY2hpbGRUYWJsZTogeyBbY2hpbGRSb3dIYXNoOiBzdHJpbmddOiBQYXJlbnRSZWYgfSA9IHt9O1xuICAgIHJlc3VsdFtjaGlsZFRhYmxlS2V5XSA9IGNoaWxkVGFibGU7XG4gICAgZm9yIChjb25zdCBjaGlsZFJvdyBvZiB0YWJsZS5fZGF0YSkge1xuICAgICAgY2hpbGRUYWJsZVtjaGlsZFJvdy5faGFzaF0gPSB7fTtcbiAgICB9XG4gIH0pO1xuXG4gIC8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbiAgLy8gR2VuZXJhdGUgcmV2ZXJzZSByZWZlcmVuY2VzXG4gIGl0ZXJhdGVUYWJsZXNTeW5jKHJsanNvbiwgKHBhcmVudFRhYmxlS2V5LCBwYXJlbnRUYWJsZSkgPT4ge1xuICAgIC8vIEl0ZXJhdGUgYWxsIHJvd3Mgb2YgZWFjaCB0YWJsZVxuICAgIGZvciAoY29uc3QgcGFyZW50VGFibGVSb3cgb2YgcGFyZW50VGFibGUuX2RhdGEpIHtcbiAgICAgIC8vIEZpbmQgb3V0IHdoZSBvdGhlciB0YWJsZXMgJiByb3dzIGFyZSByZWZlcmVuY2VkIGJ5IHRoaXMgcm93XG4gICAgICAvLyBXcml0ZSB0aGVzZSBpbmZvcm1hdGlvbiBpbnR0byByZXN1bHRcbiAgICAgIHN3aXRjaCAocGFyZW50VGFibGUuX3R5cGUpIHtcbiAgICAgICAgY2FzZSAnY29tcG9uZW50cyc6XG4gICAgICAgICAgX3dyaXRlQ29tcG9uZW50UmVmcyhwYXJlbnRUYWJsZUtleSwgcGFyZW50VGFibGVSb3csIHJlc3VsdCk7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSAnbGF5ZXJzJzoge1xuICAgICAgICAgIF93cml0ZUxheWVyUmVmcyhwYXJlbnRUYWJsZUtleSwgcGFyZW50VGFibGVSb3csIHJlc3VsdCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBjYXNlICdzbGljZUlkcyc6IHtcbiAgICAgICAgICAvLyBTbGljZSBpZHMgZG8gbm90IHJlZmVyZW5jZSBvdGhlciB0YWJsZXNcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIGNhc2UgJ2Nha2VzJzoge1xuICAgICAgICAgIF93cml0ZUNha2VSZWZzKHBhcmVudFRhYmxlS2V5LCBwYXJlbnRUYWJsZVJvdywgcmVzdWx0KTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIGNhc2UgJ2J1ZmZldHMnOiB7XG4gICAgICAgICAgX3dyaXRlQnVmZmV0UmVmcyhwYXJlbnRUYWJsZUtleSwgcGFyZW50VGFibGVSb3csIHJlc3VsdCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiByZXN1bHQ7XG59O1xuXG4vKiB2OCBpZ25vcmUgZW5kICovXG5cbi8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG5jb25zdCBfd3JpdGVDb21wb25lbnRSZWZzID0gKFxuICBwYXJlbnRUYWJsZU5hbWU6IFRhYmxlS2V5LFxuICBwYXJlbnRSb3c6IEpzb24sXG4gIHJlc3VsdDogUmV2ZXJzZVJlZnMsXG4pID0+IHtcbiAgY29uc3QgcGFyZW50Um93SGFzaCA9IHBhcmVudFJvdy5faGFzaCBhcyBzdHJpbmc7XG5cbiAgZm9yIChjb25zdCBwYXJlbnRDb2x1bW5OYW1lIGluIHBhcmVudFJvdykge1xuICAgIGlmIChwYXJlbnRDb2x1bW5OYW1lLnN0YXJ0c1dpdGgoJ18nKSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgaWYgKCFwYXJlbnRDb2x1bW5OYW1lLmVuZHNXaXRoKCdSZWYnKSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgY29uc3QgY2hpbGRUYWJsZU5hbWUgPSBwYXJlbnRDb2x1bW5OYW1lLnNsaWNlKDAsIC0zKTtcbiAgICBjb25zdCBjaGlsZFJvd0hhc2ggPSBwYXJlbnRSb3dbcGFyZW50Q29sdW1uTmFtZV0gYXMgc3RyaW5nO1xuXG4gICAgX3dyaXRlKFxuICAgICAgcmVzdWx0LFxuICAgICAgY2hpbGRUYWJsZU5hbWUsXG4gICAgICBjaGlsZFJvd0hhc2gsXG4gICAgICBwYXJlbnRUYWJsZU5hbWUsXG4gICAgICBwYXJlbnRSb3dIYXNoLFxuICAgICk7XG4gIH1cbn07XG5cbi8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG5jb25zdCBfd3JpdGVMYXllclJlZnMgPSAoXG4gIHBhcmVudFRhYmxlTmFtZTogVGFibGVLZXksXG4gIHBhcmVudFJvdzogTGF5ZXIsXG4gIHJlc3VsdDogUmV2ZXJzZVJlZnMsXG4pID0+IHtcbiAgY29uc3QgY2hpbGRUYWJsZU5hbWUgPSBwYXJlbnRSb3cuY29tcG9uZW50c1RhYmxlO1xuICBjb25zdCBwYXJlbnRSb3dIYXNoID0gcGFyZW50Um93Ll9oYXNoIGFzIHN0cmluZztcblxuICBmb3IgKGNvbnN0IHNsaWNlSWQgaW4gcGFyZW50Um93LmFkZCkge1xuICAgIGlmIChzbGljZUlkLnN0YXJ0c1dpdGgoJ18nKSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgY29uc3Qgc2xpY2VIYXNoID0gcGFyZW50Um93LmFkZFtzbGljZUlkXSBhcyBzdHJpbmc7XG5cbiAgICBfd3JpdGUocmVzdWx0LCBjaGlsZFRhYmxlTmFtZSwgc2xpY2VIYXNoLCBwYXJlbnRUYWJsZU5hbWUsIHBhcmVudFJvd0hhc2gpO1xuICB9XG59O1xuXG4vLyAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLlxuY29uc3QgX3dyaXRlQ2FrZVJlZnMgPSAoXG4gIHBhcmVudFRhYmxlTmFtZTogVGFibGVLZXksXG4gIHBhcmVudFJvdzogQ2FrZSxcbiAgcmVzdWx0OiBSZXZlcnNlUmVmcyxcbikgPT4ge1xuICBjb25zdCBwYXJlbnRSb3dIYXNoID0gcGFyZW50Um93Ll9oYXNoIGFzIHN0cmluZztcblxuICBmb3IgKGNvbnN0IGxheWVyIGluIHBhcmVudFJvdy5sYXllcnMpIHtcbiAgICBjb25zdCBjaGlsZFRhYmxlTmFtZSA9IGxheWVyO1xuICAgIGNvbnN0IGNoaWxkUm93SGFzaCA9IHBhcmVudFJvdy5sYXllcnNbbGF5ZXJdIGFzIHN0cmluZztcbiAgICBfd3JpdGUoXG4gICAgICByZXN1bHQsXG4gICAgICBjaGlsZFRhYmxlTmFtZSxcbiAgICAgIGNoaWxkUm93SGFzaCxcbiAgICAgIHBhcmVudFRhYmxlTmFtZSxcbiAgICAgIHBhcmVudFJvd0hhc2gsXG4gICAgKTtcbiAgfVxufTtcblxuLy8gLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi5cbmNvbnN0IF93cml0ZUJ1ZmZldFJlZnMgPSAoXG4gIHBhcmVudFRhYmxlTmFtZTogVGFibGVLZXksXG4gIHBhcmVudFJvdzogQnVmZmV0LFxuICByZXN1bHQ6IFJldmVyc2VSZWZzLFxuKSA9PiB7XG4gIGNvbnN0IHBhcmVudFJvd0hhc2ggPSBwYXJlbnRSb3cuX2hhc2ggYXMgc3RyaW5nO1xuXG4gIGZvciAoY29uc3QgaXRlbSBvZiBwYXJlbnRSb3cuaXRlbXMpIHtcbiAgICBjb25zdCBjaGlsZFRhYmxlTmFtZSA9IGl0ZW0udGFibGU7XG4gICAgY29uc3QgY2hpbGRSb3dIYXNoID0gaXRlbS5yZWY7XG4gICAgX3dyaXRlKFxuICAgICAgcmVzdWx0LFxuICAgICAgY2hpbGRUYWJsZU5hbWUsXG4gICAgICBjaGlsZFJvd0hhc2gsXG4gICAgICBwYXJlbnRUYWJsZU5hbWUsXG4gICAgICBwYXJlbnRSb3dIYXNoLFxuICAgICk7XG4gIH1cbn07XG5cbi8vIC4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uXG5jb25zdCBfd3JpdGUgPSAoXG4gIHJlc3VsdDogUmV2ZXJzZVJlZnMsXG4gIGNoaWxkVGFibGVOYW1lOiBzdHJpbmcsXG4gIGNoaWxkUm93SGFzaDogc3RyaW5nLFxuICBwYXJlbnRUYWJsZU5hbWU6IHN0cmluZyxcbiAgcGFyZW50Um93SGFzaDogc3RyaW5nLFxuKSA9PiB7XG4gIGNvbnN0IHJlZmVyZW5jZXNGb3JDaGlsZFRhYmxlID0gKHJlc3VsdFtjaGlsZFRhYmxlTmFtZV0gPz89IHt9KTtcbiAgY29uc3QgcmVmZXJlbmNlc0ZvckNoaWxkVGFibGVSb3cgPSAocmVmZXJlbmNlc0ZvckNoaWxkVGFibGVbY2hpbGRSb3dIYXNoXSA/Pz1cbiAgICB7fSk7XG5cbiAgcmVmZXJlbmNlc0ZvckNoaWxkVGFibGVSb3dbcGFyZW50VGFibGVOYW1lXSA/Pz0ge307XG4gIHJlZmVyZW5jZXNGb3JDaGlsZFRhYmxlUm93W3BhcmVudFRhYmxlTmFtZV1bcGFyZW50Um93SGFzaF0gPz89IHt9O1xufTtcbiIsIi8vIEBsaWNlbnNlXG4vLyBDb3B5cmlnaHQgKGMpIDIwMjUgUmxqc29uXG4vL1xuLy8gVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgdGVybXMgdGhhdCBjYW4gYmVcbi8vIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3Qgb2YgdGhpcyBwYWNrYWdlLlxuLyogdjggaWdub3JlIGZpbGUgLS0gQHByZXNlcnZlICovXG5pbXBvcnQgeyBTb2NrZXQgfSBmcm9tICcuL3NvY2tldC50cyc7XG5cbmV4cG9ydCBjbGFzcyBTb2NrZXRNb2NrIGltcGxlbWVudHMgU29ja2V0IHtcbiAgcHVibGljIGNvbm5lY3RlZDogYm9vbGVhbiA9IGZhbHNlO1xuICBwdWJsaWMgZGlzY29ubmVjdGVkOiBib29sZWFuID0gdHJ1ZTtcblxuICBwcml2YXRlIF9saXN0ZW5lcnM6IE1hcDxzdHJpbmcgfCBzeW1ib2wsIEFycmF5PCguLi5hcmdzOiBhbnlbXSkgPT4gdm9pZD4+ID1cbiAgICBuZXcgTWFwKCk7XG4gIHByaXZhdGUgX29uY2VMaXN0ZW5lcnM6IE1hcDxcbiAgICBzdHJpbmcgfCBzeW1ib2wsXG4gICAgQXJyYXk8KC4uLmFyZ3M6IGFueVtdKSA9PiB2b2lkPlxuICA+ID0gbmV3IE1hcCgpO1xuXG4gIGNvbm5lY3QoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmNvbm5lY3RlZCkge1xuICAgICAgdGhpcy5jb25uZWN0ZWQgPSB0cnVlO1xuICAgICAgdGhpcy5kaXNjb25uZWN0ZWQgPSBmYWxzZTtcbiAgICAgIHRoaXMuZW1pdCgnY29ubmVjdCcpO1xuICAgIH1cbiAgfVxuXG4gIGRpc2Nvbm5lY3QoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuY29ubmVjdGVkKSB7XG4gICAgICB0aGlzLmNvbm5lY3RlZCA9IGZhbHNlO1xuICAgICAgdGhpcy5kaXNjb25uZWN0ZWQgPSB0cnVlO1xuICAgICAgdGhpcy5lbWl0KCdkaXNjb25uZWN0Jyk7XG4gICAgfVxuICB9XG5cbiAgb24oZXZlbnROYW1lOiBzdHJpbmcgfCBzeW1ib2wsIGxpc3RlbmVyOiAoLi4uYXJnczogYW55W10pID0+IHZvaWQpOiB0aGlzIHtcbiAgICBpZiAoIXRoaXMuX2xpc3RlbmVycy5oYXMoZXZlbnROYW1lKSkge1xuICAgICAgdGhpcy5fbGlzdGVuZXJzLnNldChldmVudE5hbWUsIFtdKTtcbiAgICB9XG4gICAgdGhpcy5fbGlzdGVuZXJzLmdldChldmVudE5hbWUpIS5wdXNoKGxpc3RlbmVyKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIG9uY2UoZXZlbnROYW1lOiBzdHJpbmcgfCBzeW1ib2wsIGxpc3RlbmVyOiAoLi4uYXJnczogYW55W10pID0+IHZvaWQpOiB0aGlzIHtcbiAgICBpZiAoIXRoaXMuX29uY2VMaXN0ZW5lcnMuaGFzKGV2ZW50TmFtZSkpIHtcbiAgICAgIHRoaXMuX29uY2VMaXN0ZW5lcnMuc2V0KGV2ZW50TmFtZSwgW10pO1xuICAgIH1cbiAgICB0aGlzLl9vbmNlTGlzdGVuZXJzLmdldChldmVudE5hbWUpIS5wdXNoKGxpc3RlbmVyKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIG9mZihldmVudE5hbWU6IHN0cmluZyB8IHN5bWJvbCwgbGlzdGVuZXI/OiAoLi4uYXJnczogYW55W10pID0+IHZvaWQpOiB0aGlzIHtcbiAgICBpZiAobGlzdGVuZXIpIHtcbiAgICAgIC8vIFJlbW92ZSBzcGVjaWZpYyBsaXN0ZW5lclxuICAgICAgY29uc3QgcmVndWxhckxpc3RlbmVycyA9IHRoaXMuX2xpc3RlbmVycy5nZXQoZXZlbnROYW1lKTtcbiAgICAgIGlmIChyZWd1bGFyTGlzdGVuZXJzKSB7XG4gICAgICAgIGNvbnN0IGluZGV4ID0gcmVndWxhckxpc3RlbmVycy5pbmRleE9mKGxpc3RlbmVyKTtcbiAgICAgICAgaWYgKGluZGV4ID4gLTEpIHtcbiAgICAgICAgICByZWd1bGFyTGlzdGVuZXJzLnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3Qgb25jZUxpc3RlbmVycyA9IHRoaXMuX29uY2VMaXN0ZW5lcnMuZ2V0KGV2ZW50TmFtZSk7XG4gICAgICBpZiAob25jZUxpc3RlbmVycykge1xuICAgICAgICBjb25zdCBpbmRleCA9IG9uY2VMaXN0ZW5lcnMuaW5kZXhPZihsaXN0ZW5lcik7XG4gICAgICAgIGlmIChpbmRleCA+IC0xKSB7XG4gICAgICAgICAgb25jZUxpc3RlbmVycy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFJlbW92ZSBhbGwgbGlzdGVuZXJzIGZvciB0aGUgZXZlbnRcbiAgICAgIHRoaXMuX2xpc3RlbmVycy5kZWxldGUoZXZlbnROYW1lKTtcbiAgICAgIHRoaXMuX29uY2VMaXN0ZW5lcnMuZGVsZXRlKGV2ZW50TmFtZSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgZW1pdChldmVudE5hbWU6IHN0cmluZyB8IHN5bWJvbCwgLi4uYXJnczogYW55W10pOiBib29sZWFuIHtcbiAgICBsZXQgaGFzTGlzdGVuZXJzID0gZmFsc2U7XG5cbiAgICAvLyBFbWl0IHRvIHJlZ3VsYXIgbGlzdGVuZXJzXG4gICAgY29uc3QgcmVndWxhckxpc3RlbmVycyA9IHRoaXMuX2xpc3RlbmVycy5nZXQoZXZlbnROYW1lKTtcbiAgICBpZiAocmVndWxhckxpc3RlbmVycyAmJiByZWd1bGFyTGlzdGVuZXJzLmxlbmd0aCA+IDApIHtcbiAgICAgIGhhc0xpc3RlbmVycyA9IHRydWU7XG4gICAgICAvLyBDcmVhdGUgYSBjb3B5IHRvIGF2b2lkIGlzc3VlcyBpZiBsaXN0ZW5lcnMgYXJlIHJlbW92ZWQgZHVyaW5nIGVtaXNzaW9uXG4gICAgICBbLi4ucmVndWxhckxpc3RlbmVyc10uZm9yRWFjaCgobGlzdGVuZXIpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBsaXN0ZW5lciguLi5hcmdzKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAvLyBJbiBhIHJlYWwgRXZlbnRFbWl0dGVyLCB0aGlzIHdvdWxkIGJlIGhhbmRsZWQgZGlmZmVyZW50bHlcbiAgICAgICAgICBjb25zb2xlLmVycm9yKFxuICAgICAgICAgICAgYEVycm9yIGluIGxpc3RlbmVyIGZvciBldmVudCAke1N0cmluZyhldmVudE5hbWUpfTpgLFxuICAgICAgICAgICAgZXJyb3IsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gRW1pdCB0byBvbmNlIGxpc3RlbmVycyBhbmQgcmVtb3ZlIHRoZW1cbiAgICBjb25zdCBvbmNlTGlzdGVuZXJzID0gdGhpcy5fb25jZUxpc3RlbmVycy5nZXQoZXZlbnROYW1lKTtcbiAgICBpZiAob25jZUxpc3RlbmVycyAmJiBvbmNlTGlzdGVuZXJzLmxlbmd0aCA+IDApIHtcbiAgICAgIGhhc0xpc3RlbmVycyA9IHRydWU7XG4gICAgICAvLyBDcmVhdGUgYSBjb3B5IGFuZCBjbGVhciB0aGUgb3JpZ2luYWwgYXJyYXlcbiAgICAgIGNvbnN0IGxpc3RlbmVyc1RvQ2FsbCA9IFsuLi5vbmNlTGlzdGVuZXJzXTtcbiAgICAgIHRoaXMuX29uY2VMaXN0ZW5lcnMuZGVsZXRlKGV2ZW50TmFtZSk7XG5cbiAgICAgIGxpc3RlbmVyc1RvQ2FsbC5mb3JFYWNoKChsaXN0ZW5lcikgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGxpc3RlbmVyKC4uLmFyZ3MpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgICAgICBgRXJyb3IgaW4gb25jZSBsaXN0ZW5lciBmb3IgZXZlbnQgJHtTdHJpbmcoZXZlbnROYW1lKX06YCxcbiAgICAgICAgICAgIGVycm9yLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBoYXNMaXN0ZW5lcnM7XG4gIH1cblxuICByZW1vdmVBbGxMaXN0ZW5lcnMoZXZlbnROYW1lPzogc3RyaW5nIHwgc3ltYm9sKTogdGhpcyB7XG4gICAgaWYgKGV2ZW50TmFtZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLl9saXN0ZW5lcnMuZGVsZXRlKGV2ZW50TmFtZSk7XG4gICAgICB0aGlzLl9vbmNlTGlzdGVuZXJzLmRlbGV0ZShldmVudE5hbWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9saXN0ZW5lcnMuY2xlYXIoKTtcbiAgICAgIHRoaXMuX29uY2VMaXN0ZW5lcnMuY2xlYXIoKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBsaXN0ZW5lckNvdW50KGV2ZW50TmFtZTogc3RyaW5nIHwgc3ltYm9sKTogbnVtYmVyIHtcbiAgICBjb25zdCByZWd1bGFyQ291bnQgPSB0aGlzLl9saXN0ZW5lcnMuZ2V0KGV2ZW50TmFtZSk/Lmxlbmd0aCB8fCAwO1xuICAgIGNvbnN0IG9uY2VDb3VudCA9IHRoaXMuX29uY2VMaXN0ZW5lcnMuZ2V0KGV2ZW50TmFtZSk/Lmxlbmd0aCB8fCAwO1xuICAgIHJldHVybiByZWd1bGFyQ291bnQgKyBvbmNlQ291bnQ7XG4gIH1cblxuICBsaXN0ZW5lcnMoZXZlbnROYW1lOiBzdHJpbmcgfCBzeW1ib2wpOiBBcnJheTwoLi4uYXJnczogYW55W10pID0+IHZvaWQ+IHtcbiAgICBjb25zdCByZWd1bGFyTGlzdGVuZXJzID0gdGhpcy5fbGlzdGVuZXJzLmdldChldmVudE5hbWUpIHx8IFtdO1xuICAgIGNvbnN0IG9uY2VMaXN0ZW5lcnMgPSB0aGlzLl9vbmNlTGlzdGVuZXJzLmdldChldmVudE5hbWUpIHx8IFtdO1xuICAgIHJldHVybiBbLi4ucmVndWxhckxpc3RlbmVycywgLi4ub25jZUxpc3RlbmVyc107XG4gIH1cblxuICBldmVudE5hbWVzKCk6IEFycmF5PHN0cmluZyB8IHN5bWJvbD4ge1xuICAgIGNvbnN0IGFsbEV2ZW50cyA9IG5ldyBTZXQoW1xuICAgICAgLi4udGhpcy5fbGlzdGVuZXJzLmtleXMoKSxcbiAgICAgIC4uLnRoaXMuX29uY2VMaXN0ZW5lcnMua2V5cygpLFxuICAgIF0pO1xuICAgIHJldHVybiBBcnJheS5mcm9tKGFsbEV2ZW50cyk7XG4gIH1cblxuICAvLyBUZXN0IGhlbHBlciBtZXRob2RzXG4gIHJlc2V0KCk6IHZvaWQge1xuICAgIHRoaXMuY29ubmVjdGVkID0gZmFsc2U7XG4gICAgdGhpcy5kaXNjb25uZWN0ZWQgPSB0cnVlO1xuICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG4gIH1cblxuICBzaW11bGF0ZUVycm9yKGVycm9yOiBFcnJvcik6IHZvaWQge1xuICAgIHRoaXMuZW1pdCgnZXJyb3InLCBlcnJvcik7XG4gIH1cblxuICBzaW11bGF0ZU1lc3NhZ2UobWVzc2FnZTogYW55KTogdm9pZCB7XG4gICAgdGhpcy5lbWl0KCdtZXNzYWdlJywgbWVzc2FnZSk7XG4gIH1cblxuICAvLyBHZXQgaW50ZXJuYWwgc3RhdGUgZm9yIHRlc3RpbmdcbiAgZ2V0TGlzdGVuZXJzKCk6IE1hcDxzdHJpbmcgfCBzeW1ib2wsIEFycmF5PCguLi5hcmdzOiBhbnlbXSkgPT4gdm9pZD4+IHtcbiAgICByZXR1cm4gbmV3IE1hcCh0aGlzLl9saXN0ZW5lcnMpO1xuICB9XG5cbiAgZ2V0T25jZUxpc3RlbmVycygpOiBNYXA8c3RyaW5nIHwgc3ltYm9sLCBBcnJheTwoLi4uYXJnczogYW55W10pID0+IHZvaWQ+PiB7XG4gICAgcmV0dXJuIG5ldyBNYXAodGhpcy5fb25jZUxpc3RlbmVycyk7XG4gIH1cbn1cblxuLy8gLi4uZXhpc3RpbmcgY29kZS4uLlxuIiwiLy8gQGxpY2Vuc2Vcbi8vIENvcHlyaWdodCAoYykgMjAyNSBSbGpzb25cbi8vXG4vLyBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSB0ZXJtcyB0aGF0IGNhbiBiZVxuLy8gZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBvZiB0aGlzIHBhY2thZ2UuXG5cbi8vSW50ZXJmYWNlIGZvciBhIGdlbmVyaWMgU29ja2V0LCBzaW1pbGFyIHRvIE5vZGUuanMgRXZlbnRFbWl0dGVyXG4vL1RoaXMgaXMgYSBzaW1wbGlmaWVkIHZlcnNpb24gYW5kIG1heSBub3QgY292ZXIgYWxsIGZlYXR1cmVzIG9mIGEgZnVsbCBFdmVudEVtaXR0ZXJcbmV4cG9ydCBpbnRlcmZhY2UgU29ja2V0IHtcbiAgY29ubmVjdGVkOiBib29sZWFuO1xuICBkaXNjb25uZWN0ZWQ6IGJvb2xlYW47XG4gIGNvbm5lY3QoKTogdm9pZDtcbiAgZGlzY29ubmVjdCgpOiB2b2lkO1xuICBvbihldmVudE5hbWU6IHN0cmluZyB8IHN5bWJvbCwgbGlzdGVuZXI6ICguLi5hcmdzOiBhbnlbXSkgPT4gdm9pZCk6IHRoaXM7XG4gIGVtaXQoZXZlbnROYW1lOiBzdHJpbmcgfCBzeW1ib2wsIC4uLmFyZ3M6IGFueVtdKTogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGNvbnN0IHNvY2tldEV4YW1wbGUgPSAoKTogU29ja2V0ID0+ICh7XG4gIGNvbm5lY3RlZDogZmFsc2UsXG4gIGRpc2Nvbm5lY3RlZDogdHJ1ZSxcbiAgY29ubmVjdCgpIHtcbiAgICB0aGlzLmNvbm5lY3RlZCA9IHRydWU7XG4gICAgdGhpcy5kaXNjb25uZWN0ZWQgPSBmYWxzZTtcbiAgICB0aGlzLmVtaXQoJ2Nvbm5lY3QnKTtcbiAgfSxcbiAgZGlzY29ubmVjdCgpIHtcbiAgICB0aGlzLmNvbm5lY3RlZCA9IGZhbHNlO1xuICAgIHRoaXMuZGlzY29ubmVjdGVkID0gdHJ1ZTtcbiAgICB0aGlzLmVtaXQoJ2Rpc2Nvbm5lY3QnKTtcbiAgfSxcbiAgLyogdjggaWdub3JlIG5leHQgLS0gQHByZXNlcnZlICovXG4gIG9uKCkge1xuICAgIC8vIEltcGxlbWVudGF0aW9uIG9mIGV2ZW50IGxpc3RlbmVyIHJlZ2lzdHJhdGlvblxuICAgIHJldHVybiB0aGlzO1xuICB9LFxuICAvKiB2OCBpZ25vcmUgbmV4dCAtLSBAcHJlc2VydmUgKi9cbiAgZW1pdCgpIHtcbiAgICAvLyBJbXBsZW1lbnRhdGlvbiBvZiBldmVudCBlbWlzc2lvblxuICAgIHJldHVybiB0cnVlO1xuICB9LFxufSk7XG4iXSwibmFtZXMiOlsiZSJdLCJtYXBwaW5ncyI6Ijs7OztBQU1PLE1BQU0sZ0JBQWdCO0FBQUE7QUFBQSxFQUVwQixtQkFBMkI7QUFBQSxFQUMzQixjQUFzQjtBQUFBLEVBQ3RCLGFBQXFCO0FBQUEsRUFDckIsWUFBb0I7QUFBQTtBQUFBLEVBR3BCLGFBQXdDO0FBQUEsSUFDN0MsTUFBTTtBQUFBLElBQ04sVUFBVTtBQUFBLEVBQUE7QUFBQTtBQUFBLEVBSUosVUFBcUM7QUFBQSxJQUMzQyxLQUFLO0FBQUEsSUFDTCxLQUFLO0FBQUEsSUFDTCxLQUFLO0FBQUEsRUFBQTtBQUFBO0FBQUE7QUFBQSxFQUtDLFFBQVEsTUFBYyxLQUFxQjtBQUNqRCxXQUFPLEtBQUssU0FBUyxHQUFHLElBQUksT0FB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
|
|
1719
|
+
//# sourceMappingURL=io.js.map
|