{"_id":"@billow/vue-utilities","_rev":"3-97c8db534d60df69210d8052286059a7","name":"@billow/vue-utilities","dist-tags":{"latest":"1.0.2"},"versions":{"1.0.0":{"name":"@billow/vue-utilities","version":"1.0.0","description":"Useful set of utilities for Vue apps. Under continuous development.","main":"index.js","devDependencies":{"accounting-big":"^1.0.1","axios":"^0.18.0","filesize":"^3.6.1","he":"^1.2.0","moment":"^2.24.0","pluralize":"^7.0.0","qs":"^6.6.0"},"peerDependencies":{"vue":"^2.5.21"},"repository":{"type":"git","url":"git+https://gitlab.com/billow-thunder/vue-utilities.git"},"keywords":["Vue","Utilities","Filters","Auth","Passport"],"author":{"name":"Mike Rockett","email":"mike@billow.co.za"},"license":"ISC","bugs":{"url":"https://gitlab.com/billow-thunder/vue-utilities/issues"},"homepage":"https://gitlab.com/billow-thunder/vue-utilities#readme","gitHead":"fc794b7807e98f3fc8062da40306d61681143a92","_id":"@billow/vue-utilities@1.0.0","_npmVersion":"6.4.1","_nodeVersion":"10.13.0","_npmUser":{"name":"billow","email":"warren@billow.co.za"},"dist":{"integrity":"sha512-zgsa70gTn4/KiHwMmwIntUpPwxYrhcE4Qgw8dN+UOU9sTLBCiKX9I0oJeczT1Re1hFK6mxDvu4ZX133r8/ivGA==","shasum":"c66f0f3de72df406d6933a58ff7d18b6c94c469f","tarball":"https://registry.npmjs.org/@billow/vue-utilities/-/vue-utilities-1.0.0.tgz","fileCount":48,"unpackedSize":58882,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcuDn8CRA9TVsSAnZWagAA/2YP/1S0HeBRILhEndLvdamh\nF7YfXyJrRs29tpkwy5YVYqRatTaBQS6s8YprUSd+XI+4pOYNlaVZ76VwN+et\nhY3PENgWQUvbV+BApJsPa3JmSpiVVjGYXqyL6e+g6vnqkLWuTvowMUH4rQd4\nFPBKwRpDXG4K/sBynLvUvw8Ra4Jd3UVoNPrlXgtuI2GL7Ig7IWaTboJxe/Pa\n6vp+6Td4UhEPfCKgDZX0IYhfd5ug7qmFVHzuuW+vWtj85epwgWbiDyvYuhsZ\nbrpYxaffXGLwzt92NSmlVKL0YQTnCNIRtHB8EoD4n/fAtQk+K9AUgwSQpYxE\nziu9C48wfhSUCovFuBCDAKZ2QEyZ1jfUkJrl62Tv+ZYYucaXeVIC7NXG2INh\ngipukW/40+pBTXuBY+GCHLN4Ej77zJAGEVcKMA1q1X73r9f813y87I+QxEkN\ncO8mGDjlhlSLVeA4xBJa6VRdR7t5Mkmia0CAcR8Pd37ypoAWJPJBYlAg7Wxd\n/NAfPSa1jMaJQWdM5ByKHpjGzE+C+KGGTs+aYvr0hIVLqSSTJVj20bm+067t\n/FBanGRXbW0oFOfD/hl5tXCb54mSk5sDctAwbnzS2RWoMrexibiqzPEvqnjP\nAoJP93UedS6DxI9+JhCEK6vOoBSiPLgCPru8JUyfyPzo5rpybolNvltT2Bh5\n+1kp\r\n=vNeY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIACqhrxl42lYFuiNNkeuzwWgI03G7avMIiejYN6FwpHfAiEA00KFWeLLRrOW+pBJtEeK9sqjO1WUm9gpTEEvhEFxfsw="}]},"maintainers":[{"name":"billow","email":"warren@billow.co.za"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/vue-utilities_1.0.0_1555577339318_0.08206903305067925"},"_hasShrinkwrap":false},"1.0.1":{"name":"@billow/vue-utilities","version":"1.0.1","description":"Useful set of utilities for Vue apps. Under continuous development.","main":"index.js","dependencies":{"accounting-big":"^1.0.1","axios":"^0.18.0","filesize":"^3.6.1","he":"^1.2.0","moment":"^2.24.0","pluralize":"^7.0.0","qs":"^6.6.0"},"peerDependencies":{"vue":"^2.5.21"},"repository":{"type":"git","url":"git+https://gitlab.com/billow-thunder/vue-utilities.git"},"keywords":["Vue","Utilities","Filters","Auth","Passport"],"author":{"name":"Mike Rockett","email":"mike@billow.co.za"},"license":"ISC","bugs":{"url":"https://gitlab.com/billow-thunder/vue-utilities/issues"},"homepage":"https://gitlab.com/billow-thunder/vue-utilities#readme","gitHead":"646b69d43d9462daa8c09aed98ed2ebe30fcd10f","_id":"@billow/vue-utilities@1.0.1","_npmVersion":"6.4.1","_nodeVersion":"10.13.0","_npmUser":{"name":"billow","email":"warren@billow.co.za"},"dist":{"integrity":"sha512-PhE31YTn/c5a3vp93YfWUEouHJbmY35E9qjMFg+fnZNu9S6UuLhwDpPGrKZdXSo0b3C9VlfOvKlYS1Vh917Dkg==","shasum":"5e03d410a81f428d764622fd4b8ac75a361e9d28","tarball":"https://registry.npmjs.org/@billow/vue-utilities/-/vue-utilities-1.0.1.tgz","fileCount":48,"unpackedSize":58879,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcuD7BCRA9TVsSAnZWagAAELQP/3jqHgpQFL6Z/JqihEmY\nMKe8ppFi9DxjZAkPBXGDYdhuPIksVG2WmGUMmV7REvKDf9q0II4tRktBUlw9\n2QK30AFgX7/zZ++rsbghkPL1/52kPtnXMLwDsk54dZoY3jJyk2H+STYlPfYD\n9fGC6lqQNskwSOOC2BZkGAkWY09PJtuHBozf0tSJg+bvn684FjXX12GL654t\nvedrI5NyDYCZpeieCNtgYG56Y9zqILA+LPE1X6oclBD1GodR+fchQ190YbfO\n/8FyaG6PJIreOe2xUJhBvCJOyEx7aJveQDHF3vb0VtG0fOfoeuD8QqbfEuMv\n9JYX3kBpiW+xxPsMi99vlE4OD7+Amn7yP6AfmMz370TRz49IF41mu3LP5YJO\nkLMSReqGmmPdK1eqVQM+/3QYbeyUcVYHRJzCVd7Pk8nYySO0A18cRm+3V9cx\nAc87vwyOqKgL1K7N51jJeUcP6tH5hR75vdHqk4YCjf2W1EroaClyAAszNcZ+\nekMVQnMUsdIHk+JoRMKG25ZuFbo3PqV+4NyLyFvvUERAoVQNo5ZPQyOyTlFo\n6yFe9M1Ok7/spwxryZ1tvW9FwRVzt8fzJC5R1snvGl4ve2XKBjalcMpV59z+\nUUsO3GAY9FSke4avGXN0URKIxherdoBoqDH7LMygGjltp1IyNBd+u3NBByCM\ndTt8\r\n=39oN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDI8IZ1BYhFZqAdIQN523vBG9FaUE2GSDOfQRTiYacAcQIhANUa62yzz5fA7DB7proW/8dztcz2QD5kgBZvc9qzoUfT"}]},"maintainers":[{"name":"billow","email":"warren@billow.co.za"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/vue-utilities_1.0.1_1555578561233_0.5577777536110715"},"_hasShrinkwrap":false},"1.0.2":{"name":"@billow/vue-utilities","version":"1.0.2","description":"Useful set of utilities for Vue apps. Under continuous development.","main":"index.js","dependencies":{"accounting-big":"^1.0.1","axios":"^0.18.0","filesize":"^3.6.1","he":"^1.2.0","moment":"^2.24.0","pluralize":"^7.0.0","qs":"^6.6.0"},"peerDependencies":{"vue":"^2.5.21"},"repository":{"type":"git","url":"git+https://gitlab.com/billow-thunder/vue-utilities.git"},"keywords":["Vue","Utilities","Filters","Auth","Passport"],"author":{"name":"Mike Rockett","email":"mike@billow.co.za"},"license":"ISC","bugs":{"url":"https://gitlab.com/billow-thunder/vue-utilities/issues"},"homepage":"https://gitlab.com/billow-thunder/vue-utilities#readme","gitHead":"0904581420f6e548dba1f9792743c6c693369ad7","_id":"@billow/vue-utilities@1.0.2","_nodeVersion":"12.13.0","_npmVersion":"6.12.0","dist":{"integrity":"sha512-Zqxz+MFcCQM9rw1reRpn1ikzPc/nX5TIoJT4QMcJ13URn5yCqDMND5mvDUywSWvqQrBsZOcxCMHVPXv9xnwUXA==","shasum":"d32c64e67ce6ca8904696357a2851ae56b215ebe","tarball":"https://registry.npmjs.org/@billow/vue-utilities/-/vue-utilities-1.0.2.tgz","fileCount":48,"unpackedSize":58896,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeKCVvCRA9TVsSAnZWagAAuKMQAJXkJSPdj+RXMm6yVlEp\nMAZCBf+Tbzsj7rnxqoNv3I6h5XA7oi2WevrEa//5eHNG1wtwkoUfyu/YoUbN\nA6tmDkgEfxkAVUUUYefgnw8Zjuq/Ogu4AMaM8m5fDw49GeuibpHe/F/yWylZ\nF6goGR1IcKnSzql+XlfJq7LNn4fSKxPWIHEPewUZWQtba8YG5kLZb7ppfXbx\nBCKGyZjLM6cY8uloT9JXtdOYr9+kNRY7OnjqPWbFnkEiKzyRJm8Dny4bK1R7\nlQNUkQ04V+y/lMxr7Qz6+4/q6qKEmn4xRnF5vpMzPItAJjtA8yRqluhxVNjx\nMCzJZRQGTZMmDopiCRuhSpEV053m58ItdOPsxmrCA8rhkN+19zZWeezVIQgt\nuJDoY2b7gdoa3PxvniUTLzZH7ipADV5nzvH/fnelSFDs3T18miMLrxtPHFNQ\n2DpV5o2Q8qMKxkf2k/j9JTvV5NIAGBeQTRcPahUFR7DXOwYJdRy7Zy76xnKw\nKvk16un5TncCjEvX3mkDkrXJfo7J3zRbov7XUxDTiuZGT6//ya4hdEB/tmUN\nBSDlmgPx/S85BKrIrkGhwQFPqVGKgGlhouBAAjkoxM+zr9p607qG4QvP0SqZ\nZRDvaSU0dyeDifair424PEFyE1s9TaAEtzcSbvGzghWW+jaGGkdafyWKwTAq\nPcm/\r\n=XhfF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDpP7IeLxlAn8wadDSCNKkcTIcrDr9+4ojRk9nGPyGzkAIhAIyU2dDkSw5hkRkoiICMnNDUR+4ZVnrdP3xsjtDca1S4"}]},"maintainers":[{"name":"billow","email":"warren@billow.co.za"}],"_npmUser":{"name":"billow","email":"warren@billow.co.za"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/vue-utilities_1.0.2_1579689327095_0.4263416007274612"},"_hasShrinkwrap":false}},"time":{"created":"2019-04-18T08:48:59.317Z","1.0.0":"2019-04-18T08:48:59.528Z","modified":"2022-04-04T18:50:37.920Z","1.0.1":"2019-04-18T09:09:21.438Z","1.0.2":"2020-01-22T10:35:27.220Z"},"maintainers":[{"name":"billow","email":"warren@billow.co.za"}],"description":"Useful set of utilities for Vue apps. Under continuous development.","homepage":"https://gitlab.com/billow-thunder/vue-utilities#readme","keywords":["Vue","Utilities","Filters","Auth","Passport"],"repository":{"type":"git","url":"git+https://gitlab.com/billow-thunder/vue-utilities.git"},"author":{"name":"Mike Rockett","email":"mike@billow.co.za"},"bugs":{"url":"https://gitlab.com/billow-thunder/vue-utilities/issues"},"license":"ISC","readme":"# Vue Utiities, by Billow\n\n![Made with Vue](https://forthebadge.com/images/badges/made-with-vue.svg)\n![Does not contain tree nuts](https://forthebadge.com/images/badges/does-not-contain-treenuts.svg)\n![Built with Love](https://forthebadge.com/images/badges/built-with-love.svg)\n\nA useful set of utilities designed specifically for Vue apps. Includes the following features:\n\n- Handy set of [filters](#filters).\n- Simple [model class](#model-class) for your Vuex stores. Need a full-fledged ORM? Try [vue-orm](https://vuex-orm.github.io/vuex-orm/).\n- Dot-notation-based mutation helpers for Vuex.\n- Passport, a basic local-storage-based OAuth client manager, for general use with a password grant client. Need to authenticate with third-parties? Try [vue-authenticate](https://github.com/dgrubelic/vue-authenticate)\n- Factories: auto-register components (static or lazy) and Vuex stores (supports sync-helpers and nested mutations).\n- FormData (as well as a type-safe counterpart that converts non-files to a JSON payload that your backend will need to translate when compiling a request).\n- String, Object and Array helpers.\n\n> 💡 **WIP:** These docs are a work in progress, and may be moved to a dedicated site at a later stage.\n\n## Filters\n\n### abbreviateCount\n\nShorten long numbers into their abbreviated counter-parts.\n\n`(input, precision = 1)`\n\n```js\n2500 | abbreviateCount // 2.5k\n25000 | abbreviateCount // 25k\n250000 | abbreviateCount // 250k\n2510000 | abbreviateCount // 2.5m\n2510000 | abbreviateCount(2) // 2.51m\n```\n\n### accounting\n\nFormat numbers in accounting format, using declarative rules. Uses [accounting-big](https://www.npmjs.com/package/accounting-big).\n\n`(currency = 'R', precision = 2, thousandsSeparator = ',', precisionSeparator = '.', format = '%s %v')`\n\n```js\n2000 | accounting // R 2,000.00\n2000 | accounting('$') // $ 2,000.00\n15982.115 | accounting('R', 3) // R 15,982.115\n2000 | accounting('R', 2, ' ') // R 2 000.00\n2000 | accounting('€', 2, '.', ',') // € 2.000,00\n2000 | accounting('CAD', 2, ',', '.', '%v %s') // 2,000.00 CAD\n```\n\n### calendar\n\nFormats date objects using a calendar format. Uses moment.calendar internally.\n\n`(sameElse = 'D MMMM Y', utc = false)`\n\n```js\ndate | calendar\ndate | calendar('DD/MM/YYYY')\ndate | calendar('DD/MM/YYYY', true) // uses a UTC offset\n```\n\n### convertBreaks\n\nConvert line breaks to HTML breaks\n\n```html\n<div v-html=\"$options.filters.nl2br(multilineString)\"></div>\n```\n\n### currency\n\nFormat numbers as currency using the native `toLocaleString`. Uses the `number` if not using `Intl`-based formatting (which requires three currency symbol characters).\n\n`(currency = 'R', locale = 'en-GB', minimumFractionDigits = 2, maximumFractionDigits = 2)`\n\n```js\n2000 | currency // R 2,000.00\n2000 | currency('$') // $ 2,000.00\n123456.789 | currency('₹', 'en-IN') // ₹ 1,23,456.79\n```\n\n> **Note:** This filter is a mix-match between `Intl.NumberFormat` and manual currency-symbol concatenation. Unfortunately, the spec for `Intl` uses a non-standard format for South African currencies (1 000,00 as opposed to 1,000.00). If you’d prefer to use the Intl spec for formatting currencies, simply provide the three-digit currency code instead of the symbol and the applicable locale. If this route is taken, all rules related to Intl.NumberFormat apply.\n\n\n```js\n2000 | currency('ZAR', 'en-ZA')\n2000 | currency('ZAR')\n```\n\n### date\n\nFormat a date using moment.format.\n\n`format = 'Y-MM-DD', utc = false`\n\n```js\ndate | date\ndate | date('DD/MM/YYYY')\ndate | date('DD/MM/YYYY', true) // uses a UTC offset\n```\n\n### filesize\n\nGiven a filesize in bytes, format the size.\n\n`base = 2, exponent = -1`\n\n```js\n38889823 | filesize // 37.09 MB\n38889823 | filesize(2, 3) // 0.04 GB\n```\n\n### format\n\nFormat a string by replacing placeholders (in `:placeholder` or `{placeholder}` format, by default) within it.\n\n`(format|object)`, where the argument is the format string and the input is the object from which data is obtained, or vice-versa.\n\n```js\nuser | format('{name} has role of :role') // Mike has a role of member\n':name has role of {role}' | format(user) // Mike has a role of member\n```\n\nWhere:\n\n```js\nuser = {\n  name: 'Mike',\n  role: 'member'\n}\n```\n\nIf you’d like to use custom container formats, you can specify them in the second argument as an array of strings:\n\n```js\n'(name) has a role of *role' | format({ name: 'Mike', role: 'admin }, ['(|)', '*'])\n```\n\nEach format may be separated by a pipe if you’d like to surround the entire placeholder. Either side of the pipe may have many characters as needed. Where a pipe is not specified, the entire string will be used for the left of the placeholder.\n\n### fromNow\n\nReturn a date in human-friendly format.\n\n`(suffix = true, utc = false)`\n\n```js\n'2018-09-10' | fromNow // in 4 months\n'2018-05-24 07:24:00' | fromNow // 4 minutes ago\n'2018-05-24 07:24:00' | fromNow(false) // 4 minutes\n'2018-05-24 07:24:00' | fromNow(false, false) // uses a UTC offset\n```\n\n### get\n\nUsing dot-notation, get the value of the key/path provided from an object. If the key does not exist, the path will be printed instead, failing which a fallback can be set.\n\n`(path, fallback = undefined)`\n\n```js\nuser | get('profile.avatar.url') // https://test.test/img.jpg\nuser | get('profile.avatar.nothing') // profile.avatar.nothing\nuser | get('profile.avatar.nothing', 'Not set') // Not set\n```\n\nWhere:\n\n```js\nlet user = {\n  profile: {\n    avatar: {\n      url: 'https://test.test/img.jpg'\n    }\n  }\n}\n```\n\n### lcfirst\n\nReturn the input with the first character in lower case.\n\n```js\n'Howzit' | lcfirst // howzit\n```\n\n### lcwords\n\nReturn the input with the first character in lower case.\n\n```js\n'No Howzit' | lcfirst // no howzit\n```\n\n### log\n\nLog the input to the console.\n\n```js\nsomething.to.log | log\n```\n\n### number\n\nSimilar to the `currency` filter, but without the currency symbol. The currency filter relies on the number filter for locale-based formatting.\n\n`(minimumFractionDigits = 2, maximumFractionDigits = 2, locale = 'en-GB')`\n\n```js\n2000 | number // 2,000.00\n2000.211 | number(3) // 2,000.211\n2000.21109 | number(3, 5) // 2,000.21109\n12345678.7891 | number(3, 5, 'en-IN') // 1,23,456.7891\n```\n\n### or\n\nSimilar to using the logical-or (`a || b`, where `a` is falsy for example), only `or` uses a stricter truthy-check, unless loose is true.\n\n`(fallback, loose = false)`\n\n```js\nundefined | or('n/a')\nnull | or('n/a')\n'' | or('n/a')\n\n0 | or('n/a') // 0\n0 | or('n/a', true) // n/a\nfalse | or('n/a') // false\nfalse | or('n/a', true) // n/a\n```\n\n### ordinal\n\nReturn the ordinal of the input.\n\n```js\n1 | ordinal // 1st\n2 | ordinal // 2nd\n3 | ordinal // 3rd\n4 | ordinal // 4th\n```\n\n### plain\n\nConvert HTML to plain text.\n\n```html\n<div>body | plain</div>\n<!-- In laoreet exercitation? Accusantium, pede? Nascetur, [...] -->\n```\n\n```js\nexport default {\n  data: () => ({\n    body: '<p>In laoreet exercitation? Accusantium, pede? <br><br>' +\n      'Nascetur, aspernatur pretium feugiat, nullam rerum suscipit pulvinar' +\n      'dignissimos nulla sint, rerum dolorum fames hac.</p>'\n  })\n}\n```\n\n### plural\n\nPluralise a word when the input is a number greater than 1. Arguments are swappable.\n\n`(count|singular)`, where the argument is the singular word and the input is the count, or vice-versa.\n\n```js\n1 | plural('apple') // apple\n2 | plural('apple') // apples\n1 | plural('fish') // fish\n2 | plural('fish') // fish\n\n'apple' | plural(1)\n'apple' | plural(2)\n'fish' | plural(1)\n'fish' | plural(2)\n```\n\n### replace\n\nPass the input string to a `String.prototype.replace`.\n\n`(string, replace)`\n\n```js\n'foo bar' | replace('foo', 'boo') // boo bar\n'A123E' | replace(/\\d/, '*') // A*23E\n'A123E' | replace(/\\d/g, '*') // A***E\n```\n\n### toFixed\n\nConvert the input to a number and apply fixed precision\n\n`(precision = 2)`\n\n```js\n\"2.983726\" | toFixed // 2.98\n```\n\n### truncate\n\nTruncate the input to the nearest word or character, using the specified omission character.\n\n`(length = 20, omitWith = '…', useWordBoundary = true)`\n\n```js\n'Error gravida dis phasellus deleniti, nostrud.' | truncate\n// Error gravida dis…\n\n'Error gravida dis phasellus deleniti, nostrud.' | truncate(15)\n// Error gravida…\n\n'Error gravida dis phasellus deleniti, nostrud.' | truncate(15, '[…]')\n// Error gravida[…]\n\n'Error gravida dis phasellus deleniti, nostrud.' | truncate(15, '[…]', false)\n// Error gravida d[…]\n```\n\n### ucfirst\n\nReturn the input with the first character in upper case.\n\n```js\n'howzit' | ucfirst // Howzit\n```\n\n### ucwords\n\nReturn the input with the first character in upper case.\n\n```js\n'no howzit' | lcfirst // No Howzit\n```\n\n### yesNo\n\nA friendly way to display boolean values.\n\n`(yes = 'yes', no = 'no')`\n\n```js\ntrue | yesNo // yes\nfalse | yesNo // no\ntrue | yesNo('yep', 'nope') // yep\nfalse | yesNo('yep', 'nope') // nope\n```\n\n## Model class\n\nOften-times you’ll be setting data in your state based on a server-response, such as a user. A simple model class is provided to add some functionality atop this data, making it easier to work with in general.\n\nThe basic construct of a model is as follows (note the export notation – this is achieved with the [StoreFactory](#store-factory)):\n\n```js\n// store/models/user.js\nimport { Model } from '@billow/vue-utilities/vuex/model'\n\nexport class User extends Model {\n  constructor(payload = null) {\n    super(payload || {\n      name: '',\n      email: ''\n    })\n  }\n}\n```\n\nHere, we have a `User` class that extends `Model`, providing it with additional functionality, such as tracking whether or not the model is dirty (has been changed) or converting it to `FormData`.\n\nNow, we use the model in our state:\n\n```js\n// store/modules/user.js\nimport { User } from '../models/user'\n\nexport let state = {\n  user: new User\n}\n```\n\nModels are aware of their clean/dirty state. To turn this off, simply construct the model with a `null` payload, and turn off history by setting the second argument to `true`.\n\n```js\nnew User(null, true)\n```\n\n### Hydration\n\nModels are also hydratable, either through the `hydrate` method, or the constructor:\n\n#### Constructor (most efficient)\n\nCreate a new instance of the model, hydrating it with the provided payload, effectively resetting the original state.\n\n```js\nexport let mutations = {\n  setUser: (state, payload) => state.user = new User(payload)\n}\n```\n\n#### The `hydrate` method\n\nHydrate the model instance with the provided payload, optionally resetting the original state.\n\n```js\nexport let mutations = {\n  setUser: (state, payload) => state.user.hydrate(payload) // sets the original state to the payload\n  setUser: (state, payload) => state.user.hydrate(payload, false) // retains the original state\n}\n```\n\n### Checking the state of the model\n\nTo determine if a model is dirty, simply use the `isDirty` getter on the model instance:\n\n```vue\n// User.vue\n<template>\n  <p>User has unsaved changes: {{ user.isDirty | yesNo }}</p>\n</template>\n\n<script>\nimport { mapState } from 'vuex'\n\nexport default {\n  computed: mapState('user', ['user'])\n}\n</script>\n```\n\n### Check if tracking is enabled\n\nYou can also check if the model is tracking it’s state using the `noHistory` getter on the instance. Alternatively, you can check if originals have been set using the `hasOriginals` getter.\n\n### Reset the model state\n\nIf a model is dirty, you can reset it to the payload that was passed in the constructor or through the hydrate method. To do this, simply call the `reset` method on the model instance. If there are no originals, then nothing will happen.\n\n### Cloning a model\n\nThough meant to be used internally, feel free to clone the model with the `clone` method on the instance. This will return a fully-qualified clone of the model, however it will not be reactive unless it is set to something that Vuex can observe.\n\n### Model transformations\n\n> **Note:** This feature may change in the future to use only dot-notation (see below), or will at least support it over and above the syntax below. If the current syntax is removed, it will only be removed in a major release.\n\nSometimes, you’ll find yourself in the position where you have a subkey of type `Object` in your model, but you want that subkey’s value to be of type `Number` for the purposes of API compatibility. For example, let’s say you have the following data in a model:\n\n```js\n{\n  name: 'Mike',\n  email: 'hello@billow.co.za',\n  country: {\n    id: 1,\n    name: 'South Africa'\n  }\n}\n```\n\nWhen this payload goes up to your API, you might want to only pass the ID of the country. This is where transformations come in – they allow you to easily grab parts of the model and move them to the root, optionally using a custom key to replace it.\n\nThere are two types of transformations you can make. The first type simply hoists the value you're looking for in a subkey to the root of the model. For example:\n\n```js\nreturn user.transform({\n  country: 'id'\n})\n```\n\nThis tells the model to return only the `id` under the `country` key, whilst retaining the key name, yielding:\n\n```js\n{\n  name: 'Mike',\n  email: 'hello@billow.co.za',\n  country: 1\n}\n```\n\nAll well and good, but what if you need to rename the key to `country_id`? This is where the second type of transformation comes in. By passing an array with two parameters that resemble the current and new key names (or an object resembling the current key and the new key pair), we can rename the key easily:\n\n```js\nreturn user.transform({\n  country: ['id', 'country_id'] // or\n  // country: { id: 'country_id' }\n})\n```\n\nThese both yield:\n\n```js\n{\n  name: 'Mike',\n  email: 'hello@billow.co.za',\n  country_id: 1\n}\n```\n\n#### Hoist by dot-notation\n\nBecause models support dot-notation out of the the box (see the methods below for this), we can further expand on our transformations by hoisting a deeply nested key’s value and optionally renaming it:\n\n```js\nreturn user.transform({ country: 'profile.country.id' })\nreturn user.transform({ country: { 'profile.country.id': 'country_id' } })\n```\n\nThis will yield the same result as before, only we’re now working with a country object inside a the user’s profile.\n\n### Using dot-notation\n\nAs mentioned, models use dot-notation out of the box. With this strategy, we can easily get, pick and omit data from a model.\n\n#### `get`\n\nGet a piece of data from the model, with an optional fallback if the data is falsy.\n\n```html\n<p>{{ user.get('profile.country.name') }}</p>\n<p>{{ user.get('profile.country.name', 'Unknown') }}</p>\n```\n\n> **Tip:** Use the `get` filter when you’re not working with a model.\n\n#### `pick`\n\nReturn a limited set of data that your API may require.\n\n```js\nreturn user.pick(['name', 'email'])\n```\n\nYielding:\n\n```js\n{\n  name: 'Mike',\n  email: 'hello@billow.co.za',\n}\n```\n\n#### `omit`\n\nIn the same vein, omit data that you don’t need:\n\n```js\nreturn user.omit(['profile'])\n```\n\nWhich yields the same thing.\n\n### Conversions\n\nYou can convert a model to string, form-data and JSON-based-form-data using the built-in helper methods:\n\n```js\nreturn user.toString()\nreturn user.toFormData()\nreturn user.toJsonFormData('data')\n```\n\nIn the first case, the model’s enumerable props are simply sent off to `JSON.stringify` and returned.\n\nIn the latter two cases, the first converts the model to a standard `FormData` object, and the second converts it to a type-safe version of `FormData`, where anything that is not a file gets added to a single key in JSON format. Your backend will need to parse this out when parsing compiling the incoming request. For more information, there’s [a nice little article on it](https://blog.rockett.pw/post/dealing-with-formdata) (see the middleware example for Laravel).\n\n## Mutation Helpers\n\n…\n\n## API Client\n\n…\n\n## Passport\n\n…\n\n## Component and Store Factories\n\n…\n\n## Array, Object and String Utilities\n\n…\n","readmeFilename":"readme.md"}