{"id":18879718,"url":"https://github.com/loilo/computed-properties","last_synced_at":"2025-07-24T21:33:01.773Z","repository":{"id":57205039,"uuid":"126246995","full_name":"loilo/computed-properties","owner":"loilo","description":"A data store with support for computed properties","archived":false,"fork":false,"pushed_at":"2019-12-29T23:17:36.000Z","size":121,"stargazers_count":2,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-22T06:38:34.827Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","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/loilo.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":"2018-03-21T22:15:39.000Z","updated_at":"2023-01-29T11:04:36.000Z","dependencies_parsed_at":"2022-09-18T01:32:18.425Z","dependency_job_id":null,"html_url":"https://github.com/loilo/computed-properties","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/loilo/computed-properties","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loilo%2Fcomputed-properties","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loilo%2Fcomputed-properties/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loilo%2Fcomputed-properties/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loilo%2Fcomputed-properties/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/loilo","download_url":"https://codeload.github.com/loilo/computed-properties/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loilo%2Fcomputed-properties/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266569445,"owners_count":23949748,"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-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"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-11-08T06:39:01.111Z","updated_at":"2025-07-24T21:33:01.740Z","avatar_url":"https://github.com/loilo.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Computed Properties\n\n[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)\n[![Travis](https://img.shields.io/travis/Loilo/computed-properties.svg)](https://travis-ci.org/Loilo/computed-properties)\n[![npm](https://img.shields.io/npm/v/computed-properties.svg)](https://www.npmjs.com/package/computed-properties)\n\nThis package helps   deriving data from other data. It's especially well suited for computation-heavier dependencies since it caches and lazy-evaluates computed properties.\n\nIt conceptually borrows heavily from [Vue.js](https://vuejs.org)' computed properties, supports all evergreen browsers and IE 11 and features a reasonably small size (1.6 KB minified \u0026 gzipped).\n\n## Installation\nInstall it from npm:\n\n```bash\nnpm install --save computed-properties\n```\n\n### Include in the Browser\nYou can use this package in your browser with one of the following snippets:\n\n* The most common version. Compiled to ES5, runs in all major browsers down to IE 11:\n\n  ```html\n  \u003cscript src=\"node_modules/computed-properties/dist/store.umd.js\"\u003e\u003c/script\u003e\n\n  \u003c!-- or from CDN: --\u003e\n\n  \u003cscript src=\"https://unpkg.com/computed-properties\"\u003e\u003c/script\u003e\n  ```\n\n* If you're really living on the bleeding edge and use ES modules directly in the browser, you can `import` the package as well:\n\n  ```javascript\n  import Store from \"./node_modules/computed-properties/dist/store.mjs\"\n\n  // or from CDN:\n\n  import Store from \"https://unpkg.com/computed-properties/dist/store.mjs\"\n  ```\n\n  As opposed to the snippets above, this will not create a global `Store` function.\n\n### Include in Node.js\nInclude this package in Node.js like you usually do:\n\n```javascript\nconst Store = require('computed-properties')\n```\n\n## Usage\nCreate a store by passing a configuration object to the `Store` function:\n\n```javascript\nconst programmer = Store({\n  firstName: 'Jane',\n  lastName: 'Doe',\n  hobbies: [ 'programming', 'reading' ],\n  skills: {\n    communication: 3,\n    cleverness: 4\n  },\n  fullName () {\n    return this.firstName + ' ' + this.lastName\n  },\n  bestAt () {\n    return Object.entries(this.skills).sort(([,ratingA], [,ratingB]) =\u003e ratingB - ratingA)[0][0]\n  },\n  developerStory () {\n    return `Hi, I'm ${this.fullName}.\nI like ${this.hobbies.slice(0, -1).join(', ')}${this.hobbies.length \u003e 1 ? ' and ' : ''}${this.hobbies[this.hobbies.length - 1]}.\nI'm especially good with ${this.bestAt}.`\n  }\n})\n```\n\n\u003e You can play with this example [on CodePen](https://codepen.io/loilo/pen/xxbrewd?editors=0012).\n\nAll functions in the configuration object (`fullName`, `bestAt` and `developerStory` in our case) will be treated as computed properties. You can get their values just like with any regular property:\n\n```javascript\nprogrammer.fullName // \"Jane Doe\"\n```\n\nNow if we adjust the first name of our programmer, the `fullName` will also be updated:\n\n```javascript\nprogrammer.firstName = 'John'\nprogrammer.fullName // \"John Doe\"\n```\n\n## Context-free Computed Properties\nIf you don't like the style of computed properties accessing the `this` object, they also get passed the store as their first parameter.\n\nThe `programmer.fullName` computed property, for example, could also have been written as follows:\n\n```javascript\nStore({\n  // ...\n\n  fullName: store =\u003e store.firstName + ' ' + store.lastName\n\n  // or even:\n\n  fullName: ({ firstName, lastName }) =\u003e firstName + ' ' + lastName\n})\n```\n\n## Watch Properties\nYou can watch any regular or computed property on the created `programmer` using the `$watch()` method:\n\n```javascript\nconst unwatch = programmer.$watch('fullName', (newValue, oldValue) =\u003e {\n  // This is executed when the `fullName` computed property changes\n})\n\n// Calling unwatch() will stop watching the `fullName` property\n```\n\n\n## Set a new Property in an Object\nAll properties of an object present at initialization time will be tracked. However, if you want to add a new property, you have to use the `$set()` method:\n\n```javascript\nprogrammer.skills.$set('experience', 5)\n```\n\n## Set an Array Item's Value\nWhile all array methods (e.g. `push()`) are tracked, setting an array's item via bracket access cannot be tracked:\n\n```javascript\nprogrammer.hobbies[0] = 'Cycling' // Will not update the `developerStory`\n```\n\nTo trigger dependency changes you'd either have to replace the whole `hobbies` array, or set the respective item via the `$set()` method:\n\n```javascript\nprogrammer.hobbies.$set(0, 'Cycling') // Will update the `developerStory`\n```\n\n## Functions as Properties\nSince all functions in a `Store`'s configuration object are treated as computed properties, there's no way that a regular property can contain a function.\n\n```javascript\nStore({\n  // Evaluated as a computed property\n  someProp: function () {\n    // ...\n  }\n})\n```\n\nHowever, there's a very simple workaround: Create a computed property that returns the desired function.\n\n```javascript\nStore({\n  someProp () {\n    return function () {\n      // ...\n    }\n  }\n})\n```\n\n\n## Methods\nThe `Store` function has no built-in way to attach methods to it, but you can assign them onto the created store:\n\n```javascript\n// Possibly update last name on marriage\nprogrammer.marry = function (newLastName) {\n  if (newLastName) {\n    this.lastName = newLastName\n  }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Floilo%2Fcomputed-properties","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Floilo%2Fcomputed-properties","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Floilo%2Fcomputed-properties/lists"}