├── logo.png ├── favicon.ico ├── test.html ├── style.css ├── ldbx.min.js ├── README.md ├── ldbx.js └── index.html /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikhbalfuady/ldbx/HEAD/logo.png -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ikhbalfuady/ldbx/HEAD/favicon.ico -------------------------------------------------------------------------------- /test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | .codex { 2 | font-size: 14px; 3 | font-family: 'Consolas'; 4 | background: #262c39; 5 | color: #fff; 6 | padding: 10px; 7 | border-radius: 4px; 8 | min-height: 120px; 9 | } 10 | 11 | .code { 12 | font-size: 14px; 13 | font-family: 'Consolas'; 14 | background: #ececec; 15 | color: rgb(66, 34, 34); 16 | border-radius: 4px; 17 | padding-top: 20px; 18 | padding-bottom: 1px; 19 | } 20 | 21 | .logo { 22 | background: rgb(51,0,113); 23 | background: linear-gradient(45deg, rgba(51,0,113,1) 0%, rgba(36,14,176,1) 60%, rgba(0,212,255,1) 100%); 24 | color: #fff !important; 25 | padding: 2px 13px 2px 13px; 26 | border-radius: 3px; 27 | } 28 | 29 | pre { 30 | display: block; 31 | margin-top: 0; 32 | margin-bottom: 1rem; 33 | overflow: auto; 34 | font-size: .875em; 35 | background: #f8f8f8; 36 | padding: 5px; 37 | font-weight: bold; 38 | font-family: 'Consolas'; 39 | } 40 | 41 | .hljs-keyword { 42 | color: #d61b9f; 43 | opacity: 1; 44 | } 45 | 46 | .hljs-comment { 47 | color: #888; 48 | } 49 | 50 | 51 | .docx table { 52 | border: 1px solid #1C6EA4; 53 | background-color: #EEEEEE; 54 | width: 100%; 55 | text-align: left; 56 | border-collapse: collapse; 57 | } 58 | 59 | .docx table td, 60 | .docx table th { 61 | border: 1px solid #AAAAAA; 62 | padding: 13px 12px; 63 | } 64 | 65 | .docx table tbody td { 66 | font-size: 13px; 67 | } 68 | 69 | .docx table thead { 70 | background: #1C6EA4; 71 | border-bottom: 2px solid #444444; 72 | } 73 | 74 | .docx table thead th { 75 | font-size: 15px; 76 | font-weight: bold; 77 | color: #FFFFFF; 78 | text-align: center; 79 | border-left: 2px solid #D0E4F5; 80 | } 81 | 82 | .docx table thead th:first-child { 83 | border-left: none; 84 | } 85 | 86 | .docx table tfoot { 87 | font-size: 14px; 88 | font-weight: bold; 89 | color: #FFFFFF; 90 | background: #D0E4F5; 91 | background: -moz-linear-gradient(top, #dcebf7 0%, #d4e6f6 66%, #D0E4F5 100%); 92 | background: -webkit-linear-gradient(top, #dcebf7 0%, #d4e6f6 66%, #D0E4F5 100%); 93 | background: linear-gradient(to bottom, #dcebf7 0%, #d4e6f6 66%, #D0E4F5 100%); 94 | border-top: 2px solid #444444; 95 | } 96 | 97 | .docx table tfoot td { 98 | font-size: 14px; 99 | } 100 | 101 | .docx table tfoot .links { 102 | text-align: right; 103 | } 104 | 105 | .docx table tfoot .links a { 106 | display: inline-block; 107 | background: #1C6EA4; 108 | color: #FFFFFF; 109 | padding: 2px 8px; 110 | border-radius: 5px; 111 | } 112 | 113 | .versioning { 114 | padding-left: 10px; 115 | font-size: 16px; 116 | font-weight: bold; 117 | color: #444; 118 | } -------------------------------------------------------------------------------- /ldbx.min.js: -------------------------------------------------------------------------------- 1 | /* LDBX Version 1.2.5 2 | Author : ikhbalfuady@gmail.com 3 | This some utilities script to help you manage localStorage data 4 | the style syntax similary like laravel eloquent to help you easy to understod the query 5 | avail to save, update, delete, get all & get single 6 | */ 7 | class DB{constructor(){if(this.key=null,"undefined"!=typeof Storage)return!0;return alert("Sorry! No Web Storage support.."),!1}valueFormater(e){return"true"===e||"false"!==e&&(isNaN(e)?e:Number(e))}getFormat(e){var t="str";return"number"==typeof e&&(t="num"),"object"==typeof e&&(t="obj"),"boolean "==typeof e&&(t="bol"),t}setter(e){var t=this.getFormat(e);return"obj"==t&&(e=JSON.stringify(e)),t+"|"+e}formater(e){if(!e)return console.warn(`Failed to extract data [${this.key}]`,e),null;let[t,s]=e.split("|");return"obj"===t?JSON.parse(s):"num"===t?parseFloat(s):"bol"===t?"true"===s:s}save(e,t){this.key=e,localStorage.setItem(e,this.setter(t))}get(e){this.key=e;var t=localStorage.getItem(e);return this.formater(t)}remove(e){return this.key=e,localStorage.removeItem(e)}}class LDBX{constructor(e=null,t=!0,s=!0){"object"==typeof e&&(e.table?this.tableName=e.table:this.console("Table name not defined, plese make object with name 'table' if you using object config params!"),e.softDelete&&(this.softDelete=e.softDelete),e.showLog&&(this.showLog=e.showLog)),this.tableName=e,this.showLog=t,this.softDelete=s,this.onlyData=s?"active":"all",this.whereCondition=[],this.orderCondition=[],this.belongsToRelation=[],this.hasManyRelation=[],this.DB=new DB}getFillableColumn(e){var t=[];for(k in e)t.push(k);return t}resetProps(){this.whereCondition=[],this.orderCondition=[],this.belongsToRelation=[],this.hasManyRelation=[],this.onlyData=this.softDelete?"active":"all"}UUID(e=""){var t,s=Math.random,a="";do a+=(t=s()).toString(16).substr(3,6);while(a.length<30);return a.substr(0,8)+e+a.substr(8,4)+e+"4"+a.substr(12,3)+e+((4*t|0)+8).toString(16)+a.substr(15,3)+e+a.substr(18,12)}console(e,t="info"){var s={info:{color:"#041b24",background:"#2ba6d6"},warning:{color:"#041b24",background:"#f5ab00"},success:{color:"#041b24",background:"#0fd644"},danger:{color:"#fff",background:"#f00702"}};let a=`color: ${s[t].color}background: ${s[t].background}font-size: 11pxpadding: 5px`;var r="%c[LDBX]⇒ "+e;this.showLog&&("info"===t?console.info(r,a):"warning"===t?console.warn(r,a):"danger"===t?console.error(r,a):console.debug(r,a))}dateNow(){let e=new Date,t=e.getFullYear(),s=`0${e.getMonth()+1}`.slice(-2),a=`0${e.getDate()}`.slice(-2),r=`0${e.getHours()}`.slice(-2),o=`0${e.getMinutes()}`.slice(-2);return`${t}-${s}-${a} ${r}:${o}`}hasData(){var e=this.DB.get(this.tableName);return e&&e.length?(this.console(`[hasData] ${this.tableName} : true`,"info"),!0):(this.console(`[hasData] ${this.tableName} : false`,"info"),!1)}fixStructure(e){var t=this.fetch(this.tableName)||[];let s=e.includes("id");s||e.push("id"),t=t.map(t=>{let s={};return e.forEach(e=>{s[e]=t[e]||null}),s}),this.DB.save(this.tableName,t),console.info(`Success updating structure [${this.tableName}]`,e,t)}fetch(e,t=[],s=""){let a=performance.now();var r=this.DB.get(e)||[],o=[];if(r&&(o=t.length?this.query(r,t):this.handleSoftDeleteData(r)),this.orderCondition.length)for(let i of this.orderCondition)o=i.dateFormat?this.sortByDateFormat(o,i.key,i.type):this.sortBy(o,i.key,i.type);let n=performance.now();return this.console(`${s} Query ${o.length} of '${e}' Execution time: ${n-a} ms`,"info"),o}sortBy(e,t,s="asc"){return e.sort((e,a)=>{let r="string"==typeof e[t]?e[t].toUpperCase():e[t],o="string"==typeof a[t]?a[t].toUpperCase():a[t];return r>o?"asc"===s?1:-1:r{let r=new Date(e[t]),o=new Date(a[t]);return"asc"===s?r-o:o-r})}handleSoftDeleteObj(e){let t=!1;return this.softDelete&&("active"!==this.onlyData||e.deleted_at)?"trash"===this.onlyData&&e.deleted_at?t=!0:"all"===this.onlyData&&e.deleted_at&&(t=!0):t=!0,t}handleSoftDeleteData(e){var t=[];for(let s=0;so?"asc"===t?1:-1:r"===e&&t>s&&(a=!0),">="===e&&t>=s&&(a=!0),"<"===e&&t(this.belongsToRelation.length&&(e=this.getRelation(e,"belongsTo")),this.hasManyRelation.length&&(e=this.getRelation(e,"hasMany")),e))}getRelation(e,t="belongsTo"){return this[`${t}Relation`].map(s=>{let a=this.fetch(s.tableName,[{key:s.targetKey,operator:"=",value:e[s.foreignKey]}]);a&&a.length&&("belongsTo"===t&&(e[s.newObjectName]=a[0]),"hasMany"===t&&(e[s.newObjectName]=a))}),e}belongsTo(e,t,s,a="id"){return this.belongsToRelation.push({tableName:e,foreignKey:t,newObjectName:s,targetKey:a}),this}hasMany(e,t,s,a="id"){return this.hasManyRelation.push({tableName:e,foreignKey:t,newObjectName:s,targetKey:a}),this}get(){var e=this.fetch(this.tableName,this.whereCondition);return console.log("get",this.onlyData,e),e=this.collectRelation(e),this.resetProps(),e}first(){var e=this.fetch(this.tableName,this.whereCondition);return e=this.collectRelation(e),this.resetProps(),e.length?e[0]:null}find(e){return this.where("id",e).first()}save(e){let t=this.UUID(),s=this.dateNow(),a=this.dateNow();e.id&&(t=e.id);let r=this.DB.get(this.tableName),o=r?[...r,{...e,id:t,created_at:s,updated_at:a,deleted_at:null}]:[{...e,id:t,created_at:s,updated_at:a,deleted_at:null}];return this.DB.save(this.tableName,o),this.console(`Success saving [${this.tableName}]`,"success"),this.resetProps(),{...e,id:t}}update(e){e.updated_at=this.dateNow();var t=this.fetch(this.tableName,[]);let s=t.findIndex(t=>t.id===e.id);return s>=0?(t[s]=e,this.DB.save(this.tableName,t),this.console(`Succes updating [${this.tableName}]`,"success"),this.resetProps(),e):(this.console(`update:: index of id [${e.id}] not found in data "${this.tableName}" `,"danger"),!1)}truncate(){return this.DB.remove(this.tableName)}delete(e,t=!1){var s=this.fetch(this.tableName,[]);let a=s.findIndex(t=>t.id===e);if(!(a>=0))return this.console(`delete: index of id [${e}] not found in data "${this.tableName}" `,"danger"),!1;if(this.softDelete&&!1===t)s[a].deleted_at=this.dateNow(),this.DB.save(this.tableName,s);else{let r=s.slice(0,a).concat(s.slice(a+1));this.DB.save(this.tableName,r)}this.console(`Succes updating [${this.tableName}]`,"success")}} -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![logo]( https://ldbx.sopeus.com/logo.png) 2 | 3 | # LDBX 4 | Javascript Library for data management using localStorage with laravel eloquent syntax, 5 | Create, Read, Update, Delete and Truncate has avail in this lib. 6 | 7 | Demo : [LDXB Demo](https://ldbx.sopeus.com) 8 | 9 | # Usage 10 | 11 | **Initialize Table** 12 | 13 | There are 3 params in constructor : 14 | > using params default 15 | 1. Table Name [String] (Required) 16 | 2. Query Log in console [Boolean] (Optional) 17 | 3. Soft Delete [Boolean] (Optional) 18 | 19 | > using config params 20 | you can using object configuration params with structure like this : 21 | ``` 22 | { 23 | table: String, 24 | showLog: Boolean, 25 | softDelete: Boolean, 26 | } 27 | ``` 28 | 29 | Example instance 30 | 31 | ``` 32 | 33 | // Using default params 34 | const DataModel = new LDBX('users', true, false) 35 | 36 | 37 | // Using Config params 38 | const config = { 39 | table: 'users', 40 | log: true, 41 | softDelete: false, 42 | } 43 | const DataModel = new LDBX(config) 44 | 45 | ``` 46 | ___ 47 | 48 | 49 | **Get All Data** 50 | 51 | ``` 52 | const UserModel = new LDBX('users') 53 | var list = UserModel.get() 54 | 55 | ``` 56 | ___ 57 | 58 | 59 | **Get first / single data** 60 | 61 | ``` 62 | const UserModel = new LDBX('users') 63 | var data = UserModel.where('id', id).first() // *first its mean, first of result query 64 | 65 | ``` 66 | ___ 67 | 68 | **Single selection where** 69 | 70 | ``` 71 | const UserModel = new LDBX('users') 72 | var data = UserModel.where('name', 'ikhbalfuady').get() 73 | 74 | ``` 75 | ___ 76 | 77 | **Multiple selection where** 78 | 79 | ``` 80 | // using custom operator 81 | const UserModel = new LDBX('users') 82 | var data = UserModel.where('age', '>=' 18) 83 | .where('age', '<=', 25) 84 | .get() 85 | 86 | ``` 87 | ___ 88 | 89 | **Find by id** 90 | 91 | ``` 92 | const UserModel = new LDBX('users') 93 | var data = UserModel.find(id) 94 | 95 | ``` 96 | ___ 97 | 98 | 99 | **Store Data** 100 | 101 | ``` 102 | const UserModel = new LDBX('users') 103 | let data = { 104 | name: "John", 105 | age: 21 106 | } 107 | 108 | UserModel.save(data) 109 | 110 | ``` 111 | ___ 112 | 113 | **Update Data** 114 | 115 | ``` 116 | const UserModel = new LDBX('users') 117 | let data = UserModel.find(id) 118 | if (!data) throw error(`user with id"${id}" not found `) 119 | 120 | // set value into object 121 | data.name = "Ikhbalfuady" 122 | UserModel.update(data) 123 | 124 | ``` 125 | ___ 126 | 127 | **Delete Data** 128 | 129 | ``` 130 | const UserModel = new LDBX('users') 131 | UserModel.delete(id) // default soft delete 132 | 133 | // permanent delete 134 | const UserModel = new LDBX('users') 135 | UserModel.delete(id, true) 136 | 137 | ``` 138 | 139 | 140 | # Avail "**Where**" Operator 141 | | Name | value | Syntax | Status | 142 | |--------------------|---------|-----------------------------------------------------------|-------------| 143 | | Equal | = | .where('key', '=', value) OR .where('key', value) | READY | 144 | | Like / Contains | like | .where('key', 'like', value) | READY | 145 | | Less Than | < | .where('key', '<', value) | READY | 146 | | Less Than Equal | <= | .where('key', '<=', value) | READY | 147 | | Greater Than | > | .where('key', '>', value) | READY | 148 | | Greater Than Equal | >= | .where('key', '>=', value) | READY | 149 | | Is NULL | N/n | .where('key', 'N', value) OR .where('key', 'n', value) | READY | 150 | | Is NOT NULL | NN / nn | .where('key', 'NN', value) OR .where('key', 'nn', value) | READY | 151 | | IN | IN | .where('key', 'IN', arrayValue) // arrayValue = [1,2,3] | READY | 152 | | NOT IN | NIN | .where('key', 'NIN', arrayValue) // arrayValue = [1,2,3]| READY | 153 | 154 | ___ 155 | 156 | # Other Features 157 | 158 | **trashed()** 159 | 160 | this is method chaining to getting only trashed data 161 | 162 | ``` 163 | var UserModel = new LDBX('users') 164 | .trashed() 165 | .get() 166 | 167 | 168 | ``` 169 | 170 | **withTrashed()** 171 | 172 | this is method chaining to getting all with trashed data if you using **softDelete** 173 | 174 | ``` 175 | var UserModel = new LDBX('users') 176 | .withTrashed() 177 | .get() 178 | 179 | 180 | ``` 181 | 182 | **truncate()** 183 | 184 | this is method chaining to clean up data 185 | 186 | ``` 187 | var UserModel = new LDBX('users') 188 | .truncate() 189 | 190 | 191 | ``` 192 | 193 | **hasData()** 194 | 195 | this is method chaining to checking table has already have data or not 196 | 197 | ``` 198 | var UserModel = new LDBX('users') 199 | .hasData() 200 | 201 | 202 | ``` 203 | 204 | **getFillableColumn()** 205 | 206 | this is method chaining to getting fillable columns of object you set 207 | 208 | ``` 209 | // getting fillable of existing data 210 | var UserModel = new LDBX('users') 211 | var user = UserModel.find(1) 212 | var fillableColumns = UserModel.getFillableColumn(user) 213 | 214 | ``` 215 | 216 | **fixStructure()** 217 | 218 | this is method chaining to fixing structure like ALTER TABLE in SQL\ 219 | when you chaning structure of object model you have, you just call this method for fix that 220 | example : 221 | 222 | ``` 223 | // current model 224 | let UsersSpec = { 225 | dbConfig: { 226 | table: 'users', 227 | showLog: true, 228 | softDelete: true, 229 | }, 230 | dataModel: { 231 | id: null, 232 | name: null, 233 | email: null 234 | } 235 | } 236 | const UserModel = new LDBX(UsersSpec.dbConfig) 237 | const fillableColumns = UserModel.getFillableColumn(UsersSpec.dataModel) 238 | /* return 239 | ['id', 'name', 'email'] 240 | */ 241 | 242 | // and you want to change the users to model to like this 243 | let UsersSpec = { 244 | dbConfig: { 245 | table: 'users', 246 | showLog: true, 247 | softDelete: true, 248 | }, 249 | dataModel: { 250 | id: null, 251 | name: null, 252 | email: null, 253 | phone: null, // new 254 | born_date: null, // new 255 | } 256 | } 257 | 258 | // just do like this 259 | const UserModel = new LDBX(UsersSpec.dbConfig) 260 | const newFillableColumns = UserModel.getFillableColumn(UsersSpec.dataModel) 261 | UserModel.fixStructure(newFillableColumns) // all of data will be updated with new fillable structure 262 | 263 | ``` 264 | 265 | 266 | **orderBy(key, type?, dateFormat?)** 267 | 268 | this is method chaining to implementing "order data" of result query \ 269 | - key : String // object key 270 | - type : Enum(asc,desc) (default : asc) 271 | - dateFormat : Boolean (default : false) // for sorting date type data 272 | 273 | ``` 274 | const UserModel = new LDBX('jorunal') 275 | .orderBy('key') // order ASC 276 | .get() 277 | 278 | const UserModel = new LDBX('jorunal') 279 | .orderBy('key', 'desc') // order DESC 280 | .get() 281 | 282 | // ordering date data 283 | const UserModel = new LDBX('transaction') 284 | .orderBy('date', 'desc', true) // fot better result activate date format with set 3 in third parameter 285 | .get() 286 | 287 | 288 | ``` 289 | 290 | * Atenttion : order can only be executed once per query, even if you add multiple 'orderBy', the last 'orderBy' is recognized 291 | 292 | ___ 293 | 294 | **belongsTo(tableName, foreignKey, newObjectName?, targetKey?)** 295 | 296 | this is method chaining to implementing relation of some data \ 297 | this method will be created new single object for every object result data \ 298 | 299 | - tableName : name of table 300 | - foreignKey : foreign key object, ex : role_id 301 | - newObjectName : object name for the relation , ex : role 302 | - targetKey : target key object of source data, default is "id" 303 | 304 | 305 | ``` 306 | const UserModel = new LDBX('users') 307 | .belongsTo('roles', 'role_id', 'role') // simply version 308 | .first() 309 | 310 | /* return 311 | { 312 | id: 1 313 | name: 'John', 314 | role_id: 1, 315 | roles: { 316 | id: 1, 317 | name: 'Admin', 318 | }, 319 | } 320 | */ 321 | 322 | const UserModel = new LDBX('jorunal') 323 | .belongsTo('coa', 'coa_revenue_code', 'coa_revenue', 'code') // full version 324 | .get() 325 | 326 | /* return 327 | [ 328 | { 329 | id: 1 330 | name: 'TRX Forex', 331 | coa_revenue_code: '101020230' 332 | coa_revenue: { 333 | code: '101020230', 334 | name: 'Fix Revenue', 335 | } 336 | }, 337 | { 338 | id: 2 339 | name: 'TRX others', 340 | coa_revenue_code: '4305353353' 341 | coa_revenue: { 342 | code: '4305353353', 343 | name: 'Other Revenue', 344 | } 345 | } 346 | ] 347 | */ 348 | 349 | ``` 350 | 351 | ___ 352 | 353 | **hasMany(tableName, foreignKey, newObjectName?, targetKey?)** 354 | 355 | this is method chaining to implementing relation of some data\ 356 | this method will be created new single object with array result for every object in result data\ 357 | 358 | - tableName : name of table 359 | - foreignKey : foreign key object, ex : role_id 360 | - newObjectName : object name for the relation , ex : role 361 | - targetKey : target key object of source data, default is "id" 362 | 363 | 364 | ``` 365 | const UserModel = new LDBX('users') 366 | .hasMany('roles', 'role_id', 'roles') // simply version 367 | .first() 368 | /* return 369 | { 370 | id: 1 371 | name: 'John', 372 | roles: [ 373 | { 374 | id: 1, 375 | name: 'Admin', 376 | }, 377 | { 378 | id: 2, 379 | name: 'Staff', 380 | } 381 | ], 382 | } 383 | */ 384 | 385 | const UserModel = new LDBX('jorunal') 386 | .hasMany('coa', 'coa_revenue_code', 'coa_revenues', 'code') // full version 387 | .get() 388 | 389 | /* return 390 | [ 391 | { 392 | id: 1 393 | name: 'transaction', 394 | coa_revenues: [ 395 | { 396 | code: '101020230', 397 | name: 'Fix Reveneu', 398 | }, 399 | { 400 | code: '105020230', 401 | name: 'Other Revenue 402 | ], 403 | } 404 | ] 405 | */ 406 | 407 | ``` -------------------------------------------------------------------------------- /ldbx.js: -------------------------------------------------------------------------------- 1 | /* LDBX Version 1.2.5 2 | Author : ikhbalfuady@gmail.com 3 | This some utilities script to help you manage localStorage data 4 | the style syntax similary like laravel eloquent to help you easy to understod the query 5 | avail to save, update, delete, get all & get single 6 | */ 7 | 8 | /* LocalStorage Helper */ 9 | class DB { 10 | constructor() { 11 | this.key = null 12 | if (typeof(Storage) !== "undefined") { 13 | // console.log('LocalStorage initialize') 14 | return true 15 | } else { 16 | alert('Sorry! No Web Storage support..') 17 | return false 18 | } 19 | } 20 | 21 | valueFormater (val) { 22 | if (val === 'true') return true 23 | if (val === 'false') return false 24 | if (!isNaN(val)) return Number(val) 25 | return val 26 | } 27 | 28 | getFormat (val) { 29 | var res = 'str' 30 | if (typeof(val) === 'number') res = 'num' 31 | if (typeof(val) === 'object') res = 'obj' 32 | if (typeof(val) === 'boolean ') res = 'bol' 33 | return res 34 | } 35 | 36 | setter (data) { 37 | var format = this.getFormat(data) 38 | if (format == 'obj') data = JSON.stringify(data) 39 | var val = format + '|' + data 40 | return val 41 | } 42 | 43 | formater(val) { 44 | if (!val) { 45 | console.warn(`Failed to extract data [${this.key}]`, val) 46 | return null 47 | } 48 | 49 | const [format, value] = val.split("|") 50 | if (format === 'obj') return JSON.parse(value) 51 | if (format === 'num') return parseFloat(value) 52 | if (format === 'bol') return value === 'true' 53 | return value 54 | } 55 | 56 | save (key, value) { 57 | this.key = key 58 | localStorage.setItem(key, this.setter(value)) 59 | } 60 | 61 | get (key) { 62 | this.key = key 63 | var val = localStorage.getItem(key) 64 | val = this.formater(val) 65 | return val 66 | } 67 | 68 | remove (key) { 69 | this.key = key 70 | return localStorage.removeItem(key) 71 | } 72 | } 73 | 74 | /* Eloquent */ 75 | class LDBX { 76 | constructor(tableOrConfig = null, showLog = true, softDelete = true) { 77 | if (typeof(tableOrConfig) === 'object') { 78 | if (tableOrConfig.table) this.tableName = tableOrConfig.table 79 | else this.console("Table name not defined, plese make object with name 'table' if you using object config params!") 80 | 81 | if (tableOrConfig.softDelete) this.softDelete = tableOrConfig.softDelete 82 | if (tableOrConfig.showLog) this.showLog = tableOrConfig.showLog 83 | } 84 | this.tableName = tableOrConfig // localstorage key name 85 | this.showLog = showLog // log performance 86 | this.softDelete = softDelete // softDelete 87 | this.onlyData = softDelete ? 'active' : 'all' // data filtering : active,trash,all 88 | 89 | /* whereCondition : arrayObject 90 | N : IS NULL 91 | NN : NOT NULL 92 | NIN : NOT IN 93 | { 94 | key : String, 95 | operator: Enum(=, >, >=, <, <, like, N, NN, IN, NIN) 96 | value : String,Number, 97 | } 98 | */ 99 | this.whereCondition = [] 100 | 101 | /* orderCondition : arrayObject 102 | { 103 | key : String, 104 | type : Enum('asc','desc), 105 | dateFormat : Boolean, 106 | } 107 | */ 108 | this.orderCondition = [] 109 | 110 | /* belongsToRelation & hasManyRelation : arrayObject 111 | { 112 | tableName : String, 113 | foreignKey : String, 114 | newObjectName : String, 115 | targetKey : String 116 | } 117 | */ 118 | this.belongsToRelation = [] 119 | this.hasManyRelation = [] 120 | 121 | /* LocalStorage Instance */ 122 | this.DB = new DB() 123 | } 124 | 125 | getFillableColumn (obj) { 126 | var res = [] 127 | for (k in obj) { res.push(k) } 128 | return res 129 | } 130 | 131 | resetProps () { 132 | this.whereCondition = [] 133 | this.orderCondition = [] 134 | this.belongsToRelation = [] 135 | this.hasManyRelation = [] 136 | this.onlyData = this.softDelete ? 'active' : 'all' 137 | } 138 | 139 | // Utilities 140 | UUID (separator = '') { 141 | var rand = Math.random 142 | 143 | var nbr, randStr = "" 144 | do { 145 | randStr += (nbr = rand()).toString(16).substr(3, 6) 146 | } while (randStr.length < 30) 147 | return ( 148 | randStr.substr(0, 8) + separator + 149 | randStr.substr(8, 4) + separator + "4" + 150 | randStr.substr(12, 3) + separator + 151 | ((nbr*4|0)+8).toString(16) + // [89ab] 152 | randStr.substr(15, 3) + separator + 153 | randStr.substr(18, 12) 154 | ) 155 | } 156 | 157 | console (msg, type = 'info') { 158 | var theme = { 159 | info : { color: '#041b24', background: '#2ba6d6'}, 160 | warning : { color: '#041b24', background: '#f5ab00'}, 161 | success : { color: '#041b24', background: '#0fd644'}, 162 | danger : { color: '#fff', background: '#f00702'}, 163 | } 164 | const styles = [ 165 | `color: ${theme[type].color}`, 166 | `background: ${theme[type].background}`, 167 | 'font-size: 11px', 168 | 'padding: 5px', 169 | ].join('') // 2. Concatenate the individual array item and concatenate them into a string separated by a semi-colon () 170 | 171 | // 3. Pass the styles variable 172 | var csl = '%c'+ '[LDBX]⇒ ' +msg 173 | if (this.showLog) { 174 | if (type === 'info') console.info(csl, styles) 175 | else if (type === 'warning') console.warn(csl, styles) 176 | else if (type === 'danger') console.error(csl, styles) 177 | else console.debug(csl, styles) 178 | } 179 | } 180 | 181 | dateNow () { 182 | const date = new Date(); 183 | const year = date.getFullYear(); 184 | const month = `0${date.getMonth() + 1}`.slice(-2); // Add 1 to the month because it is 0-based, and pad with a leading 0 if necessary 185 | const day = `0${date.getDate()}`.slice(-2); // Pad with a leading 0 if necessary 186 | const hour = `0${date.getHours()}`.slice(-2); // Pad with a leading 0 if necessary 187 | const minute = `0${date.getMinutes()}`.slice(-2); // Pad with a leading 0 if necessary 188 | return `${year}-${month}-${day} ${hour}:${minute}`; 189 | } 190 | 191 | hasData () { 192 | var table = this.DB.get(this.tableName) 193 | if (table && table.length) { 194 | this.console(`[hasData] ${this.tableName} : true`, 'info') 195 | return true 196 | } else { 197 | this.console(`[hasData] ${this.tableName} : false`, 'info') 198 | return false 199 | } 200 | } 201 | 202 | /* 203 | fillableColumns : ['id', 'name', 'code'] 204 | */ 205 | fixStructure (fillableColumns) { 206 | var data = this.fetch(this.tableName) || [] 207 | const hasId = fillableColumns.includes('id') 208 | if (!hasId) fillableColumns.push('id') 209 | 210 | data = data.map(row => { 211 | const fixRow = {} 212 | fillableColumns.forEach(col => { 213 | fixRow[col] = row[col] || null 214 | }) 215 | return fixRow 216 | }) 217 | 218 | this.DB.save(this.tableName, data) // commiting 219 | console.info(`Success updating structure [${this.tableName}]`, fillableColumns, data) 220 | } 221 | 222 | /* criteria = whereCondition */ 223 | fetch (tableName, criteria = [], tag = '') { 224 | const start = performance.now() 225 | var table = this.DB.get(tableName) || [] 226 | var data = [] 227 | if (table) { 228 | if (criteria.length) data = this.query(table, criteria) 229 | else data = this.handleSoftDeleteData(table) 230 | } 231 | 232 | if (this.orderCondition.length) { 233 | for (let order of this.orderCondition) { 234 | if (order.dateFormat) data = this.sortByDateFormat(data, order.key, order.type) 235 | else data = this.sortBy(data, order.key, order.type) 236 | } 237 | } 238 | 239 | const end = performance.now() 240 | this.console(`${tag} Query ${data.length} of '${tableName}' Execution time: ${end - start} ms`, 'info') 241 | return data 242 | } 243 | 244 | sortBy(data, key, order = 'asc') { 245 | return data.sort((a, b) => { 246 | const aValue = typeof a[key] === 'string' ? a[key].toUpperCase() : a[key] 247 | const bValue = typeof b[key] === 'string' ? b[key].toUpperCase() : b[key] 248 | return aValue > bValue ? (order === 'asc' ? 1 : -1) : aValue < bValue ? (order === 'asc' ? -1 : 1) : 0 249 | }) 250 | } 251 | 252 | sortByDateFormat(data, key, order = 'asc') { 253 | return data.sort((a, b) => { 254 | const aValue = new Date(a[key]); 255 | const bValue = new Date(b[key]); 256 | if (order === 'asc') return aValue - bValue; 257 | else return bValue - aValue; 258 | }) 259 | } 260 | 261 | handleSoftDeleteObj (obj) { 262 | let res = false 263 | if (this.softDelete) { 264 | if (this.onlyData === 'active' && !obj.deleted_at) res = true 265 | else if (this.onlyData === 'trash' && obj.deleted_at) res = true 266 | else if (this.onlyData === 'all' && obj.deleted_at) res = true 267 | } else res = true 268 | return res 269 | } 270 | 271 | handleSoftDeleteData (data) { 272 | var res = [] 273 | for (let i = 0; i < data.length; i++) { 274 | if (data[i] && this.handleSoftDeleteObj(data[i])) res.push(data[i]) 275 | } 276 | return res 277 | } 278 | 279 | compareValues (key, order = 'asc') { 280 | return function(a, b) { 281 | if (!a.hasOwnProperty(key) || !b.hasOwnProperty(key)) return 0 282 | const aValue = typeof a[key] === 'string' ? a[key].toUpperCase() : a[key] 283 | const bValue = typeof b[key] === 'string' ? b[key].toUpperCase() : b[key] 284 | return aValue > bValue ? (order === 'asc' ? 1 : -1) : aValue < bValue ? (order === 'asc' ? -1 : 1) : 0 285 | } 286 | } 287 | 288 | operator (operator, value, valueComparison) { 289 | var res = false 290 | if (operator === '=' && value === valueComparison) res = true 291 | if (operator === '>' && value > valueComparison) res = true 292 | if (operator === '>=' && value >= valueComparison) res = true 293 | if (operator === '<' && value < valueComparison) res = true 294 | if (operator === '<=' && value <= valueComparison) res = true 295 | if (operator === 'like' && value.includes(valueComparison)) res = true 296 | if (operator === 'N' && value === null) res = true // NULL 297 | if (operator === 'NN' && value !== null) res = true // NOT NULL 298 | if (Array.isArray(valueComparison) && operator === 'IN' && valueComparison.includes(value)) res = true // IN 299 | if (Array.isArray(valueComparison) && operator === 'NIN' && !valueComparison.includes(value)) res = true // NOT IN 300 | return res 301 | } 302 | 303 | query (data, criteria = []) { 304 | console.log('asd', this.tableName, this.onlyData) 305 | var countWhere = criteria ? criteria.length : 0 306 | if (countWhere === 0) return data 307 | var res = [] 308 | var totalChecked = 0 309 | for (let val of data) { 310 | totalChecked = totalChecked + 1 311 | var match = 0 312 | for (let where of criteria) { 313 | var colVal = val[where.key] 314 | var value = where.value ? where.value : null 315 | if (this.operator(where.operator, colVal, value)) match = match + 1 316 | } 317 | if (match === countWhere) { 318 | // if (this.softDelete) { 319 | // if (this.onlyData === 'active' && !val.deleted_at) res.push(val) 320 | // else if (this.onlyData === 'trash' && val.deleted_at) res.push(val) 321 | // else if (this.onlyData === 'all' && val.deleted_at) res.push(val) 322 | // } else res.push(val) 323 | if (this.handleSoftDeleteObj(val)) res.push(val) 324 | } 325 | } 326 | // console.info(`querying ${totalChecked} of ${data.length} data`) 327 | return res 328 | } 329 | 330 | // Chain 331 | trashed() { 332 | this.onlyData = 'trash' 333 | return this 334 | } 335 | 336 | withTrashed() { 337 | this.onlyData = 'all' 338 | return this 339 | } 340 | 341 | orderBy (key, type = 'asc', dateFormat = false) { 342 | this.orderCondition.push({ key: key, type: type, dateFormat}) 343 | return this 344 | } 345 | 346 | where (col, oprOrVal, value) { 347 | var criteria = { 348 | key: col, 349 | operator: value ? oprOrVal : '=', 350 | value: value ? value : oprOrVal, 351 | } 352 | 353 | if (criteria.operator.toLowerCase() === 'n') criteria = { key: col, operator: 'N', value: null} 354 | if (criteria.operator.toLowerCase() === 'nn') criteria = { key: col, operator: 'NN', value: null} 355 | if (criteria.operator.toLowerCase() === 'in') criteria = { key: col, operator: 'IN', value: value} 356 | if (criteria.operator.toLowerCase() === 'nin') criteria = { key: col, operator: 'NIN', value: value} 357 | 358 | this.whereCondition.push(criteria) 359 | return this 360 | } 361 | 362 | // Relations 363 | collectRelation (data) { 364 | return data.map( obj => { 365 | if (this.belongsToRelation.length) obj = this.getRelation(obj, 'belongsTo') 366 | if (this.hasManyRelation.length) obj = this.getRelation(obj, 'hasMany') 367 | return obj 368 | }) 369 | } 370 | 371 | getRelation(obj, type = 'belongsTo') { 372 | var relationMapName = `${type}Relation` 373 | this[relationMapName].map(rel => { 374 | let objRel = this.fetch(rel.tableName, [{key: rel.targetKey, operator: '=', value: obj[rel.foreignKey]}]) 375 | // console.info(`${type} ${rel.tableName} WHERE ${rel.targetKey} = ${obj[rel.foreignKey]}`) 376 | if (objRel && objRel.length) { 377 | if (type === 'belongsTo') obj[rel.newObjectName] = objRel[0] 378 | if (type === 'hasMany') obj[rel.newObjectName] = objRel 379 | } 380 | }) 381 | return obj 382 | } 383 | 384 | belongsTo(tableName, foreignKey, newObjectName, targetKey = 'id') { 385 | var criteria = { 386 | tableName, 387 | foreignKey, 388 | newObjectName, 389 | targetKey 390 | } 391 | this.belongsToRelation.push(criteria) 392 | return this 393 | } 394 | 395 | hasMany(tableName, foreignKey, newObjectName, targetKey = 'id') { 396 | var criteria = { 397 | tableName, 398 | foreignKey, 399 | newObjectName, 400 | targetKey 401 | } 402 | this.hasManyRelation.push(criteria) 403 | return this 404 | } 405 | 406 | // Trigger 407 | get () { 408 | var data = this.fetch(this.tableName, this.whereCondition) 409 | console.log('get', this.onlyData, data) 410 | data = this.collectRelation(data) 411 | this.resetProps() 412 | return data 413 | } 414 | 415 | first () { 416 | var data = this.fetch(this.tableName, this.whereCondition) 417 | data = this.collectRelation(data) 418 | this.resetProps() 419 | return data.length ? data[0] : null 420 | } 421 | 422 | find (id) { 423 | return this.where('id', id).first() 424 | } 425 | 426 | // Commiting 427 | save (data) { 428 | let id = this.UUID() 429 | const created_at = this.dateNow() 430 | const updated_at = this.dateNow() 431 | const deleted_at = null 432 | 433 | if (data.id) id = data.id 434 | const table = this.DB.get(this.tableName) 435 | const db = table ? [...table, { ...data, id, created_at, updated_at, deleted_at }] : [{ ...data, id, created_at, updated_at, deleted_at }] // merging 436 | this.DB.save(this.tableName, db) // commiting 437 | this.console(`Success saving [${this.tableName}]`, 'success') 438 | this.resetProps() 439 | return { ...data, id } 440 | } 441 | 442 | update (data) { 443 | data.updated_at = this.dateNow() 444 | var db = this.fetch(this.tableName, []) 445 | const index = db.findIndex(item => item.id === data.id) 446 | if (index >= 0) { 447 | db[index] = data 448 | // commiting 449 | this.DB.save(this.tableName, db) 450 | this.console(`Succes updating [${this.tableName}]`, 'success') 451 | this.resetProps() 452 | return data 453 | } else { 454 | this.console(`update:: index of id [${data.id}] not found in data "${this.tableName}" `, 'danger') 455 | return false 456 | } 457 | 458 | } 459 | 460 | truncate () { 461 | return this.DB.remove(this.tableName) 462 | } 463 | 464 | delete (id, force = false) { 465 | var db = this.fetch(this.tableName, []) 466 | const index = db.findIndex(item => item.id === id) 467 | if (index >= 0) { 468 | // commiting 469 | if (this.softDelete && force === false) { 470 | db[index].deleted_at = this.dateNow() 471 | this.DB.save(this.tableName, db) 472 | } else { 473 | const newArr = db.slice(0, index).concat(db.slice(index + 1)) 474 | this.DB.save(this.tableName, newArr) 475 | } 476 | this.console(`Succes updating [${this.tableName}]`, 'success') 477 | } else { 478 | this.console(`delete: index of id [${id}] not found in data "${this.tableName}" `, 'danger') 479 | return false 480 | } 481 | } 482 | 483 | 484 | } 485 | 486 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | LDBX - LocalStorage Laravel Syntax 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
38 |
39 |
40 | v.1.2.5 43 | 44 | 50 |
51 | 52 |
53 |

LDBX

54 |

Local Storage management with sweet syntax style & feature like Laravel Eloquent using native Javascript

55 |
56 |
57 | 58 | 59 |
60 |
61 |

# Store

62 |

You can test store into localstorage with this example, you can define the table / source and define the object structure for every data you want to save.

63 |
64 |
65 |
66 |

Table / Source

67 | 68 |
69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 82 | 85 | 88 | 89 | 90 | 93 | 96 | 99 | 100 | 101 | 104 | 107 | 110 | 111 | 112 | 115 | 118 | 121 | 122 | 123 | 124 | 125 | 126 | 129 | 130 | 131 | 132 | 135 | 136 | 137 |
KeyValue
80 | 81 | 83 | 84 | 86 | 87 |
91 | 92 | 94 | 95 | 97 | 98 |
102 | 103 | 105 | 106 | 108 | 109 |
113 | 114 | 116 | 117 | 119 | 120 |
When you added new colum, you can update the structure object of data using "fixStructure" 127 | 128 |
133 | 134 |
138 |
139 |
140 |
141 |

Object Result

142 |
143 | 144 |

LDB Logs

145 |
146 | 147 |
148 | 149 |
150 | 151 | 168 | 169 | 170 | 194 | 195 | 196 |
197 |
198 |

# Manage

199 |

you can Edit, Delete & Query of data you have, and has support to filter by date data type

200 |
201 |
202 |
203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 |
211 |
212 |
213 | 214 |
215 | 216 |
217 | 218 |
219 |

# Documentation

220 |

221 | first of all, make sure the script has been called in your html 222 |

223 |
 224 |         <script src="ldbx.js"></script>
 225 |       
226 |
227 | 228 | 229 |
230 |
231 |

Usages

232 |
233 |
234 | 235 |

Initialize Table

236 |

There are 3 params in constructor :

237 |
238 |

using params default

239 |
    240 |
  1. Table Name [String] (Required)
  2. 241 |
  3. Query Log in console [Boolean] (Optional)
  4. 242 |
  5. Soft Delete [Boolean] (Optional)
  6. 243 |
244 |

using config params 245 | you can using object configuration params with structure like this :

246 |
{
 247 |   table: String,
 248 |   showLog: Boolean,
 249 |   softDelete: Boolean,
 250 | }
 251 | 
252 |

Example instance

253 |

 254 | // Using default params
 255 | const DataModel = new LDBX('users', true, false) 
 256 | 
 257 | 
 258 | // Using Config params
 259 | const config = {
 260 |   table: 'users',
 261 |   log: true,
 262 |   softDelete: false,
 263 | }
 264 | const DataModel = new LDBX(config)
 265 | 

266 |

Get All Data

267 |
const UserModel = new LDBX('users')
 268 | var list = UserModel.get()
 269 | 

270 |

Get first / single data

271 |
const UserModel = new LDBX('users')
 272 | var data = UserModel.where('id', id).first() // *first its mean, first of result query
 273 | 

274 |

Single selection where

275 |
const UserModel = new LDBX('users')
 276 | var data = UserModel.where('name', 'ikhbalfuady').get()
 277 | 

278 |

Multiple selection where

279 |
// using custom operator
 280 | const UserModel = new LDBX('users')
 281 | var data = UserModel.where('age', '>=' 18)
 282 |             .where('age', '<=', 25)
 283 |             .get()
 284 | 

285 |

Find by id

286 |
const UserModel = new LDBX('users')
 287 | var data = UserModel.find(id)
 288 | 

289 |

Store Data

290 |
const UserModel = new LDBX('users')
 291 | let data = {
 292 |   name: "John",
 293 |   age: 21
 294 | }
 295 | 
 296 | UserModel.save(data)
 297 | 

298 |

Update Data

299 |
const UserModel = new LDBX('users')
 300 | let data = UserModel.find(id)
 301 | if (!data) throw error(`user with id"${id}" not found `)
 302 | 
 303 | // set value into object
 304 | data.name = "Ikhbalfuady"
 305 | UserModel.update(data)
 306 | 

307 |

Delete Data

308 |
const UserModel = new LDBX('users')
 309 | UserModel.delete(id) // default soft delete
 310 | 
 311 | // permanent delete
 312 | const UserModel = new LDBX('users')
 313 | UserModel.delete(id, true)
 314 | 

Avail "Where" Operator

315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 |
NamevalueSyntaxStatus
Equal=.where('key', '=', value) OR .where('key', value)READY
Like / Containslike.where('key', 'like', value)READY
Less Than<.where('key', '<', value)READY
Less Than Equal<=.where('key', '<=', value)READY
Greater Than>.where('key', '>', value)READY
Greater Than Equal>=.where('key', '>=', value)READY
Is NULLN/n.where('key', 'N', value) OR .where('key', 'n', value)READY
Is NOT NULLNN / nn.where('key', 'NN', value) OR .where('key', 'nn', value)READY
ININ.where('key', 'IN', arrayValue) // arrayValue = [1,2,3]READY
NOT INNIN.where('key', 'NIN', arrayValue) // arrayValue = [1,2,3]READY
387 |
388 |

Other Features

389 |

trashed()

390 |

this is method chaining to getting only trashed data

391 |
var UserModel = new LDBX('users')
 392 | .trashed()
 393 | .get()
 394 | 

withTrashed()

395 |

this is method chaining to getting all with trashed data if you using softDelete

396 |
var UserModel = new LDBX('users')
 397 | .withTrashed()
 398 | .get()
 399 | 

truncate()

400 |

this is method chaining to clean up data

401 |
var UserModel = new LDBX('users')
 402 | .truncate()
 403 | 

hasData()

404 |

this is method chaining to checking table has already have data or not

405 |
var UserModel = new LDBX('users')
 406 | .hasData()
 407 | 

getFillableColumn()

408 |

this is method chaining to getting fillable columns of object you set

409 |
// getting fillable of existing data
 410 | var UserModel = new LDBX('users')
 411 | var user = UserModel.find(1)
 412 | var fillableColumns = UserModel.getFillableColumn(user)
 413 | 

fixStructure()

414 |

this is method chaining to fixing structure like ALTER TABLE in SQL\ 415 | when you chaning structure of object model you have, you just call this method for fix that 416 | example :

417 |
// current model
 418 | let UsersSpec = {
 419 |   dbConfig: {
 420 |     table: 'users',
 421 |     showLog: true,
 422 |     softDelete: true,
 423 |   },
 424 |   dataModel: {
 425 |     id: null,
 426 |     name: null,
 427 |     email: null
 428 |   }
 429 | }
 430 | const UserModel = new LDBX(UsersSpec.dbConfig)
 431 | const fillableColumns = UserModel.getFillableColumn(UsersSpec.dataModel)
 432 | /* return 
 433 | ['id', 'name', 'email']
 434 | */
 435 | 
 436 | // and you want to change the users to model to like this
 437 | let UsersSpec = {
 438 |   dbConfig: {
 439 |     table: 'users',
 440 |     showLog: true,
 441 |     softDelete: true,
 442 |   },
 443 |   dataModel: {
 444 |     id: null,
 445 |     name: null,
 446 |     email: null,
 447 |     phone: null, // new
 448 |     born_date: null, // new
 449 |   }
 450 | }
 451 | 
 452 | // just do like this
 453 | const UserModel = new LDBX(UsersSpec.dbConfig)
 454 | const newFillableColumns = UserModel.getFillableColumn(UsersSpec.dataModel)
 455 | UserModel.fixStructure(newFillableColumns) // all of data will be updated with new fillable structure
 456 | 

orderBy(key, type?, dateFormat?)

457 |

this is method chaining to implementing "order data" of result query \

458 |
    459 |
  • key : String // object key
  • 460 |
  • type : Enum(asc,desc) (default : asc)
  • 461 |
  • dateFormat : Boolean (default : false) // for sorting date type data
  • 462 |
463 |
const UserModel = new LDBX('jorunal')
 464 | .orderBy('key') // order ASC
 465 | .get()
 466 | 
 467 | const UserModel = new LDBX('jorunal')
 468 | .orderBy('key', 'desc') // order DESC
 469 | .get()
 470 | 
 471 | // ordering date data
 472 | const UserModel = new LDBX('transaction')
 473 | .orderBy('date', 'desc', true) // fot better result activate date format with set 3 in third parameter
 474 | .get()
 475 | 
    476 |
  • Atenttion : order can only be executed once per query, even if you add multiple 'orderBy', the last 'orderBy' is recognized
  • 477 |
478 |
479 |

belongsTo(tableName, foreignKey, newObjectName?, targetKey?)

480 |

this is method chaining to implementing relation of some data \ 481 | this method will be created new single object for every object result data \

482 |
    483 |
  • tableName : name of table
  • 484 |
  • foreignKey : foreign key object, ex : role_id
  • 485 |
  • newObjectName : object name for the relation , ex : role
  • 486 |
  • targetKey : target key object of source data, default is "id"
  • 487 |
488 |
const UserModel = new LDBX('users')
 489 | .belongsTo('roles', 'role_id', 'role') // simply version
 490 | .first()
 491 | 
 492 | /* return 
 493 | {
 494 |   id: 1
 495 |   name: 'John',
 496 |   role_id: 1,
 497 |   roles: {
 498 |     id: 1,
 499 |     name: 'Admin',
 500 |   },
 501 | }
 502 | */
 503 | 
 504 | const UserModel = new LDBX('jorunal')
 505 | .belongsTo('coa', 'coa_revenue_code', 'coa_revenue', 'code') // full version
 506 | .get()
 507 | 
 508 | /* return 
 509 | [
 510 |   {
 511 |     id: 1
 512 |     name: 'TRX Forex',
 513 |     coa_revenue_code: '101020230'
 514 |     coa_revenue: {
 515 |       code: '101020230',
 516 |       name: 'Fix Revenue',
 517 |     }
 518 |   },
 519 |   {
 520 |     id: 2
 521 |     name: 'TRX others',
 522 |     coa_revenue_code: '4305353353'
 523 |     coa_revenue: {
 524 |       code: '4305353353',
 525 |       name: 'Other Revenue',
 526 |     }
 527 |   }
 528 | ]
 529 | */
 530 | 

531 |

hasMany(tableName, foreignKey, newObjectName?, targetKey?)

532 |

this is method chaining to implementing relation of some data\ 533 | this method will be created new single object with array result for every object in result data\

534 |
    535 |
  • tableName : name of table
  • 536 |
  • foreignKey : foreign key object, ex : role_id
  • 537 |
  • newObjectName : object name for the relation , ex : role
  • 538 |
  • targetKey : target key object of source data, default is "id"
  • 539 |
540 |
const UserModel = new LDBX('users')
 541 | .hasMany('roles', 'role_id', 'roles') // simply version
 542 | .first()
 543 | /* return 
 544 | {
 545 |   id: 1
 546 |   name: 'John',
 547 |   roles: [
 548 |     {
 549 |       id: 1,
 550 |       name: 'Admin',
 551 |     },
 552 |     {
 553 |       id: 2,
 554 |       name: 'Staff',
 555 |     }
 556 |   ],
 557 | }
 558 | */
 559 | 
 560 | const UserModel = new LDBX('jorunal')
 561 | .hasMany('coa', 'coa_revenue_code', 'coa_revenues', 'code') // full version
 562 | .get()
 563 | 
 564 | /* return 
 565 | [
 566 |   {
 567 |     id: 1
 568 |     name: 'transaction',
 569 |     coa_revenues: [
 570 |       {
 571 |         code: '101020230',
 572 |         name: 'Fix Reveneu',
 573 |       },
 574 |       {
 575 |           code: '105020230',
 576 |         name: 'Other Revenue
 577 |     ],
 578 |   }
 579 | ]
 580 | */
 581 | 
582 | 583 |
584 | 585 |
586 |
587 | 588 |
589 |
590 |
591 | © 2021–2022 | ikhbalfuady 592 |
593 | 594 |
595 |
596 |
597 | 598 | 599 | 998 | 999 | 1000 | 1001 | --------------------------------------------------------------------------------