Uno-Dan

DBMagic

Mar 2nd, 2021
849
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.    
  2. const log = console.log;
  3.  
  4. const indexedDB = window.indexedDB || window.mozIndexedDB ||
  5.     window.webkitIndexedDB || window.msIndexedDB;
  6.    
  7. class Table {
  8.   constructor( db, name) {
  9.     this.db = db;
  10.     this.name = name;
  11.     this.debug = db.debug;
  12.     this.limitSize = 0;
  13.   }
  14.  
  15.   limit( limit ) {
  16.     this.limitSize = limit;
  17.     return this;
  18.   }
  19.  
  20.   orderby( keys, mode = 'asc' ) {
  21.     this.order = ( mode === 'asc' ? true : false );
  22.     this.orderby = Array.isArray( keys ) ? keys : [ keys ];
  23.     return this;
  24.   }
  25.  
  26.   async transaction( store, mode ) {    
  27.     const db = this.db.name;  
  28.    
  29.     return new Promise(( resolve, reject ) => {
  30.       let openReq = indexedDB.open( db );
  31.  
  32.       openReq.onerror = e => reject( e );
  33.  
  34.       openReq.onsuccess = () => {
  35.         const tx = openReq.result.transaction ( [ store ], mode );
  36.         resolve( tx );
  37.         openReq.result.close();
  38.       };
  39.     } );
  40.   }
  41.  
  42.   async add( args, opt=false ) {
  43.     const db = this.db.name;
  44.    
  45.     if ( ! Array.isArray( args ) ) args = [ args ];
  46.    
  47.     const stores = await this.db.stores();
  48.     const version = await this.db.version();
  49.     const create_store = ! stores.contains( this.name );
  50.    
  51.     let promise = false;
  52.    
  53.     if ( create_store ) {
  54.       promise = new Promise( ( resolve, reject ) => {
  55.         let req = indexedDB.open( db, version + 1 );
  56.        
  57.         req.onerror = e => {
  58.           reject( e )
  59.         };
  60.         req.onsuccess = () => { req.result.close(); resolve(); };
  61.         req.onupgradeneeded = () => {
  62.           req.result.createObjectStore( this.name, { keyPath: 'id' } );
  63.         };
  64.       } );
  65.     }
  66.    
  67.     if ( promise ) await promise;
  68.    
  69.     let promises = [];
  70.    
  71.     return new Promise( ( resolve, reject ) => {
  72.       args.forEach( item => { promises.push( this.que_add( item, opt ) ); } );
  73.       Promise.all( promises )
  74.       .then( () => resolve( this ) )
  75.       .catch( err => reject( err ) );
  76.     } );
  77.   }
  78.  
  79.   async get( args ) {
  80.     const sortColumns = ( arr, props, mode = true ) => {
  81.       if ( ! Array.isArray( props ) ) props = [ props ];
  82.      
  83.       const sorted = arr.sort( ( a, b ) => {
  84.         let prop = props[ 0 ];
  85.         for ( let idx = 0; idx < props.length; idx++ ) {
  86.           const curProp = props[ idx ];
  87.           if ( a[ curProp ] !== b[ curProp ] ) {
  88.             prop = curProp;
  89.             break;
  90.           }  
  91.         }  
  92.         if ( a[ prop ] === b[ prop ] ) return 0;
  93.           return ( a[ prop ] > b[ prop ] ? -1 : 1 ) * ( mode ? -1 : 1 );
  94.       } );  
  95.       return sorted;
  96.     };
  97.    
  98.     const db = this.db.name;
  99.     const stores = await this.db.stores();
  100.     if ( ! stores.contains( this.name ) ) return false;
  101.    
  102.     if ( ! Array.isArray( args ) ) args = [ args ];
  103.    
  104.     let promises = [];
  105.     return new Promise( ( resolve, reject ) => {
  106.       if ( args )
  107.         args.forEach( item => { promises.push( this.que_get( item) ); } );
  108.       else
  109.         promises.push( this.que_get() );
  110.              
  111.       Promise.all(promises)      
  112.       .then( results => {
  113.         if ( results.length ) {
  114.           if ( this.limitSize )
  115.             results = [ results[ 0 ].slice( 0, this.limitSize ) ];
  116.           results = sortColumns( results[ 0 ], this.orderby, this.order );
  117.         }
  118.         this.limitSize = 0;
  119.         resolve( results );
  120.       } )
  121.       .catch( err => reject( err ) );
  122.     } );
  123.   }
  124.          
  125.   async update( args ) {
  126.     const db = this.db.name;
  127.     const stores = await this.db.stores();
  128.     if ( ! stores.contains( this.name ) ) return false;
  129.    
  130.     let promises = [];
  131.    
  132.     return new Promise( ( resolve, reject ) => {
  133.      
  134.       args.forEach( item => { promises.push( this.que_update( item ) ); } );
  135.       Promise.all( promises )
  136.       .then( () => resolve( this ) )
  137.       .catch( err => reject( err ) );
  138.     } );
  139.   }
  140.  
  141.   async delete() {
  142.     const db = this.db.name;
  143.     const stores = await this.db.stores();
  144.     const version = await this.db.version();
  145.    
  146.     return new Promise( ( resolve, reject ) => {
  147.       var req = indexedDB.open( this.db.name, version + 1  );
  148.  
  149.         req.onerror = e => reject( e );
  150.  
  151.         req.onsuccess = ( ) => { req.result.close(); resolve( this ); };
  152.        
  153.         req.onupgradeneeded = () => {
  154.           req.result.deleteObjectStore( this.name );
  155.         };
  156.     } );
  157.   }
  158.  
  159.   async que_add( args, opt=false ) {
  160.     const db = this.db.name;
  161.     const tx = await this.transaction( [ this.name ], 'readwrite' );
  162.    
  163.     return new Promise(( resolve, reject ) => {
  164.       let addReq = tx.objectStore( this.name ).add( args );
  165.  
  166.       addReq.onerror = e => {
  167.         if ( this.debug ) {  
  168.           const err = opt ? 'WARN' : 'ERROR';
  169.           const msg = `[ ${ err }:add ], could not add key [${ args.id
  170.           }] in store [${  addReq.source.name }] in database [${ db }], ` +
  171.           e.target.error;
  172.           log( msg );
  173.         }
  174.         opt ? resolve( this ) : reject( e );  
  175.       };
  176.  
  177.       addReq.onsuccess = () => {  
  178.         if ( this.debug )
  179.           log( `[ INFO:add ], Added key [${ args.id }] in store [${
  180.           addReq.source.name }] in database [${ db }]` );
  181.         resolve( this );  
  182.       };
  183.     } );
  184.   }
  185.  
  186.   async que_get( args ) {
  187.     const db = this.db.name;
  188.     const tx = await this.transaction( [ this.name ], 'readonly' );
  189.    
  190.     return new Promise( ( resolve, reject ) => {
  191.       let obj = tx.objectStore( this.name );
  192.       let req = args ? obj.get( args.id ) : obj.getAll();
  193.       req.onerror = e => {
  194.         if ( this.debug )
  195.           log( `[ ERROR:getAll ], could not retrieve keys from store [${
  196.           req.source.name }] in database [${ db }]` );
  197.         reject( e );  
  198.       };
  199.  
  200.       req.onsuccess = () => {
  201.         if ( this.debug )
  202.           log( `[ INFO:getAll ], Retrieved all keys from store [${
  203.           req.source.name }] in database [${ db }]` );
  204.  
  205.         const result = ! Array.isArray( req.result ) ?
  206.         [ req.result ] : req.result;
  207.         resolve( result );  
  208.       };
  209.     } );
  210.   }
  211.  
  212.   async que_update( args ) {
  213.     const db = this.db.name;
  214.    
  215.     const values = await this.get( { id: args.id } );
  216.     if ( ! values.length ) return this;
  217.    
  218.     args = { ...values[0], ...args };
  219.  
  220.     const tx = await this.transaction( [ this.name ], 'readwrite' );
  221.     return new Promise(( resolve, reject ) => {
  222.         let addReq = tx.objectStore( this.name ).put( args );
  223.  
  224.         addReq.onerror = e => {
  225.           if ( this.debug )
  226.             log( `[ ERROR:add ], could not update key [${ args.id
  227.             }] in store [${ addReq.source.name }] in database [${ db }]` );
  228.           reject( e );  
  229.         };
  230.  
  231.         addReq.onsuccess = () => {  
  232.           if ( this.debug )
  233.             log( `[ INFO:update ], Updated key [${ args.id }] in store [${
  234.             addReq.source.name }] in database [${ db }]` );
  235.           resolve( this );  
  236.         };
  237.     } );
  238.   }
  239. }
  240.  
  241. export default class DBMagic {
  242.   constructor( name ) {
  243.     this.name = name;
  244.     this.debug = false;
  245.     this.tables = {};
  246.     this.init();
  247.   }
  248.  
  249.   init() {
  250.     Object.values( this.stores() ).forEach( name => this.table( name ) );
  251.   }
  252.  
  253.   table( name ) {
  254.     let args = {}
  255.     if ( ! ( name in this.tables ) ) {
  256.       this.tables[ name ] = new Table( this, name, args );
  257.     }
  258.     return this.tables[ name ];
  259.   }
  260.  
  261.   config( args ) {
  262.     for (var key in args )
  263.       this[ key ] = args[ key ];
  264.     return this;
  265.   }
  266.  
  267.   delete( args ) {
  268.     if ( args ) {
  269.       if ( ! Array.isArray( args ) ) args = [ args ];
  270.    
  271.       args.forEach( store => {
  272.         if ( store in this.tables ) {
  273.           this.tables[ store ].delete();
  274.           delete this.tables[ store ];
  275.         }
  276.       } );
  277.     } else {
  278.       return new Promise( ( resolve, reject ) => {
  279.         var req = indexedDB.deleteDatabase( this.name );
  280.  
  281.         req.onerror = err => { reject( err ); };
  282.  
  283.         req.onsuccess = () => {
  284.           if( this.debug )
  285.             log( '[INFO:delete], Deleted database [' + this.name + ']');
  286.          
  287.           this.tables = {};
  288.           resolve( this );
  289.         };
  290.       } );
  291.     }
  292.   }
  293.  
  294.   stores() {
  295.     return new Promise( ( resolve, reject ) => {
  296.       var req = indexedDB.open( this.name );
  297.  
  298.       req.onerror = err => { reject( err ); };
  299.  
  300.       req.onsuccess = () => {
  301.         let names = req.result.objectStoreNames;
  302.         if( this.debug )
  303.           log( '[INFO:db_version], Database [' + this.name +
  304.           '], version []');
  305.  
  306.         resolve( names );
  307.         req.result.close();
  308.       };
  309.      
  310.       req.onupgradeneeded = () => { return true; };
  311.     } );
  312.   }
  313.  
  314.   version() {
  315.     const db = this.name;
  316.     return new Promise( ( resolve, reject ) => {
  317.       var req = indexedDB.open( db );
  318.  
  319.       req.onerror = err => { reject( err ); };
  320.  
  321.       req.onsuccess = () => {
  322.         let version = req.result.version;
  323.         if( this.debug )
  324.           log( '[INFO:db_version], Database [' + db +
  325.           '], version [' + version + ']');
  326.  
  327.         req.result.close();
  328.         resolve( version );
  329.       };
  330.       req.onupgradeneeded = () => { return true; };
  331.     } );
  332.   }
  333. }
  334.  
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×