/** * SecureSql is the javascript interface to Sencha Web Application Client's encrypted * SQL database. SecureSql uses an encrypted form of SQLite 3. Please see * http://sqlite.org/ for more details on the subset of SQL that sqlite supports. * * * Basic Usage * ---- * * Open a connection to the database. An application can have as many named databases as * needed. Each database is independent of the other databases in the application. * * var db = Ext.space.SecureSql.get("test"); * * Schema * ---- * * Next you will need to define a schema in the database. Each version of the database * should have a version number. When the database is ready to create tables and * indexes, the callback function will be called with a * `Ext.space.securesql.Transaction`. Add queries to create the tables and indexes * needed for this database. * * db.createSechema(1, function(tx){ * tx.query("CREATE TABLE IF NOT EXISTS test (id int, name text, PRIMARY KEY (id))"); * tx.query("CREATE TABLE IF NOT EXISTS person (id int, firstName text,lastName text, email text, PRIMARY KEY (id))"); * }); * * Do not run the transaction from within the callback. It will be executed * automatically after the callback function returns. * * The callback on createSchema is only called if a database of that version does not * already exist. If the schema of the application's database changes overtime then the * data will need to be migrated. See the Migration section below. * * See `Ext.space.securesql.Database.createSchema` for more details. * * Inserting Data * ---- * * SecureSql provides two convenience methods for inserting data into the database. The * application can pass either an array of data or a javascript object. * * `Ext.space.securesql.Database.insert` will insert record into a table using a single * transaction. * `Ext.space.securesql.Database.insertMany` will insert multiple records into a table * single transaction. * * * * Queries * ---- * * `Ext.space.securesql.Database.query` will execute a query against the database in a * single transaction. * * * Transactions * ---- * * SecureSql supports executing multiple inserts and queries in a single logical * transaction * * var tx = Ext.space.securesql.Database.createTransaction() * * tx.query() * tx.insert() * tx.query() * tx.query() * tx.execute() * * see `Ext.space.securesql.Database.createTransaction` * * * Data Migration * ---- * SecureSql provides methods to migrate a schema from one version to the next. Data * migrations can become complex so we recommend modification the database as little as * possible after the initial creation. * * If the application loads and createSechema attempts to create version 3 of the schema * * db.createSchema(3, function(tx){ * //.... * }); * * 1) if this client does not have a database then createSchema executes and the schema * version is set to 3 * 2) if the client already has schema version 3 then nothing happens, and queries will * be executed. * 3) if the schema version is less that 3 then each of the registered migration * callbacks are executed until the version is equal to the version defined in * createSchema * * It is the responsibility of the developer to ensure that the table mutation * operations in the migration callbacks will correctly update the database to the * current schema. * * IF the developer has defined version 3 of createSchema then they should define two * version migrations. * * This migration will upgrade version 1 of the database to version 2. * * db.migrate(2, function(tx){ * //.... * }); * * This migration will upgrade version 2 to version 3: * * db.migrate(3, function(tx){ * //.... * }); * * Database List * ---- * * If you need to programmatically determine what databases are available, call the * `listDatabases` API: * * Ext.space.SecureSql.listDatabases().then(function(databaseList) { * databaseList.forEach(function(db) { * // db.name, db.version, etc... * }); * }); */Ext.define("Ext.space.SecureSql", { singleton: true, /* * @private */ _openDBs: null, /* * @private */ constructor: function() { this._openDBs = {}; }, /** * List the available databases. * * @return {Ext.space.Promise} Promise which receives an array of database info objects * like {name, displayName} */ listDatabases: function() { var result = new Ext.space.Promise(); Ext.space.Communicator.send({ command: "Sqlite#listDatabases", callbacks: { onSuccess: function(databaseList) { result.fulfill(databaseList.map(function(db) { return { name: db.name, displayName: db.displayName }; })); }, onError: function(error) { result.reject(error); } } }); return result; }, /** * * Open a connection to a database. A database will automatically be created if it does not already exist. * * @param {String} name The name of the database to open. * @return {Ext.space.securesql.Database} the secure collection. */ get: function(name) { function release(database) { Ext.space.Logger.debug("releasing DB: " + name); if (this._openDBs[database.name]) { delete this._openDBs[database.name]; } } var db = this._openDBs[name]; Ext.space.Logger.info("Get database", name, db); if (!db) { db = new Ext.space.securesql.Database({name: name, cleanup: release.bind(this)}); this._openDBs[name] = db; } return db; }, /** * Permanently delete this database. This operation cannot be undone. All data in * this database will be lost. * * @param {String} name The name of the database to delete. * @return {Ext.space.Promise} a promise that will resolve when the database has been removed. */ drop: function(name) { var db = this._openDBs[name]; return db ? db.drop() : this.get(name).drop(); }, /** * Opens the database with the given name; if it does not exist, it will be created. * * @private * @param {Object} options Database options * @param {String} options.name Database name * @param {String} options.displayName (optional) Database name for display purposes * @return {Ext.space.Promise} The promise that will resolve when the database is opened and returned. */ _open: function(options) { var promise = new Ext.space.Promise(); if (options.name) { Ext.space.Communicator.send({ command: "Sqlite#openDatabase", name: options.name, displayName: options.displayName || options.name, callbacks: { success: function(dbSpec) { promise.fulfill(dbSpec); }, failure: function(e) { promise.reject(e); } } }); } else { promise.reject("Cannot open database; no name specified."); } return promise; }});