{"id":23138222,"url":"https://github.com/softlayer/sl-ember-store","last_synced_at":"2025-08-17T11:32:49.167Z","repository":{"id":23503717,"uuid":"26869410","full_name":"softlayer/sl-ember-store","owner":"softlayer","description":"An Ember CLI Addon to provide a model layer for an Ember application.","archived":false,"fork":false,"pushed_at":"2016-03-01T16:21:14.000Z","size":1592,"stargazers_count":12,"open_issues_count":18,"forks_count":7,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-08-04T08:56:46.607Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://softlayer.github.io/sl-ember-store","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/softlayer.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-11-19T16:07:15.000Z","updated_at":"2019-12-16T12:02:34.000Z","dependencies_parsed_at":"2022-08-22T01:30:47.087Z","dependency_job_id":null,"html_url":"https://github.com/softlayer/sl-ember-store","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/softlayer/sl-ember-store","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softlayer%2Fsl-ember-store","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softlayer%2Fsl-ember-store/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softlayer%2Fsl-ember-store/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softlayer%2Fsl-ember-store/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/softlayer","download_url":"https://codeload.github.com/softlayer/sl-ember-store/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/softlayer%2Fsl-ember-store/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270840768,"owners_count":24655024,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-17T02:00:09.016Z","response_time":129,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-17T13:10:11.059Z","updated_at":"2025-08-17T11:32:48.879Z","avatar_url":"https://github.com/softlayer.png","language":"JavaScript","readme":"\n[![Latest Release](https://img.shields.io/github/release/softlayer/sl-ember-store.svg)](https://github.com/softlayer/sl-ember-store/releases) ![Ember CLI version](https://img.shields.io/badge/ember%20cli-0.1.15-orange.svg) [![License](https://img.shields.io/npm/l/sl-ember-store.svg)](LICENSE.md) [![Downloads](https://img.shields.io/npm/dm/sl-ember-store.svg)](https://www.npmjs.com/package/sl-ember-store)\n\n[![Dependencies](https://img.shields.io/david/softlayer/sl-ember-store.svg)](https://david-dm.org/softlayer/sl-ember-store) [![Dev Dependencies](https://img.shields.io/david/dev/softlayer/sl-ember-store.svg)](https://david-dm.org/softlayer/sl-ember-store#info=devDependencies)\n\n[![Build Status](https://img.shields.io/travis/softlayer/sl-ember-store/master.svg)](https://travis-ci.org/softlayer/sl-ember-store) [![Code Climate](https://img.shields.io/codeclimate/github/softlayer/sl-ember-store.svg)](https://codeclimate.com/github/softlayer/sl-ember-store)\n\nTo see which issues are currently being worked on or are scheduled to be worked on next, visit [https://huboard.com/softlayer/sl-ember-store/#/](https://huboard.com/softlayer/sl-ember-store/#/)\n\n---\n\n### Is currently in BETA\n\n---\n\n# What sl-ember-store is\n\nA library for managing model data in your Ember.js applications. It is designed to be agnostic to the underlying\npersistence mechanism, so it works just as well with JSON APIs over HTTP as it does with streaming WebSockets or local storage.\n\nThis library **does not** support relationships or manage data state such as how Ember Data does.\n\nWhat this library **DOES** do is allow you to work with models that do not have to be pre-defined.  Having a dependency on [sl-ember-modelize](https://github.com/softlayer/sl-ember-modelize), this libary is able to dynamically set data returned from an endpoint onto the correct model objects without having any knowledge of the data it will be receiving.\n\nThis library is also compatible with [Ember Inspector](https://github.com/emberjs/ember-inspector)\n\n---\n\n# Demo\n\n## Live\n\n[http://softlayer.github.io/sl-ember-store/#/demos](http://softlayer.github.io/sl-ember-store/#/demos)\n\n## Development Environment\n\n### Installation\n\n* `git clone` this repository\n* `npm install`\n* `bower install`\n\n### Running\n\n* `ember server`\n* View the demo at http://localhost:4200\n\nFor more information on using ember-cli, visit [http://www.ember-cli.com/](http://www.ember-cli.com/).\n\n---\n\n# How to use this addon in your application\n\n## Install this addon as a Node module\n\n```\nember install:addon sl-ember-store\n```\n\n## Instantiating the Store\n\nIn *sl-ember-store*, the store is responsible for managing the lifecycle of your models. Every time you need a model or a collection of models, you'll ask the store for it.\n\nTo create a store, you don't need to do anything. Just by loading the *sl-ember-store* library all of the routes and\ncontrollers in your application will get a new store property. This property is an instance of *sl-ember-store/Store* that will be shared across all of the routes and controllers in your app.\n\n\n## Defining Your Models\n\n### Using the generator\n\nTo add a model to your project, simple do `ember g model \u003cmodelname\u003e`.  You can also specify the url and/or the\nadapter by appending the options:\n\n    ember g model \u003cmodelname\u003e url:\u003curl\u003e adapter:\u003cadapter\u003e\n\nMore on these options later.\n\n### Creating by hand\n\nFirst create a new model in your */models* folder:\n\n    $touch models/foo.js\n\nAdd inside that file:\n\n```javascript\nimport Model from 'sl-ember-store/model';\n\nvar Foo = Model.extend({ });\n```\n\n## Using Adapters:\nsl-ember-store has two adapters out of the box: ajax and localstorage.  You can specify your adapter in your model by reopening it's class:\n\n```javascript\nFoo.reopenClass({\n    adapter: 'ajax'\n});\n```\n\nModels have `ajax` specified as default, so you don't need to do this unless you want to use a different adapter.\n\nsl-ember-store adapters always return [Ember Promise Proxies](http://emberjs.com/api/classes/Ember.PromiseProxyMixin.html).\nIf you request a single object then you will get an `Ember.ObjectProxy` with the promise proxy mixin applied.  Requests for\nMultiple records will return an `Ember.ArrayProxy` with the promise proxy mixin applied.\n\n### Ajax adapter\nThe `ajax` adapter uses [ic-ajax](https://github.com/instructure/ic-ajax) to make `xhr` requests to your remote api.\nSuccessful responses will be serialized and then applied to a new created instance of your model.\nIn the case of an error, the promise will be rejected and you will be provided with the exact response provided\nby `ic-ajax`.\n\n### Urls, Endpoints, Serializers:\n\nWhen using the `ajax` adapter you can setup a single url if your api is restful or  multiple endpoints if you need fine grain control.  Multiple endpoints come in handy if your api isn't so restful.\n\nThe base level `url` and `serializer` will be used by default.  Override them or add different ones at any endpoint.\nEndpoints that return multiple records should only return an array.  You can add any metadata for those queries to the store via the `metaForType` function.\n\n```javascript\nFoo.reopenClass({\n    url: '/foo',\n    serializer: function( response, store ) { return xformData( response ); },\n    endpoints: {\n        'superFoo': {\n            get: {\n                url: '/superFoo',\n                serializer: function( response, store ) {\n                    store.metaForType( 'device', {\n                        totalCount: response.totalCount,\n                        totalPages: response.totalPages\n                    });\n\n                    return response.result;\n                }\n            },\n            post: '/superFooPost',\n            put: '/superFooPut',\n            delete: 'superFooDelete'\n        },\n        'boringFoo': {\n            url: '/boringFoo',\n            serializer: someSerializer\n        },\n        'superBoringFoo': '/superBoringFoo'\n    }\n});\n\nexport default Foo;\n```\nIn the example above, the `superFoo:post` endpoint will use the default serializer.  Please note that specific endpoint\nactions ( get, post, put, and delete ) MUST be in lowercase.\nAll HTTP verbs on the `boringfoo` endpoint will use the `someSerializer` function as their serializer.\nAll HTTP verbs on the `superBoringFoo` endpoint will use the default serializer.\n\nModels should always have a `url` specified.  Further urls can be specified in the `endpoints` object.  Urls and\nSerializers can be specified on a per endpoint/action basis and will default to the top level url and serializer.\n\nThe creation of a new record, one in which an id has not yet been assigned by your API, will result in a POST action.\nUpdating a record, one in which an id has been assigned by your API, will result in a PUT action.  The model's save()\nmethod is responsible for both the creation and update of a record.  In both cases, the request body payload will be passed through.\nThe difference in whether a POST or a PUT is sent is dependent on whether the record already has an id assigned to it from the API.\nThe deletion of a record requires that a record has an id already assigned to it from the API.\n\nIf you find you need an `inflection` service to support your api, we recommend\nyou use [Ember-Inflector](https://github.com/stefanpenner/ember-inflector).  You\ncan then use `Ember.Inflector` in your serializers and models.\n\n### Local Storage Adapter\nThe `localstorage` adapter works in much the same way as the ajax adapter.  It returns Object and Array proxies,\nwith the promise proxy mixin applied.  In the case of errors the promise will get rejected with an error object\nsimilar to the `ic-ajax` error object, minus the `jqXHR` key and object.\n\n#### If you installed *sl-ember-store* as an Ember CLI Addon\n\nThe localStorage adapter is initialized by default with your project's namespace.\n\nIf you want to change the default namespace then you will want to create an initializer:\n\n    ember g localstorage-initializer\n\nNow edit the file that was generated in `app/initializers/localstorage-initializer.js` and define the `namespace` value.\n\n```javascript\nimport LocalstorageAdapter from 'sl-ember-store/adapters/localstorage';\n\nexport default {\n    name: 'sl-ember-store-localstorage',\n\n    after: 'sl-ember-store',\n\n    initialize: function( container ) {\n        var localStorageAdapter = LocalstorageAdapter;\n\n        localStorageAdapter.reopenClass({\n            namespace: '\u003cnamespace\u003e'\n        });\n\n        container.register( 'adapter:localstorage', localStorageAdapter );\n    }\n};\n```\n\n#### If you are manually importing *sl-ember-store*\n\nYou will want to create an initializer:\n\n    ember g initializer localstorage-initializer \u003cnamespace\u003e\n\n\n#### Assign the localstorage adapter to your models\n\n```javascript\nFoo.reopenClass({\n    adapter: 'localstorage',\n    url: '/foo'\n});\n```\n\nNotice that the url variable is still needed as it will be used to store this model's records under the adapter's\nnamespace in localStorage.\n\n### Error handling\n\nBoth the `ajax` adapter and the `localstorage` adapter\n\n## Using the `store`\n\nThe `store` variable is injected into every route and controller and is the entry-point into the Sl-Ember-Store system.  Store has the\n`find`, `findOne`, `createRecord`, and `metadataFor` methods.\n\n\n### Some example use cases in a route:\n\n`find`:\n\n```javascript\nmodel: function() {\n    return this.store.find( 'foo' );\n}\n```\n\n```javascript\nmodel: function() {\n    //load foo with id 23\n    return this.store.find( 'foo', 23 );\n}\n```\n\n```javascript\nmodel: function() {\n    //send query params to the server: ?start=0\u0026limit=25\n    return this.store.find( 'foo', { data: { start: 0, limit: 25 }} );\n}\n```\n\n\n```javascript\nsetupController: function( controller, model ) {\n    //would cause the route to skip the loading state and transition immediately to route while model is loading\n    controller.set( 'model', this.store.find( 'foo' ) );\n}\n```\n\n`findOne`:\n\n```javascript\nmodel: function() {\n    //would return the first record from the cache or make a request for the first record\n    return this.store.findOne( 'foo' );\n}\n```\n\n`createRecord`:\n\n```javascript\nsetupController: function() {\n    this.set( 'model', this.store.createRecord( 'foo' ) );\n}\n```\n\n`metadataFor`:\n\n```javascript\nmodel: function() {\n    var model = this.store.find( 'foo' );\n\n    model.then( function() {\n        this.controller.setProperties( this.store.metadataFor( 'foo' ) );\n    }.bind( this ) );\n\n    return model;\n}\n```\n\n### Some example use cases in a controller\n\n```javascript\nactions: {\n    //change to a different page\n    changePage: function( page ) {\n        var model;\n\n        if( this.isPageLoaded( page ) ){\n            //records are in cache\n            model = this.store.find( 'device' ).then( function( records ){\n                        //extract just the records for this page\n                        return this.getPage( records, page );\n                    });\n        } else {\n            //records are requested and will be added to cache, only the records\n            //returned by the request will be present here\n            model = this.store.find( 'device', { data: { page: page } } );\n        }\n\n        model.then( function() {\n            this.pageIsLoaded( page );\n            this.set( 'currentPage', page );\n            this.set( 'model', model );\n        }.bind(this) );\n    },\n    reloadModel: function() {\n        //a request will be made just for this page, the cache will be cleared\n        var model = this.store.find( 'device', {\n            reload: true,\n            data: { page: this.get( 'currentPage' ) } } );\n\n        model.then( function() {\n            this.set( 'model', model );\n        }.bind(this) );\n    }\n}\n```\n\n### Options parameter in the `store.find` method\n\nThe `store.find` method can take up to three parameters.  The first parameter is always the model type.  The second parameter can either be a number or an object.  In the case of a number it is interpreted as an id and a single record will be returned.  In the case of an object it will be parsed as the `options` object.  If the second parameter is a number, then the third parameter (if present) will be the `options` object.  The `options` object has three importan keys:\n\n    * reload    Boolean flag, clears the cache and loads data from the adapter\n    * add       Boolean flag, load data from the adapter\n    * data      Object, load data from the adapter with these key/value pairs\n\nIt is up to the specified adapter to determine how the `data` key/value pairs will be utilized.  The built in `ajax` adapter send these key/value pairs as query parameters.  The `localstorage` adapter does not make use of them.  The `add` and `reload` flags control how the store utilizes the cache.  In the case of `add` the records are requested from the adapter then added to the cache.  Records of the same `id` will get replaced.  In the case of `reload` the records are requested from the adapter, the cache is cleared, then the new records are added to the cache.  If only the `data` property is set on the `options` parameter then the request will be handled the same as if `add` had been specified.\n\n---\n\n# Hooks\n\nYou may want to set up some pre/post query hooks that run after every query.  If so just create an initializer in your\napplication's initializers folder:\n\n```javascript\nexport default {\n    name: 'sl-ember-store-hooks',\n\n    after: 'sl-ember-store',\n\n    initialize: function( container ) {\n        container.lookup( 'store:main' ).registerPostQueryHook(\n            function( status ) {\n                if ( 401 === status ) {\n                    container.lookup( 'controller:application' ).send( 'forceLogout' );\n                } else if ( 401 != status ) {\n                    var authController = container.lookup( 'controller:auth' );\n\n                    if ( authController ) {\n                        authController.sendAction( 'session-keep-alive' );\n                    }\n                }\n            }\n        );\n    }\n};\n```\n\n---\n\n# Versioning\nEmploys [Semantic Versioning 2.0.0](http://semver.org/)\n\n---\n\n# Contribution\n[See CONTRIBUTING.md](CONTRIBUTING.md)\n\n---\n\n# Copyright and License\nsl-ember-store and its source files are Copyright © 2014 [SoftLayer Technologies, Inc.](http://www.softlayer.com/) The software is [MIT Licensed](LICENSE.md)\n\n---\n\n# Warranty\nThis software is provided “as is” and without any express or implied warranties, including, without limitation, the\nimplied warranties of merchantability and fitness for a particular purpose.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoftlayer%2Fsl-ember-store","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsoftlayer%2Fsl-ember-store","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoftlayer%2Fsl-ember-store/lists"}