{"id":24747894,"url":"https://github.com/codingitwrong/vuex-jsonapi","last_synced_at":"2025-10-25T09:08:34.105Z","repository":{"id":97570777,"uuid":"135951846","full_name":"CodingItWrong/vuex-jsonapi","owner":"CodingItWrong","description":"Library to access JSON API data via Vuex stores","archived":false,"fork":false,"pushed_at":"2020-02-20T07:52:27.000Z","size":31,"stargazers_count":22,"open_issues_count":2,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-10T16:32:46.824Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CodingItWrong.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2018-06-04T00:34:09.000Z","updated_at":"2021-06-21T09:58:25.000Z","dependencies_parsed_at":null,"dependency_job_id":"a265abb6-4e3e-49e1-9a0e-d010ec31f5a1","html_url":"https://github.com/CodingItWrong/vuex-jsonapi","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/CodingItWrong/vuex-jsonapi","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CodingItWrong%2Fvuex-jsonapi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CodingItWrong%2Fvuex-jsonapi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CodingItWrong%2Fvuex-jsonapi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CodingItWrong%2Fvuex-jsonapi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CodingItWrong","download_url":"https://codeload.github.com/CodingItWrong/vuex-jsonapi/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CodingItWrong%2Fvuex-jsonapi/sbom","scorecard":{"id":31818,"data":{"date":"2025-08-11","repo":{"name":"github.com/CodingItWrong/vuex-jsonapi","commit":"84f0f4454d56434690eb82d0c3a2118db5810c04"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.6,"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"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-14T19:18:15.637Z","repository_id":97570777,"created_at":"2025-08-14T19:18:15.637Z","updated_at":"2025-08-14T19:18:15.637Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":280930506,"owners_count":26415552,"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-10-25T02:00:06.499Z","response_time":81,"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":"2025-01-28T05:18:04.194Z","updated_at":"2025-10-25T09:08:34.100Z","avatar_url":"https://github.com/CodingItWrong.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# vuex-jsonapi\n\n*`vuex-jsonapi` has been renamed to [`@reststate/vuex`](https://vuex.reststate.codingitwrong.com) and all future development will happen there. Check it out!*\n\n`vuex-jsonapi`, unsurprisingly, allows you to access data from a [JSON API](http://jsonapi.org/) web service via [Vuex](https://vuex.vuejs.org/) stores. Because of JSON API's strong conventions, in most cases all you should need to do is tell `vuex-jsonapi` the base URL of your web service, and which resources to access, and you should be set. No manual web request juggling!\n\nThis is a very early proof-of-concept, so THERE IS NO ERROR HANDLING YET, and many features of JSON API are not yet supported. Open a GitHub issue with any other features you'd like to see!\n\n## Installation\n\n```\n# npm install --save vuex-jsonapi\n```\n\n## Setup\n\nTo create a Vuex module corresponding to a resource on the server, call `resourceModule()`:\n\n```javascript\nimport { Store } from 'vuex';\nimport { resourceModule } from 'vuex-jsonapi';\nimport api from './api';\n\nconst store = new Store({\n  modules: {\n    'widgets': resourceModule({\n      name: 'widgets',\n      httpClient: api,\n    }),\n  },\n});\n```\n\nIf you are accessing multiple resources, you can use `mapResourceModules()`:\n\n```javascript\nimport { Store } from 'vuex';\nimport { mapResourceModules } from 'vuex-jsonapi';\nimport api from './api';\n\nconst store = new Store({\n  modules: {\n    ...mapResourceModules({\n      names: [\n        'widgets',\n        'purchases',\n      ],\n      httpClient: api,\n    }),\n  },\n});\n```\n\nThe `httpClient` accepts an object with a signature similar to the popular [Axios](https://github.com/axios/axios) HTTP client directory. You can either pass in an Axios client configured with your base URL and headers. Note that spec-compliant servers will require a `Content-Type` header of `application/vnd.api+json`; you will need to configure your HTTP client to send that.\n\n```javascript\nimport axios from 'axios';\n\nconst httpClient = axios.create({\n  baseURL: 'http://api.example.com/',\n  headers: {\n    'Content-Type': 'application/vnd.api+json',\n    'Authentication': `Bearer ${token}`,\n  },\n});\n\nconst module = resourceModule({\n  name: 'widgets',\n  httpClient,\n});\n```\n\nOr else you can pass in an object that exposes the following methods:\n\n```javascript\nconst httpClient = {\n  get(path) {\n    // ...\n  },\n  post(path, body) {\n    // ...\n  },\n  patch(path, body) {\n    // ...\n  },\n  delete(path, body) {\n    // ...\n  },\n};\n```\n\nThat's all you need to do--the JSON API spec takes care of the rest!\n\n## Usage\n\nWorking with JSON API data is split into two parts to follow Vuex conventions:\n\n- **Actions** are used to request data from the server or update data on the server, storing the results into the module's state.\n- **Getters** are used to access data from the module's state.\n\n### loadAll action / all getter\n\nSo, for example, to retrieve all of the records for a resource, dispatch the `loadAll` action to save them into the store. They can then be accessed using `all` getter:\n\n```javascript\nthis.$store.dispatch('widgets/loadAll')\n  .then(() =\u003e {\n    const widgets = this.$store.getters['widgets/all'];\n    console.log(widgets);\n  });\n```\n\nIf you're accessing these from within a Vue component, you can use Vuex's `mapActions` and `mapGetters` as usual:\n\n```javascript\nimport { mapActions, mapGetters } from 'vuex';\n\nexport default {\n  // ...\n  methods: {\n    ...mapActions({\n      loadWidgets: 'widgets/loadAll',\n    }),\n  },\n  computed: {\n    ...mapGetters({\n      widgets: 'widgets/all',\n    }),\n  },\n  // ...\n};\n```\n\n### loadById action / byId getter\n\nTo retrieve a single record by ID, dispatch the `loadById` action, then access the `byId` getter:\n\n```javascript\nthis.$store.dispatch('widgets/loadById', { id: 42 })\n  .then(() =\u003e {\n    const widget = this.$store.getters['widgets/byId']({ id: 42 });\n    console.log(widget);\n  });\n```\n\nHowever, the beauty of storing your data in Vuex is that if you know the record has already been retrieved, you don't need to load it again. For example, if you've loaded all records on a list screen, and then you click to view the details for a single record, you can just use the getter directly:\n\n```javascript\nconst widget = this.$store.getters['widgets/byId']({ id: 42 });\nconsole.log(widget);\n```\n\n### loadWhere action / where getter\n\nTo filter/query for records based on certain criteria, use the `loadWhere` action, passing it an object of filter keys and values to send to the server, then pass those same filters to the `where` getter:\n\n```js\nconst filter = {\n  category: 'whizbang',\n};\nthis.$store.dispatch('widgets/loadWhere', { filter });\n  .then(() =\u003e {\n    const widgets = this.$store.getters['widgets/where']({ filter });\n    console.log(widgets);\n  });\n```\n\nThis doesn’t perform any filtering logic on the client side; it simply keeps track of which IDs were returned by the server side request and retrieves those records.\n\n### loadRelated action / related getter\n\nFinally, to load records related via JSON API relationships, use the `loadRelated` action. A nested resource URL is constructed like `categories/27/widgets`. (In the future we will look into using HATEOAS to let the server tell us the relationship URL).\n\n```javascript\nconst parent = {\n  type: 'category',\n  id: 27,\n};\n\nthis.$store.dispatch('widgets/loadRelated', { parent })\n  .then(() =\u003e {\n    const widgets = this.$store.getters['widgets/related']({ parent });\n    console.log(widgets);\n  });\n```\n\nBy default, the name of the relationship on `parent` is assumed to be the same as the name of the other model: in this case, `widgets`. In cases where the names are not the same, you can explicitly pass the relationship name:\n\n```js\nconst parent = {\n  type: 'categories',\n  id: 27,\n};\n\nconst relationship = 'purchased-widgets';\n\nthis.$store.dispatch('widgets/loadRelated', { parent, relationship })\n  .then(() =\u003e {\n    const widgets = this.$store.getters['widgets/related']({ parent, relationship });\n    console.log(widgets);\n  });\n```\n\n### create\n\nTo create records on the server and also store it locally, use the `create` action. Pass it an object containing an `attributes` object. This is similar to a JSON API record, but you don't need to specify the type -- the store will add the type.\n\n```javascript\nconst recordData = {\n  attributes: {\n    title: 'My Widget',\n  },\n};\nthis.$store.dispatch('widgets/create', recordData);\n```\n\nYou can also save relationships by providing a `relationships` attribute, just like in the JSON API spec:\n\n```javascript\nconst recordData = {\n  attributes: {\n    title: 'My Widget',\n  },\n  relationships: {\n    category: {\n      data: {\n        type: 'categories',\n        id: 42,\n      },\n    },\n  },\n};\nthis.$store.dispatch('widgets/create', recordData);\n```\n\n### update\n\nTo update records, pass the entire updated record object to the `update` action:\n\n```javascript\nconst widget = this.$store.getters['widgets/byId']({ id: 42 });\nwidget.attributes.title = 'Updated Title';\nthis.$store.dispatch('widgets/update', widget);\n```\n\n### delete\n\nTo delete, pass either a full record or just an object with an ID field:\n\n```javascript\nconst widgetIdObject = { id: 42 };\nthis.$store.dispatch('widgets/delete', widgetIdObject);\n```\n\n## License\n\nApache 2.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodingitwrong%2Fvuex-jsonapi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodingitwrong%2Fvuex-jsonapi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodingitwrong%2Fvuex-jsonapi/lists"}