/lodis.js
JavaScript | 672 lines | 672 code | 0 blank | 0 comment | 108 complexity | 0c8c3cf84ca3a1431ffe1826b0cb1adf MD5 | raw file
1(function() { 2 var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __slice = Array.prototype.slice, __indexOf = Array.prototype.indexOf || function(item) { 3 for (var i = 0, l = this.length; i < l; i++) { 4 if (this[i] === item) return i; 5 } 6 return -1; 7 }; 8 this.Lodis = (function() { 9 function Lodis() { 10 this._expire_key = __bind(this._expire_key, this); this.storage = window.localStorage; 11 } 12 Lodis.prototype._pack = function(value) { 13 return JSON.stringify(value); 14 }; 15 Lodis.prototype._unpack = function(value) { 16 return JSON.parse(value); 17 }; 18 Lodis.prototype._expire_key = function(key) { 19 this.del(key); 20 return delete this._expiration_hash[key]; 21 }; 22 Lodis.prototype._get_set_or_default = function(key, default_value) { 23 return this._unpack(this.get(key)) || default_value; 24 }; 25 Lodis.prototype._get_set = function(key) { 26 return this._get_set_or_default(key, []); 27 }; 28 Lodis.prototype._extract_from_set = function() { 29 var item, member, members, result, source, _i, _j, _len, _len2, _ref; 30 source = arguments[0], members = 2 <= arguments.length ? __slice.call(arguments, 1) : []; 31 result = []; 32 for (_i = 0, _len = members.length; _i < _len; _i++) { 33 member = members[_i]; 34 if (__indexOf.call(this.smembers(source), member) >= 0) { 35 _ref = this._get_set(source); 36 for (_j = 0, _len2 = _ref.length; _j < _len2; _j++) { 37 item = _ref[_j]; 38 if (item !== member) { 39 result.push(item); 40 } 41 } 42 } 43 } 44 return result; 45 }; 46 Lodis.prototype._get_unpacked = function(key) { 47 try { 48 return this._unpack(this.get(key)); 49 } catch (error) { 50 return this.get(key); 51 } 52 }; 53 Lodis.prototype._get_hash = function(key) { 54 return this._get_set_or_default(key, {}); 55 }; 56 Lodis.prototype._set_packed = function(key, value) { 57 value = this._pack(value); 58 return this.set(key, value); 59 }; 60 Lodis.prototype._get_difference_or_intersection_for_sets = function() { 61 var action, condition, head, key, keys, other_set, result, set, tail, value, _i, _j, _len, _len2; 62 action = arguments[0], keys = 2 <= arguments.length ? __slice.call(arguments, 1) : []; 63 if (action == null) { 64 action = 'DIFF'; 65 } 66 head = keys[0], tail = 2 <= keys.length ? __slice.call(keys, 1) : []; 67 set = this._get_set(head); 68 other_set = result = []; 69 for (_i = 0, _len = tail.length; _i < _len; _i++) { 70 key = tail[_i]; 71 other_set = other_set.concat(this._get_set(key)); 72 } 73 for (_j = 0, _len2 = set.length; _j < _len2; _j++) { 74 value = set[_j]; 75 condition = (function() { 76 switch (action.toUpperCase()) { 77 case 'DIFF': 78 return __indexOf.call(other_set, value) < 0; 79 case 'INTER': 80 return __indexOf.call(other_set, value) >= 0; 81 } 82 })(); 83 if (condition) { 84 result.push(value); 85 } 86 } 87 return result.reverse(); 88 }; 89 Lodis.prototype._get_from_hash = function(key, options) { 90 var hash, result, value; 91 if (options == null) { 92 options = { 93 with_keys: true, 94 with_values: true, 95 only: [] 96 }; 97 } 98 hash = this._get_hash(key); 99 result = []; 100 for (key in hash) { 101 value = hash[key]; 102 if (options["with_keys"]) { 103 result.push(key); 104 } 105 if (options["with_values"] || (options["only"] && __indexOf.call(options["only"], key) >= 0)) { 106 result.push(value); 107 } 108 } 109 return result; 110 }; 111 Lodis.prototype._alter_int_value = function(key, quantity) { 112 var value; 113 if (this.exists(key)) { 114 value = parseInt(this.get(key)); 115 if (typeof value === "number") { 116 value = value + quantity; 117 this.set(key, value); 118 return value; 119 } else { 120 throw new Error; 121 } 122 } 123 }; 124 Lodis.prototype._expiration_hash = {}; 125 Lodis.prototype.del = function() { 126 var key, keys, _i, _len; 127 keys = 1 <= arguments.length ? __slice.call(arguments, 0) : []; 128 for (_i = 0, _len = keys.length; _i < _len; _i++) { 129 key = keys[_i]; 130 this.storage.removeItem(key); 131 } 132 return true; 133 }; 134 Lodis.prototype.set = function(key, value) { 135 this.storage.setItem(key, value); 136 return true; 137 }; 138 Lodis.prototype.get = function(key) { 139 return this.storage.getItem(key); 140 }; 141 Lodis.prototype.exists = function(key) { 142 return this.get(key) != null; 143 }; 144 Lodis.prototype.dbsize = function() { 145 return this.storage.length; 146 }; 147 Lodis.prototype.keys = function(regexp) { 148 var found_keys, i, key, _ref; 149 found_keys = []; 150 for (i = 0, _ref = this.dbsize() - 1; 0 <= _ref ? i <= _ref : i >= _ref; 0 <= _ref ? i++ : i--) { 151 key = this.storage.key(i); 152 if (key.match(regexp)) { 153 found_keys.push(key); 154 } 155 } 156 return found_keys; 157 }; 158 Lodis.prototype.expire = function(key, seconds) { 159 var miliseconds, timeout_id; 160 miliseconds = seconds * 1000; 161 timeout_id = setTimeout(this._expire_key, miliseconds, key); 162 this._expiration_hash[key] = { 163 id: timeout_id, 164 timeout: new Date().getTime() + miliseconds 165 }; 166 return true; 167 }; 168 Lodis.prototype.expireat = function(key, miliseconds) { 169 var seconds; 170 if ((miliseconds < new Date().getTime()) || !this.exists(key)) { 171 return false; 172 } 173 seconds = (miliseconds - new Date().getTime()) / 1000; 174 this.expire(key, seconds); 175 return true; 176 }; 177 Lodis.prototype.ttl = function(key) { 178 if (this.exists(key)) { 179 if (this._expiration_hash[key]) { 180 return Math.floor((this._expiration_hash[key].timeout - new Date().getTime()) / 1000); 181 } else { 182 return -1; 183 } 184 } 185 }; 186 Lodis.prototype.append = function(key, value) { 187 if (this.exists(key)) { 188 return this.set(key, "" + (this.get(key)) + value); 189 } 190 }; 191 Lodis.prototype.auth = function(password) { 192 return true; 193 }; 194 Lodis.prototype.bgrewriteaof = function() { 195 return true; 196 }; 197 Lodis.prototype.bgsave = function() { 198 return true; 199 }; 200 Lodis.prototype.blpop = function() {}; 201 Lodis.prototype.lrange = function(key, start, end) { 202 var result, set; 203 end += 1; 204 set = this._get_set(key); 205 if (end < 1) { 206 end = set.length + end; 207 } 208 result = set.slice(start, end); 209 if (result.constructor === String) { 210 result = [result]; 211 } 212 return result; 213 }; 214 Lodis.prototype.lpush = function(key, item) { 215 var set; 216 set = this._get_set(key); 217 set.unshift(item); 218 return this._set_packed(key, set); 219 }; 220 Lodis.prototype.rpush = function(key, item) { 221 var set; 222 set = this._get_set(key); 223 set.push(item); 224 return this._set_packed(key, set); 225 }; 226 Lodis.prototype.rpushx = function(key, item) { 227 if (this.exists(key)) { 228 return this.rpush(key, item); 229 } 230 }; 231 Lodis.prototype.decr = function(key) { 232 return this.decrby(key, 1); 233 }; 234 Lodis.prototype.incr = function(key) { 235 return this.incrby(key, 1); 236 }; 237 Lodis.prototype.decrby = function(key, quantity) { 238 if (quantity == null) { 239 quantity = 1; 240 } 241 return this._alter_int_value(key, -quantity); 242 }; 243 Lodis.prototype.incrby = function(key, quantity) { 244 if (quantity == null) { 245 quantity = 1; 246 } 247 return this._alter_int_value(key, quantity); 248 }; 249 Lodis.prototype.echo = function(message) { 250 return message; 251 }; 252 Lodis.prototype.flushall = function() { 253 return this.storage.clear(); 254 }; 255 Lodis.prototype.flushdb = function() { 256 return this.flushall(); 257 }; 258 Lodis.prototype.getrange = function(key, start, end) { 259 var string; 260 if (this.exists(key)) { 261 string = this.get(key); 262 if (start < 0) { 263 start = string.length + start; 264 } 265 if (end < 0) { 266 end = string.length + end; 267 } 268 return string.substr(start, end + 1); 269 } 270 }; 271 Lodis.prototype.getset = function(key, value) { 272 var old_value; 273 if (this.exists(key)) { 274 old_value = this.get(key); 275 this.set(key, value); 276 return old_value; 277 } 278 }; 279 Lodis.prototype.hset = function(hash_key, key, value) { 280 var hash; 281 hash = this._get_hash(hash_key); 282 hash[key] = value; 283 this._set_packed(hash_key, hash); 284 return true; 285 }; 286 Lodis.prototype.hget = function(hash_key, key) { 287 var hash; 288 if (this.exists(hash_key)) { 289 hash = this._get_hash(hash_key); 290 return hash[key]; 291 } 292 }; 293 Lodis.prototype.hgetall = function(hash_key) { 294 if (this.exists(hash_key)) { 295 return this._get_from_hash(hash_key); 296 } 297 }; 298 Lodis.prototype.hexists = function(hash_key, key) { 299 return this.hget(hash_key, key) != null; 300 }; 301 Lodis.prototype.hkeys = function(hash_key) { 302 if (this.exists(hash_key)) { 303 return this._get_from_hash(hash_key, { 304 with_keys: true, 305 with_values: false 306 }); 307 } 308 }; 309 Lodis.prototype.hlen = function(hash_key) { 310 if (this.exists(hash_key)) { 311 return this.hkeys(hash_key).length; 312 } 313 }; 314 Lodis.prototype.hincrby = function(hash_key, key, quantity) { 315 var new_value, old_value; 316 if (this.hexists(hash_key, key)) { 317 old_value = parseInt(this.hget(hash_key, key)); 318 if (typeof old_value === "number") { 319 new_value = old_value + quantity; 320 this.hset(hash_key, key, new_value); 321 return new_value; 322 } else { 323 throw new Error("Invalid type"); 324 } 325 } 326 }; 327 Lodis.prototype.hmget = function() { 328 var hash_key, keys; 329 hash_key = arguments[0], keys = 2 <= arguments.length ? __slice.call(arguments, 1) : []; 330 if (this.exists(hash_key)) { 331 return this._get_from_hash(hash_key, { 332 with_values: true, 333 with_keys: false, 334 only: keys 335 }); 336 } 337 }; 338 Lodis.prototype.hmset = function() { 339 var hash_key, i, keys_and_values, result, value; 340 hash_key = arguments[0], keys_and_values = 2 <= arguments.length ? __slice.call(arguments, 1) : []; 341 result = {}; 342 for (i in keys_and_values) { 343 value = keys_and_values[i]; 344 if (i % 2) { 345 result[keys_and_values[i - 1]] = value; 346 } 347 } 348 return this._set_packed(hash_key, result); 349 }; 350 Lodis.prototype.hsetnx = function(hash_key, key, value) { 351 if (!this.exists(hash_key)) { 352 this.hset(hash_key, key, value); 353 return true; 354 } else { 355 return false; 356 } 357 }; 358 Lodis.prototype.hvals = function(hash_key) { 359 if (this.exists(hash_key)) { 360 return this._get_from_hash(hash_key, { 361 with_keys: false, 362 with_values: true 363 }); 364 } 365 }; 366 Lodis.prototype.lindex = function(key, index) { 367 var hash; 368 if (this.exists(key)) { 369 hash = this._get_set(key); 370 if (index < 0) { 371 index = hash.length + index; 372 } 373 return hash[index] || false; 374 } 375 }; 376 Lodis.prototype.linsert = function(key, direction, reference_value, value) { 377 var left_side, result, right_side, set, _ref; 378 if (this.exists(key)) { 379 direction = (function() { 380 switch (direction.toUpperCase()) { 381 case "BEFORE": 382 return -1; 383 case "AFTER": 384 return 1; 385 } 386 })(); 387 set = this._get_set(key); 388 reference_value = set.indexOf(reference_value) + direction; 389 _ref = [set.slice(0, reference_value), set.slice(reference_value)], left_side = _ref[0], right_side = _ref[1]; 390 result = left_side.concat([value]); 391 result = result.concat(right_side); 392 return this._set_packed(key, result); 393 } 394 }; 395 Lodis.prototype.llen = function(key) { 396 var set; 397 if (this.exists(key)) { 398 set = this._get_set(key); 399 return set.length; 400 } 401 }; 402 Lodis.prototype.lpop = function(key) { 403 var set, value; 404 if (this.exists(key)) { 405 set = this._get_set(key); 406 value = set.slice(1); 407 this._set_packed(key, value); 408 return value; 409 } 410 }; 411 Lodis.prototype.lpushx = function(key, value) { 412 if (this.exists(key)) { 413 return this.lpush(key, value); 414 } else { 415 return false; 416 } 417 }; 418 Lodis.prototype.lrem = function(key, count, item) { 419 var quantity, result, set, value, _i, _len; 420 if (this.exists(key)) { 421 quantity = Math.abs(count); 422 set = this._get_set(key); 423 if (count < 0) { 424 set = set.reverse(); 425 } 426 result = []; 427 for (_i = 0, _len = set.length; _i < _len; _i++) { 428 value = set[_i]; 429 if (value === item && quantity > 0) { 430 quantity -= 1; 431 } else { 432 result.push(value); 433 } 434 } 435 if (count < 0) { 436 result = result.reverse(); 437 } 438 return this._set_packed(key, result); 439 } 440 }; 441 Lodis.prototype.lset = function(key, index, value) { 442 var set; 443 if (this.exists(key)) { 444 set = this._get_set(key); 445 if (index < 0) { 446 index = set.length + index; 447 } 448 set[index] = value; 449 return this._set_packed(key, set); 450 } 451 }; 452 Lodis.prototype.ltrim = function(key, start, end) { 453 var result, set; 454 if (this.exists(key)) { 455 set = this._get_set(key); 456 if (end < 0) { 457 end = set.length + end; 458 } 459 result = set.slice(start, (end + 1) || 9e9); 460 return this._set_packed(key, result); 461 } 462 }; 463 Lodis.prototype.mget = function() { 464 var key, keys, result, _i, _len; 465 keys = 1 <= arguments.length ? __slice.call(arguments, 0) : []; 466 result = []; 467 for (_i = 0, _len = keys.length; _i < _len; _i++) { 468 key = keys[_i]; 469 result.push(this.get(key)); 470 } 471 return result; 472 }; 473 Lodis.prototype.mset = function() { 474 var i, keys_and_values, value, _results; 475 keys_and_values = 1 <= arguments.length ? __slice.call(arguments, 0) : []; 476 _results = []; 477 for (i in keys_and_values) { 478 value = keys_and_values[i]; 479 if (i % 2) { 480 _results.push(this.set(keys_and_values[i - 1], value)); 481 } 482 } 483 return _results; 484 }; 485 Lodis.prototype.msetnx = function() { 486 var i, key_or_value, keys_and_values; 487 keys_and_values = 1 <= arguments.length ? __slice.call(arguments, 0) : []; 488 for (i in keys_and_values) { 489 key_or_value = keys_and_values[i]; 490 if (!(i % 2) && this.exists(key_or_value)) { 491 return; 492 } 493 } 494 return this.mset.apply(this, keys_and_values); 495 }; 496 Lodis.prototype.persist = function(key) { 497 if (this.exists(key)) { 498 if (this._expiration_hash[key]) { 499 clearTimeout(this._expiration_hash[key].id); 500 return delete this._expiration_hash[key]; 501 } 502 } 503 }; 504 Lodis.prototype.ping = function() { 505 return "PONG"; 506 }; 507 Lodis.prototype.randomkey = function() { 508 var keys; 509 keys = this.keys(); 510 return keys[Math.floor(Math.random() * keys.length)]; 511 }; 512 Lodis.prototype.rename = function(key, new_key) { 513 var value; 514 value = this.get(key); 515 this.del(key); 516 return this.set(new_key, value); 517 }; 518 Lodis.prototype.renamenx = function(key, new_key) { 519 if (!this.exists(new_key)) { 520 return this.rename(key, new_key); 521 } 522 }; 523 Lodis.prototype.rpop = function(key) { 524 var set, value; 525 if (this.exists(key)) { 526 set = this._get_set(key); 527 value = set.pop(); 528 this._set_packed(key, set); 529 return value; 530 } 531 }; 532 Lodis.prototype.rpoplpush = function(hash_key, other_hash_key) { 533 var value; 534 if (this.exists(hash_key)) { 535 value = this.rpop(hash_key); 536 this.lpush(other_hash_key, value); 537 return value; 538 } 539 }; 540 Lodis.prototype.sadd = function() { 541 var key, member, members, set, _i, _len, _results; 542 key = arguments[0], members = 2 <= arguments.length ? __slice.call(arguments, 1) : []; 543 set = this._get_set(key); 544 _results = []; 545 for (_i = 0, _len = members.length; _i < _len; _i++) { 546 member = members[_i]; 547 if (__indexOf.call(set, member) < 0) { 548 _results.push(this.lpush(key, member)); 549 } 550 } 551 return _results; 552 }; 553 Lodis.prototype.smembers = function(key) { 554 if (this.exists(key)) { 555 return this._get_set(key); 556 } 557 }; 558 Lodis.prototype.save = function() { 559 return true; 560 }; 561 Lodis.prototype.scard = function(key) { 562 return this._get_set(key).length; 563 }; 564 Lodis.prototype.sdiff = function() { 565 var keys; 566 keys = 1 <= arguments.length ? __slice.call(arguments, 0) : []; 567 return this._get_difference_or_intersection_for_sets.apply(this, ['DIFF'].concat(__slice.call(keys))); 568 }; 569 Lodis.prototype.sdiffstore = function() { 570 var destination, keys; 571 destination = arguments[0], keys = 2 <= arguments.length ? __slice.call(arguments, 1) : []; 572 return this._set_packed(destination, this.sdiff.apply(this, keys)); 573 }; 574 Lodis.prototype.select = function(db) { 575 return db === 0; 576 }; 577 Lodis.prototype.setex = function(key, expire, value) { 578 this.set(key, value); 579 return this.expire(key, expire); 580 }; 581 Lodis.prototype.setnx = function(key, value) { 582 if (!this.exists(key)) { 583 return this.set(key, value); 584 } 585 }; 586 Lodis.prototype.setrange = function(key, offset, value) { 587 var i, old_value, result; 588 old_value = (function() { 589 if (this.exists(key)) { 590 return this.get(key).substr(0, offset); 591 } else { 592 result = new String; 593 for (i = 0; 0 <= offset ? i < offset : i > offset; 0 <= offset ? i++ : i--) { 594 result += " "; 595 } 596 return result; 597 } 598 }).call(this); 599 return this.set(key, "" + old_value + value); 600 }; 601 Lodis.prototype.shutdown = function() { 602 return true; 603 }; 604 Lodis.prototype.sinter = function() { 605 var keys; 606 keys = 1 <= arguments.length ? __slice.call(arguments, 0) : []; 607 return this._get_difference_or_intersection_for_sets.apply(this, ['INTER'].concat(__slice.call(keys))); 608 }; 609 Lodis.prototype.sinterstore = function() { 610 var destination, keys; 611 destination = arguments[0], keys = 2 <= arguments.length ? __slice.call(arguments, 1) : []; 612 return this._set_packed(destination, this.sinter.apply(this, keys)); 613 }; 614 Lodis.prototype.sismember = function(key, value) { 615 var set; 616 if (this.exists(key)) { 617 set = this._get_set(key); 618 return set.indexOf(value) > -1; 619 } 620 }; 621 Lodis.prototype.smove = function(source, destination, member) { 622 var result; 623 if (this.exists(source)) { 624 if (__indexOf.call(this.smembers(source), member) >= 0) { 625 result = this._extract_from_set(source, member); 626 this._set_packed(source, result); 627 this.rpush(destination, member); 628 return true; 629 } else { 630 return false; 631 } 632 } 633 }; 634 Lodis.prototype.spop = function(key) { 635 var set; 636 if (this.exists(key)) { 637 set = this._get_set(key); 638 set.pop(); 639 return this._set_packed(key, set); 640 } 641 }; 642 Lodis.prototype.srandmember = function(key) { 643 var set; 644 if (this.exists(key)) { 645 set = this._get_set(key); 646 return set[Math.floor(Math.random() * set.length)]; 647 } 648 }; 649 Lodis.prototype.srem = function() { 650 var key, members, result, set; 651 key = arguments[0], members = 2 <= arguments.length ? __slice.call(arguments, 1) : []; 652 if (this.exists(key)) { 653 set = this._get_set(key); 654 result = this._extract_from_set.apply(this, [key].concat(__slice.call(members))); 655 return this._set_packed(key, result); 656 } 657 }; 658 Lodis.prototype.strlen = function(key) { 659 if (this.exists(key)) { 660 return this.get(key).length; 661 } else { 662 return 0; 663 } 664 }; 665 Lodis.prototype.type = function(key) { 666 if (this.exists(key)) { 667 return this._get_unpacked(key).constructor.name.toLowerCase(); 668 } 669 }; 670 return Lodis; 671 })(); 672}).call(this);