1 line
109 KiB
Plaintext
1 line
109 KiB
Plaintext
{"version":3,"sources":["node_modules/browser-pack/_prelude.js","src/Connector.js","src/Connectors/Test.js","src/Database.js","src/Struct.js","src/Transaction.js","src/Utils.js","src/y.js"],"names":[],"mappings":"AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1ZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3XA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC53BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5ZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"y.es6","sourceRoot":"/source/","sourcesContent":["(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})","/* @flow */\r\n'use strict'\r\n\r\nmodule.exports = function (Y/* :any */) {\r\n class AbstractConnector {\r\n /* ::\r\n y: YConfig;\r\n role: SyncRole;\r\n connections: Object;\r\n isSynced: boolean;\r\n userEventListeners: Array<Function>;\r\n whenSyncedListeners: Array<Function>;\r\n currentSyncTarget: ?UserId;\r\n syncingClients: Array<UserId>;\r\n forwardToSyncingClients: boolean;\r\n debug: boolean;\r\n broadcastedHB: boolean;\r\n syncStep2: Promise;\r\n userId: UserId;\r\n send: Function;\r\n broadcast: Function;\r\n */\r\n /*\r\n opts contains the following information:\r\n role : String Role of this client (\"master\" or \"slave\")\r\n userId : String Uniquely defines the user.\r\n debug: Boolean Whether to print debug messages (optional)\r\n */\r\n constructor (y, opts) {\r\n this.y = y\r\n if (opts == null) {\r\n opts = {}\r\n }\r\n if (opts.role == null || opts.role === 'master') {\r\n this.role = 'master'\r\n } else if (opts.role === 'slave') {\r\n this.role = 'slave'\r\n } else {\r\n throw new Error(\"Role must be either 'master' or 'slave'!\")\r\n }\r\n this.y.db.forwardAppliedOperations = opts.forwardAppliedOperations || false\r\n this.role = opts.role\r\n this.connections = {}\r\n this.isSynced = false\r\n this.userEventListeners = []\r\n this.whenSyncedListeners = []\r\n this.currentSyncTarget = null\r\n this.syncingClients = []\r\n this.forwardToSyncingClients = opts.forwardToSyncingClients !== false\r\n this.debug = opts.debug === true\r\n this.broadcastedHB = false\r\n this.syncStep2 = Promise.resolve()\r\n this.broadcastOpBuffer = []\r\n this.protocolVersion = 8\r\n }\r\n reconnect () {\r\n }\r\n disconnect () {\r\n this.connections = {}\r\n this.isSynced = false\r\n this.currentSyncTarget = null\r\n this.broadcastedHB = false\r\n this.syncingClients = []\r\n this.whenSyncedListeners = []\r\n return this.y.db.stopGarbageCollector()\r\n }\r\n setUserId (userId) {\r\n if (this.userId == null) {\r\n this.userId = userId\r\n return this.y.db.setUserId(userId)\r\n } else {\r\n return null\r\n }\r\n }\r\n onUserEvent (f) {\r\n this.userEventListeners.push(f)\r\n }\r\n userLeft (user) {\r\n if (this.connections[user] != null) {\r\n delete this.connections[user]\r\n if (user === this.currentSyncTarget) {\r\n this.currentSyncTarget = null\r\n this.findNextSyncTarget()\r\n }\r\n this.syncingClients = this.syncingClients.filter(function (cli) {\r\n return cli !== user\r\n })\r\n for (var f of this.userEventListeners) {\r\n f({\r\n action: 'userLeft',\r\n user: user\r\n })\r\n }\r\n }\r\n }\r\n userJoined (user, role) {\r\n if (role == null) {\r\n throw new Error('You must specify the role of the joined user!')\r\n }\r\n if (this.connections[user] != null) {\r\n throw new Error('This user already joined!')\r\n }\r\n this.connections[user] = {\r\n isSynced: false,\r\n role: role\r\n }\r\n for (var f of this.userEventListeners) {\r\n f({\r\n action: 'userJoined',\r\n user: user,\r\n role: role\r\n })\r\n }\r\n if (this.currentSyncTarget == null) {\r\n this.findNextSyncTarget()\r\n }\r\n }\r\n // Execute a function _when_ we are connected.\r\n // If not connected, wait until connected\r\n whenSynced (f) {\r\n if (this.isSynced) {\r\n f()\r\n } else {\r\n this.whenSyncedListeners.push(f)\r\n }\r\n }\r\n /*\r\n\r\n returns false, if there is no sync target\r\n true otherwise\r\n */\r\n findNextSyncTarget () {\r\n if (this.currentSyncTarget != null || this.isSynced) {\r\n return // \"The current sync has not finished!\"\r\n }\r\n\r\n var syncUser = null\r\n for (var uid in this.connections) {\r\n if (!this.connections[uid].isSynced) {\r\n syncUser = uid\r\n break\r\n }\r\n }\r\n if (syncUser != null) {\r\n var conn = this\r\n this.currentSyncTarget = syncUser\r\n this.y.db.requestTransaction(function *() {\r\n var stateSet = yield* this.getStateSet()\r\n var deleteSet = yield* this.getDeleteSet()\r\n conn.send(syncUser, {\r\n type: 'sync step 1',\r\n stateSet: stateSet,\r\n deleteSet: deleteSet\r\n })\r\n })\r\n } else {\r\n this.isSynced = true\r\n // call when synced listeners\r\n for (var f of this.whenSyncedListeners) {\r\n f()\r\n }\r\n this.whenSyncedListeners = []\r\n this.y.db.requestTransaction(function *() {\r\n yield* this.garbageCollectAfterSync()\r\n })\r\n }\r\n }\r\n send (uid, message) {\r\n if (this.debug) {\r\n console.log(`send ${this.userId} -> ${uid}: ${message.type}`, message) // eslint-disable-line\r\n }\r\n }\r\n /*\r\n Buffer operations, and broadcast them when ready.\r\n */\r\n broadcastOps (ops) {\r\n ops = ops.map(function (op) {\r\n return Y.Struct[op.struct].encode(op)\r\n })\r\n var self = this\r\n function broadcastOperations () {\r\n if (self.broadcastOpBuffer.length > 0) {\r\n self.broadcast({\r\n type: 'update',\r\n ops: self.broadcastOpBuffer\r\n })\r\n self.broadcastOpBuffer = []\r\n }\r\n }\r\n if (this.broadcastOpBuffer.length === 0) {\r\n this.broadcastOpBuffer = ops\r\n if (this.y.db.transactionInProgress) {\r\n this.y.db.whenTransactionsFinished().then(broadcastOperations)\r\n } else {\r\n setTimeout(broadcastOperations, 0)\r\n }\r\n } else {\r\n this.broadcastOpBuffer = this.broadcastOpBuffer.concat(ops)\r\n }\r\n }\r\n /*\r\n You received a raw message, and you know that it is intended for Yjs. Then call this function.\r\n */\r\n receiveMessage (sender/* :UserId */, message/* :Message */) {\r\n if (sender === this.userId) {\r\n return\r\n }\r\n if (this.debug) {\r\n console.log(`receive ${sender} -> ${this.userId}: ${message.type}`, JSON.parse(JSON.stringify(message))) // eslint-disable-line\r\n }\r\n if (message.protocolVersion != null && message.protocolVersion !== this.protocolVersion) {\r\n console.error(\r\n `You tried to sync with a yjs instance that has a different protocol version\r\n (You: ${this.protocolVersion}, Client: ${message.protocolVersion}).\r\n The sync was stopped. You need to upgrade your dependencies (especially Yjs & the Connector)!\r\n `)\r\n this.send(sender, {\r\n type: 'sync stop',\r\n protocolVersion: this.protocolVersion\r\n })\r\n return\r\n }\r\n if (message.type === 'sync step 1') {\r\n // TODO: make transaction, stream the ops\r\n let conn = this\r\n let m = message\r\n this.y.db.requestTransaction(function *() {\r\n var currentStateSet = yield* this.getStateSet()\r\n yield* this.applyDeleteSet(m.deleteSet)\r\n\r\n var ds = yield* this.getDeleteSet()\r\n var ops = yield* this.getOperations(m.stateSet)\r\n conn.send(sender, {\r\n type: 'sync step 2',\r\n os: ops,\r\n stateSet: currentStateSet,\r\n deleteSet: ds\r\n })\r\n if (this.forwardToSyncingClients) {\r\n conn.syncingClients.push(sender)\r\n setTimeout(function () {\r\n conn.syncingClients = conn.syncingClients.filter(function (cli) {\r\n return cli !== sender\r\n })\r\n conn.send(sender, {\r\n type: 'sync done'\r\n })\r\n }, 5000) // TODO: conn.syncingClientDuration)\r\n } else {\r\n conn.send(sender, {\r\n type: 'sync done'\r\n })\r\n }\r\n conn._setSyncedWith(sender)\r\n })\r\n } else if (message.type === 'sync step 2') {\r\n let conn = this\r\n var broadcastHB = !this.broadcastedHB\r\n this.broadcastedHB = true\r\n var db = this.y.db\r\n var defer = {}\r\n defer.promise = new Promise(function (resolve) {\r\n defer.resolve = resolve\r\n })\r\n this.syncStep2 = defer.promise\r\n let m /* :MessageSyncStep2 */ = message\r\n db.requestTransaction(function * () {\r\n yield* this.applyDeleteSet(m.deleteSet)\r\n this.store.apply(m.os)\r\n db.requestTransaction(function * () {\r\n var ops = yield* this.getOperations(m.stateSet)\r\n if (ops.length > 0) {\r\n if (!broadcastHB) { // TODO: consider to broadcast here..\r\n conn.send(sender, {\r\n type: 'update',\r\n ops: ops\r\n })\r\n } else {\r\n // broadcast only once!\r\n conn.broadcastOps(ops)\r\n }\r\n }\r\n defer.resolve()\r\n })\r\n })\r\n } else if (message.type === 'sync done') {\r\n var self = this\r\n this.syncStep2.then(function () {\r\n self._setSyncedWith(sender)\r\n })\r\n } else if (message.type === 'update') {\r\n if (this.forwardToSyncingClients) {\r\n for (var client of this.syncingClients) {\r\n this.send(client, message)\r\n }\r\n }\r\n if (this.y.db.forwardAppliedOperations) {\r\n var delops = message.ops.filter(function (o) {\r\n return o.struct === 'Delete'\r\n })\r\n if (delops.length > 0) {\r\n this.broadcastOps(delops)\r\n }\r\n }\r\n this.y.db.apply(message.ops)\r\n }\r\n }\r\n _setSyncedWith (user) {\r\n var conn = this.connections[user]\r\n if (conn != null) {\r\n conn.isSynced = true\r\n }\r\n if (user === this.currentSyncTarget) {\r\n this.currentSyncTarget = null\r\n this.findNextSyncTarget()\r\n }\r\n }\r\n /*\r\n Currently, the HB encodes operations as JSON. For the moment I want to keep it\r\n that way. Maybe we support encoding in the HB as XML in the future, but for now I don't want\r\n too much overhead. Y is very likely to get changed a lot in the future\r\n\r\n Because we don't want to encode JSON as string (with character escaping, wich makes it pretty much unreadable)\r\n we encode the JSON as XML.\r\n\r\n When the HB support encoding as XML, the format should look pretty much like this.\r\n\r\n does not support primitive values as array elements\r\n expects an ltx (less than xml) object\r\n */\r\n parseMessageFromXml (m/* :any */) {\r\n function parseArray (node) {\r\n for (var n of node.children) {\r\n if (n.getAttribute('isArray') === 'true') {\r\n return parseArray(n)\r\n } else {\r\n return parseObject(n)\r\n }\r\n }\r\n }\r\n function parseObject (node/* :any */) {\r\n var json = {}\r\n for (var attrName in node.attrs) {\r\n var value = node.attrs[attrName]\r\n var int = parseInt(value, 10)\r\n if (isNaN(int) || ('' + int) !== value) {\r\n json[attrName] = value\r\n } else {\r\n json[attrName] = int\r\n }\r\n }\r\n for (var n/* :any */ in node.children) {\r\n var name = n.name\r\n if (n.getAttribute('isArray') === 'true') {\r\n json[name] = parseArray(n)\r\n } else {\r\n json[name] = parseObject(n)\r\n }\r\n }\r\n return json\r\n }\r\n parseObject(m)\r\n }\r\n /*\r\n encode message in xml\r\n we use string because Strophe only accepts an \"xml-string\"..\r\n So {a:4,b:{c:5}} will look like\r\n <y a=\"4\">\r\n <b c=\"5\"></b>\r\n </y>\r\n m - ltx element\r\n json - Object\r\n */\r\n encodeMessageToXml (msg, obj) {\r\n // attributes is optional\r\n function encodeObject (m, json) {\r\n for (var name in json) {\r\n var value = json[name]\r\n if (name == null) {\r\n // nop\r\n } else if (value.constructor === Object) {\r\n encodeObject(m.c(name), value)\r\n } else if (value.constructor === Array) {\r\n encodeArray(m.c(name), value)\r\n } else {\r\n m.setAttribute(name, value)\r\n }\r\n }\r\n }\r\n function encodeArray (m, array) {\r\n m.setAttribute('isArray', 'true')\r\n for (var e of array) {\r\n if (e.constructor === Object) {\r\n encodeObject(m.c('array-element'), e)\r\n } else {\r\n encodeArray(m.c('array-element'), e)\r\n }\r\n }\r\n }\r\n if (obj.constructor === Object) {\r\n encodeObject(msg.c('y', { xmlns: 'http://y.ninja/connector-stanza' }), obj)\r\n } else if (obj.constructor === Array) {\r\n encodeArray(msg.c('y', { xmlns: 'http://y.ninja/connector-stanza' }), obj)\r\n } else {\r\n throw new Error(\"I can't encode this json!\")\r\n }\r\n }\r\n }\r\n Y.AbstractConnector = AbstractConnector\r\n}\r\n","/* global getRandom, async */\r\n'use strict'\r\n\r\nmodule.exports = function (Y) {\r\n var globalRoom = {\r\n users: {},\r\n buffers: {},\r\n removeUser: function (user) {\r\n for (var i in this.users) {\r\n this.users[i].userLeft(user)\r\n }\r\n delete this.users[user]\r\n delete this.buffers[user]\r\n },\r\n addUser: function (connector) {\r\n this.users[connector.userId] = connector\r\n this.buffers[connector.userId] = []\r\n for (var uname in this.users) {\r\n if (uname !== connector.userId) {\r\n var u = this.users[uname]\r\n u.userJoined(connector.userId, 'master')\r\n connector.userJoined(u.userId, 'master')\r\n }\r\n }\r\n },\r\n whenTransactionsFinished: function () {\r\n var ps = []\r\n for (var name in this.users) {\r\n ps.push(this.users[name].y.db.whenTransactionsFinished())\r\n }\r\n return Promise.all(ps)\r\n },\r\n flushOne: function flushOne () {\r\n var bufs = []\r\n for (var i in globalRoom.buffers) {\r\n if (globalRoom.buffers[i].length > 0) {\r\n bufs.push(i)\r\n }\r\n }\r\n if (bufs.length > 0) {\r\n var userId = getRandom(bufs)\r\n var m = globalRoom.buffers[userId].shift()\r\n var user = globalRoom.users[userId]\r\n user.receiveMessage(m[0], m[1])\r\n return user.y.db.whenTransactionsFinished()\r\n } else {\r\n return false\r\n }\r\n },\r\n flushAll: function () {\r\n return new Promise(function (resolve) {\r\n // flushes may result in more created operations,\r\n // flush until there is nothing more to flush\r\n function nextFlush () {\r\n var c = globalRoom.flushOne()\r\n if (c) {\r\n while (c) {\r\n c = globalRoom.flushOne()\r\n }\r\n globalRoom.whenTransactionsFinished().then(nextFlush)\r\n } else {\r\n setTimeout(function () {\r\n var c = globalRoom.flushOne()\r\n if (c) {\r\n c.then(function () {\r\n globalRoom.whenTransactionsFinished().then(nextFlush)\r\n })\r\n } else {\r\n resolve()\r\n }\r\n }, 10)\r\n }\r\n }\r\n globalRoom.whenTransactionsFinished().then(nextFlush)\r\n })\r\n }\r\n }\r\n Y.utils.globalRoom = globalRoom\r\n\r\n var userIdCounter = 0\r\n\r\n class Test extends Y.AbstractConnector {\r\n constructor (y, options) {\r\n if (options === undefined) {\r\n throw new Error('Options must not be undefined!')\r\n }\r\n options.role = 'master'\r\n options.forwardToSyncingClients = false\r\n super(y, options)\r\n this.setUserId((userIdCounter++) + '').then(() => {\r\n globalRoom.addUser(this)\r\n })\r\n this.globalRoom = globalRoom\r\n this.syncingClientDuration = 0\r\n }\r\n receiveMessage (sender, m) {\r\n super.receiveMessage(sender, JSON.parse(JSON.stringify(m)))\r\n }\r\n send (userId, message) {\r\n var buffer = globalRoom.buffers[userId]\r\n if (buffer != null) {\r\n buffer.push(JSON.parse(JSON.stringify([this.userId, message])))\r\n }\r\n }\r\n broadcast (message) {\r\n for (var key in globalRoom.buffers) {\r\n globalRoom.buffers[key].push(JSON.parse(JSON.stringify([this.userId, message])))\r\n }\r\n }\r\n isDisconnected () {\r\n return globalRoom.users[this.userId] == null\r\n }\r\n reconnect () {\r\n if (this.isDisconnected()) {\r\n globalRoom.addUser(this)\r\n super.reconnect()\r\n }\r\n return Y.utils.globalRoom.flushAll()\r\n }\r\n disconnect () {\r\n if (!this.isDisconnected()) {\r\n globalRoom.removeUser(this.userId)\r\n super.disconnect()\r\n }\r\n return this.y.db.whenTransactionsFinished()\r\n }\r\n flush () {\r\n var self = this\r\n return async(function * () {\r\n while (globalRoom.buffers[self.userId].length > 0) {\r\n var m = globalRoom.buffers[self.userId].shift()\r\n this.receiveMessage(m[0], m[1])\r\n }\r\n yield self.whenTransactionsFinished()\r\n })\r\n }\r\n }\r\n\r\n Y.Test = Test\r\n}\r\n","/* @flow */\n'use strict'\n\nmodule.exports = function (Y /* :any */) {\n /*\n Partial definition of an OperationStore.\n TODO: name it Database, operation store only holds operations.\n\n A database definition must alse define the following methods:\n * logTable() (optional)\n - show relevant information information in a table\n * requestTransaction(makeGen)\n - request a transaction\n * destroy()\n - destroy the database\n */\n class AbstractDatabase {\n /* ::\n y: YConfig;\n forwardAppliedOperations: boolean;\n listenersById: Object;\n listenersByIdExecuteNow: Array<Object>;\n listenersByIdRequestPending: boolean;\n initializedTypes: Object;\n whenUserIdSetListener: ?Function;\n waitingTransactions: Array<Transaction>;\n transactionInProgress: boolean;\n executeOrder: Array<Object>;\n gc1: Array<Struct>;\n gc2: Array<Struct>;\n gcTimeout: number;\n gcInterval: any;\n garbageCollect: Function;\n executeOrder: Array<any>; // for debugging only\n userId: UserId;\n opClock: number;\n transactionsFinished: ?{promise: Promise, resolve: any};\n transact: (x: ?Generator) => any;\n */\n constructor (y, opts) {\n this.y = y\n var os = this\n this.userId = null\n var resolve\n this.userIdPromise = new Promise(function (r) {\n resolve = r\n })\n this.userIdPromise.resolve = resolve\n // whether to broadcast all applied operations (insert & delete hook)\n this.forwardAppliedOperations = false\n // E.g. this.listenersById[id] : Array<Listener>\n this.listenersById = {}\n // Execute the next time a transaction is requested\n this.listenersByIdExecuteNow = []\n // A transaction is requested\n this.listenersByIdRequestPending = false\n /* To make things more clear, the following naming conventions:\n * ls : we put this.listenersById on ls\n * l : Array<Listener>\n * id : Id (can't use as property name)\n * sid : String (converted from id via JSON.stringify\n so we can use it as a property name)\n\n Always remember to first overwrite\n a property before you iterate over it!\n */\n // TODO: Use ES7 Weak Maps. This way types that are no longer user,\n // wont be kept in memory.\n this.initializedTypes = {}\n this.waitingTransactions = []\n this.transactionInProgress = false\n this.transactionIsFlushed = false\n if (typeof YConcurrency_TestingMode !== 'undefined') {\n this.executeOrder = []\n }\n this.gc1 = [] // first stage\n this.gc2 = [] // second stage -> after that, remove the op\n this.gcTimeout = opts.gcTimeout || 50000\n function garbageCollect () {\n return os.whenTransactionsFinished().then(function () {\n if (os.gc1.length > 0 || os.gc2.length > 0) {\n return new Promise((resolve) => {\n os.requestTransaction(function * () {\n if (os.y.connector != null && os.y.connector.isSynced) {\n for (var i = 0; i < os.gc2.length; i++) {\n var oid = os.gc2[i]\n yield* this.garbageCollectOperation(oid)\n }\n os.gc2 = os.gc1\n os.gc1 = []\n }\n // TODO: Use setInterval here instead (when garbageCollect is called several times there will be several timeouts..)\n if (os.gcTimeout > 0) {\n os.gcInterval = setTimeout(garbageCollect, os.gcTimeout)\n }\n resolve()\n })\n })\n } else {\n // TODO: see above\n if (os.gcTimeout > 0) {\n os.gcInterval = setTimeout(garbageCollect, os.gcTimeout)\n }\n return Promise.resolve()\n }\n })\n }\n this.garbageCollect = garbageCollect\n if (this.gcTimeout > 0) {\n garbageCollect()\n }\n }\n addToDebug () {\n if (typeof YConcurrency_TestingMode !== 'undefined') {\n var command /* :string */ = Array.prototype.map.call(arguments, function (s) {\n if (typeof s === 'string') {\n return s\n } else {\n return JSON.stringify(s)\n }\n }).join('').replace(/\"/g, \"'\").replace(/,/g, ', ').replace(/:/g, ': ')\n this.executeOrder.push(command)\n }\n }\n getDebugData () {\n console.log(this.executeOrder.join('\\n'))\n }\n stopGarbageCollector () {\n var self = this\n return new Promise(function (resolve) {\n self.requestTransaction(function * () {\n var ungc /* :Array<Struct> */ = self.gc1.concat(self.gc2)\n self.gc1 = []\n self.gc2 = []\n for (var i = 0; i < ungc.length; i++) {\n var op = yield* this.getOperation(ungc[i])\n delete op.gc\n yield* this.setOperation(op)\n }\n resolve()\n })\n })\n }\n /*\n Try to add to GC.\n\n TODO: rename this function\n\n Rulez:\n * Only gc if this user is online\n * The most left element in a list must not be gc'd.\n => There is at least one element in the list\n\n returns true iff op was added to GC\n */\n addToGarbageCollector (op, left) {\n if (\n op.gc == null &&\n op.deleted === true &&\n this.y.connector.isSynced &&\n left != null &&\n left.deleted === true\n ) {\n op.gc = true\n this.gc1.push(op.id)\n return true\n } else {\n return false\n }\n }\n removeFromGarbageCollector (op) {\n function filter (o) {\n return !Y.utils.compareIds(o, op.id)\n }\n this.gc1 = this.gc1.filter(filter)\n this.gc2 = this.gc2.filter(filter)\n delete op.gc\n }\n * destroy () {\n clearInterval(this.gcInterval)\n this.gcInterval = null\n for (var key in this.initializedTypes) {\n var type = this.initializedTypes[key]\n if (type._destroy != null) {\n type._destroy()\n } else {\n console.error('The type you included does not provide destroy functionality, it will remain in memory (updating your packages will help).')\n }\n }\n }\n setUserId (userId) {\n if (!this.userIdPromise.inProgress) {\n this.userIdPromise.inProgress = true\n var self = this\n self.requestTransaction(function * () {\n self.userId = userId\n var state = yield* this.getState(userId)\n self.opClock = state.clock\n self.userIdPromise.resolve(userId)\n })\n }\n return this.userIdPromise\n }\n whenUserIdSet (f) {\n this.userIdPromise.then(f)\n }\n getNextOpId () {\n if (this.userId == null) {\n throw new Error('OperationStore not yet initialized!')\n } else {\n return [this.userId, this.opClock++]\n }\n }\n /*\n Apply a list of operations.\n\n * get a transaction\n * check whether all Struct.*.requiredOps are in the OS\n * check if it is an expected op (otherwise wait for it)\n * check if was deleted, apply a delete operation after op was applied\n */\n apply (ops) {\n for (var i = 0; i < ops.length; i++) {\n var o = ops[i]\n if (o.id == null || o.id[0] !== this.y.connector.userId) {\n var required = Y.Struct[o.struct].requiredOps(o)\n if (o.requires != null) {\n required = required.concat(o.requires)\n }\n this.whenOperationsExist(required, o)\n }\n }\n }\n /*\n op is executed as soon as every operation requested is available.\n Note that Transaction can (and should) buffer requests.\n */\n whenOperationsExist (ids, op) {\n if (ids.length > 0) {\n let listener = {\n op: op,\n missing: ids.length\n }\n\n for (let i = 0; i < ids.length; i++) {\n let id = ids[i]\n let sid = JSON.stringify(id)\n let l = this.listenersById[sid]\n if (l == null) {\n l = []\n this.listenersById[sid] = l\n }\n l.push(listener)\n }\n } else {\n this.listenersByIdExecuteNow.push({\n op: op\n })\n }\n\n if (this.listenersByIdRequestPending) {\n return\n }\n\n this.listenersByIdRequestPending = true\n var store = this\n\n this.requestTransaction(function * () {\n var exeNow = store.listenersByIdExecuteNow\n store.listenersByIdExecuteNow = []\n\n var ls = store.listenersById\n store.listenersById = {}\n\n store.listenersByIdRequestPending = false\n\n for (let key = 0; key < exeNow.length; key++) {\n let o = exeNow[key].op\n yield* store.tryExecute.call(this, o)\n }\n\n for (var sid in ls) {\n var l = ls[sid]\n var id = JSON.parse(sid)\n var op = yield* this.getOperation(id)\n if (op == null) {\n store.listenersById[sid] = l\n } else {\n for (let i = 0; i < l.length; i++) {\n let listener = l[i]\n let o = listener.op\n if (--listener.missing === 0) {\n yield* store.tryExecute.call(this, o)\n }\n }\n }\n }\n })\n }\n /*\n Actually execute an operation, when all expected operations are available.\n */\n /* :: // TODO: this belongs somehow to transaction\n store: Object;\n getOperation: any;\n isGarbageCollected: any;\n addOperation: any;\n whenOperationsExist: any;\n */\n * tryExecute (op) {\n this.store.addToDebug('yield* this.store.tryExecute.call(this, ', JSON.stringify(op), ')')\n if (op.struct === 'Delete') {\n yield* Y.Struct.Delete.execute.call(this, op)\n yield* this.store.operationAdded(this, op)\n } else {\n var defined = yield* this.getOperation(op.id)\n if (defined == null) {\n var isGarbageCollected = yield* this.isGarbageCollected(op.id)\n if (!isGarbageCollected) {\n yield* Y.Struct[op.struct].execute.call(this, op)\n yield* this.addOperation(op)\n yield* this.store.operationAdded(this, op)\n }\n }\n }\n }\n // called by a transaction when an operation is added\n * operationAdded (transaction, op) {\n if (op.struct === 'Delete') {\n var target = yield* transaction.getOperation(op.target)\n if (target != null) {\n var type = transaction.store.initializedTypes[JSON.stringify(target.parent)]\n if (type != null) {\n yield* type._changed(transaction, {\n struct: 'Delete',\n target: op.target\n })\n }\n }\n } else {\n // increase SS\n var o = op\n var state = yield* transaction.getState(op.id[0])\n while (o != null && o.id[1] === state.clock && op.id[0] === o.id[0]) {\n // either its a new operation (1. case), or it is an operation that was deleted, but is not yet in the OS\n state.clock++\n yield* transaction.checkDeleteStoreForState(state)\n o = yield* transaction.os.findNext(o.id)\n }\n yield* transaction.setState(state)\n\n // notify whenOperation listeners (by id)\n var sid = JSON.stringify(op.id)\n var l = this.listenersById[sid]\n delete this.listenersById[sid]\n\n if (l != null) {\n for (var key in l) {\n var listener = l[key]\n if (--listener.missing === 0) {\n this.whenOperationsExist([], listener.op)\n }\n }\n }\n var t = this.initializedTypes[JSON.stringify(op.parent)]\n\n // Delete if DS says this is actually deleted\n var opIsDeleted = yield* transaction.isDeleted(op.id)\n if (!op.deleted && opIsDeleted) {\n var delop = {\n struct: 'Delete',\n target: op.id\n }\n yield* Y.Struct['Delete'].execute.call(transaction, delop)\n }\n\n // notify parent, if it was instanciated as a custom type\n if (t != null && !opIsDeleted) {\n yield* t._changed(transaction, Y.utils.copyObject(op))\n }\n }\n }\n whenTransactionsFinished () {\n if (this.transactionInProgress) {\n if (this.transactionsFinished == null) {\n var resolve\n var promise = new Promise(function (r) {\n resolve = r\n })\n this.transactionsFinished = {\n resolve: resolve,\n promise: promise\n }\n return promise\n } else {\n return this.transactionsFinished.promise\n }\n } else {\n return Promise.resolve()\n }\n }\n // Check if there is another transaction request.\n // * the last transaction is always a flush :)\n getNextRequest () {\n if (this.waitingTransactions.length === 0) {\n if (this.transactionIsFlushed) {\n this.transactionInProgress = false\n this.transactionIsFlushed = false\n if (this.transactionsFinished != null) {\n this.transactionsFinished.resolve()\n this.transactionsFinished = null\n }\n return null\n } else {\n this.transactionIsFlushed = true\n return function * () {\n yield* this.flush()\n }\n }\n } else {\n this.transactionIsFlushed = false\n return this.waitingTransactions.shift()\n }\n }\n requestTransaction (makeGen/* :any */, callImmediately) {\n this.waitingTransactions.push(makeGen)\n if (!this.transactionInProgress) {\n this.transactionInProgress = true\n if (false || callImmediately) { // TODO: decide whether this is ok or not..\n this.transact(this.getNextRequest())\n } else {\n var self = this\n setTimeout(function () {\n self.transact(self.getNextRequest())\n }, 0)\n }\n }\n }\n }\n Y.AbstractDatabase = AbstractDatabase\n}\n","/* @flow */\n'use strict'\n\n/*\n An operation also defines the structure of a type. This is why operation and\n structure are used interchangeably here.\n\n It must be of the type Object. I hope to achieve some performance\n improvements when working on databases that support the json format.\n\n An operation must have the following properties:\n\n * encode\n - Encode the structure in a readable format (preferably string- todo)\n * decode (todo)\n - decode structure to json\n * execute\n - Execute the semantics of an operation.\n * requiredOps\n - Operations that are required to execute this operation.\n*/\nmodule.exports = function (Y/* :any */) {\n var Struct = {\n /* This is the only operation that is actually not a structure, because\n it is not stored in the OS. This is why it _does not_ have an id\n\n op = {\n target: Id\n }\n */\n Delete: {\n encode: function (op) {\n return op\n },\n requiredOps: function (op) {\n return [] // [op.target]\n },\n execute: function * (op) {\n return yield* this.deleteOperation(op.target)\n }\n },\n Insert: {\n /* {\n content: any,\n id: Id,\n left: Id,\n origin: Id,\n right: Id,\n parent: Id,\n parentSub: string (optional), // child of Map type\n }\n */\n encode: function (op/* :Insertion */) /* :Insertion */ {\n // TODO: you could not send the \"left\" property, then you also have to\n // \"op.left = null\" in $execute or $decode\n var e/* :any */ = {\n id: op.id,\n left: op.left,\n right: op.right,\n origin: op.origin,\n parent: op.parent,\n struct: op.struct\n }\n if (op.parentSub != null) {\n e.parentSub = op.parentSub\n }\n if (op.hasOwnProperty('opContent')) {\n e.opContent = op.opContent\n } else {\n e.content = op.content\n }\n\n return e\n },\n requiredOps: function (op) {\n var ids = []\n if (op.left != null) {\n ids.push(op.left)\n }\n if (op.right != null) {\n ids.push(op.right)\n }\n if (op.origin != null && !Y.utils.compareIds(op.left, op.origin)) {\n ids.push(op.origin)\n }\n // if (op.right == null && op.left == null) {\n ids.push(op.parent)\n\n if (op.opContent != null) {\n ids.push(op.opContent)\n }\n return ids\n },\n getDistanceToOrigin: function * (op) {\n if (op.left == null) {\n return 0\n } else {\n var d = 0\n var o = yield* this.getOperation(op.left)\n while (!Y.utils.compareIds(op.origin, (o ? o.id : null))) {\n d++\n if (o.left == null) {\n break\n } else {\n o = yield* this.getOperation(o.left)\n }\n }\n return d\n }\n },\n /*\n # $this has to find a unique position between origin and the next known character\n # case 1: $origin equals $o.origin: the $creator parameter decides if left or right\n # let $OL= [o1,o2,o3,o4], whereby $this is to be inserted between o1 and o4\n # o2,o3 and o4 origin is 1 (the position of o2)\n # there is the case that $this.creator < o2.creator, but o3.creator < $this.creator\n # then o2 knows o3. Since on another client $OL could be [o1,o3,o4] the problem is complex\n # therefore $this would be always to the right of o3\n # case 2: $origin < $o.origin\n # if current $this insert_position > $o origin: $this ins\n # else $insert_position will not change\n # (maybe we encounter case 1 later, then this will be to the right of $o)\n # case 3: $origin > $o.origin\n # $this insert_position is to the left of $o (forever!)\n */\n execute: function *(op) {\n var i // loop counter\n var distanceToOrigin = i = yield* Struct.Insert.getDistanceToOrigin.call(this, op) // most cases: 0 (starts from 0)\n\n if (op.origin != null) { // TODO: !== instead of !=\n // we save in origin that op originates in it\n // we need that later when we eventually garbage collect origin (see transaction)\n var origin = yield* this.getOperation(op.origin)\n if (origin.originOf == null) {\n origin.originOf = []\n }\n origin.originOf.push(op.id)\n yield* this.setOperation(origin)\n }\n\n // now we begin to insert op in the list of insertions..\n var o\n var parent\n var start\n\n // find o. o is the first conflicting operation\n if (op.left != null) {\n o = yield* this.getOperation(op.left)\n o = (o.right == null) ? null : yield* this.getOperation(o.right)\n } else { // left == null\n parent = yield* this.getOperation(op.parent)\n let startId = op.parentSub ? parent.map[op.parentSub] : parent.start\n start = startId == null ? null : yield* this.getOperation(startId)\n o = start\n }\n\n // handle conflicts\n while (true) {\n if (o != null && !Y.utils.compareIds(o.id, op.right)) {\n var oOriginDistance = yield* Struct.Insert.getDistanceToOrigin.call(this, o)\n if (oOriginDistance === i) {\n // case 1\n if (o.id[0] < op.id[0]) {\n op.left = o.id\n distanceToOrigin = i + 1\n }\n } else if (oOriginDistance < i) {\n // case 2\n if (i - distanceToOrigin <= oOriginDistance) {\n op.left = o.id\n distanceToOrigin = i + 1\n }\n } else {\n break\n }\n i++\n if (o.right != null) {\n o = yield* this.getOperation(o.right)\n } else {\n o = null\n }\n } else {\n break\n }\n }\n\n // reconnect..\n var left = null\n var right = null\n if (parent == null) {\n parent = yield* this.getOperation(op.parent)\n }\n\n // reconnect left and set right of op\n if (op.left != null) {\n left = yield* this.getOperation(op.left)\n op.right = left.right\n left.right = op.id\n\n yield* this.setOperation(left)\n } else {\n op.right = op.parentSub ? parent.map[op.parentSub] || null : parent.start\n }\n // reconnect right\n if (op.right != null) {\n right = yield* this.getOperation(op.right)\n right.left = op.id\n\n // if right exists, and it is supposed to be gc'd. Remove it from the gc\n if (right.gc != null) {\n this.store.removeFromGarbageCollector(right)\n }\n yield* this.setOperation(right)\n }\n\n // update parents .map/start/end properties\n if (op.parentSub != null) {\n if (left == null) {\n parent.map[op.parentSub] = op.id\n yield* this.setOperation(parent)\n }\n // is a child of a map struct.\n // Then also make sure that only the most left element is not deleted\n if (op.right != null) {\n yield* this.deleteOperation(op.right, true)\n }\n if (op.left != null) {\n yield* this.deleteOperation(op.id, true)\n }\n } else {\n if (right == null || left == null) {\n if (right == null) {\n parent.end = op.id\n }\n if (left == null) {\n parent.start = op.id\n }\n yield* this.setOperation(parent)\n }\n }\n }\n },\n List: {\n /*\n {\n start: null,\n end: null,\n struct: \"List\",\n type: \"\",\n id: this.os.getNextOpId()\n }\n */\n create: function (id) {\n return {\n start: null,\n end: null,\n struct: 'List',\n id: id\n }\n },\n encode: function (op) {\n var e = {\n struct: 'List',\n id: op.id,\n type: op.type\n }\n if (op.requires != null) {\n e.requires = op.requires\n }\n if (op.info != null) {\n e.info = op.info\n }\n return e\n },\n requiredOps: function () {\n /*\n var ids = []\n if (op.start != null) {\n ids.push(op.start)\n }\n if (op.end != null){\n ids.push(op.end)\n }\n return ids\n */\n return []\n },\n execute: function * (op) {\n op.start = null\n op.end = null\n },\n ref: function * (op, pos) {\n if (op.start == null) {\n return null\n }\n var res = null\n var o = yield* this.getOperation(op.start)\n\n while (true) {\n if (!o.deleted) {\n res = o\n pos--\n }\n if (pos >= 0 && o.right != null) {\n o = yield* this.getOperation(o.right)\n } else {\n break\n }\n }\n return res\n },\n map: function * (o, f) {\n o = o.start\n var res = []\n while (o != null) { // TODO: change to != (at least some convention)\n var operation = yield* this.getOperation(o)\n if (!operation.deleted) {\n res.push(f(operation))\n }\n o = operation.right\n }\n return res\n }\n },\n Map: {\n /*\n {\n map: {},\n struct: \"Map\",\n type: \"\",\n id: this.os.getNextOpId()\n }\n */\n create: function (id) {\n return {\n id: id,\n map: {},\n struct: 'Map'\n }\n },\n encode: function (op) {\n var e = {\n struct: 'Map',\n type: op.type,\n id: op.id,\n map: {} // overwrite map!!\n }\n if (op.requires != null) {\n e.requires = op.requires\n }\n if (op.info != null) {\n e.info = op.info\n }\n return e\n },\n requiredOps: function () {\n return []\n },\n execute: function * () {},\n /*\n Get a property by name\n */\n get: function * (op, name) {\n var oid = op.map[name]\n if (oid != null) {\n var res = yield* this.getOperation(oid)\n if (res == null || res.deleted) {\n return void 0\n } else if (res.opContent == null) {\n return res.content\n } else {\n return yield* this.getType(res.opContent)\n }\n }\n }\n }\n }\n Y.Struct = Struct\n}\n","/* @flow */\r\n'use strict'\r\n\r\n/*\r\n Partial definition of a transaction\r\n\r\n A transaction provides all the the async functionality on a database.\r\n\r\n By convention, a transaction has the following properties:\r\n * ss for StateSet\r\n * os for OperationStore\r\n * ds for DeleteStore\r\n\r\n A transaction must also define the following methods:\r\n * checkDeleteStoreForState(state)\r\n - When increasing the state of a user, an operation with an higher id\r\n may already be garbage collected, and therefore it will never be received.\r\n update the state to reflect this knowledge. This won't call a method to save the state!\r\n * getDeleteSet(id)\r\n - Get the delete set in a readable format:\r\n {\r\n \"userX\": [\r\n [5,1], // starting from position 5, one operations is deleted\r\n [9,4] // starting from position 9, four operations are deleted\r\n ],\r\n \"userY\": ...\r\n }\r\n * getOpsFromDeleteSet(ds) -- TODO: just call this.deleteOperation(id) here\r\n - get a set of deletions that need to be applied in order to get to\r\n achieve the state of the supplied ds\r\n * setOperation(op)\r\n - write `op` to the database.\r\n Note: this is allowed to return an in-memory object.\r\n E.g. the Memory adapter returns the object that it has in-memory.\r\n Changing values on this object will be stored directly in the database\r\n without calling this function. Therefore,\r\n setOperation may have no functionality in some adapters. This also has\r\n implications on the way we use operations that were served from the database.\r\n We try not to call copyObject, if not necessary.\r\n * addOperation(op)\r\n - add an operation to the database.\r\n This may only be called once for every op.id\r\n Must return a function that returns the next operation in the database (ordered by id)\r\n * getOperation(id)\r\n * removeOperation(id)\r\n - remove an operation from the database. This is called when an operation\r\n is garbage collected.\r\n * setState(state)\r\n - `state` is of the form\r\n {\r\n user: \"1\",\r\n clock: 4\r\n } <- meaning that we have four operations from user \"1\"\r\n (with these id's respectively: 0, 1, 2, and 3)\r\n * getState(user)\r\n * getStateVector()\r\n - Get the state of the OS in the form\r\n [{\r\n user: \"userX\",\r\n clock: 11\r\n },\r\n ..\r\n ]\r\n * getStateSet()\r\n - Get the state of the OS in the form\r\n {\r\n \"userX\": 11,\r\n \"userY\": 22\r\n }\r\n * getOperations(startSS)\r\n - Get the all the operations that are necessary in order to achive the\r\n stateSet of this user, starting from a stateSet supplied by another user\r\n * makeOperationReady(ss, op)\r\n - this is called only by `getOperations(startSS)`. It makes an operation\r\n applyable on a given SS.\r\n*/\r\nmodule.exports = function (Y/* :any */) {\r\n class TransactionInterface {\r\n /* ::\r\n store: Y.AbstractDatabase;\r\n ds: Store;\r\n os: Store;\r\n ss: Store;\r\n */\r\n /*\r\n Get a type based on the id of its model.\r\n If it does not exist yes, create it.\r\n TODO: delete type from store.initializedTypes[id] when corresponding id was deleted!\r\n */\r\n * getType (id, args) {\r\n var sid = JSON.stringify(id)\r\n var t = this.store.initializedTypes[sid]\r\n if (t == null) {\r\n var op/* :MapStruct | ListStruct */ = yield* this.getOperation(id)\r\n if (op != null) {\r\n t = yield* Y[op.type].typeDefinition.initType.call(this, this.store, op, args)\r\n this.store.initializedTypes[sid] = t\r\n }\r\n }\r\n return t\r\n }\r\n * createType (typedefinition, id) {\r\n var structname = typedefinition[0].struct\r\n id = id || this.store.getNextOpId()\r\n var op\r\n if (id[0] === '_') {\r\n op = yield* this.getOperation(id)\r\n } else {\r\n op = Y.Struct[structname].create(id)\r\n op.type = typedefinition[0].name\r\n }\r\n if (typedefinition[0].appendAdditionalInfo != null) {\r\n yield* typedefinition[0].appendAdditionalInfo.call(this, op, typedefinition[1])\r\n }\r\n if (op[0] === '_') {\r\n yield* this.setOperation(op)\r\n } else {\r\n yield* this.applyCreatedOperations([op])\r\n }\r\n return yield* this.getType(id, typedefinition[1])\r\n }\r\n /* createType (typedefinition, id) {\r\n var structname = typedefinition[0].struct\r\n id = id || this.store.getNextOpId()\r\n var op = Y.Struct[structname].create(id)\r\n op.type = typedefinition[0].name\r\n if (typedefinition[0].appendAdditionalInfo != null) {\r\n yield* typedefinition[0].appendAdditionalInfo.call(this, op, typedefinition[1])\r\n }\r\n // yield* this.applyCreatedOperations([op])\r\n yield* Y.Struct[op.struct].execute.call(this, op)\r\n yield* this.addOperation(op)\r\n yield* this.store.operationAdded(this, op)\r\n return yield* this.getType(id, typedefinition[1])\r\n }*/\r\n /*\r\n Apply operations that this user created (no remote ones!)\r\n * does not check for Struct.*.requiredOps()\r\n * also broadcasts it through the connector\r\n */\r\n * applyCreatedOperations (ops) {\r\n var send = []\r\n for (var i = 0; i < ops.length; i++) {\r\n var op = ops[i]\r\n yield* this.store.tryExecute.call(this, op)\r\n if (op.id == null || typeof op.id[1] !== 'string') {\r\n send.push(Y.Struct[op.struct].encode(op))\r\n }\r\n }\r\n if (!this.store.y.connector.isDisconnected() && send.length > 0) { // TODO: && !this.store.forwardAppliedOperations (but then i don't send delete ops)\r\n // is connected, and this is not going to be send in addOperation\r\n this.store.y.connector.broadcastOps(send)\r\n }\r\n }\r\n\r\n * deleteList (start) {\r\n if (this.store.y.connector.isSynced) {\r\n while (start != null && this.store.y.connector.isSynced) {\r\n start = yield* this.getOperation(start)\r\n start.gc = true\r\n yield* this.setOperation(start)\r\n // TODO: will always reset the parent..\r\n this.store.gc1.push(start.id)\r\n start = start.right\r\n }\r\n } else {\r\n // TODO: when not possible??? do later in (gcWhenSynced)\r\n }\r\n }\r\n\r\n /*\r\n Mark an operation as deleted, and add it to the GC, if possible.\r\n */\r\n * deleteOperation (targetId, preventCallType) /* :Generator<any, any, any> */ {\r\n var target = yield* this.getOperation(targetId)\r\n var callType = false\r\n\r\n if (target == null || !target.deleted) {\r\n yield* this.markDeleted(targetId, 1)\r\n }\r\n\r\n if (target != null) {\r\n if (!target.deleted) {\r\n callType = true\r\n // set deleted & notify type\r\n target.deleted = true\r\n /*\r\n if (!preventCallType) {\r\n var type = this.store.initializedTypes[JSON.stringify(target.parent)]\r\n if (type != null) {\r\n yield* type._changed(this, {\r\n struct: 'Delete',\r\n target: targetId\r\n })\r\n }\r\n }\r\n */\r\n // delete containing lists\r\n if (target.start != null) {\r\n // TODO: don't do it like this .. -.-\r\n yield* this.deleteList(target.start)\r\n yield* this.deleteList(target.id)\r\n }\r\n if (target.map != null) {\r\n for (var name in target.map) {\r\n yield* this.deleteList(target.map[name])\r\n }\r\n // TODO: here to.. (see above)\r\n yield* this.deleteList(target.id)\r\n }\r\n if (target.opContent != null) {\r\n yield* this.deleteOperation(target.opContent)\r\n // target.opContent = null\r\n }\r\n }\r\n var left\r\n if (target.left != null) {\r\n left = yield* this.getOperation(target.left)\r\n } else {\r\n left = null\r\n }\r\n\r\n this.store.addToGarbageCollector(target, left)\r\n\r\n // set here because it was deleted and/or gc'd\r\n yield* this.setOperation(target)\r\n\r\n /*\r\n Check if it is possible to add right to the gc.\r\n Because this delete can't be responsible for left being gc'd,\r\n we don't have to add left to the gc..\r\n */\r\n var right\r\n if (target.right != null) {\r\n right = yield* this.getOperation(target.right)\r\n } else {\r\n right = null\r\n }\r\n if (\r\n right != null &&\r\n this.store.addToGarbageCollector(right, target)\r\n ) {\r\n yield* this.setOperation(right)\r\n }\r\n return callType\r\n }\r\n }\r\n /*\r\n Mark an operation as deleted&gc'd\r\n */\r\n * markGarbageCollected (id, len) {\r\n // this.mem.push([\"gc\", id]);\r\n var n = yield* this.markDeleted(id, len)\r\n if (n.id[1] < id[1] && !n.gc) {\r\n // un-extend left\r\n var newlen = n.len - (id[1] - n.id[1])\r\n n.len -= newlen\r\n yield* this.ds.put(n)\r\n n = {id: id, len: newlen, gc: false}\r\n yield* this.ds.put(n)\r\n }\r\n // get prev&next before adding a new operation\r\n var prev = yield* this.ds.findPrev(id)\r\n var next = yield* this.ds.findNext(id)\r\n\r\n if (id[1] < n.id[1] + n.len - len && !n.gc) {\r\n // un-extend right\r\n yield* this.ds.put({id: [id[0], id[1] + 1], len: n.len - 1, gc: false})\r\n n.len = 1\r\n }\r\n // set gc'd\r\n n.gc = true\r\n // can extend left?\r\n if (\r\n prev != null &&\r\n prev.gc &&\r\n Y.utils.compareIds([prev.id[0], prev.id[1] + prev.len], n.id)\r\n ) {\r\n prev.len += n.len\r\n yield* this.ds.delete(n.id)\r\n n = prev\r\n // ds.put n here?\r\n }\r\n // can extend right?\r\n if (\r\n next != null &&\r\n next.gc &&\r\n Y.utils.compareIds([n.id[0], n.id[1] + n.len], next.id)\r\n ) {\r\n n.len += next.len\r\n yield* this.ds.delete(next.id)\r\n }\r\n yield* this.ds.put(n)\r\n }\r\n /*\r\n Mark an operation as deleted.\r\n\r\n returns the delete node\r\n */\r\n * markDeleted (id, length) {\r\n if (length == null) {\r\n length = 1\r\n }\r\n // this.mem.push([\"del\", id]);\r\n var n = yield* this.ds.findWithUpperBound(id)\r\n if (n != null && n.id[0] === id[0]) {\r\n if (n.id[1] <= id[1] && id[1] <= n.id[1] + n.len) {\r\n // id is in n's range\r\n var diff = id[1] + length - (n.id[1] + n.len) // overlapping right\r\n if (diff > 0) {\r\n // id+length overlaps n\r\n if (!n.gc) {\r\n n.len += diff\r\n } else {\r\n diff = n.id[1] + n.len - id[1] // overlapping left (id till n.end)\r\n if (diff < length) {\r\n // a partial deletion\r\n n = {id: [id[0], id[1] + diff], len: length - diff, gc: false}\r\n yield* this.ds.put(n)\r\n } else {\r\n // already gc'd\r\n throw new Error('Cannot happen! (it dit though.. :()')\r\n // return n\r\n }\r\n }\r\n } else {\r\n // no overlapping, already deleted\r\n return n\r\n }\r\n } else {\r\n // cannot extend left (there is no left!)\r\n n = {id: id, len: length, gc: false}\r\n yield* this.ds.put(n) // TODO: you double-put !!\r\n }\r\n } else {\r\n // cannot extend left\r\n n = {id: id, len: length, gc: false}\r\n yield* this.ds.put(n)\r\n }\r\n // can extend right?\r\n var next = yield* this.ds.findNext(n.id)\r\n if (\r\n next != null &&\r\n n.id[0] === next.id[0] &&\r\n n.id[1] + n.len >= next.id[1]\r\n ) {\r\n diff = n.id[1] + n.len - next.id[1] // from next.start to n.end\r\n if (next.gc) {\r\n if (diff >= 0) {\r\n n.len -= diff\r\n if (diff > next.len) {\r\n // need to create another deletion after $next\r\n // TODO: (may not be necessary, because this case shouldn't happen!)\r\n // also this is supposed to return a deletion range. which one to choose? n or the new created deletion?\r\n throw new Error('This case is not handled (on purpose!)')\r\n }\r\n } // else: everything is fine :)\r\n } else {\r\n if (diff >= 0) {\r\n if (diff > next.len) {\r\n // may be neccessary to extend next.next!\r\n // TODO: (may not be necessary, because this case shouldn't happen!)\r\n throw new Error('This case is not handled (on purpose!)')\r\n }\r\n n.len += next.len - diff\r\n yield* this.ds.delete(next.id)\r\n }\r\n }\r\n }\r\n yield* this.ds.put(n)\r\n return n\r\n }\r\n /*\r\n Call this method when the client is connected&synced with the\r\n other clients (e.g. master). This will query the database for\r\n operations that can be gc'd and add them to the garbage collector.\r\n */\r\n * garbageCollectAfterSync () {\r\n yield* this.os.iterate(this, null, null, function * (op) {\r\n if (op.deleted && op.left != null) {\r\n var left = yield* this.getOperation(op.left)\r\n this.store.addToGarbageCollector(op, left)\r\n }\r\n })\r\n }\r\n /*\r\n Really remove an op and all its effects.\r\n The complicated case here is the Insert operation:\r\n * reset left\r\n * reset right\r\n * reset parent.start\r\n * reset parent.end\r\n * reset origins of all right ops\r\n */\r\n * garbageCollectOperation (id) {\r\n this.store.addToDebug('yield* this.garbageCollectOperation(', id, ')')\r\n var o = yield* this.getOperation(id)\r\n yield* this.markGarbageCollected(id, 1) // always mark gc'd\r\n // if op exists, then clean that mess up..\r\n if (o != null) {\r\n /*\r\n if (!o.deleted) {\r\n yield* this.deleteOperation(id)\r\n o = yield* this.getOperation(id)\r\n }\r\n */\r\n\r\n // remove gc'd op from the left op, if it exists\r\n if (o.left != null) {\r\n var left = yield* this.getOperation(o.left)\r\n left.right = o.right\r\n yield* this.setOperation(left)\r\n }\r\n // remove gc'd op from the right op, if it exists\r\n // also reset origins of right ops\r\n if (o.right != null) {\r\n var right = yield* this.getOperation(o.right)\r\n right.left = o.left\r\n\r\n if (o.originOf != null && o.originOf.length > 0) {\r\n // find new origin of right ops\r\n // origin is the first left deleted operation\r\n var neworigin = o.left\r\n var neworigin_ = null\r\n while (neworigin != null) {\r\n neworigin_ = yield* this.getOperation(neworigin)\r\n if (neworigin_.deleted) {\r\n break\r\n }\r\n neworigin = neworigin_.left\r\n }\r\n\r\n // reset origin of all right ops (except first right - duh!),\r\n\r\n /* ** The following code does not rely on the the originOf property **\r\n I recently added originOf to all Insert Operations (see Struct.Insert.execute),\r\n which saves which operations originate in a Insert operation.\r\n Garbage collecting without originOf is more memory efficient, but is nearly impossible for large texts, or lists!\r\n But I keep this code for now\r\n ```\r\n // reset origin of right\r\n right.origin = neworigin\r\n // search until you find origin pointer to the left of o\r\n if (right.right != null) {\r\n var i = yield* this.getOperation(right.right)\r\n var ids = [o.id, o.right]\r\n while (ids.some(function (id) {\r\n return Y.utils.compareIds(id, i.origin)\r\n })) {\r\n if (Y.utils.compareIds(i.origin, o.id)) {\r\n // reset origin of i\r\n i.origin = neworigin\r\n yield* this.setOperation(i)\r\n }\r\n // get next i\r\n if (i.right == null) {\r\n break\r\n } else {\r\n ids.push(i.id)\r\n i = yield* this.getOperation(i.right)\r\n }\r\n }\r\n }\r\n ```\r\n */\r\n // ** Now the new implementation starts **\r\n // reset neworigin of all originOf[*]\r\n for (var _i in o.originOf) {\r\n var originsIn = yield* this.getOperation(o.originOf[_i])\r\n if (originsIn != null) {\r\n originsIn.origin = neworigin\r\n yield* this.setOperation(originsIn)\r\n }\r\n }\r\n if (neworigin != null) {\r\n if (neworigin_.originOf == null) {\r\n neworigin_.originOf = o.originOf\r\n } else {\r\n neworigin_.originOf = o.originOf.concat(neworigin_.originOf)\r\n }\r\n yield* this.setOperation(neworigin_)\r\n }\r\n // we don't need to set right here, because\r\n // right should be in o.originOf => it is set it the previous for loop\r\n } else {\r\n // we didn't need to reset the origin of right\r\n // so we have to set right here\r\n yield* this.setOperation(right)\r\n }\r\n // o may originate in another operation.\r\n // Since o is deleted, we have to reset o.origin's `originOf` property\r\n if (o.origin != null) {\r\n var origin = yield* this.getOperation(o.origin)\r\n origin.originOf = origin.originOf.filter(function (_id) {\r\n return !Y.utils.compareIds(id, _id)\r\n })\r\n yield* this.setOperation(origin)\r\n }\r\n }\r\n var parent\r\n if (o.parent != null){ \r\n parent = yield* this.getOperation(o.parent)\r\n }\r\n // remove gc'd op from parent, if it exists\r\n if (parent != null) {\r\n var setParent = false // whether to save parent to the os\r\n if (o.parentSub != null) {\r\n if (Y.utils.compareIds(parent.map[o.parentSub], o.id)) {\r\n setParent = true\r\n parent.map[o.parentSub] = o.right\r\n }\r\n } else {\r\n if (Y.utils.compareIds(parent.start, o.id)) {\r\n // gc'd op is the start\r\n setParent = true\r\n parent.start = o.right\r\n }\r\n if (Y.utils.compareIds(parent.end, o.id)) {\r\n // gc'd op is the end\r\n setParent = true\r\n parent.end = o.left\r\n }\r\n }\r\n if (setParent) {\r\n yield* this.setOperation(parent)\r\n }\r\n }\r\n // finally remove it from the os\r\n yield* this.removeOperation(o.id)\r\n }\r\n }\r\n * checkDeleteStoreForState (state) {\r\n var n = yield* this.ds.findWithUpperBound([state.user, state.clock])\r\n if (n != null && n.id[0] === state.user && n.gc) {\r\n state.clock = Math.max(state.clock, n.id[1] + n.len)\r\n }\r\n }\r\n /*\r\n apply a delete set in order to get\r\n the state of the supplied ds\r\n */\r\n * applyDeleteSet (ds) {\r\n var deletions = []\r\n function createDeletions (user, start, len, gc) {\r\n deletions.push([user, start, len, gc])\r\n }\r\n\r\n for (var user in ds) {\r\n var dv = ds[user]\r\n var pos = 0\r\n var d = dv[pos]\r\n yield* this.ds.iterate(this, [user, 0], [user, Number.MAX_VALUE], function * (n) {\r\n // cases:\r\n // 1. d deletes something to the right of n\r\n // => go to next n (break)\r\n // 2. d deletes something to the left of n\r\n // => create deletions\r\n // => reset d accordingly\r\n // *)=> if d doesn't delete anything anymore, go to next d (continue)\r\n // 3. not 2) and d deletes something that also n deletes\r\n // => reset d so that it doesn't contain n's deletion\r\n // *)=> if d does not delete anything anymore, go to next d (continue)\r\n while (d != null) {\r\n var diff = 0 // describe the diff of length in 1) and 2)\r\n if (n.id[1] + n.len <= d[0]) {\r\n // 1)\r\n break\r\n } else if (d[0] < n.id[1]) {\r\n // 2)\r\n // delete maximum the len of d\r\n // else delete as much as possible\r\n diff = Math.min(n.id[1] - d[0], d[1])\r\n createDeletions(user, d[0], diff, d[2])\r\n } else {\r\n // 3)\r\n diff = n.id[1] + n.len - d[0] // never null (see 1)\r\n if (d[2] && !n.gc) {\r\n // d marks as gc'd but n does not\r\n // then delete either way\r\n createDeletions(user, d[0], Math.min(diff, d[1]), d[2])\r\n }\r\n }\r\n if (d[1] <= diff) {\r\n // d doesn't delete anything anymore\r\n d = dv[++pos]\r\n } else {\r\n d[0] = d[0] + diff // reset pos\r\n d[1] = d[1] - diff // reset length\r\n }\r\n }\r\n })\r\n // for the rest.. just apply it\r\n for (; pos < dv.length; pos++) {\r\n d = dv[pos]\r\n createDeletions(user, d[0], d[1], d[2])\r\n }\r\n }\r\n for (var i = 0; i < deletions.length; i++) {\r\n var del = deletions[i]\r\n // always try to delete..\r\n var state = yield* this.getState(del[0])\r\n if (del[1] < state.clock) {\r\n for (let c = del[1]; c < del[1] + del[2]; c++) {\r\n var id = [del[0], c]\r\n var addOperation = yield* this.deleteOperation(id)\r\n if (addOperation) {\r\n // TODO:.. really .. here? You could prevent calling all these functions in operationAdded\r\n yield* this.store.operationAdded(this, {struct: 'Delete', target: id})\r\n }\r\n if (del[3]) {\r\n // gc\r\n yield* this.garbageCollectOperation(id)\r\n }\r\n }\r\n } else {\r\n if (del[3]) {\r\n yield* this.markGarbageCollected([del[0], del[1]], del[2])\r\n } else {\r\n yield* this.markDeleted([del[0], del[1]], del[2])\r\n }\r\n }\r\n if (del[3]) {\r\n // check to increase the state of the respective user\r\n if (state.clock >= del[1] && state.clock < del[1] + del[2]) {\r\n state.clock = del[1] + del[2]\r\n // also check if more expected operations were gc'd\r\n yield* this.checkDeleteStoreForState(state) // TODO: unneccessary?\r\n // then set the state\r\n yield* this.setState(state)\r\n }\r\n }\r\n if (this.store.forwardAppliedOperations) {\r\n var ops = []\r\n for (let c = del[1]; c < del[1] + del[2]; c++) {\r\n ops.push({struct: 'Delete', target: [d[0], c]}) // TODO: implement Delete with deletion length!\r\n }\r\n this.store.y.connector.broadcastOps(ops)\r\n }\r\n }\r\n }\r\n * isGarbageCollected (id) {\r\n var n = yield* this.ds.findWithUpperBound(id)\r\n return n != null && n.id[0] === id[0] && id[1] < n.id[1] + n.len && n.gc\r\n }\r\n /*\r\n A DeleteSet (ds) describes all the deleted ops in the OS\r\n */\r\n * getDeleteSet () {\r\n var ds = {}\r\n yield* this.ds.iterate(this, null, null, function * (n) {\r\n var user = n.id[0]\r\n var counter = n.id[1]\r\n var len = n.len\r\n var gc = n.gc\r\n var dv = ds[user]\r\n if (dv === void 0) {\r\n dv = []\r\n ds[user] = dv\r\n }\r\n dv.push([counter, len, gc])\r\n })\r\n return ds\r\n }\r\n * isDeleted (id) {\r\n var n = yield* this.ds.findWithUpperBound(id)\r\n return n != null && n.id[0] === id[0] && id[1] < n.id[1] + n.len\r\n }\r\n * setOperation (op) {\r\n yield* this.os.put(op)\r\n return op\r\n }\r\n * addOperation (op) {\r\n yield* this.os.put(op)\r\n if (!this.store.y.connector.isDisconnected() && this.store.forwardAppliedOperations && typeof op.id[1] !== 'string') {\r\n // is connected, and this is not going to be send in addOperation\r\n this.store.y.connector.broadcastOps([op])\r\n }\r\n }\r\n * getOperation (id/* :any */)/* :Transaction<any> */ {\r\n var o = yield* this.os.find(id)\r\n if (o != null || id[0] !== '_') {\r\n return o\r\n } else {\r\n // generate this operation?\r\n var comp = id[1].split('_')\r\n if (comp.length > 1) {\r\n var struct = comp[0]\r\n var op = Y.Struct[struct].create(id)\r\n op.type = comp[1]\r\n yield* this.setOperation(op)\r\n return op\r\n } else {\r\n // won't be called. but just in case..\r\n console.error('Unexpected case. How can this happen?')\r\n debugger // eslint-disable-line\r\n return null\r\n }\r\n return null\r\n }\r\n }\r\n * removeOperation (id) {\r\n yield* this.os.delete(id)\r\n }\r\n * setState (state) {\r\n var val = {\r\n id: [state.user],\r\n clock: state.clock\r\n }\r\n yield* this.ss.put(val)\r\n }\r\n * getState (user) {\r\n var n = yield* this.ss.find([user])\r\n var clock = n == null ? null : n.clock\r\n if (clock == null) {\r\n clock = 0\r\n }\r\n return {\r\n user: user,\r\n clock: clock\r\n }\r\n }\r\n * getStateVector () {\r\n var stateVector = []\r\n yield* this.ss.iterate(this, null, null, function * (n) {\r\n stateVector.push({\r\n user: n.id[0],\r\n clock: n.clock\r\n })\r\n })\r\n return stateVector\r\n }\r\n * getStateSet () {\r\n var ss = {}\r\n yield* this.ss.iterate(this, null, null, function * (n) {\r\n ss[n.id[0]] = n.clock\r\n })\r\n return ss\r\n }\r\n /*\r\n Here, we make all missing operations executable for the receiving user.\r\n\r\n Notes:\r\n startSS: denotes to the SV that the remote user sent\r\n currSS: denotes to the state vector that the user should have if he\r\n applies all already sent operations (increases is each step)\r\n\r\n We face several problems:\r\n * Execute op as is won't work because ops depend on each other\r\n -> find a way so that they do not anymore\r\n * When changing left, must not go more to the left than the origin\r\n * When changing right, you have to consider that other ops may have op\r\n as their origin, this means that you must not set one of these ops\r\n as the new right (interdependencies of ops)\r\n * can't just go to the right until you find the first known operation,\r\n With currSS\r\n -> interdependency of ops is a problem\r\n With startSS\r\n -> leads to inconsistencies when two users join at the same time.\r\n Then the position depends on the order of execution -> error!\r\n\r\n Solution:\r\n -> re-create originial situation\r\n -> set op.left = op.origin (which never changes)\r\n -> set op.right\r\n to the first operation that is known (according to startSS)\r\n or to the first operation that has an origin that is not to the\r\n right of op.\r\n -> Enforces unique execution order -> happy user\r\n\r\n Improvements: TODO\r\n * Could set left to origin, or the first known operation\r\n (startSS or currSS.. ?)\r\n -> Could be necessary when I turn GC again.\r\n -> Is a bad(ish) idea because it requires more computation\r\n\r\n What we do:\r\n * Iterate over all missing operations.\r\n * When there is an operation, where the right op is known, send this op all missing ops to the left to the user\r\n * I explained above what we have to do with each operation. Here is how we do it efficiently:\r\n 1. Go to the left until you find either op.origin, or a known operation (let o denote current operation in the iteration)\r\n 2. Found a known operation -> set op.left = o, and send it to the user. stop\r\n 3. Found o = op.origin -> set op.left = op.origin, and send it to the user. start again from 1. (set op = o)\r\n 4. Found some o -> set o.right = op, o.left = o.origin, send it to the user, continue\r\n */\r\n * getOperations (startSS) {\r\n // TODO: use bounds here!\r\n if (startSS == null) {\r\n startSS = {}\r\n }\r\n var send = []\r\n\r\n var endSV = yield* this.getStateVector()\r\n for (var endState of endSV) {\r\n var user = endState.user\r\n if (user === '_') {\r\n continue\r\n }\r\n var startPos = startSS[user] || 0\r\n\r\n yield* this.os.iterate(this, [user, startPos], [user, Number.MAX_VALUE], function * (op) {\r\n op = Y.Struct[op.struct].encode(op)\r\n if (op.struct !== 'Insert') {\r\n send.push(op)\r\n } else if (op.right == null || op.right[1] < (startSS[op.right[0]] || 0)) {\r\n // case 1. op.right is known\r\n var o = op\r\n // Remember: ?\r\n // -> set op.right\r\n // 1. to the first operation that is known (according to startSS)\r\n // 2. or to the first operation that has an origin that is not to the\r\n // right of op.\r\n // For this we maintain a list of ops which origins are not found yet.\r\n var missing_origins = [op]\r\n var newright = op.right\r\n while (true) {\r\n if (o.left == null) {\r\n op.left = null\r\n send.push(op)\r\n if (!Y.utils.compareIds(o.id, op.id)) {\r\n o = Y.Struct[op.struct].encode(o)\r\n o.right = missing_origins[missing_origins.length - 1].id\r\n send.push(o)\r\n }\r\n break\r\n }\r\n o = yield* this.getOperation(o.left)\r\n // we set another o, check if we can reduce $missing_origins\r\n while (missing_origins.length > 0 && Y.utils.compareIds(missing_origins[missing_origins.length - 1].origin, o.id)) {\r\n missing_origins.pop()\r\n }\r\n if (o.id[1] < (startSS[o.id[0]] || 0)) {\r\n // case 2. o is known\r\n op.left = o.id\r\n send.push(op)\r\n break\r\n } else if (Y.utils.compareIds(o.id, op.origin)) {\r\n // case 3. o is op.origin\r\n op.left = op.origin\r\n send.push(op)\r\n op = Y.Struct[op.struct].encode(o)\r\n op.right = newright\r\n if (missing_origins.length > 0) {\r\n console.log('This should not happen .. :( please report this')\r\n }\r\n missing_origins = [op]\r\n } else {\r\n // case 4. send o, continue to find op.origin\r\n var s = Y.Struct[op.struct].encode(o)\r\n s.right = missing_origins[missing_origins.length - 1].id\r\n s.left = s.origin\r\n send.push(s)\r\n missing_origins.push(o)\r\n }\r\n }\r\n }\r\n })\r\n }\r\n return send.reverse()\r\n }\r\n /* this is what we used before.. use this as a reference..\r\n * makeOperationReady (startSS, op) {\r\n op = Y.Struct[op.struct].encode(op)\r\n op = Y.utils.copyObject(op)\r\n var o = op\r\n var ids = [op.id]\r\n // search for the new op.right\r\n // it is either the first known op (according to startSS)\r\n // or the o that has no origin to the right of op\r\n // (this is why we use the ids array)\r\n while (o.right != null) {\r\n var right = yield* this.getOperation(o.right)\r\n if (o.right[1] < (startSS[o.right[0]] || 0) || !ids.some(function (id) {\r\n return Y.utils.compareIds(id, right.origin)\r\n })) {\r\n break\r\n }\r\n ids.push(o.right)\r\n o = right\r\n }\r\n op.right = o.right\r\n op.left = op.origin\r\n return op\r\n }\r\n */\r\n * flush () {\r\n yield* this.os.flush()\r\n yield* this.ss.flush()\r\n yield* this.ds.flush()\r\n }\r\n }\r\n Y.Transaction = TransactionInterface\r\n}\r\n","/* @flow */\n'use strict'\n\n/*\n EventHandler is an helper class for constructing custom types.\n\n Why: When constructing custom types, you sometimes want your types to work\n synchronous: E.g.\n ``` Synchronous\n mytype.setSomething(\"yay\")\n mytype.getSomething() === \"yay\"\n ```\n versus\n ``` Asynchronous\n mytype.setSomething(\"yay\")\n mytype.getSomething() === undefined\n mytype.waitForSomething().then(function(){\n mytype.getSomething() === \"yay\"\n })\n ```\n\n The structures usually work asynchronously (you have to wait for the\n database request to finish). EventHandler helps you to make your type\n synchronous.\n*/\nmodule.exports = function (Y /* : any*/) {\n Y.utils = {}\n\n class EventListenerHandler {\n constructor () {\n this.eventListeners = []\n }\n destroy () {\n this.eventListeners = null\n }\n /*\n Basic event listener boilerplate...\n */\n addEventListener (f) {\n this.eventListeners.push(f)\n }\n removeEventListener (f) {\n this.eventListeners = this.eventListeners.filter(function (g) {\n return f !== g\n })\n }\n removeAllEventListeners () {\n this.eventListeners = []\n }\n callEventListeners (event) {\n for (var i = 0; i < this.eventListeners.length; i++) {\n try {\n this.eventListeners[i](event)\n } catch (e) {\n console.error('User events must not throw Errors!')\n }\n }\n }\n }\n Y.utils.EventListenerHandler = EventListenerHandler\n\n class EventHandler extends EventListenerHandler {\n /* ::\n waiting: Array<Insertion | Deletion>;\n awaiting: number;\n onevent: Function;\n eventListeners: Array<Function>;\n */\n /*\n onevent: is called when the structure changes.\n\n Note: \"awaiting opertations\" is used to denote operations that were\n prematurely called. Events for received operations can not be executed until\n all prematurely called operations were executed (\"waiting operations\")\n */\n constructor (onevent /* : Function */) {\n super()\n this.waiting = []\n this.awaiting = 0\n this.onevent = onevent\n }\n destroy () {\n super.destroy()\n this.waiting = null\n this.awaiting = null\n this.onevent = null\n }\n /*\n Call this when a new operation arrives. It will be executed right away if\n there are no waiting operations, that you prematurely executed\n */\n receivedOp (op) {\n if (this.awaiting <= 0) {\n this.onevent([op])\n } else {\n this.waiting.push(Y.utils.copyObject(op))\n }\n }\n /*\n You created some operations, and you want the `onevent` function to be\n called right away. Received operations will not be executed untill all\n prematurely called operations are executed\n */\n awaitAndPrematurelyCall (ops) {\n this.awaiting++\n this.onevent(ops)\n }\n /*\n Call this when you successfully awaited the execution of n Insert operations\n */\n awaitedInserts (n) {\n var ops = this.waiting.splice(this.waiting.length - n)\n for (var oid = 0; oid < ops.length; oid++) {\n var op = ops[oid]\n if (op.struct === 'Insert') {\n for (var i = this.waiting.length - 1; i >= 0; i--) {\n let w = this.waiting[i]\n if (w.struct === 'Insert') {\n if (Y.utils.compareIds(op.left, w.id)) {\n // include the effect of op in w\n w.right = op.id\n // exclude the effect of w in op\n op.left = w.left\n } else if (Y.utils.compareIds(op.right, w.id)) {\n // similar..\n w.left = op.id\n op.right = w.right\n }\n }\n }\n } else {\n throw new Error('Expected Insert Operation!')\n }\n }\n this._tryCallEvents()\n }\n /*\n Call this when you successfully awaited the execution of n Delete operations\n */\n awaitedDeletes (n, newLeft) {\n var ops = this.waiting.splice(this.waiting.length - n)\n for (var j = 0; j < ops.length; j++) {\n var del = ops[j]\n if (del.struct === 'Delete') {\n if (newLeft != null) {\n for (var i = 0; i < this.waiting.length; i++) {\n let w = this.waiting[i]\n // We will just care about w.left\n if (w.struct === 'Insert' && Y.utils.compareIds(del.target, w.left)) {\n w.left = newLeft\n }\n }\n }\n } else {\n throw new Error('Expected Delete Operation!')\n }\n }\n this._tryCallEvents()\n }\n /* (private)\n Try to execute the events for the waiting operations\n */\n _tryCallEvents () {\n this.awaiting--\n if (this.awaiting <= 0 && this.waiting.length > 0) {\n var events = this.waiting\n this.waiting = []\n this.onevent(events)\n }\n }\n }\n Y.utils.EventHandler = EventHandler\n\n /*\n A wrapper for the definition of a custom type.\n Every custom type must have three properties:\n\n * struct\n - Structname of this type\n * initType\n - Given a model, creates a custom type\n * class\n - the constructor of the custom type (e.g. in order to inherit from a type)\n */\n class CustomType { // eslint-disable-line\n /* ::\n struct: any;\n initType: any;\n class: Function;\n name: String;\n */\n constructor (def) {\n if (def.struct == null ||\n def.initType == null ||\n def.class == null ||\n def.name == null\n ) {\n throw new Error('Custom type was not initialized correctly!')\n }\n this.struct = def.struct\n this.initType = def.initType\n this.class = def.class\n this.name = def.name\n if (def.appendAdditionalInfo != null) {\n this.appendAdditionalInfo = def.appendAdditionalInfo\n }\n this.parseArguments = (def.parseArguments || function () {\n return [this]\n }).bind(this)\n this.parseArguments.typeDefinition = this\n }\n }\n Y.utils.CustomType = CustomType\n\n Y.utils.isTypeDefinition = function isTypeDefinition (v) {\n if (v != null) {\n if (v instanceof Y.utils.CustomType) return [v]\n else if (v.constructor === Array && v[0] instanceof Y.utils.CustomType) return v\n else if (v instanceof Function && v.typeDefinition instanceof Y.utils.CustomType) return [v.typeDefinition]\n }\n return false\n }\n\n /*\n Make a flat copy of an object\n (just copy properties)\n */\n function copyObject (o) {\n var c = {}\n for (var key in o) {\n c[key] = o[key]\n }\n return c\n }\n Y.utils.copyObject = copyObject\n\n /*\n Defines a smaller relation on Id's\n */\n function smaller (a, b) {\n return a[0] < b[0] || (a[0] === b[0] && (a[1] < b[1] || typeof a[1] < typeof b[1]))\n }\n Y.utils.smaller = smaller\n\n function compareIds (id1, id2) {\n if (id1 == null || id2 == null) {\n if (id1 == null && id2 == null) {\n return true\n }\n return false\n }\n if (id1[0] === id2[0] && id1[1] === id2[1]) {\n return true\n } else {\n return false\n }\n }\n Y.utils.compareIds = compareIds\n\n function createEmptyOpsArray (n) {\n var a = new Array(n)\n for (var i = 0; i < a.length; i++) {\n a[i] = {\n id: [null, null]\n }\n }\n return a\n }\n\n function createSmallLookupBuffer (Store) {\n /*\n This buffer implements a very small buffer that temporarily stores operations\n after they are read / before they are written.\n The buffer basically implements FIFO. Often requested lookups will be re-queued every time they are looked up / written.\n\n It can speed up lookups on Operation Stores and State Stores. But it does not require notable use of memory or processing power.\n\n Good for os and ss, bot not for ds (because it often uses methods that require a flush)\n\n I tried to optimize this for performance, therefore no highlevel operations.\n */\n class SmallLookupBuffer extends Store {\n constructor () {\n super(...arguments)\n this.writeBuffer = createEmptyOpsArray(5)\n this.readBuffer = createEmptyOpsArray(10)\n }\n * find (id) {\n var i, r\n for (i = this.readBuffer.length - 1; i >= 0; i--) {\n r = this.readBuffer[i]\n // we don't have to use compareids, because id is always defined!\n if (r.id[1] === id[1] && r.id[0] === id[0]) {\n // found r\n // move r to the end of readBuffer\n for (; i < this.readBuffer.length - 1; i++) {\n this.readBuffer[i] = this.readBuffer[i + 1]\n }\n this.readBuffer[this.readBuffer.length - 1] = r\n return r\n }\n }\n var o\n for (i = this.writeBuffer.length - 1; i >= 0; i--) {\n r = this.writeBuffer[i]\n if (r.id[1] === id[1] && r.id[0] === id[0]) {\n o = r\n break\n }\n }\n if (i < 0) {\n // did not reach break in last loop\n // read id and put it to the end of readBuffer\n o = yield* super.find(id)\n }\n if (o != null) {\n for (i = 0; i < this.readBuffer.length - 1; i++) {\n this.readBuffer[i] = this.readBuffer[i + 1]\n }\n this.readBuffer[this.readBuffer.length - 1] = o\n }\n return o\n }\n * put (o) {\n var id = o.id\n var i, r // helper variables\n for (i = this.writeBuffer.length - 1; i >= 0; i--) {\n r = this.writeBuffer[i]\n if (r.id[1] === id[1] && r.id[0] === id[0]) {\n // is already in buffer\n // forget r, and move o to the end of writeBuffer\n for (; i < this.writeBuffer.length - 1; i++) {\n this.writeBuffer[i] = this.writeBuffer[i + 1]\n }\n this.writeBuffer[this.writeBuffer.length - 1] = o\n break\n }\n }\n if (i < 0) {\n // did not reach break in last loop\n // write writeBuffer[0]\n var write = this.writeBuffer[0]\n if (write.id[0] !== null) {\n yield* super.put(write)\n }\n // put o to the end of writeBuffer\n for (i = 0; i < this.writeBuffer.length - 1; i++) {\n this.writeBuffer[i] = this.writeBuffer[i + 1]\n }\n this.writeBuffer[this.writeBuffer.length - 1] = o\n }\n // check readBuffer for every occurence of o.id, overwrite if found\n // whether found or not, we'll append o to the readbuffer\n for (i = 0; i < this.readBuffer.length - 1; i++) {\n r = this.readBuffer[i + 1]\n if (r.id[1] === id[1] && r.id[0] === id[0]) {\n this.readBuffer[i] = o\n } else {\n this.readBuffer[i] = r\n }\n }\n this.readBuffer[this.readBuffer.length - 1] = o\n }\n * delete (id) {\n var i, r\n for (i = 0; i < this.readBuffer.length; i++) {\n r = this.readBuffer[i]\n if (r.id[1] === id[1] && r.id[0] === id[0]) {\n this.readBuffer[i] = {\n id: [null, null]\n }\n }\n }\n yield* this.flush()\n yield* super.delete(id)\n }\n * findWithLowerBound () {\n yield* this.flush()\n return yield* super.findWithLowerBound.apply(this, arguments)\n }\n * findWithUpperBound () {\n yield* this.flush()\n return yield* super.findWithUpperBound.apply(this, arguments)\n }\n * findNext () {\n yield* this.flush()\n return yield* super.findNext.apply(this, arguments)\n }\n * findPrev () {\n yield* this.flush()\n return yield* super.findPrev.apply(this, arguments)\n }\n * iterate () {\n yield* this.flush()\n yield* super.iterate.apply(this, arguments)\n }\n * flush () {\n for (var i = 0; i < this.writeBuffer.length; i++) {\n var write = this.writeBuffer[i]\n if (write.id[0] !== null) {\n yield* super.put(write)\n this.writeBuffer[i] = {\n id: [null, null]\n }\n }\n }\n }\n }\n return SmallLookupBuffer\n }\n Y.utils.createSmallLookupBuffer = createSmallLookupBuffer\n}\n","/* @flow */\r\n'use strict'\r\n\r\nrequire('./Connector.js')(Y)\r\nrequire('./Database.js')(Y)\r\nrequire('./Transaction.js')(Y)\r\nrequire('./Struct.js')(Y)\r\nrequire('./Utils.js')(Y)\r\nrequire('./Connectors/Test.js')(Y)\r\n\r\nvar requiringModules = {}\r\n\r\nmodule.exports = Y\r\nY.requiringModules = requiringModules\r\n\r\nY.extend = function (name, value) {\r\n if (value instanceof Y.utils.CustomType) {\r\n Y[name] = value.parseArguments\r\n } else {\r\n Y[name] = value\r\n }\r\n if (requiringModules[name] != null) {\r\n requiringModules[name].resolve()\r\n delete requiringModules[name]\r\n }\r\n}\r\n\r\nY.requestModules = requestModules\r\nfunction requestModules (modules) {\r\n // determine if this module was compiled for es5 or es6 (y.js vs. y.es6)\r\n // if Insert.execute is a Function, then it isnt a generator..\r\n // then load the es5(.js) files..\r\n var extention = typeof regeneratorRuntime !== 'undefined' ? '.js' : '.es6'\r\n var promises = []\r\n for (var i = 0; i < modules.length; i++) {\r\n var module = modules[i].split('(')[0]\r\n var modulename = 'y-' + module.toLowerCase()\r\n if (Y[module] == null) {\r\n if (requiringModules[module] == null) {\r\n // module does not exist\r\n if (typeof window !== 'undefined' && window.Y !== 'undefined') {\r\n var imported = document.createElement('script')\r\n imported.src = Y.sourceDir + '/' + modulename + '/' + modulename + extention\r\n document.head.appendChild(imported)\r\n\r\n let requireModule = {}\r\n requiringModules[module] = requireModule\r\n requireModule.promise = new Promise(function (resolve) {\r\n requireModule.resolve = resolve\r\n })\r\n promises.push(requireModule.promise)\r\n } else {\r\n require(modulename)(Y)\r\n }\r\n } else {\r\n promises.push(requiringModules[modules[i]].promise)\r\n }\r\n }\r\n }\r\n return Promise.all(promises)\r\n}\r\n\r\n/* ::\r\ntype MemoryOptions = {\r\n name: 'memory'\r\n}\r\ntype IndexedDBOptions = {\r\n name: 'indexeddb',\r\n namespace: string\r\n}\r\ntype DbOptions = MemoryOptions | IndexedDBOptions\r\n\r\ntype WebRTCOptions = {\r\n name: 'webrtc',\r\n room: string\r\n}\r\ntype WebsocketsClientOptions = {\r\n name: 'websockets-client',\r\n room: string\r\n}\r\ntype ConnectionOptions = WebRTCOptions | WebsocketsClientOptions\r\n\r\ntype YOptions = {\r\n connector: ConnectionOptions,\r\n db: DbOptions,\r\n types: Array<TypeName>,\r\n sourceDir: string,\r\n share: {[key: string]: TypeName}\r\n}\r\n*/\r\n\r\nfunction Y (opts/* :YOptions */) /* :Promise<YConfig> */ {\r\n opts.types = opts.types != null ? opts.types : []\r\n var modules = [opts.db.name, opts.connector.name].concat(opts.types)\r\n for (var name in opts.share) {\r\n modules.push(opts.share[name])\r\n }\r\n Y.sourceDir = opts.sourceDir\r\n return Y.requestModules(modules).then(function () {\r\n return new Promise(function (resolve, reject) {\r\n if (opts == null) reject('An options object is expected! ')\r\n else if (opts.connector == null) reject('You must specify a connector! (missing connector property)')\r\n else if (opts.connector.name == null) reject('You must specify connector name! (missing connector.name property)')\r\n else if (opts.db == null) reject('You must specify a database! (missing db property)')\r\n else if (opts.connector.name == null) reject('You must specify db name! (missing db.name property)')\r\n else if (opts.share == null) reject('You must specify a set of shared types!')\r\n else {\r\n var yconfig = new YConfig(opts)\r\n yconfig.db.whenUserIdSet(function () {\r\n yconfig.init(function () {\r\n resolve(yconfig)\r\n })\r\n })\r\n }\r\n })\r\n })\r\n}\r\n\r\nclass YConfig {\r\n /* ::\r\n db: Y.AbstractDatabase;\r\n connector: Y.AbstractConnector;\r\n share: {[key: string]: any};\r\n options: Object;\r\n */\r\n constructor (opts, callback) {\r\n this.options = opts\r\n this.db = new Y[opts.db.name](this, opts.db)\r\n this.connector = new Y[opts.connector.name](this, opts.connector)\r\n }\r\n init (callback) {\r\n var opts = this.options\r\n var share = {}\r\n this.share = share\r\n this.db.requestTransaction(function * requestTransaction () {\r\n // create shared object\r\n for (var propertyname in opts.share) {\r\n var typeConstructor = opts.share[propertyname].split('(')\r\n var typeName = typeConstructor.splice(0, 1)\r\n var args = []\r\n if (typeConstructor.length === 1) {\r\n try {\r\n args = JSON.parse('[' + typeConstructor[0].split(')')[0] + ']')\r\n } catch (e) {\r\n throw new Error('Was not able to parse type definition! (share.' + propertyname + ')')\r\n }\r\n }\r\n var type = Y[typeName]\r\n var typedef = type.typeDefinition\r\n var id = ['_', typedef.struct + '_' + typeName + '_' + propertyname + '_' + typeConstructor]\r\n share[propertyname] = yield* this.createType(type.apply(typedef, args), id)\r\n }\r\n this.store.whenTransactionsFinished()\r\n .then(callback)\r\n })\r\n }\r\n isConnected () {\r\n return this.connector.isSynced\r\n }\r\n disconnect () {\r\n return this.connector.disconnect()\r\n }\r\n reconnect () {\r\n return this.connector.reconnect()\r\n }\r\n destroy () {\r\n if (this.connector.destroy != null) {\r\n this.connector.destroy()\r\n } else {\r\n this.connector.disconnect()\r\n }\r\n var self = this\r\n this.db.requestTransaction(function * () {\r\n yield* self.db.destroy()\r\n self.connector = null\r\n self.db = null\r\n })\r\n }\r\n}\r\n\r\nif (typeof window !== 'undefined') {\r\n window.Y = Y\r\n}\r\n"]} |