{"id":32248450,"url":"https://github.com/rhaldkhein/mithril-data","last_synced_at":"2026-02-21T02:01:13.607Z","repository":{"id":57298429,"uuid":"58549401","full_name":"rhaldkhein/mithril-data","owner":"rhaldkhein","description":"A rich data model library for Mithril javascript framework","archived":false,"fork":false,"pushed_at":"2018-03-17T18:52:31.000Z","size":518,"stargazers_count":18,"open_issues_count":0,"forks_count":2,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-01-23T13:35:44.985Z","etag":null,"topics":["collection","data","database","javascript","lodash","mithril","model","schema","state","stream"],"latest_commit_sha":null,"homepage":"","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/rhaldkhein.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-05-11T13:53:35.000Z","updated_at":"2024-06-03T08:40:39.000Z","dependencies_parsed_at":"2022-08-31T00:00:57.135Z","dependency_job_id":null,"html_url":"https://github.com/rhaldkhein/mithril-data","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/rhaldkhein/mithril-data","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhaldkhein%2Fmithril-data","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhaldkhein%2Fmithril-data/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhaldkhein%2Fmithril-data/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhaldkhein%2Fmithril-data/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rhaldkhein","download_url":"https://codeload.github.com/rhaldkhein/mithril-data/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rhaldkhein%2Fmithril-data/sbom","scorecard":{"id":773941,"data":{"date":"2025-08-11","repo":{"name":"github.com/rhaldkhein/mithril-data","commit":"f7ad00c30bc0794c42e0521f6d8a5db81273c1cb"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-23T03:01:56.317Z","repository_id":57298429,"created_at":"2025-08-23T03:01:56.318Z","updated_at":"2025-08-23T03:01:56.318Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29671513,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-21T00:11:43.526Z","status":"online","status_checked_at":"2026-02-21T02:00:07.432Z","response_time":107,"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":["collection","data","database","javascript","lodash","mithril","model","schema","state","stream"],"created_at":"2025-10-22T17:43:53.457Z","updated_at":"2026-02-21T02:01:13.583Z","avatar_url":"https://github.com/rhaldkhein.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mithril-data\n\nA rich data model library for Mithril javascript framework.\n\n[![Build Status](https://travis-ci.org/rhaldkhein/mithril-data.svg?branch=master)](https://travis-ci.org/rhaldkhein/mithril-data)\n\n#### Features\n\n* Create brilliant application with **Schema**-based **Model** and **Collection**\n* Enriched with **Lodash** methods, integrated into Model \u0026 Collection\n* **Auto Redraw** on Model \u0026 Collection changes\n* **State** (View-Model) using Mithril's stream\n* Extensible, Configurable and Customizable\n* And many more ...\n\n#### Dependencies\n\n- [Mithril](http://mithril.js.org/) (\u003e= 1.0.0)\n- [Lodash](http://lodash.com/) (\u003e= 4.12.0) - Many Lodash methods are attached to Model and Collection\n\n- - - -\n\n## Schema\n\n```javascript\nvar userSchema = {\n   name : 'User',\n   props : ['name', 'age']\n}\n\nvar noteSchema = {\n   name : 'Note',\n   props : ['title', 'body', 'author'],\n   defaults : {\n      title: 'Default Title',\n      body: 'Default Body'\n   },\n   refs : {\n      author: 'User'\n   },\n   url : '/customurl',\n   redraw : true\n}\n```\n\nAll available schema options:\n* **name** - (string, **required**) name of the model\n* **props** - (string array, **required**) list of model props\n* **defaults** - (object {prop:value}) default value of props\n* **refs** - (object {prop:model}) list of references to other models\n* **url** - (string) the specific url of the model. defaults to model's `name`\n* **redraw** - (boolean) trigger a redraw when a model with this schema is updated. defaults to `false`\n* **methods** - (object {name:function}) add custom methods to model instances (by schema)\n* **parser** - (function) add data parser to automatically parse data storing to model\n\nAdditional option information:\n\n**parser** - An option to parse different data objects.\n\n```javascript\n// Parsers for Notes schema\nparser : function(obj) {\n  if(obj.kind === '3rd#party') {\n    return {\n      title : obj.wrap.title,\n      body : obj.wrap.inner.body,\n      author : obj.wrap.inner.author\n    }\n  } else {\n    // Another source\n  }\n}\n// This auto parse wrapped data. Also parsed with `setObject()`.\nvar note = new Note({wrapped: 'data'})\nnote.setObject({wrapped: 'data'})\n// To disable parsing. Set `parse: false` in the options.\nvar note = new Note({unwrapped: 'data'}, {parse: false})\n```\n\n- - - -\n\n## Model\n```javascript\nvar User = md.model(userSchema)\nvar Note = md.model(noteSchema)\n\nvar userA = new User()\nuserA.name('Foo')\nuserA.age(123)\nuserA.save(function (err) {\n   if (!err)\n     console.log('Saved')\n})\n\nvar noteA = new Note({\n   title: 'My Notes'\n}, {\n   redraw : true\n})\nnoteA.body('A note content')\nnoteA.author(userA)\nnoteA.save().then(fnResolve, fnReject)\n```\n\n#### new \\\u003cModelConstructor\u003e([initials, options])\nCreates an instance of model.\n* **initials** - (object {prop:value}) initial values of props\n* **options** - (object) specific options to model instance\n  * **redraw** - (boolean) redraw\n  * **parse** - (boolean) set `false` to disable parsing. defaults to `true`\n\n#### \\#\\\u003cprop\u003e([value, silent])\nGet or set value of prop. If auto-redraw is enabled, pass `true` at the end to set without auto redrawing. This uses the basic usage of stream, and to get the stream itself, use `\u003cprop\u003e.stream`. \n```javascript\nuser.name('Foo') // Sets the name to `Foo`\nvar n = user.name() // Get the name... returns `Foo`\nuser.name('Bar', true) // Silently sets the name to `Bar` (without redrawing)\nvar s = user.name.stream.map(callback) // Get the stream object with `\u003cprop\u003e.stream`\n```\n\n#### \\#opt(key[, value])\nSets an option(s) specific to the model. See `ModelConstructor` for list of options.\n\n#### \\#id([strId])\nGet or set the ID of model regardless of real ID prop. This is useful if you have different id prop like `_id` (mongodb).\n```javascript\n// Assumes that you configure `keyId` to `_id`\nuser._id('Bar') // Sets the id to `Bar`\nvar id = user.id() // Returns `Bar`\n// user.id('Bar') // You can also use this\n```\n\n#### \\#lid()\nGet the local ID of model. This ID is generated automatically when model is created.\n\n#### \\#url()\nGet the url. It return the combination of `baseUrl` and the models' `url`.\n\n#### \\#set(key[, value, silent])\nSet a value to a prop of the model. \n```javascript\nuser.set('name', 'Foo') // Sets single prop\n// Silent set, will NOT trigger the auto redraw\nuser.set('age', 34, true) // Pass true at the end\n```\n\n#### \\#setObject(obj[, silent])\nSet multiple values at once using object. \n```javascript\nuser.set({name: 'Bar', age: 12}) // Sets multiple props using object\nuser.set(existingModelInstance) // Sets multiple props user existing model instance\n// Silent set, will NOT trigger the auto redraw\nuser.set({age: 32}, true) // Pass true at the end\n```\n\n#### \\#get(key)\nGet a value or a copy of all values in object literal format. \n```javascript\nuser.get('name') // Returns the value of name\nuser.get() // Returns an object (copy) with all props and values. e.g. {name: \"Foo\", age: 12}\n```\n\n#### \\#getCopy([deep])\nGet a copy model in object literal format. Additionally, you can set deep to `true` to copy all props recursively.\n\n#### \\#attachCollection(collection)\nAttach the model to a collection.\n\n#### \\#detachCollection(collection)\nDetach the model from a collection.\n\n#### \\#detach()\nDetach the model from ALL associated collections.\n\n#### \\#remove()\nTriggers `detach` and also `dispose` the object. Make sure you're not using the model anymore.\n\n#### \\#isSaved()\nTrue if it contains id and fresh from store (server or local storage).\n\n#### \\#isModified()\nTrue when a prop is modified.\n\n#### \\#isDirty()\nTrue if the model is modified or not saved.\n\n#### \\#save([options, callback])\nSaves the model to data store. To check for result, you can use either `callback` or `then`. Callback arguments are `(err, response, model)`. Properties for `options` is the same with `m.request`'s options but with additional `path` string property. `path` is the path to actual value for the model in the response object. Like in `response:{outer:{model:{}}}` will be `\"outer.model\"`.\n```javascript\nuser.save()\n   .then(\n      function (model) { console.log('Saved') },\n      function (err) { console.log(err) }\n   )\n   .catch(\n      function(catchErr) { console.log(catchErr) }\n   )\n```\n\n#### \\#fetch([options, callback])\nFetches the model from data store. Model ID required to fetch. This method also accept `callback` or `then`. Properties for `options` is the same with `#save()`'s options. If `placeholder` is given in the configuration, the returned value will be that placeholder string.\n```javascript\nuser.id('abc123')\nuser.fetch().then( function (model) { /* Success! model now have other prop values */ } );\n// If placeholder is set as 'Loading...'\nuser.name(); // Returns `Loading...`, until the fetch completed\n```\n\n#### \\#destroy([options, callback])\nDestroys the model from data store and triggers `remove` method. Also accept `callback` or `then`. Parameter `options` is the same with `#save()`'s options.\n\n#### \\#populate()\nPopulates all references. This will trigger fetch if necessary.\n\n#### \\#\\\u003clodash methods\u003e()\nModel includes few methods of Lodash. `has`, `keys`, `values`, `pick`, and `omit`. See **Lodash** for info.\n```javascript\nuserA.pick(['name', 'age'])\n// Returns an object with only two properties `name` and `age`, excluding others.\n```\n\n- - - -\n\n## Collection\n```javascript\nvar userCollection = new md.Collection({\n   model : User,\n   url : '/usercollectionurl',\n   redraw : true\n})\nuserCollection.add(new User())\n```\n\n#### new Collection([options])\n\nAll available collection options:\n* **model** - (model constructor) the associated model to the collection\n* **url** - (string) the specific url of the collection. defaults to associated model's `name`\n* **redraw** - (boolean) trigger a redraw when the collection is updated. Defaults to `false`\n* **state** - (State | object | array) set a state factory (View-Model) for the collection. See `#stateOf()` method and `md.State()` for more info.\n\n\u003e A collection with redraw = `true` will always trigger a `redraw` even though the contained model has redraw = `false`.\n\n\u003e Omitted `model` in option is allowed and will make the collection `generic`. Therefore, some methods will NOT be available, like `create` and `fetch`.\n\n#### \\#opt(key[, value])\nSets an option(s) to the collection. See `Collection` for list of options.\n\n#### \\#add(model[, unshift, silent])\nAdds a model to the collection. Optionally, you can add at the beginning with `unshift` = `true` and silently with `silent` = `true`.\n\n#### \\#addAll(models[, unshift, silent])\nAdds an array of models to the collection. Optionally, you can set `unshift` and `silent` as well.\n\n#### \\#create(objects)\nCreate and add multiple models to the collection from passed array of objects.\n```javascript\nuserCollection.create([ {name:'Foo'}, {name:'Bar'} ])\n```\n\n#### \\#get(mixed)\nGet a model from collection. Argument `mixed` can be a `number`, `string`, `object` or `model` instance. Returns the first matched only otherwise `undefined`.\n```javascript\nuserCollection.get('abc') \nuserCollection.get(123) // If string or number, it will find by Id\nuserCollection.get({name:'Foo'}) // Will match the first model with name equal to `Foo`\nuserCollection.get(model) // Will find by model instance, compared with Lodash's `indexOf`\n```\n\n#### \\#getAll(mixedArr[, falsy])\nGet multiple models from collection. Array can contain `mixed` type, same with `get()`. Returns an array of first matched only of each array element. Argument `falsy` will include falsy value like `undifened` in the list, instead of omitting.\n\n#### \\#remove(mixed[, silent])\nRemoves a model from collection. `mixed` can be same with `get()`'s mixed argument.\n\n#### \\#push(model[, silent])\nAdds a model or array of models at the end.\n\n#### \\#unshift(model[, silent])\nAdds a model or array of models at the beginning.\n\n#### \\#shift([silent])\nRemoves the model at the beginning.\n\n#### \\#pop([silent])\nRemoves the model at the end.\n\n#### \\#clear([silent])\nRemoves ALL models.\n\n#### \\#sort(props[, orders])\nSort the collection. Argument `props` is an array of props to sort and `orders` is an array of `asc` or `desc`. Optioanally, if you're sorting only single prop, you can pass a string instread of array.\n```javascript\n// Sort the collection by `name` in default order `asc`\nuserCollection.sort('name')\n// Sort the collection by `name` in `desc` order\nuserCollection.sort('name', 'desc')\n// Sort the collection by `age` first starting from old (desc) and then `name`\nuserCollection.sort(['age', 'name'], ['desc', 'asc'])\n```\n\n#### \\#sortByOrder(order \u003cArray\u003e, path \u003cstring\u003e)\nSort the collection by giver order.\n\n#### \\#pluck()\nPluck a prop from each model.\n```javascript\nuserCollection.pluck('id') \n// Returns [123, 456, 789]\n```\n\n#### \\#contains(mixed)\nReturns `true` if the model contains in the collection, otherwise `false`. Argument `mixed` is the same with `get()` method.\n\n#### \\#reserve()\nReverse the order of the collection.\n\n#### \\#randomize()\nRandomize the order of the collection.\n\n#### \\#model()\nGet the associated model constructor.\n\n#### \\#stateOf(mixed)\nGet the state of a model in the collection. Argument `mixed` is the same with `get()` method.\n```javascript\n// Set state signature on creating collection\nvar col = new md.Collection({\n   state : {\n      isEditing: true,\n      isLoading: false  \n   }\n})\n// Create user\nvar user = new User()\n// Add user to collection\ncol.add(user);\n// Retrieving state value\ncol.stateOf(user).isEditing() // Returns `true`\n// Setting state\ncol.stateOf(user).isEditing(false) // Sets and returns `false`\n```\n\n#### \\#url()\nGet the url.\n\n#### \\#fetch(query[, options, callback])\nQuery to data store and populate the collection. Callback arguments are `(err, response, models)`. Properties for `options` is the same with `m.request`'s options but with additional `path` and `clear` property. `path` is the path to actual array of items for the collection in the response object. Like in `response:{outer:{items:[]}}` will be `\"outer.items\"`. And `clear` will clear the collection before placing the fetched data.\n```javascript\nuserCollection.fetch({ age : 30 }).then(function (){\n   // Success! `userCollection` now have models with age 30\n})\n```\n\n#### \\#hasModel()\nReturns `true` if the collection has associated model, otherwise `false`.\n\n#### \\#destroy()\nDestroys the collection. Trigger `clear` and `dispose`.\n\n#### \\#isFetching()\nChecks if the collection is fetching.\n\n#### \\#\\\u003clodash methods\u003e()\nCollection includes several methods of Lodash. `forEach`, `map`, `find`, `findIndex`, `findLastIndex`, `filter`, `reject`, `every`, `some`, `invoke`, `maxBy`, `minBy`, `sortBy`, `groupBy`, `shuffle`, `size`, `initial`, `without`, `indexOf`, `lastIndexOf`, `difference`, `sample`, `reverse`, `nth`, `first`, `last`, `toArray`, `slice`, `orderBy`, `transform`. See **Lodash** for info.\n```javascript\nvar filtered = userCollection.filter({age: 30})\n// Returns an array of models with age of 30.\n```\n\n- - - -\n\n## State\nAlso known as View-Model. See Mithril's view-model description for more info.\n```javascript\nvar _isEditing = md.stream(false)\n// Create state factory\nvar stateFactory = new md.State({\n   isLoading: false,\n   isEditing: _isEditing // Add exisiting stream created somewhere\n})\n// Creating states \nstateFactory.set('A');\nstateFactory.set('B');\n// Using states\nvar component = {\n   controller: function() {\n      this.stateA = stateFactory.get('A')\n      this.stateA.isEditing(true)\n      var s = this.stateA.isEditing.map(callback) // Using with stream\n   },\n   view: function(ctrl) {\n      return m('div', 'Is editing ' + ctrl.stateA.isEditing()) // Displays `Is editing true`\n   }\n}\n```\n\n#### new State(signature[, options])\nCreates a new State factory. `signature` can be object or array.\n\nAll available state options:\n* **store** - (function) the custom store function (it must return a function). defaults to `stream` that was set in `md.config`\n* **prefix** - (string) the string prefix for custom store.\n\n#### \\#set(key)\nInternally creates a new state by `key`.\n\n#### \\#get(key)\nGet the state by `key`.\n\n#### \\#remove(key)\nRemoves the state by `key`.\n\n#### md.State.create(signature[, options])\nCreates a state without instantiating new State factory. `options` is same with state factory constructor.\n```javascript\n// Create state factory\nvar state = md.State.create({\n   isWorking: false\n})\nstate.isWorking() // Get state. =\u003e false\nstate.isWorking(true) // Set state. =\u003e true\n```\n\n#### md.State.assign(object, signature[, options])\nSame with `create` but assigns to given `object`, instead of creating new object.\n```javascript\n// Existing object\nvar obj = {};\n// Create state factory\nmd.State.assign(obj, {\n   isWorking: false\n})\nobj.isWorking()\n```\n\n- - - -\n\n## Configure \u0026 Customize\nConfiguration must be set before using any of `mithril-data`'s functionality.\n```javascript\nmd.config({\n   baseUrl : '/baseurl',\n   keyId : '_id', // mongodb\n   store : customStoreFunction\n})\n```\nAll available config options:\n* **baseUrl** - (string) the base url\n* **keyId** - (string) the custom ID of the model. defaults to `id`\n* **redraw** - (boolean) the global redraw flag. default to `false`\n* **cache** - (boolean) enable caching the models created by a collection. defaults to `false`\n* **modelMethods** - (object { methodName : `function()` }) additional methods to bind to `model`'s prototype\n* **collectionMethods** - (object { methodName : `function()` }) additional methods to bind to `collection`'s prototype\n* **modelBindMethods** - (string array) model's methods to bind to itself. see Lodash `bindAll()`\n* **collectionBindMethods** - (string array) collection's methods to bind to itself\n* **storeConfigOptions** - (function) a function to `manipulate the options` before sending data to data-store\n* **storeConfigXHR** - (function) a function to `manipulate XHR` before sending data to data-store. see Mithril's `m.request` for more info\n* **storeExtract** - (function) a function to trigger after receiving data from data-store. see Mithril's `m.request` for more info\n* **storeSerializer** - (function) a function that overrides data-store serializer. see Mithril's `m.request` for more info\n* **storeDeserializer** - (function) a function that overrides data-store deserializer. see Mithril's `m.request` for more info\n* **store** - (function) a function that handles the storing of data. defaults to `m.request`\n* **stream** - (function) a function that handles the model props as well as md's State class. defaults to Mithril's `Stream`\n* **cache** - (boolean) should use cache or not in all collections. defaults to `false`\n* **cacheLimit** - (number) limit of cache. defaults to `100`\n* **placeholder** - (string) the string to return by prop when the model fetching or collection through `isFetching` method\n\n#### storeConfigOptions\nThis is useful when you want to modify the `options` object before sending to data-store. One scenario is to create custom url instead of default generated url.\n```javascript\nuser.id('abc123')\nuser.fetch()\n// The default url is `/user?id=abc123` but we want `/user/abc123\nmd.config({ storeConfigOptions : function (options) {\n    options.url = options.url + '/' + options.data.id\n    options.data = null // clear the data as we've used it already\n}})\n```\n\n#### store\nA function responsible for storing the data (defaults to `m.request`). An example is, if you want to store data using local storage.\n```javascript\nvar fnLocalStorage = function (data) {\n    if (data.method === 'POST') { /* Writing data... */ }\n    else if (data.method === 'GET') { /* Reading data... */ }\n    else if (data.method === 'DELETE') { /* Deleting data... */ }\n    else { /* Do something with other methods */ }\n}\nmd.config({ store : fnLocalStorage})\n```\n\u003e Just make sure that your custom store should return a Promise.\n\n- - - -\n\n## More\n\n#### md.store\nA handy tool that handles request to data-store. The result is through `then` / `catch`.\n* **request(url[, method, data, opt])** - creates a request to data-store. the `opt` will override the options when storing to data-store\n* **get(url[, data, opt])** - calls`request` with `GET` method, passing the `data` and `opt`\n* **post(url[, data, opt])** - calls`request` with `POST` method, passing the `data` and `opt`\n* **destroy(url[, data, opt])** - calls`request` with `DELETE` method, passing the `data` and `opt`\n\n#### md.stream\nExpose Mithril's Stream (unmodified and only bundled).\n\n#### md.toStream\nA helper function to convert any value to stream.\n\n#### md.model.get(name)\nA way to get a model constructor from other scope. Argument `name` is the model name.\n\n#### md.defaultConfig(config)\nOverrides the default config.\n\n#### md.resetConfig()\nResets the config to default. If `defaultConfig()` is used, it will reset to that config.\n\n#### md.noConflict()\nReturn the old reference to `md`.\n\n#### md.version()\nReturn the current version.\n\n- - - -\n\n## Installation\n```sh\n# NPM\nnpm install mithril-data\n# Bower\nbower install mithril-data\n```\nNode / CommonJS:\n```javascript\nvar md = require('mithril-data');\n```\nHTML: (`md` is automatically exposed to browser's global scope)\n```html\n\u003cscript type=\"text/javascript\" src=\"lodash.min.js\"\u003e\u003c/script\u003e\n\u003cscript type=\"text/javascript\" src=\"mithril.min.js\"\u003e\u003c/script\u003e\n\u003cscript type=\"text/javascript\" src=\"mithril-data.min.js\"\u003e\u003c/script\u003e\n\u003cscript type=\"text/javascript\"\u003e\n  console.log(md.version());\n\u003c/script\u003e\n```\n\n- - - -\n\n### License\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frhaldkhein%2Fmithril-data","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frhaldkhein%2Fmithril-data","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frhaldkhein%2Fmithril-data/lists"}