Compare commits
	
		
			No commits in common. "master" and "v1.1.0" have entirely different histories.
		
	
	
		
	
		
							
								
								
									
										99
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										99
									
								
								README.md
									
									
									
									
									
								
							| @ -1,71 +1,61 @@ | |||||||
| JsonStorage | jsonStorage | ||||||
| ==== | ==== | ||||||
| 
 | 
 | ||||||
| A light, sensible abstraction for DOMStorage (such as localStorage). | A light abstraction for DOMStorage (such as localStorage). | ||||||
| 
 | 
 | ||||||
| Installation | Installation | ||||||
| === | === | ||||||
| 
 | 
 | ||||||
| Bower (Browser) | Ender.JS (Browser) | ||||||
| 
 | 
 | ||||||
| ```bash |     ender build json-storage | ||||||
| bower install json-storage |  | ||||||
| # or |  | ||||||
| wget https://git.coolaj86.com/coolaj86/json-storage.js/raw/branch/master/json-storage.js |  | ||||||
| ``` |  | ||||||
| 
 | 
 | ||||||
| Node.JS (Server) | Node.JS (Server) | ||||||
| 
 | 
 | ||||||
| ```bash |     npm install localStorage json-storage | ||||||
| npm install -S localStorage json-storage |  | ||||||
| ``` |  | ||||||
| 
 | 
 | ||||||
| Usage | Usage | ||||||
| === | === | ||||||
| 
 | 
 | ||||||
| Made for Node.js and Bower (browser-side). | Made fo for Node.JS and Ender.JS (browser-side). | ||||||
| 
 | 
 | ||||||
| ```javascript |     var localStorage = require('localStorage') | ||||||
| var localStorage = require('localStorage') |       , JsonStorage = require('json-storage') | ||||||
|   , JsonStorage = require('json-storage').JsonStorage |       , store = JsonStorage.create(localStorage, 'my-widget-namespace') | ||||||
|   , store = JsonStorage.create(localStorage, 'my-widget-namespace', { stringify: true }) |  | ||||||
|       , myValue = { |       , myValue = { | ||||||
|             foo: "bar" |             foo: "bar" | ||||||
|           , baz: "quux" |           , baz: "quux" | ||||||
|         } |         } | ||||||
|       ; |       ; | ||||||
| 
 | 
 | ||||||
| store.set('myKey', myValue); |     store.set('myKey', myValue);  | ||||||
| myValue = store.get('myKey'); |     myValue = store.get('myKey'); | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| NOTE: When using with Node and the `localStorage` module, |  | ||||||
| you may wish to pass the `{ stringify: false }` option to prevent double stringification. |  | ||||||
| 
 | 
 | ||||||
| API | API | ||||||
| === | === | ||||||
| 
 | 
 | ||||||
|   * `JsonStorage.create(DOMStorage, namespace, opts)` |   * `create(DOMStorage, namespace)` | ||||||
|     * `DOMStorage` should be globalStorage, sessionStorage, or localStorage. Defaults to window.localStorage if set to `null`. |     * `DOMStorage` should be globalStorage, sessionStorage, or localStorage | ||||||
|     * `namespace` is optional string which allows multiple non-conflicting storage containers. For example you could pass two widgets different storage containers and not worry about naming conflicts: |     * `namespace` is optional string which allows multiple non-conflicting storage containers | ||||||
|       * `Gizmos.create(JsonStorage.create(null, 'my-gizmos'))` |   * `get(key)` | ||||||
|       * `Gadgets.create(JsonStorage.create(null, 'my-gadgets'))` |   * `set(key, value)` | ||||||
|       * Namespacing can be turned off by explicitly setting `false` |   * `remove(key)` | ||||||
|         * `Gadgets.create(JsonStorage.create(null, false))` |   * `clear()` | ||||||
|     * `opts` |   * `keys()` | ||||||
|       * `stringify` set to `false` in `node` to avoid double stringifying |   * `size()` | ||||||
|   * `store.get(key)` |   * `toJSON()` | ||||||
|   * `store.set(key, value)` |  | ||||||
|   * `store.remove(key)` |  | ||||||
|   * `store.clear()` |  | ||||||
|   * `store.keys()` |  | ||||||
|   * `store.size()` |  | ||||||
|   * `store.toJSON()` |  | ||||||
|   * `JSON.stringify(store)` |   * `JSON.stringify(store)` | ||||||
| 
 | 
 | ||||||
| **NOTE**: You cannot omit optional parameters. Use `null` if you want accepts the defaults for some things and provide a values for others. For example: `JsonStorage.create(null, null, { stringify: false })` | Upgrading from localStorage and 1.0.x to 1.1.x | ||||||
|  | === | ||||||
| 
 | 
 | ||||||
| JSON / DOMStorage Conversion Gotchas | 1.1.x automatically attempts to upgrade your DOMStorage to use namespaces in backwards-compatible way. | ||||||
|  | 
 | ||||||
|  | However, you can prevent this behaviour: | ||||||
|  | 
 | ||||||
|  |     localStorage.getItem('_json-storage-namespaced_', true); | ||||||
|  | 
 | ||||||
|  | null vs undefined in JSON | ||||||
| === | === | ||||||
| 
 | 
 | ||||||
| These notes do not reflect a bugs or defects in this library, | These notes do not reflect a bugs or defects in this library, | ||||||
| @ -75,8 +65,6 @@ they're simply to inform you of a few 'gotchas' inherent in JSON / DOMStorage co | |||||||
| If they do, you're probably doing something wrong in the first place. | If they do, you're probably doing something wrong in the first place. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ### `undefined` vs `null` |  | ||||||
| 
 |  | ||||||
| It is not valid to set `undefined` in JSON. So setting a key to `undefined` will remove it from the store. | It is not valid to set `undefined` in JSON. So setting a key to `undefined` will remove it from the store. | ||||||
| 
 | 
 | ||||||
| This means that `store.set('x')` is the same as `store.remove('x')`. | This means that `store.set('x')` is the same as `store.remove('x')`. | ||||||
| @ -86,34 +74,13 @@ To save `undefined`, use `null` instead. | |||||||
| 
 | 
 | ||||||
| Note that both values that exist as `null` and values that don't exist at all will return `null`. | Note that both values that exist as `null` and values that don't exist at all will return `null`. | ||||||
| 
 | 
 | ||||||
| ```javascript |     store.set('existing-key', null); | ||||||
| store.set('existing-key', null); |     null === store.get('existing-key'); | ||||||
| null === store.get('existing-key'); |     null === store.get('non-existant-key'); | ||||||
| null === store.get('non-existant-key'); |  | ||||||
| ``` |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ### `null` vs `"null"` |  | ||||||
| 
 |  | ||||||
| The special case of `null` as `"null"`, aka `"\"null\""`: | The special case of `null` as `"null"`, aka `"\"null\""`: | ||||||
| 
 | 
 | ||||||
| ``` |  | ||||||
| typeof null        // object |  | ||||||
| typeof "null"      // string |  | ||||||
| typeof "\"null\""  // string |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| `null`, and `"null"` both parse as `null` the "object", instead of one being the string (which would be `"\"null\""`). | `null`, and `"null"` both parse as `null` the "object", instead of one being the string (which would be `"\"null\""`). | ||||||
| 
 | 
 | ||||||
| ``` |  | ||||||
| JSON.parse(null)       // null (object) |  | ||||||
| JSON.parse("null")     // null (object) |  | ||||||
| JSON.parse("\"null\"") // 'null' (string) |  | ||||||
| ``` |  | ||||||
| 
 |  | ||||||
| Objects containing `null`, however, parse as expected `{ "foo": null, "bar": "null" }` will parse as `foo` being `null` but `bar` being `"null"`, much unlike the value `"null"` being parsed on its own. | Objects containing `null`, however, parse as expected `{ "foo": null, "bar": "null" }` will parse as `foo` being `null` but `bar` being `"null"`, much unlike the value `"null"` being parsed on its own. | ||||||
| 
 |  | ||||||
| ``` |  | ||||||
| JSON.parse('{ "foo": null }')    // { foo: null } |  | ||||||
| JSON.parse('{ "foo": "null" }')  // { foo: 'null' } |  | ||||||
| ``` |  | ||||||
							
								
								
									
										28
									
								
								bower.json
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								bower.json
									
									
									
									
									
								
							| @ -1,28 +0,0 @@ | |||||||
| { |  | ||||||
|   "name": "json-storage", |  | ||||||
|   "version": "2.0.1", |  | ||||||
|   "homepage": "https://github.com/coolaj86/json-storage-js", |  | ||||||
|   "authors": [ |  | ||||||
|     "AJ ONeal <coolaj86@gmail.com>" |  | ||||||
|   ], |  | ||||||
|   "description": "A wrapper for storage engines which use the W3C Storage API", |  | ||||||
|   "main": "json-storage.js", |  | ||||||
|   "keywords": [ |  | ||||||
|     "dom", |  | ||||||
|     "storage", |  | ||||||
|     "json", |  | ||||||
|     "w3c", |  | ||||||
|     "localStorage", |  | ||||||
|     "sessionStorage", |  | ||||||
|     "globalStorage", |  | ||||||
|     "Storage" |  | ||||||
|   ], |  | ||||||
|   "license": "Apache2", |  | ||||||
|   "ignore": [ |  | ||||||
|     "**/.*", |  | ||||||
|     "node_modules", |  | ||||||
|     "bower_components", |  | ||||||
|     "test", |  | ||||||
|     "tests" |  | ||||||
|   ] |  | ||||||
| } |  | ||||||
							
								
								
									
										282
									
								
								json-storage-model/lib/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										282
									
								
								json-storage-model/lib/index.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,282 @@ | |||||||
|  | (function () { | ||||||
|  |   "use strict"; | ||||||
|  | 
 | ||||||
|  |   var localStorage = require('localStorage') | ||||||
|  |     , JsonStorage = require('json-storage') | ||||||
|  |     , jsonStorage = JsonStorage(localStorage) | ||||||
|  |     , db = jsonStorage | ||||||
|  |     , uuidgen = require('node-uuid') | ||||||
|  |     , schemamap = {} | ||||||
|  |     ; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   function create(schema) { | ||||||
|  |     var models = {}; | ||||||
|  | 
 | ||||||
|  |     function createModel(lsmodel, prefix, submodels, uuid) { | ||||||
|  |       //
 | ||||||
|  |       // New Model
 | ||||||
|  |       //
 | ||||||
|  |       function LModel(obj) { | ||||||
|  |         var lmodel = this; | ||||||
|  | 
 | ||||||
|  |         // Add any already-appended submodels
 | ||||||
|  |         // TODO DRY this up
 | ||||||
|  |         submodels.forEach(function (subname) { | ||||||
|  |           var sub_ids = '_' + subname + '_ids' | ||||||
|  |             , subs = obj[subname] | ||||||
|  |             , suuid = schemamap[subname].uuid || 'uuid'; | ||||||
|  | 
 | ||||||
|  |           // Just in case the object is already created
 | ||||||
|  |           if ('function' === typeof obj.__lookupGetter__(subname)) { | ||||||
|  |             return; | ||||||
|  |           } | ||||||
|  | 
 | ||||||
|  |           if (false === Array.isArray(subs)) { | ||||||
|  |             return; | ||||||
|  |           } | ||||||
|  | 
 | ||||||
|  |           obj[sub_ids] = []; | ||||||
|  |           lmodel[sub_ids] = obj[sub_ids]; | ||||||
|  | 
 | ||||||
|  |           subs.forEach(function (sub) { | ||||||
|  |             if (!sub[suuid]) { | ||||||
|  |               sub[suuid] = uuidgen(); | ||||||
|  |             } | ||||||
|  |             models[subname].set(sub[suuid], sub); | ||||||
|  |             lmodel[sub_ids].push(sub[suuid]); | ||||||
|  |           }); | ||||||
|  | 
 | ||||||
|  |           obj[subname] = undefined; | ||||||
|  |           delete obj[subname]; | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         // Copy object to this
 | ||||||
|  |         Object.keys(obj).forEach(function (k) { | ||||||
|  |           lmodel[k] = obj[k]; | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         // create uuid if it has none
 | ||||||
|  |         if (undefined === obj[uuid]) { | ||||||
|  |           obj[uuid] = uuidgen(); | ||||||
|  |           lmodel[uuid] = obj[uuid]; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       // A simple save method
 | ||||||
|  |       LModel.prototype.save = function () { | ||||||
|  |         lsmodel.set(this[uuid], this); | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |       // getters for submodels
 | ||||||
|  |       submodels.forEach(function (subname) { | ||||||
|  |         var sub_ids = '_' + subname + '_ids'; | ||||||
|  | 
 | ||||||
|  |         LModel.prototype.__defineGetter__(subname, function () { | ||||||
|  |           // not all submodels exist at "compile-time"
 | ||||||
|  |           var submodel = models[subname] | ||||||
|  |             , lmodel = this | ||||||
|  |             , subs | ||||||
|  |             , suuid = schemamap[subname].uuid || 'uuid'; | ||||||
|  | 
 | ||||||
|  |           lmodel[sub_ids] = lmodel[sub_ids] || []; | ||||||
|  | 
 | ||||||
|  |           subs = submodel.some(lmodel[sub_ids]); | ||||||
|  | 
 | ||||||
|  |           // modify collection, but leave as array with forEach
 | ||||||
|  |           // XXX maybe create prototype with forEach
 | ||||||
|  |           subs.add = function (obj) { | ||||||
|  |             subs.push(obj); | ||||||
|  |             if (undefined === obj[suuid]) { | ||||||
|  |               submodel.add(obj); | ||||||
|  |             } else { | ||||||
|  |               submodel.set(obj[suuid], obj); | ||||||
|  |             } | ||||||
|  |             lmodel[sub_ids].push(obj[suuid]); | ||||||
|  |             lmodel.save(); | ||||||
|  |           }; | ||||||
|  | 
 | ||||||
|  |           return subs; | ||||||
|  |         }); | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |       return LModel; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     // A database abstraction
 | ||||||
|  |     function Model(model) { | ||||||
|  |       var lsmodel = this | ||||||
|  |         , prefix = model.name | ||||||
|  |         , submodels = model.has_many || [] | ||||||
|  |         , uuid = model.uuid || 'uuid' | ||||||
|  |         , LModel = createModel(lsmodel, prefix, submodels, uuid); | ||||||
|  | 
 | ||||||
|  |       lsmodel.create = function (a, b, c) { | ||||||
|  |         return new LModel(a, b, c) | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |       // clear
 | ||||||
|  |       lsmodel.clear = function () { | ||||||
|  |         return db.set(prefix + '-lsm', []); | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  |       // all keys
 | ||||||
|  |       lsmodel.keys = function () { | ||||||
|  |         return db.get(prefix + '-lsm'); | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  |       // all items
 | ||||||
|  |       lsmodel.all = function () { | ||||||
|  |         var items = []; | ||||||
|  |         lsmodel.keys().forEach(function (uuid) { | ||||||
|  |           var item = lsmodel.get(uuid) | ||||||
|  |           // TODO this should be a useless check
 | ||||||
|  |           if (null === item) { | ||||||
|  |             lsmodel.remove(uuid); | ||||||
|  |             return; | ||||||
|  |           } | ||||||
|  |           items.push(item); | ||||||
|  |         }); | ||||||
|  |         return items; | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  |       // TODO query accepts objects
 | ||||||
|  |       lsmodel.query = function (obj) { | ||||||
|  |         //
 | ||||||
|  |         return null; | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  |       // pass in your filter function
 | ||||||
|  |       lsmodel.filter = function (test) { | ||||||
|  |         var all = lsmodel.all(), | ||||||
|  |           results = []; | ||||||
|  | 
 | ||||||
|  |         all.forEach(function (one) { | ||||||
|  |           if (!test(one)) { | ||||||
|  |             return; | ||||||
|  |           } | ||||||
|  |           results.push(one); | ||||||
|  |         }); | ||||||
|  |         return results; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       lsmodel.some = function (uuids) { | ||||||
|  |         var results = []; | ||||||
|  | 
 | ||||||
|  |         uuids.forEach(function (uuid) { | ||||||
|  |           var one = lsmodel.get(uuid); | ||||||
|  |           // push null elements to keep array indices
 | ||||||
|  |           results.push(one); | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         return results; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       // TODO query object
 | ||||||
|  |       lsmodel.get = function (uuid) { | ||||||
|  |         var item = db.get(uuid); | ||||||
|  |         if (null === item) { | ||||||
|  |           return null; | ||||||
|  |         } | ||||||
|  |         return new LModel(item); | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  |       lsmodel.set = function (uuid, val) { | ||||||
|  |         var keys; | ||||||
|  | 
 | ||||||
|  |         if (null === val || undefined === val) { | ||||||
|  |           return db.remove(uuid); | ||||||
|  |         } | ||||||
|  |         keys = db.get(prefix + '-lsm') || []; | ||||||
|  | 
 | ||||||
|  |         // add the key if it didn't exist
 | ||||||
|  |         if (-1 === keys.indexOf(uuid)) { | ||||||
|  |           keys.push(uuid); | ||||||
|  |           db.set(prefix + '-lsm', keys); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         submodels.forEach(function (mod) { | ||||||
|  |           var children = val[mod] || []; | ||||||
|  | 
 | ||||||
|  |           // TODO decouple or create new objects
 | ||||||
|  |           children.forEach(function (child) { | ||||||
|  |             var e; | ||||||
|  |             if (null === child) { | ||||||
|  |               return; | ||||||
|  |             } | ||||||
|  |             if ('string' === typeof child) { | ||||||
|  |               return; | ||||||
|  |             } | ||||||
|  |             if ('string' !== typeof child.uuid) { | ||||||
|  |               return; | ||||||
|  |             } | ||||||
|  |             // TODO other[mod].set(uuid, child);
 | ||||||
|  |           }); | ||||||
|  |         }); | ||||||
|  |         /* | ||||||
|  |         console.log('\n\n val'); | ||||||
|  |         console.log(val); | ||||||
|  |         console.log('\n\n'); | ||||||
|  |         */ | ||||||
|  |         db.set(uuid, val) | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  |       // Remove an item from the table list and the db
 | ||||||
|  |       lsmodel.remove = function (uuid) { | ||||||
|  |         var keys = db.get(prefix + '-lsm') | ||||||
|  |           , i; | ||||||
|  | 
 | ||||||
|  |         keys.forEach(function (key, j) { | ||||||
|  |           if (key === uuid) { | ||||||
|  |             i = j; | ||||||
|  |           } | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         if (undefined === i) { | ||||||
|  |           return; | ||||||
|  |         } | ||||||
|  |         db.remove(uuid); | ||||||
|  |         keys.splice(i,1); | ||||||
|  |         db.set(prefix + '-lsm', keys); | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  |       // Remove all objects from the table list and db
 | ||||||
|  |       lsmodel.clear = function () { | ||||||
|  |         lsmodel.keys().forEach(function (uuid) { | ||||||
|  |           db.remove(uuid); | ||||||
|  |         }); | ||||||
|  |         db.set(prefix + '-lsm', []); | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  |       lsmodel.add = function (val) { | ||||||
|  |         var obj = lsmodel.create(val); | ||||||
|  |         obj.save(); | ||||||
|  |         return obj; | ||||||
|  |       }; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // TODO compare versions of schema
 | ||||||
|  |     db.set('schema-lsm', schema); | ||||||
|  | 
 | ||||||
|  |     schema.forEach(function (scheme) { | ||||||
|  |       var table = scheme.name | ||||||
|  |         , x = db.get(table + '-lsm') | ||||||
|  |         ; | ||||||
|  | 
 | ||||||
|  |       // Pre-create the "models" tableshould always have 
 | ||||||
|  |       schemamap[scheme.name] = scheme; | ||||||
|  |       if (!Array.isArray(x)) { | ||||||
|  |         db.set(table + '-lsm', []); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       models[scheme.name] = new Model(scheme); | ||||||
|  |     }); | ||||||
|  |      | ||||||
|  |     return models; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   module.exports = create; | ||||||
|  | }()); | ||||||
							
								
								
									
										20
									
								
								json-storage-model/lib/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								json-storage-model/lib/package.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | |||||||
|  | { | ||||||
|  |   "author": "AJ ONeal <coolaj86@gmail.com> (http://coolaj86.info)", | ||||||
|  |   "name": "json-storage-model", | ||||||
|  |   "description": "An abstraction for models to be stored in json-storage", | ||||||
|  |   "keywords": ["ender", "model", "json-storage", "localStorage", "sessionStorage", "globalStorage", "Storage"], | ||||||
|  |   "version": "0.9.1", | ||||||
|  |   "repository": { | ||||||
|  |     "type": "git", | ||||||
|  |     "url": "git://github.com/coolaj86/json-storage-js.git" | ||||||
|  |   }, | ||||||
|  |   "engines": { | ||||||
|  |     "node": ">= v0.2.0" | ||||||
|  |   }, | ||||||
|  |   "main": "index", | ||||||
|  |   "dependencies": { | ||||||
|  |       "json-storage": ">= 1.0.0" | ||||||
|  |     , "node-uuid": ">= 0.0.0" | ||||||
|  |   }, | ||||||
|  |   "devDependencies": {} | ||||||
|  | } | ||||||
							
								
								
									
										247
									
								
								json-storage-model/test/test.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										247
									
								
								json-storage-model/test/test.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,247 @@ | |||||||
|  | (function () { | ||||||
|  |   "use strict"; | ||||||
|  | 
 | ||||||
|  |   var Model = require('json-storage-model') | ||||||
|  |     , assert = require('assert') | ||||||
|  |     , schema | ||||||
|  |     , lsmAll = {} | ||||||
|  |     , Returns | ||||||
|  |     , Batches; | ||||||
|  | 
 | ||||||
|  |   schema = [ | ||||||
|  |     { | ||||||
|  |       name: "returns", | ||||||
|  |       has_many: ['batches'], | ||||||
|  |       uuid: "key" | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       name: "batches", | ||||||
|  |       has_many: ['products'] | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       name: "products" | ||||||
|  |     } | ||||||
|  |   ]; | ||||||
|  | 
 | ||||||
|  |   function setup() { | ||||||
|  |     lsmAll = new Model(schema); | ||||||
|  |     //console.log(lsmAll);
 | ||||||
|  |     Returns = lsmAll.returns; | ||||||
|  |     Batches = lsmAll.batches; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function empty() { | ||||||
|  |     assert.deepEqual([], Returns.keys()); | ||||||
|  |     assert.deepEqual([], Returns.all()); | ||||||
|  |     assert.deepEqual([], Returns.some([])); | ||||||
|  |     assert.deepEqual([null], Returns.some(['x'])); | ||||||
|  |     assert.deepEqual([null, null], Returns.some(['x','y'])); | ||||||
|  |     assert.deepEqual(null, Returns.get('nada')); | ||||||
|  |     Returns.clear(); | ||||||
|  |     assert.deepEqual([], Returns.keys()); | ||||||
|  |     assert.deepEqual([], Returns.all()); | ||||||
|  |     assert.deepEqual([], Returns.some([])); | ||||||
|  |     assert.deepEqual([null], Returns.some(['x'])); | ||||||
|  |     assert.deepEqual([null, null], Returns.some(['x','y'])); | ||||||
|  |     assert.deepEqual(null, Returns.get('nada')); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function errors() { | ||||||
|  |     var errcount = 0; | ||||||
|  |     // TODO make throw
 | ||||||
|  |     try { | ||||||
|  |       Returns.get(); | ||||||
|  |     } catch(e) { | ||||||
|  |       errcount += 1; | ||||||
|  |     } | ||||||
|  |     //assert.equal(1, errcount);
 | ||||||
|  |     console.log('skipped `throw error on get(undefined)`'); | ||||||
|  | 
 | ||||||
|  |     try { | ||||||
|  |       Returns.some(); | ||||||
|  |     } catch(e) { | ||||||
|  |       errcount += 1; | ||||||
|  |     } | ||||||
|  |     assert.equal(1, errcount); | ||||||
|  | 
 | ||||||
|  |     Returns.some([]); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function createWithoutKey() { | ||||||
|  |     var ret = Returns.create({ | ||||||
|  |         memo: "031811-IHC", | ||||||
|  |       }) | ||||||
|  |       , ret2; | ||||||
|  | 
 | ||||||
|  |     assert.ok(ret.key); | ||||||
|  |     assert.equal("031811-IHC", ret.memo); | ||||||
|  | 
 | ||||||
|  |     ret2 = Returns.get(ret.key); | ||||||
|  |     assert.equal(null, ret2); | ||||||
|  | 
 | ||||||
|  |     ret.test1 = true; | ||||||
|  |     ret.save(); | ||||||
|  | 
 | ||||||
|  |     ret2 = Returns.get(ret.key); | ||||||
|  |     assert.equal("031811-IHC", ret2.memo); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function createWithKey() { | ||||||
|  |     var ret = Returns.create({ | ||||||
|  |         key: "ajs-test", | ||||||
|  |         memo: "031811-IHC", | ||||||
|  |       }) | ||||||
|  |       , ret2; | ||||||
|  | 
 | ||||||
|  |     ret2 = Returns.get(ret.key); | ||||||
|  |     assert.ok(!ret2); | ||||||
|  | 
 | ||||||
|  |     assert.equal("ajs-test", ret.key); | ||||||
|  |     ret.save(); | ||||||
|  | 
 | ||||||
|  |     ret2 = Returns.get(ret.key); | ||||||
|  |     assert.ok(ret2.memo); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function insertRemove() { | ||||||
|  |     var keys = [] | ||||||
|  |       , all = [] | ||||||
|  |       , ids = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] | ||||||
|  |       , k; | ||||||
|  | 
 | ||||||
|  |     Returns.clear(); | ||||||
|  | 
 | ||||||
|  |     // add
 | ||||||
|  |     function populate() { | ||||||
|  |       all = []; | ||||||
|  |       keys = []; | ||||||
|  |       ids.forEach(function (id, i) { | ||||||
|  |                             // this is private logic
 | ||||||
|  |         all.push({ key: id, _batches_ids: [] }); | ||||||
|  |         keys.push(all[i].key); | ||||||
|  |         Returns.create(all[i]).save(); | ||||||
|  |       }); | ||||||
|  |       assert.deepEqual(all, Returns.all()); | ||||||
|  |       assert.deepEqual(keys, Returns.keys()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Remove from first
 | ||||||
|  |     populate(); | ||||||
|  |     for (k = 0; k < ids.length; k += 1) { | ||||||
|  |       Returns.remove(ids[k]); | ||||||
|  |     } | ||||||
|  |     assert.deepEqual([], Returns.all()); | ||||||
|  |     assert.deepEqual([], Returns.keys()); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     // Remove from last
 | ||||||
|  |     populate(); | ||||||
|  |     for (k = ids.length - 1; k >= 0; k -= 1) { | ||||||
|  |       Returns.remove(ids[k]); | ||||||
|  |     } | ||||||
|  |     assert.deepEqual([], Returns.all()); | ||||||
|  |     assert.deepEqual([], Returns.keys()); | ||||||
|  | 
 | ||||||
|  |     // Remove from middle
 | ||||||
|  |     populate(); | ||||||
|  |     ids.sort(function () { return 0.5 - Math.random(); }); | ||||||
|  |     for (k = ids.length - 1; k >= 0; k -= 1) { | ||||||
|  |       Returns.remove(ids[k]); | ||||||
|  |     } | ||||||
|  |     assert.deepEqual([], Returns.all()); | ||||||
|  |     assert.deepEqual([], Returns.keys()); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // testing all, keys, some, filter
 | ||||||
|  |   function all() { | ||||||
|  |     var keys = [], | ||||||
|  |       all = [], | ||||||
|  |       some, | ||||||
|  |       ids = []; | ||||||
|  | 
 | ||||||
|  |     Returns.clear(); | ||||||
|  |     assert.deepEqual(all, Returns.all()); | ||||||
|  |     assert.deepEqual(keys, Returns.keys()); | ||||||
|  | 
 | ||||||
|  |     all.push({ key: "one", memo: "3131-mtn", _batches_ids: [] }); | ||||||
|  |     keys.push(all[0].key); | ||||||
|  |     Returns.create(all[0]).save(); | ||||||
|  |      | ||||||
|  |     all.push({ key: "two", memo: "3232-hlt", _batches_ids: [] }); | ||||||
|  |     keys.push(all[1].key); | ||||||
|  |     Returns.create(all[1]).save(); | ||||||
|  | 
 | ||||||
|  |     all.push({ key: "three", memo: "4123-hbc", _batches_ids: [] }); | ||||||
|  |     keys.push(all[2].key); | ||||||
|  |     Returns.create(all[2]).save(); | ||||||
|  |      | ||||||
|  |     all.push({ key: "four", memo: "4441-dtf", _batches_ids: [] }); | ||||||
|  |     keys.push(all[3].key); | ||||||
|  |     Returns.create(all[3]).save(); | ||||||
|  |      | ||||||
|  |     all.push({ key: "five", memo: "4412-abn", _batches_ids: [] }); | ||||||
|  |     keys.push(all[4].key); | ||||||
|  |     Returns.create(all[4]).save(); | ||||||
|  | 
 | ||||||
|  |     some = Returns.filter(function (ret) { | ||||||
|  |       return /^4\d/.test(ret.memo); | ||||||
|  |     }); | ||||||
|  |     assert.equal(3, some.length); | ||||||
|  | 
 | ||||||
|  |     some.forEach(function (one) { | ||||||
|  |       ids.push(one.key); | ||||||
|  |     }); | ||||||
|  |     assert.deepEqual(some, Returns.some(ids)); | ||||||
|  |      | ||||||
|  |     assert.deepEqual(all, Returns.all()); | ||||||
|  |     assert.deepEqual(keys, Returns.keys()); | ||||||
|  |     assert.deepEqual(all.slice(1,3), Returns.some(["two", "three"])); | ||||||
|  | 
 | ||||||
|  |     assert.deepEqual(keys, Returns.keys()); | ||||||
|  | 
 | ||||||
|  |     console.log('skipping not-implemented `query`'); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function relate() { | ||||||
|  |     var batches = [ | ||||||
|  |         { | ||||||
|  |           uuid: "a", | ||||||
|  |           name: "chuck", | ||||||
|  |           _products_ids: [] | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           name: "daryl", | ||||||
|  |           _products_ids: [] | ||||||
|  |         } | ||||||
|  |       ] | ||||||
|  |       , ret = Returns.create({}) | ||||||
|  |       , batch; | ||||||
|  | 
 | ||||||
|  |     // Add relation
 | ||||||
|  |     ret.save(); | ||||||
|  |     ret = Returns.get(ret.key); | ||||||
|  |     ret.batches.add(batches[0]); | ||||||
|  |     assert.deepEqual(Batches.all()[0], batches[0]); | ||||||
|  |     assert.deepEqual(ret.batches[0], batches[0]); | ||||||
|  |     ret.save(); | ||||||
|  | 
 | ||||||
|  |     // create with an existing relation
 | ||||||
|  |     ret = Returns.create({ batches: batches }); | ||||||
|  |     batches[1].uuid = ret.batches[1].uuid; | ||||||
|  | 
 | ||||||
|  |     console.log('skipping assert which requires visual inspection'); | ||||||
|  |     //assert.deepEqual(batches, ret.batches);
 | ||||||
|  |     //console.log(Batches.all());
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   setup(); | ||||||
|  |   empty(); | ||||||
|  |   errors(); | ||||||
|  |   createWithoutKey(); | ||||||
|  |   createWithKey(); | ||||||
|  |   insertRemove(); | ||||||
|  |   all(); | ||||||
|  |   relate(); | ||||||
|  | 
 | ||||||
|  |   console.log("All tests passed"); | ||||||
|  | }()); | ||||||
							
								
								
									
										140
									
								
								json-storage.js
									
									
									
									
									
								
							
							
						
						
									
										140
									
								
								json-storage.js
									
									
									
									
									
								
							| @ -1,140 +0,0 @@ | |||||||
| /*jshint -W054 */ |  | ||||||
| ;(function (exports) { |  | ||||||
|   'use strict'; |  | ||||||
| 
 |  | ||||||
|   var proto |  | ||||||
|     , delim = ':' |  | ||||||
|     ; |  | ||||||
| 
 |  | ||||||
|   function stringify(obj) { |  | ||||||
|     var str; |  | ||||||
|     try { |  | ||||||
|       str = JSON.stringify(obj); |  | ||||||
|     } catch(e) { |  | ||||||
|       str = ""; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return str; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   function parse(str) { |  | ||||||
|     var obj = null; |  | ||||||
|     try { |  | ||||||
|       obj = JSON.parse(str); |  | ||||||
|     } catch(e) {} |  | ||||||
| 
 |  | ||||||
|     return obj; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   function JsonStorage(w3cStorage, namespace, opts) { |  | ||||||
|     var me = this |  | ||||||
|       ; |  | ||||||
| 
 |  | ||||||
|     if (!(this instanceof JsonStorage)) { |  | ||||||
|       return new JsonStorage(w3cStorage, namespace, opts); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (!w3cStorage) { |  | ||||||
|       w3cStorage = window.localStorage; |  | ||||||
|     } else if ('function' !== typeof w3cStorage.getItem) { |  | ||||||
|       throw new Error('You must supply a W3C DOM Storage mechanism such as window.localStorage or window.sessionStorage'); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     me._opts = opts || {}; |  | ||||||
|     if (false === me._opts.stringify) { |  | ||||||
|       me._stringify = false; |  | ||||||
|     } else { |  | ||||||
|       me._stringify = true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // if we didn't always add at least the delimeter
 |  | ||||||
|     // then if a keyname with the delim, it would be more
 |  | ||||||
|     // complicated to figure it out
 |  | ||||||
|     this._namespace = delim; |  | ||||||
|     this._namespace += (namespace || 'jss'); |  | ||||||
|     if (false === namespace) { |  | ||||||
|       this._namespace = ''; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     this._store = w3cStorage; |  | ||||||
|     this._keysAreDirty = true; |  | ||||||
|     this._keys = []; |  | ||||||
|   } |  | ||||||
|   proto = JsonStorage.prototype; |  | ||||||
|    |  | ||||||
|   proto.clear = function () { |  | ||||||
|     this._keysAreDirty = true; |  | ||||||
|     this.keys().forEach(function (key) { |  | ||||||
|       this.remove(key); |  | ||||||
|     }, this); |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   proto.remove = function (key) { |  | ||||||
|     this._keysAreDirty = true; |  | ||||||
|     this._store.removeItem(key + this._namespace); |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   proto.get = function (key) { |  | ||||||
|     var item = this._store.getItem(key + this._namespace) |  | ||||||
|       ; |  | ||||||
| 
 |  | ||||||
|     if ('undefined' === typeof item) { |  | ||||||
|       item = null; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (this._stringify) { |  | ||||||
|       item = parse(item); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return item; |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   proto.set = function (key, val) { |  | ||||||
|     this._keysAreDirty = true; |  | ||||||
|     return this._store.setItem(key + this._namespace, this._stringify && stringify(val) || val); |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   proto.keys = function () { |  | ||||||
|     var i |  | ||||||
|       , key |  | ||||||
|       , delimAt |  | ||||||
|       ; |  | ||||||
| 
 |  | ||||||
|     if (!this._keysAreDirty) { |  | ||||||
|       return this._keys.concat([]); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     this._keys = []; |  | ||||||
|     for (i = 0; i < this._store.length; i += 1) { |  | ||||||
|       key = this._store.key(i) || ''; |  | ||||||
| 
 |  | ||||||
|       delimAt = key.lastIndexOf(this._namespace); |  | ||||||
|       // test if this key belongs to this widget
 |  | ||||||
|       if (!this._namespace || (-1 !== delimAt)) { |  | ||||||
|         this._keys.push(key.substr(0, delimAt)); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     this._keysAreDirty = false; |  | ||||||
| 
 |  | ||||||
|     return this._keys.concat([]); |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   proto.size = function () { |  | ||||||
|     return this._store.length; |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   proto.toJSON = function () { |  | ||||||
|     var json = {} |  | ||||||
|       ; |  | ||||||
| 
 |  | ||||||
|     this.keys().forEach(function (key) { |  | ||||||
|       json[key] = this.get(key); |  | ||||||
|     }, this); |  | ||||||
| 
 |  | ||||||
|     return json; |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   JsonStorage.create = JsonStorage; |  | ||||||
| 
 |  | ||||||
|   exports.JsonStorage = JsonStorage; |  | ||||||
| }('undefined' !== typeof exports && exports || new Function('return this')())); |  | ||||||
							
								
								
									
										176
									
								
								json-tables/lib/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								json-tables/lib/index.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,176 @@ | |||||||
|  | (function () { | ||||||
|  |   "use strict"; | ||||||
|  | 
 | ||||||
|  |   var Future = require('future') | ||||||
|  |     , __id_ = 'id' | ||||||
|  |     , nameToString = function () { | ||||||
|  |         return this.name; | ||||||
|  |       }; | ||||||
|  |    | ||||||
|  |   function RowType(table) { | ||||||
|  |     var name = table.name, | ||||||
|  |       columns = table.columns, | ||||||
|  |       klass; | ||||||
|  | 
 | ||||||
|  |     klass = function (id, arr) { | ||||||
|  |       /* | ||||||
|  |       // Extending Array doesn't work very well
 | ||||||
|  | 
 | ||||||
|  |       var self = this; | ||||||
|  |       arr.forEach(function (item, i) { | ||||||
|  |         self[i] = item; | ||||||
|  |       }); | ||||||
|  |       */ | ||||||
|  |       if (!(__id_ in this)) { | ||||||
|  |         this[__id_] = id; | ||||||
|  |       } | ||||||
|  |       this.arr = arr; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     // TODO make more directive-like
 | ||||||
|  |     // TODO create a delegates_to directive
 | ||||||
|  |     klass.prototype.toString = table.toString || nameToString; | ||||||
|  | 
 | ||||||
|  |     columns.forEach(function (column, i) { | ||||||
|  |       klass.prototype.__defineGetter__(column, function () { | ||||||
|  |         return this.arr[i]; | ||||||
|  |         //return this[i];
 | ||||||
|  |       }); | ||||||
|  |     }); | ||||||
|  |     return klass; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function createIndexes(tables) { | ||||||
|  |     Object.keys(tables).forEach(function (name) { | ||||||
|  |       var table = tables[name], | ||||||
|  |         index, | ||||||
|  |         krow; | ||||||
|  | 
 | ||||||
|  |       if (!table.columns) { | ||||||
|  |         console.log("missing columns"); | ||||||
|  |         console.log(table); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       table.klass = RowType(table); | ||||||
|  | 
 | ||||||
|  |       index = table.indexed = {}; | ||||||
|  | 
 | ||||||
|  |       table.rows.forEach(function (row, z) { | ||||||
|  |         // TODO no need to index
 | ||||||
|  |         var krow = new table.klass(z, row); | ||||||
|  |         //krow.id = z;
 | ||||||
|  |         index[krow[__id_]] = krow; | ||||||
|  |         table.rows[z] = krow; | ||||||
|  |       }); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function createRelationships(tables) { | ||||||
|  |     Object.keys(tables).forEach(function (name) { | ||||||
|  |       var table = tables[name], | ||||||
|  |         relationships, | ||||||
|  |         relHandlers = {}; | ||||||
|  | 
 | ||||||
|  |       // TODO create a delegates_to directive
 | ||||||
|  |       relHandlers.belongs_to = function (relname) {   | ||||||
|  |         // TODO abstract name mutation
 | ||||||
|  |         var relation = tables[relname + 's'], | ||||||
|  |           relname_s = relname + '_id'; | ||||||
|  | 
 | ||||||
|  |         table.klass.prototype.__defineGetter__(relname, function () { | ||||||
|  |           var fid = this[relname_s]; | ||||||
|  | 
 | ||||||
|  |           return relation.indexed[fid]; | ||||||
|  |         }); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       //relationships = table.relationships && table.relationships.belongs_to;
 | ||||||
|  |       //relationships = relationships || [];
 | ||||||
|  | 
 | ||||||
|  |       relationships = table.relationships || {}; | ||||||
|  | 
 | ||||||
|  |       Object.keys(relationships).forEach(function (relType) { | ||||||
|  |         if (!relHandlers[relType]) { | ||||||
|  |           console.log('relationship type "' + relType + '" is not supported'); | ||||||
|  |           return; | ||||||
|  |         } | ||||||
|  |         relationships[relType].forEach(relHandlers[relType]); | ||||||
|  |       }); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   function createRelate(tables) { | ||||||
|  |     var future = Future() | ||||||
|  |       ; | ||||||
|  |      | ||||||
|  |     createIndexes(tables); | ||||||
|  |     createRelationships(tables); | ||||||
|  |     //testRelationships(tables);
 | ||||||
|  |     //console.log(Object.keys(data));
 | ||||||
|  | 
 | ||||||
|  |     future.fulfill(null, tables); | ||||||
|  | 
 | ||||||
|  |     return future.passable(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   var Future = require('future') | ||||||
|  |     , Join = require('Join') | ||||||
|  |     ; | ||||||
|  | 
 | ||||||
|  |   function createGet(pathname, tables) { | ||||||
|  |     var future = Future() | ||||||
|  |       , join = Join() | ||||||
|  |       , request = require('ahr2') | ||||||
|  |       , db = {} | ||||||
|  |       , errs = [] | ||||||
|  |       ; | ||||||
|  | 
 | ||||||
|  |     tables.forEach(function (tablename) { | ||||||
|  |       var resource = pathname + '/' + tablename + ".json" | ||||||
|  |         , req = request.get(resource) | ||||||
|  |         ; | ||||||
|  | 
 | ||||||
|  |       req.when(function (err, xhr, data) { | ||||||
|  |         if (err) { | ||||||
|  |           console.log('error tables-get'); | ||||||
|  |           console.log(err); | ||||||
|  |           console.log(err.message); | ||||||
|  |           return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (global.Buffer && data instanceof global.Buffer) { | ||||||
|  |           data = data.toString(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // TODO need to refactor AHR and fix JSON / text handling
 | ||||||
|  |         try { | ||||||
|  |           data = JSON.parse(data.toString()); | ||||||
|  |         } catch (e) { | ||||||
|  |           // ignore, it was probably already parsed
 | ||||||
|  |         } | ||||||
|  |         // follow convention
 | ||||||
|  |         tablename = tablename.replace('-','_'); | ||||||
|  |         db[tablename] = data; | ||||||
|  |       }); | ||||||
|  | 
 | ||||||
|  |       join.add(req); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     join.when(function () { | ||||||
|  |       // TODO add timeout as error
 | ||||||
|  |       if (0 == errs.length) { | ||||||
|  |         errs = null; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       future.fulfill(errs, db); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     return future.passable(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   module.exports = { | ||||||
|  |       get: createGet | ||||||
|  |     , relate: createRelate | ||||||
|  |   }; | ||||||
|  | }()); | ||||||
							
								
								
									
										21
									
								
								json-tables/lib/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								json-tables/lib/package.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | |||||||
|  | { | ||||||
|  |     "author": "AJ ONeal <coolaj86@gmail.com> (http://coolaj86.info)" | ||||||
|  |   , "name": "json-tables" | ||||||
|  |   , "description": "An abstraction for models to be stored in json-storage" | ||||||
|  |   , "keywords": ["ender", "orm", "sql", "model", "json-storage", "localStorage", "sessionStorage", "globalStorage", "Storage"] | ||||||
|  |   , "version": "0.7.1" | ||||||
|  |   , "repository": { | ||||||
|  |         "type": "git" | ||||||
|  |       , "url": "git://github.com/coolaj86/json-storage-js.git" | ||||||
|  |     } | ||||||
|  |   , "engines": { | ||||||
|  |         "node": ">= v0.2.0" | ||||||
|  |     } | ||||||
|  |   , "main": "index" | ||||||
|  |   , "dependencies": { | ||||||
|  |         "json-storage-model": ">= 0.9.0" | ||||||
|  |       , "json-storage": ">= 1.0.0" | ||||||
|  |       , "node-uuid": ">= 0.0.0" | ||||||
|  |     } | ||||||
|  |   , "devDependencies": {} | ||||||
|  | } | ||||||
							
								
								
									
										146
									
								
								lib/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								lib/index.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,146 @@ | |||||||
|  | (function () { | ||||||
|  |   "use strict"; | ||||||
|  | 
 | ||||||
|  |   var Store | ||||||
|  |     , delim = ':' | ||||||
|  |     ; | ||||||
|  | 
 | ||||||
|  |   function Stringify(obj) { | ||||||
|  |     var str; | ||||||
|  |     try { | ||||||
|  |       str = JSON.stringify(obj); | ||||||
|  |     } catch(e) { | ||||||
|  |       str = ""; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return str; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function Parse(str) { | ||||||
|  |     var obj = null; | ||||||
|  |     try { | ||||||
|  |       obj = JSON.parse(str); | ||||||
|  |     } catch(e) {} | ||||||
|  | 
 | ||||||
|  |     return obj; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function escapeRegExp(str) { | ||||||
|  |     return str.replace(/[-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function upgradeStorage(jss, w3cs) { | ||||||
|  |     var i | ||||||
|  |       , key | ||||||
|  |       , val | ||||||
|  |       , json = {} | ||||||
|  |       ; | ||||||
|  | 
 | ||||||
|  |     if (jss._store.getItem('_json-storage-namespaced_', true)) { | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // we can't modify the db while were reading or
 | ||||||
|  |     // the keys will shift all over the place
 | ||||||
|  |     for (i = 0; i < w3cs.length; i += 1) { | ||||||
|  |       key = w3cs.key(i); | ||||||
|  |       val = w3cs.getItem(key); | ||||||
|  |       json[key] = val; | ||||||
|  |     } | ||||||
|  |     w3cs.clear(); | ||||||
|  | 
 | ||||||
|  |     Object.keys(json).forEach(function (key) { | ||||||
|  |       jss.set(key, json[key]); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     jss._store.setItem('_json-storage-namespaced_', true); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function JsonStorage(w3cStorage, namespace) { | ||||||
|  |     // called without new or create
 | ||||||
|  |     // global will be undefined
 | ||||||
|  |     if (!this) { | ||||||
|  |       return new JsonStorage(w3cStorage, namespace); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // if we didn't always add at least the delimeter
 | ||||||
|  |     // then if a keyname with the delim, it would be more
 | ||||||
|  |     // complicated to figure it out
 | ||||||
|  |     this._namespace = delim; | ||||||
|  |     this._namespace += (namespace || 'jss'); | ||||||
|  | 
 | ||||||
|  |     this._store = w3cStorage; | ||||||
|  |     this._keysAreDirty = true; | ||||||
|  |     if (!this._store.getItem('_json-storage-namespaced_')) { | ||||||
|  |       upgradeStorage(this, w3cStorage); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   Store = JsonStorage; | ||||||
|  |    | ||||||
|  |   Store.prototype.clear = function () { | ||||||
|  |     this._keysAreDirty = true; | ||||||
|  |     this.keys().forEach(function (key) { | ||||||
|  |       this.remove(key); | ||||||
|  |     }, this); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   Store.prototype.remove = function (key) { | ||||||
|  |     this._keysAreDirty = true; | ||||||
|  |     this._store.removeItem(key + this._namespace); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   Store.prototype.get = function (key) { | ||||||
|  |     return Parse(this._store.getItem(key + this._namespace)); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   Store.prototype.set = function (key, val) { | ||||||
|  |     this._keysAreDirty = true; | ||||||
|  |     return this._store.setItem(key + this._namespace, Stringify(val)); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   Store.prototype.keys = function () { | ||||||
|  |     var i | ||||||
|  |       , key | ||||||
|  |       , delimAt | ||||||
|  |       ; | ||||||
|  | 
 | ||||||
|  |     if (!this._keysAreDirty) { | ||||||
|  |       return this._keys.concat([]); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     this._keys = []; | ||||||
|  |     for (i = 0; i < this._store.length; i += 1) { | ||||||
|  |       key = this._store.key(i) || ''; | ||||||
|  | 
 | ||||||
|  |       delimAt = key.lastIndexOf(this._namespace); | ||||||
|  |       // test if this key belongs to this widget
 | ||||||
|  |       if (-1 !== delimAt) { | ||||||
|  |         this._keys.push(key.substr(0, delimAt)); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     this._keysAreDirty = false; | ||||||
|  | 
 | ||||||
|  |     return this._keys.concat([]); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   Store.prototype.size = function () { | ||||||
|  |     return this._store.length; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   Store.prototype.toJSON = function () { | ||||||
|  |     var json = {} | ||||||
|  |       ; | ||||||
|  | 
 | ||||||
|  |     this._keys.forEach(function (key) { | ||||||
|  |       json[key] = this.get(key); | ||||||
|  |     }, this); | ||||||
|  | 
 | ||||||
|  |     return json; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   Store.create = function (w3cStorage, namespace) { | ||||||
|  |     return new JsonStorage(w3cStorage, namespace); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   module.exports = Store; | ||||||
|  | }()); | ||||||
							
								
								
									
										18
									
								
								lib/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								lib/package.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | |||||||
|  | { | ||||||
|  |   "author": "AJ ONeal <coolaj86@gmail.com> (http://coolaj86.info)", | ||||||
|  |   "name": "json-storage", | ||||||
|  |   "description": "A wrapper for storage engines which use the W3C Storage API", | ||||||
|  |   "keywords": ["ender", "localStorage", "sessionStorage", "globalStorage", "Storage"], | ||||||
|  |   "version": "1.1.0", | ||||||
|  |   "repository": { | ||||||
|  |     "type": "git", | ||||||
|  |     "url": "git://github.com/coolaj86/json-storage-js.git" | ||||||
|  |   }, | ||||||
|  |   "engines": { | ||||||
|  |     "node": ">= v0.2.0" | ||||||
|  |   }, | ||||||
|  |   "main": "index", | ||||||
|  |   "browserDependencies": {}, | ||||||
|  |   "dependencies": {}, | ||||||
|  |   "devDependencies": {} | ||||||
|  | } | ||||||
							
								
								
									
										18
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								package.json
									
									
									
									
									
								
							| @ -1,18 +0,0 @@ | |||||||
| { |  | ||||||
|   "author": "AJ ONeal <coolaj86@gmail.com> (http://coolaj86.com)", |  | ||||||
|   "name": "json-storage", |  | ||||||
|   "description": "A wrapper for storage engines which use the W3C Storage API", |  | ||||||
|   "keywords": ["dom", "storage", "json", "w3c", "localStorage", "sessionStorage", "globalStorage", "Storage"], |  | ||||||
|   "version": "2.1.2", |  | ||||||
|   "repository": { |  | ||||||
|     "type": "git", |  | ||||||
|     "url": "git://git.coolaj86.com/coolaj86/json-storage.js.git" |  | ||||||
|   }, |  | ||||||
|   "engines": { |  | ||||||
|     "node": ">= v0.2.0" |  | ||||||
|   }, |  | ||||||
|   "main": "json-storage", |  | ||||||
|   "browserDependencies": {}, |  | ||||||
|   "dependencies": {}, |  | ||||||
|   "devDependencies": {} |  | ||||||
| } |  | ||||||
| @ -2,8 +2,8 @@ | |||||||
|   "use strict"; |   "use strict"; | ||||||
| 
 | 
 | ||||||
|   var localStorage = require('localStorage') |   var localStorage = require('localStorage') | ||||||
|     , JsonStorage = require('../lib/').JsonStorage |     , JsonStorage = require('json-storage') | ||||||
|     , db = JsonStorage.create(localStorage) |     , db = JsonStorage(localStorage) | ||||||
|     , assert = require('assert') |     , assert = require('assert') | ||||||
|     ; |     ; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -3,8 +3,8 @@ | |||||||
| 
 | 
 | ||||||
|   var assert = require('assert') |   var assert = require('assert') | ||||||
|     , localStorage = require('localStorage') |     , localStorage = require('localStorage') | ||||||
|     , JsonStorage = require('../lib/').JsonStorage |     , JsonStorage = require('json-storage') | ||||||
|     , db = JsonStorage.create(localStorage) |     , db = JsonStorage(localStorage) | ||||||
|     ; |     ; | ||||||
| 
 | 
 | ||||||
|   assert.strictEqual(null, db.get('a')); |   assert.strictEqual(null, db.get('a')); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user