Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const log = console.log;
- const indexedDB = window.indexedDB || window.mozIndexedDB ||
- window.webkitIndexedDB || window.msIndexedDB;
- class Table {
- constructor( db, name) {
- this.db = db;
- this.name = name;
- this.debug = db.debug;
- this.limitSize = 0;
- }
- limit( limit ) {
- this.limitSize = limit;
- return this;
- }
- order( mode = 'asc' ) {
- this.mode = ( mode === 'asc' ? true : false );
- return this;
- }
- orderBy( ...keys ) {
- this.orderby = keys;
- return this;
- }
- async bound( ...args ) {
- return IDBKeyRange.lowerBound( ...args );
- }
- async add( ...args ) {
- const db = this.db.name;
- if ( ! Array.isArray( args ) ) args = [ args ];
- const stores = await this.db.stores();
- const version = await this.db.version();
- const create_store = ! stores.contains( this.name );
- let promise = false;
- if ( create_store ) {
- promise = new Promise( ( resolve, reject ) => {
- let req = indexedDB.open( db, version + 1 );
- req.onerror = e => { reject( e ); };
- req.onsuccess = () => { req.result.close(); resolve(); };
- req.onupgradeneeded = () => {
- req.result.createObjectStore( this.name, { keyPath: 'id' } );
- };
- } );
- }
- if ( promise ) await promise;
- let promises = [];
- const tx = await this.transaction( this.name, 'readwrite' );
- return new Promise( ( resolve, reject ) => {
- args.forEach( item => {
- promises.push( this.do_add( tx, item ) );
- } );
- Promise.all( promises )
- .then( () => resolve( this ) )
- .catch( err => reject( err ) );
- } );
- }
- async do_add( tx, args) {
- const db = this.db.name;
- return new Promise(( resolve, reject ) => {
- let addReq = tx.objectStore( this.name ).add( args );
- addReq.onerror = e => {
- if ( this.debug ) {
- const err = this.db.haltErrors ? 'ERROR' : 'WARN';
- const msg = `[ ${ err }:add ], could not add key [${ args.id
- }] in store [${ addReq.source.name }] in database [${ db }], ` +
- e.target.error;
- log( msg );
- }
- this.db.haltErrors ? reject( e ) : resolve( this );
- };
- addReq.onsuccess = () => {
- if ( this.debug )
- log( `[ INFO:add ], Added key [${ args.id }] in store [${
- addReq.source.name }] in database [${ db }]` );
- resolve( this );
- };
- } );
- }
- async get( ...args ) {
- const sortColumns = ( arr, props, mode = true ) => {
- if ( ! Array.isArray( props ) ) props = [ props ];
- let sorted = arr.sort( ( a, b ) => {
- let prop = props[ 0 ];
- for ( let idx = 0; idx < props.length; idx++ ) {
- const curProp = props[ idx ];
- if ( a[ curProp ] !== b[ curProp ] ) {
- prop = curProp;
- break;
- }
- }
- if ( a[ prop ] === b[ prop ] ) return 0;
- return ( a[ prop ] > b[ prop ] ? -1 : 1 ) * ( mode ? -1 : 1 );
- } );
- return sorted;
- };
- switch ( typeof args) {
- case 'string': args = parseInt( args );
- case 'number': args = [ args ];
- case 'object':
- if ( Array.isArray( args ) ) {
- args.forEach( ( item, idx ) => {
- if ( typeof item === 'number' )
- args[ idx ] = { id: item };
- else if ( typeof item === 'string' )
- args[ idx ] = { id: parseInt( item) };
- } );
- }
- break;
- case 'undefined': args = false; break;
- }
- if ( ! args.length ) args = false;
- const db = this.db.name;
- const stores = await this.db.stores();
- if ( ! stores.contains( this.name ) ) return false;
- if ( args && ! Array.isArray( args ) ) args = [ args ];
- let promises = [];
- const tx = await this.transaction( this.name, 'readonly' );
- return new Promise( ( resolve, reject ) => {
- if ( args )
- args.forEach( item => { promises.push( this.do_get( tx, item ) ); } );
- else
- promises.push( this.do_get( tx ) );
- Promise.all( promises )
- .then( results => {
- let results_copy = [];
- if ( args ) {
- results.forEach( item => results_copy.push( item[0] ) );
- results = results_copy;
- } else results = results[ 0 ];
- if ( this.limitSize && results.length > 1 ) {
- results = results.slice( 0, this.limitSize );
- this.limitSize = 0;
- }
- if ( this.orderby ) {
- results = sortColumns( results, this.orderby, this.mode );
- }
- resolve( results );
- } )
- .catch( err => reject( err ) );
- } );
- }
- async do_get( tx, args ) {
- const db = this.db.name;
- return new Promise( ( resolve, reject ) => {
- let obj = tx.objectStore( this.name );
- let req = args ? obj.get( parseInt( args.id ) ) : obj.getAll();
- req.onerror = e => {
- if ( this.debug )
- log( `[ ERROR:getAll ], could not retrieve keys from store [${
- req.source.name }] in database [${ db }]` );
- reject( e );
- };
- req.onsuccess = () => {
- if ( this.debug )
- log( `[ INFO:getAll ], Retrieved all keys from store [${
- req.source.name }] in database [${ db }]` );
- const result = ! Array.isArray( req.result ) ?
- [ req.result ] : req.result;
- resolve( result );
- };
- } );
- }
- async update( ...args ) {
- const db = this.db.name;
- const stores = await this.db.stores();
- if ( ! stores.contains( this.name ) ) return this;
- const values = await this.get( ...args );
- args.forEach( ( item, idx ) => {
- let id = item.id;
- let defaults = values.find( x => x.id === id );
- if ( defaults ) {
- item = { ...defaults, ...item };
- args[ idx ] = item;
- }
- } );
- let promises = [];
- const tx = await this.transaction( this.name, 'readwrite' );
- return new Promise( ( resolve, reject ) => {
- args.forEach( item => { promises.push( this.do_update( tx, item ) ); } );
- Promise.all( promises )
- .then( () => resolve( this ) )
- .catch( err => reject( err ) );
- } );
- }
- async do_update( tx, args ) {
- const db = this.db.name;
- return new Promise(( resolve, reject ) => {
- let addReq = tx.objectStore( this.name ).put( args );
- addReq.onerror = e => {
- if ( this.debug )
- log( `[ ERROR:add ], could not update key [${ args.id
- }] in store [${ addReq.source.name }] in database [${ db }]` );
- reject( e );
- };
- addReq.onsuccess = () => {
- if ( this.debug )
- log( `[ INFO:update ], Updated key [${ args.id }] in store [${
- addReq.source.name }] in database [${ db }]` );
- resolve( this );
- };
- } );
- }
- async delete( ...args ) {
- const db = this.db.name;
- const stores = await this.db.stores();
- const version = await this.db.version();
- switch ( typeof args) {
- case 'string': args = parseInt( args );
- case 'number': args = [ args ];
- case 'object':
- if ( Array.isArray( args ) ) {
- args.forEach( ( item, idx ) => {
- if ( typeof item === 'number' )
- args[ idx ] = { id: item };
- else if ( typeof item === 'string' )
- args[ idx ] = { id: parseInt( item) };
- } );
- }
- break;
- case 'undefined': args = false; break;
- }
- if ( ! args.length ) args = false;
- let promises = [];
- if ( ! args )
- return new Promise( ( resolve, reject ) => {
- var req = indexedDB.open( this.db.name, version + 1 );
- req.onerror = e => reject( e );
- req.onsuccess = ( ) => { req.result.close(); resolve( this ); };
- req.onupgradeneeded = () => {
- req.result.deleteObjectStore( this.name );
- };
- } );
- else return new Promise( ( resolve, reject ) => {
- args.forEach( item => { promises.push( this.do_delete( item ) ); } );
- Promise.all( promises )
- .then( () => resolve( this ) )
- .catch( err => reject( err ) );
- } );
- }
- async do_delete( args ) {
- const db = this.db.name;
- const tx = await this.transaction( this.name, 'readwrite' );
- return new Promise(( resolve, reject ) => {
- let req = tx.objectStore( this.name ).delete( args.id );
- req.onerror = e => {
- if ( this.debug ) {
- const err = this.db.haltErrors ? 'ERROR' : 'WARN';
- const msg = `[ ${ err }:add ], could not add key [${ args.id
- }] in store [${ req.source.name }] in database [${ db }], ` +
- e.target.error;
- log( msg );
- }
- this.db.haltErrors ? reject( e ) : resolve( this );
- };
- req.onsuccess = () => {
- if ( this.debug )
- log( `[ INFO:add ], Deleted key [${ args.id }] from store [${
- req.source.name }] in database [${ db }]` );
- resolve( this );
- };
- } );
- }
- async addIndex( ...keys ) {
- const db = this.db.name;
- let version = await this.db.version();
- return new Promise( ( resolve, reject ) => {
- var req = indexedDB.open( this.db.name, version + 1 );
- req.onerror = e => reject( e );
- req.onsuccess = ( ) => { req.result.close(); resolve( this ); };
- req.onupgradeneeded = ( e ) => {
- let db = e.target.result;
- let tx = event.target.transaction;
- let objectStore = ( ! db.objectStoreNames.contains( this.name ) ) ?
- db.createObjectStore( this.name ) : tx.objectStore( this.name );
- keys.forEach( key => {
- if ( ! objectStore.indexNames.contains( `${ key }IDX` ) ) {
- objectStore.createIndex( `${ key }IDX`, key, { unique: false } );
- }
- } );
- };
- } );
- }
- async getIndex( index ) {
- let tx = await this.transaction( this.name );
- let store = tx.objectStore( this.name );
- return store.index( `${index}IDX` );
- }
- async transaction( store, mode ) {
- const db = this.db.name;
- if ( ! Array.isArray( store ) ) store = [ store ];
- return new Promise(( resolve, reject ) => {
- let openReq = indexedDB.open( db );
- openReq.onerror = e => reject( e );
- openReq.onsuccess = () => {
- const tx = openReq.result.transaction ( store, mode );
- resolve( tx );
- openReq.result.close();
- };
- } );
- }
- }
- export default class DBMagic {
- constructor( name ) {
- this.name = name;
- this.debug = false;
- this.tables = {};
- this.init();
- }
- init() {
- Object.values( this.stores() ).forEach( name => this.table( name ) );
- }
- table( name ) {
- let args = {}
- if ( ! ( name in this.tables ) ) {
- this.tables[ name ] = new Table( this, name, args );
- }
- return this.tables[ name ];
- }
- config( args ) {
- for (var key in args )
- this[ key ] = args[ key ];
- return this;
- }
- delete( args ) {
- if ( args ) {
- if ( ! Array.isArray( args ) ) args = [ args ];
- args.forEach( store => {
- if ( store in this.tables ) {
- this.tables[ store ].delete();
- delete this.tables[ store ];
- }
- } );
- } else {
- return new Promise( ( resolve, reject ) => {
- var req = indexedDB.deleteDatabase( this.name );
- req.onerror = err => { reject( err ); };
- req.onsuccess = () => {
- if( this.debug )
- log( '[INFO:delete], Deleted database [' + this.name + ']');
- this.tables = {};
- resolve( this );
- };
- } );
- }
- }
- stores() {
- return new Promise( ( resolve, reject ) => {
- var req = indexedDB.open( this.name );
- req.onerror = err => { reject( err ); };
- req.onsuccess = () => {
- let names = req.result.objectStoreNames;
- if( this.debug )
- log( '[INFO:db_version], Database [' + this.name +
- '], version []');
- resolve( names );
- req.result.close();
- };
- req.onupgradeneeded = () => { return true; };
- } );
- }
- version() {
- const db = this.name;
- return new Promise( ( resolve, reject ) => {
- var req = indexedDB.open( db );
- req.onerror = err => { reject( err ); };
- req.onsuccess = () => {
- let version = req.result.version;
- if( this.debug )
- log( '[INFO:db_version], Database [' + db +
- '], version [' + version + ']');
- req.result.close();
- resolve( version );
- };
- req.onupgradeneeded = () => { return true; };
- } );
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement