{"version":3,"sources":["jsdelivr-header.js","/npm/backbone-indexeddb@0.0.13/backbone-indexeddb.js"],"names":[],"mappings":"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","file":"/npm/backbone-indexeddb@0.0.13/backbone-indexeddb.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/backbone-indexeddb@0.0.13/backbone-indexeddb.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","(function () { /*global _: false, Backbone: false */\n    // Generate four random hex digits.\n    function S4() {\n        return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);\n    }\n\n    // Generate a pseudo-GUID by concatenating random hexadecimal.\n    function guid() {\n        return (S4() + S4() + \"-\" + S4() + \"-\" + S4() + \"-\" + S4() + \"-\" + S4() + S4() + S4());\n    }\n\n    if(typeof exports !== 'undefined'){\n        _ = require('underscore');\n        Backbone = require('backbone');\n    }\n\n\n     // Naming is a mess!\n     var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB ;\n     var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || { READ_WRITE: \"readwrite\" }; // No prefix in moz\n     var IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange ; // No prefix in moz\n\n     window.IDBCursor = window.IDBCursor || window.webkitIDBCursor ||  window.mozIDBCursor ||  window.msIDBCursor ;\n\n\n    // Driver object\n    // That's the interesting part.\n    // There is a driver for each schema provided. The schema is a te combination of name (for the database), a version as well as migrations to reach that\n    // version of the database.\n    function Driver(schema, ready, nolog) {\n        this.schema         = schema;\n        this.ready          = ready;\n        this.error          = null;\n        this.transactions   = []; // Used to list all transactions and keep track of active ones.\n        this.db             = null;\n        this.nolog          = nolog;\n        this.supportOnUpgradeNeeded = false;\n        var lastMigrationPathVersion = _.last(this.schema.migrations).version;\n        if (!this.nolog) debugLog(\"opening database \" + this.schema.id + \" in version #\" + lastMigrationPathVersion);\n        this.dbRequest      = indexedDB.open(this.schema.id,lastMigrationPathVersion); //schema version need to be an unsigned long\n\n        this.launchMigrationPath = function(dbVersion) {\n            var clonedMigrations = _.clone(schema.migrations);\n            this.migrate(clonedMigrations, dbVersion, {\n                success: function () {\n                    this.ready();\n                }.bind(this),\n                error: function () {\n                    this.error = \"Database not up to date. \" + dbVersion + \" expected was \" + lastMigrationPathVersion;\n                }.bind(this)\n            });\n        };\n\n        this.dbRequest.onblocked = function(event){\n            if (!this.nolog) debugLog(\"blocked\");\n        }\n\n        this.dbRequest.onsuccess = function (e) {\n            this.db = e.target.result; // Attach the connection ot the queue.\n            if(!this.supportOnUpgradeNeeded)\n            {\n                var currentIntDBVersion = (parseInt(this.db.version) ||  0); // we need convert beacuse chrome store in integer and ie10 DP4+ in int;\n                var lastMigrationInt = (parseInt(lastMigrationPathVersion) || 0);  // And make sure we compare numbers with numbers.\n\n                if (currentIntDBVersion === lastMigrationInt) { //if support new event onupgradeneeded will trigger the ready function\n                    // No migration to perform!\n\n                    this.ready();\n                } else if (currentIntDBVersion < lastMigrationInt ) {\n                    // We need to migrate up to the current migration defined in the database\n                    this.launchMigrationPath(currentIntDBVersion);\n                } else {\n                    // Looks like the IndexedDB is at a higher version than the current driver schema.\n                    this.error = \"Database version is greater than current code \" + currentIntDBVersion + \" expected was \" + lastMigrationInt;\n                }\n            };\n        }.bind(this);\n\n\n\n        this.dbRequest.onerror = function (e) {\n            // Failed to open the database\n            this.error = \"Couldn't not connect to the database\"\n        }.bind(this);\n\n        this.dbRequest.onabort = function (e) {\n            // Failed to open the database\n            this.error = \"Connection to the database aborted\"\n        }.bind(this);\n\n\n\n        this.dbRequest.onupgradeneeded = function(iDBVersionChangeEvent){\n            this.db =iDBVersionChangeEvent.target.transaction.db;\n\n            this.supportOnUpgradeNeeded = true;\n\n            if (!this.nolog) debugLog(\"onupgradeneeded = \" + iDBVersionChangeEvent.oldVersion + \" => \" + iDBVersionChangeEvent.newVersion);\n            this.launchMigrationPath(iDBVersionChangeEvent.oldVersion);\n\n\n        }.bind(this);\n    }\n\n    function debugLog(str) {\n        if (typeof window !== \"undefined\" && typeof window.console !== \"undefined\" && typeof window.console.log !== \"undefined\") {\n            window.console.log(str);\n        }\n        else if(console.log !== \"undefined\") {\n            console.log(str)\n        }\n    }\n\n    // Driver Prototype\n    Driver.prototype = {\n\n        // Tracks transactions. Mostly for debugging purposes. TO-IMPROVE\n        _track_transaction: function(transaction) {\n            this.transactions.push(transaction);\n            function removeIt() {\n                var idx = this.transactions.indexOf(transaction);\n                if (idx !== -1) {this.transactions.splice(idx); }\n            };\n            transaction.oncomplete = removeIt.bind(this);\n            transaction.onabort = removeIt.bind(this);\n            transaction.onerror = removeIt.bind(this);\n        },\n\n        // Performs all the migrations to reach the right version of the database.\n        migrate: function (migrations, version, options) {\n            if (!this.nolog) debugLog(\"Starting migrations from \" + version);\n            this._migrate_next(migrations, version, options);\n        },\n\n        // Performs the next migrations. This method is private and should probably not be called.\n        _migrate_next: function (migrations, version, options) {\n            if (!this.nolog) debugLog(\"_migrate_next begin version from #\" + version);\n            var that = this;\n            var migration = migrations.shift();\n            if (migration) {\n                if (!version || version < migration.version) {\n                    // We need to apply this migration-\n                    if (typeof migration.before == \"undefined\") {\n                        migration.before = function (next) {\n                            next();\n                        };\n                    }\n                    if (typeof migration.after == \"undefined\") {\n                        migration.after = function (next) {\n                            next();\n                        };\n                    }\n                    // First, let's run the before script\n                    if (!this.nolog) debugLog(\"_migrate_next begin before version #\" + migration.version);\n                    migration.before(function () {\n                        if (!this.nolog) debugLog(\"_migrate_next done before version #\" + migration.version);\n\n                        var continueMigration = function (e) {\n                            if (!this.nolog) debugLog(\"_migrate_next continueMigration version #\" + migration.version);\n\n                            var transaction = this.dbRequest.transaction || versionRequest.result;\n                            if (!this.nolog) debugLog(\"_migrate_next begin migrate version #\" + migration.version);\n\n                            migration.migrate(transaction, function () {\n                                if (!this.nolog) debugLog(\"_migrate_next done migrate version #\" + migration.version);\n                                // Migration successfully appliedn let's go to the next one!\n                                if (!this.nolog) debugLog(\"_migrate_next begin after version #\" + migration.version);\n                                migration.after(function () {\n                                    if (!this.nolog) debugLog(\"_migrate_next done after version #\" + migration.version);\n                                    if (!this.nolog) debugLog(\"Migrated to \" + migration.version);\n\n                                    //last modification occurred, need finish\n                                    if(migrations.length ==0) {\n                                        /*if(this.supportOnUpgradeNeeded){\n                                            debugLog(\"Done migrating\");\n                                            // No more migration\n                                            options.success();\n                                        }\n                                        else{*/\n                                            if (!this.nolog) debugLog(\"_migrate_next setting transaction.oncomplete to finish  version #\" + migration.version);\n                                            transaction.oncomplete = function() {\n                                                if (!that.nolog) debugLog(\"_migrate_next done transaction.oncomplete version #\" + migration.version);\n\n                                                if (!that.nolog) debugLog(\"Done migrating\");\n                                                // No more migration\n                                                options.success();\n                                            }\n                                        //}\n                                    }\n                                    else\n                                    {\n                                        if (!this.nolog) debugLog(\"_migrate_next setting transaction.oncomplete to recursive _migrate_next  version #\" + migration.version);\n                                        transaction.oncomplete = function() {\n                                           if (!this.nolog) debugLog(\"_migrate_next end from version #\" + version + \" to \" + migration.version);\n                                           that._migrate_next(migrations, version, options);\n                                       }\n                                    }\n\n                                }.bind(this));\n                            }.bind(this));\n                        }.bind(this);\n\n                        if(!this.supportOnUpgradeNeeded){\n                            if (!this.nolog) debugLog(\"_migrate_next begin setVersion version #\" + migration.version);\n                            var versionRequest = this.db.setVersion(migration.version);\n                            versionRequest.onsuccess = continueMigration;\n                            versionRequest.onerror = options.error;\n                        }\n                        else {\n                            continueMigration();\n                        }\n\n                    }.bind(this));\n                } else {\n                    // No need to apply this migration\n                    if (!this.nolog) debugLog(\"Skipping migration \" + migration.version);\n                    this._migrate_next(migrations, version, options);\n                }\n            }\n        },\n\n        // This is the main method, called by the ExecutionQueue when the driver is ready (database open and migration performed)\n        execute: function (storeName, method, object, options) {\n            if (!this.nolog) debugLog(\"execute : \" + method +  \" on \" + storeName + \" for \" + object.id);\n            switch (method) {\n            case \"create\":\n                this.create(storeName, object, options);\n                break;\n            case \"read\":\n                if (object.id || object.cid) {\n                    this.read(storeName, object, options); // It's a model\n                } else {\n                    this.query(storeName, object, options); // It's a collection\n                }\n                break;\n            case \"update\":\n                this.update(storeName, object, options); // We may want to check that this is not a collection. TOFIX\n                break;\n            case \"delete\":\n                if (object.id || object.cid) {\n                    this.delete(storeName, object, options);\n                } else {\n                    this.clear(storeName, object, options);\n                }\n                break;\n            default:\n                // Hum what?\n            }\n        },\n\n        // Writes the json to the storeName in db. It is a create operations, which means it will fail if the key already exists\n        // options are just success and error callbacks.\n        create: function (storeName, object, options) {\n            var writeTransaction = this.db.transaction([storeName], 'readwrite');\n            //this._track_transaction(writeTransaction);\n            var store = writeTransaction.objectStore(storeName);\n            var json = object.toJSON();\n            var writeRequest;\n\n            if (json.id === undefined) json.id = guid();\n            if (json.id === null) delete json.id;\n\n            writeTransaction.onerror = function (e) {\n                options.error(e);\n            };\n            writeTransaction.oncomplete = function (e) {\n                options.success(json);\n            };\n\n            if (!store.keyPath)\n                writeRequest = store.add(json, json.id);\n            else\n                writeRequest = store.add(json);\n        },\n\n        // Writes the json to the storeName in db. It is an update operation, which means it will overwrite the value if the key already exist\n        // options are just success and error callbacks.\n        update: function (storeName, object, options) {\n            var writeTransaction = this.db.transaction([storeName], 'readwrite');\n            //this._track_transaction(writeTransaction);\n            var store = writeTransaction.objectStore(storeName);\n            var json = object.toJSON();\n            var writeRequest;\n\n            if (!json.id) json.id = guid();\n\n            if (!store.keyPath)\n              writeRequest = store.put(json, json.id);\n            else\n              writeRequest = store.put(json);\n\n            writeRequest.onerror = function (e) {\n                options.error(e);\n            };\n            writeTransaction.oncomplete = function (e) {\n                options.success(json);\n            };\n        },\n\n        // Reads from storeName in db with json.id if it's there of with any json.xxxx as long as xxx is an index in storeName\n        read: function (storeName, object, options) {\n            var readTransaction = this.db.transaction([storeName], \"readonly\");\n            this._track_transaction(readTransaction);\n\n            var store = readTransaction.objectStore(storeName);\n            var json = object.toJSON();\n\n            var getRequest = null;\n            if (json.id) {\n                getRequest = store.get(json.id);\n            } else {\n                // We need to find which index we have\n                _.each(store.indexNames, function (key, index) {\n                    index = store.index(key);\n                    if (json[index.keyPath] && !getRequest) {\n                        getRequest = index.get(json[index.keyPath]);\n                    }\n                });\n            }\n            if (getRequest) {\n                getRequest.onsuccess = function (event) {\n                    if (event.target.result) {\n                        options.success(event.target.result);\n                    } else {\n                        options.error(\"Not Found\");\n                    }\n                };\n                getRequest.onerror = function () {\n                    options.error(\"Not Found\"); // We couldn't find the record.\n                }\n            } else {\n                options.error(\"Not Found\"); // We couldn't even look for it, as we don't have enough data.\n            }\n        },\n\n        // Deletes the json.id key and value in storeName from db.\n        delete: function (storeName, object, options) {\n            var deleteTransaction = this.db.transaction([storeName], 'readwrite');\n            //this._track_transaction(deleteTransaction);\n\n            var store = deleteTransaction.objectStore(storeName);\n            var json = object.toJSON();\n\n            var deleteRequest = store.delete(json.id);\n\n            deleteTransaction.oncomplete = function (event) {\n                options.success(null);\n            };\n            deleteRequest.onerror = function (event) {\n                options.error(\"Not Deleted\");\n            };\n        },\n\n        // Clears all records for storeName from db.\n        clear: function (storeName, object, options) {\n            var deleteTransaction = this.db.transaction([storeName], \"readwrite\");\n            //this._track_transaction(deleteTransaction);\n\n            var store = deleteTransaction.objectStore(storeName);\n\n            var deleteRequest = store.clear();\n            deleteRequest.onsuccess = function (event) {\n                options.success(null);\n            };\n            deleteRequest.onerror = function (event) {\n                options.error(\"Not Cleared\");\n            };\n        },\n\n        // Performs a query on storeName in db.\n        // options may include :\n        // - conditions : value of an index, or range for an index\n        // - range : range for the primary key\n        // - limit : max number of elements to be yielded\n        // - offset : skipped items.\n        query: function (storeName, collection, options) {\n            var elements = [];\n            var skipped = 0, processed = 0;\n            var queryTransaction = this.db.transaction([storeName], \"readonly\");\n            //this._track_transaction(queryTransaction);\n\n            var readCursor = null;\n            var store = queryTransaction.objectStore(storeName);\n            var index = null,\n                lower = null,\n                upper = null,\n                bounds = null;\n\n            if (options.conditions) {\n                // We have a condition, we need to use it for the cursor\n                _.each(store.indexNames, function (key) {\n                    if (!readCursor) {\n                        index = store.index(key);\n                        if (options.conditions[index.keyPath] instanceof Array) {\n                            lower = options.conditions[index.keyPath][0] > options.conditions[index.keyPath][1] ? options.conditions[index.keyPath][1] : options.conditions[index.keyPath][0];\n                            upper = options.conditions[index.keyPath][0] > options.conditions[index.keyPath][1] ? options.conditions[index.keyPath][0] : options.conditions[index.keyPath][1];\n                            bounds = IDBKeyRange.bound(lower, upper, true, true);\n\n                            if (options.conditions[index.keyPath][0] > options.conditions[index.keyPath][1]) {\n                                // Looks like we want the DESC order\n                                readCursor = index.openCursor(bounds, window.IDBCursor.PREV || \"prev\");\n                            } else {\n                                // We want ASC order\n                                readCursor = index.openCursor(bounds, window.IDBCursor.NEXT || \"next\");\n                            }\n                        } else if (options.conditions[index.keyPath] != undefined) {\n                            bounds = IDBKeyRange.only(options.conditions[index.keyPath]);\n                            readCursor = index.openCursor(bounds);\n                        }\n                    }\n                });\n            } else {\n                // No conditions, use the index\n                if (options.range) {\n                    lower = options.range[0] > options.range[1] ? options.range[1] : options.range[0];\n                    upper = options.range[0] > options.range[1] ? options.range[0] : options.range[1];\n                    bounds = IDBKeyRange.bound(lower, upper);\n                    if (options.range[0] > options.range[1]) {\n                        readCursor = store.openCursor(bounds, window.IDBCursor.PREV || \"prev\");\n                    } else {\n                        readCursor = store.openCursor(bounds, window.IDBCursor.NEXT || \"next\");\n                    }\n                } else {\n                    readCursor = store.openCursor();\n                }\n            }\n\n            if (typeof (readCursor) == \"undefined\" || !readCursor) {\n                options.error(\"No Cursor\");\n            } else {\n                readCursor.onerror = function(e){\n                    options.error(\"readCursor error\", e);\n                };\n                // Setup a handler for the cursor’s `success` event:\n                readCursor.onsuccess = function (e) {\n                    var cursor = e.target.result;\n                    if (!cursor) {\n                        if (options.addIndividually || options.clear) {\n                            // nothing!\n                            // We need to indicate that we're done. But, how?\n                            collection.trigger(\"reset\");\n                        } else {\n                            options.success(elements); // We're done. No more elements.\n                        }\n                    }\n                    else {\n                        // Cursor is not over yet.\n                        if (options.limit && processed >= options.limit) {\n                            // Yet, we have processed enough elements. So, let's just skip.\n                            if (bounds && options.conditions[index.keyPath]) {\n                                cursor.continue(options.conditions[index.keyPath][1] + 1); /* We need to 'terminate' the cursor cleany, by moving to the end */\n                            } else {\n                                cursor.continue(); /* We need to 'terminate' the cursor cleany, by moving to the end */\n                            }\n                        }\n                        else if (options.offset && options.offset > skipped) {\n                            skipped++;\n                            cursor.continue(); /* We need to Moving the cursor forward */\n                        } else {\n                            // This time, it looks like it's good!\n                            if (options.addIndividually) {\n                                collection.add(cursor.value);\n                            } else if (options.clear) {\n                                var deleteRequest = store.delete(cursor.value.id);\n                                deleteRequest.onsuccess = function (event) {\n                                    elements.push(cursor.value);\n                                };\n                                deleteRequest.onerror = function (event) {\n                                    elements.push(cursor.value);\n                                };\n\n                            } else {\n                                elements.push(cursor.value);\n                            }\n                            processed++;\n                            cursor.continue();\n                        }\n                    }\n                };\n            }\n        },\n        close :function(){\n            if(this.db){\n                this.db.close()\n;            }\n        }\n    };\n\n    // ExecutionQueue object\n    // The execution queue is an abstraction to buffer up requests to the database.\n    // It holds a \"driver\". When the driver is ready, it just fires up the queue and executes in sync.\n    function ExecutionQueue(schema,next,nolog) {\n        this.driver     = new Driver(schema, this.ready.bind(this), nolog);\n        this.started    = false;\n        this.stack      = [];\n        this.version    = _.last(schema.migrations).version;\n        this.next = next;\n    }\n\n    // ExecutionQueue Prototype\n    ExecutionQueue.prototype = {\n        // Called when the driver is ready\n        // It just loops over the elements in the queue and executes them.\n        ready: function () {\n            this.started = true;\n            _.each(this.stack, function (message) {\n                this.execute(message);\n            }.bind(this));\n            this.next();\n        },\n\n        // Executes a given command on the driver. If not started, just stacks up one more element.\n        execute: function (message) {\n            if (this.started) {\n                this.driver.execute(message[1].storeName, message[0], message[1], message[2]); // Upon messages, we execute the query\n            } else {\n                this.stack.push(message);\n            }\n        },\n\n        close : function(){\n            this.driver.close();\n        }\n    };\n\n    // Method used by Backbone for sync of data with data store. It was initially designed to work with \"server side\" APIs, This wrapper makes\n    // it work with the local indexedDB stuff. It uses the schema attribute provided by the object.\n    // The wrapper keeps an active Executuon Queue for each \"schema\", and executes querues agains it, based on the object type (collection or\n    // single model), but also the method... etc.\n    // Keeps track of the connections\n    var Databases = {};\n\n    function sync(method, object, options) {\n\n        if(method==\"closeall\"){\n            _.each(Databases,function(database){\n                database.close();\n            });\n            // Clean up active databases object.\n            Databases = {}\n            return;\n        }\n\n        var schema = object.database;\n        if (Databases[schema.id]) {\n            if(Databases[schema.id].version != _.last(schema.migrations).version){\n                Databases[schema.id].close();\n                delete Databases[schema.id];\n            }\n        }\n\n        var promise;\n        var noop = function() {};\n\n        if (typeof($) != 'undefined' && $.Deferred) {\n            var dfd = $.Deferred();\n            var resolve = dfd.resolve;\n            var reject = dfd.reject;\n\n            promise = dfd.promise();\n        } else {\n            var resolve = noop;\n            var reject = noop;\n        }\n\n        var success = options.success;\n        options.success = function(resp) {\n            resolve();\n            if (success) success(object, resp, options);\n            object.trigger('sync', object, resp, options);\n        };\n\n        var error = options.error;\n        options.error = function(resp) {\n            reject();\n            if (error) error(object, resp, options);\n            object.trigger('error', object, resp, options);\n        };\n\n        var next = function(){\n            Databases[schema.id].execute([method, object, options]);\n        };\n\n        if (!Databases[schema.id]) {\n              Databases[schema.id] = new ExecutionQueue(schema,next,schema.nolog);\n        } else {\n            next();\n        }\n\n    \treturn promise;\n    };\n\n    if(typeof exports == 'undefined'){\n        Backbone.ajaxSync = Backbone.sync;\n        Backbone.sync = sync;\n    }\n    else {\n        exports.sync = sync;\n        exports.debugLog = debugLog;\n    }\n\n    //window.addEventListener(\"unload\",function(){Backbone.sync(\"closeall\")})\n})();\n"]}