{"id":13555846,"url":"https://github.com/pouchdb-community/ember-pouch","last_synced_at":"2025-12-12T04:04:16.891Z","repository":{"id":19790041,"uuid":"23049298","full_name":"pouchdb-community/ember-pouch","owner":"pouchdb-community","description":"PouchDB/CouchDB adapter for Ember Data","archived":false,"fork":false,"pushed_at":"2023-02-02T02:44:46.000Z","size":556,"stargazers_count":280,"open_issues_count":47,"forks_count":76,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-09-18T22:36:42.369Z","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":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pouchdb-community.png","metadata":{"files":{"readme":"README.md","changelog":null,"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-08-17T20:06:55.000Z","updated_at":"2025-03-06T08:28:13.000Z","dependencies_parsed_at":"2023-02-17T13:31:15.457Z","dependency_job_id":null,"html_url":"https://github.com/pouchdb-community/ember-pouch","commit_stats":null,"previous_names":["nolanlawson/ember-pouch"],"tags_count":60,"template":false,"template_full_name":null,"purl":"pkg:github/pouchdb-community/ember-pouch","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pouchdb-community%2Fember-pouch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pouchdb-community%2Fember-pouch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pouchdb-community%2Fember-pouch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pouchdb-community%2Fember-pouch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pouchdb-community","download_url":"https://codeload.github.com/pouchdb-community/ember-pouch/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pouchdb-community%2Fember-pouch/sbom","scorecard":{"id":693420,"data":{"date":"2025-08-11","repo":{"name":"github.com/pouchdb-community/ember-pouch","commit":"0b7ebc6ee2dc45534acb38e1b5afc29bb11b125e"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.8,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","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":"Code-Review","score":3,"reason":"Found 5/13 approved changesets -- score normalized to 3","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":"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":"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":"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":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/node.js.yml:1","Info: no jobLevel write permissions found"],"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":"Pinned-Dependencies","score":1,"reason":"dependency not pinned by hash detected -- score normalized to 1","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/node.js.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/pouchdb-community/ember-pouch/node.js.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/node.js.yml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/pouchdb-community/ember-pouch/node.js.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/node.js.yml:47: update your workflow using https://app.stepsecurity.io/secureworkflow/pouchdb-community/ember-pouch/node.js.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/node.js.yml:48: update your workflow using https://app.stepsecurity.io/secureworkflow/pouchdb-community/ember-pouch/node.js.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/node.js.yml:78: update your workflow using https://app.stepsecurity.io/secureworkflow/pouchdb-community/ember-pouch/node.js.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/node.js.yml:80: update your workflow using https://app.stepsecurity.io/secureworkflow/pouchdb-community/ember-pouch/node.js.yml/master?enable=pin","Warn: npmCommand not pinned by hash: .github/workflows/node.js.yml:35","Warn: npmCommand not pinned by hash: .github/workflows/node.js.yml:54","Warn: npmCommand not pinned by hash: .github/workflows/node.js.yml:91","Info:   0 out of   6 GitHub-owned GitHubAction dependencies pinned","Info:   2 out of   5 npmCommand dependencies pinned"],"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":"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.md:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE.md:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"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":"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"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 22 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-22T02:53:55.915Z","repository_id":19790041,"created_at":"2025-08-22T02:53:55.915Z","updated_at":"2025-08-22T02:53:55.915Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":280431153,"owners_count":26329780,"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-22T02:00:06.515Z","response_time":63,"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-08-01T12:03:27.272Z","updated_at":"2025-10-22T11:41:30.235Z","avatar_url":"https://github.com/pouchdb-community.png","language":"JavaScript","funding_links":[],"categories":["JavaScript","Packages","others"],"sub_categories":["Adapters"],"readme":"# Ember Pouch [![Build Status](https://travis-ci.org/pouchdb-community/ember-pouch.svg)](https://travis-ci.org/pouchdb-community/ember-pouch) [![GitHub version](https://badge.fury.io/gh/pouchdb-community%2Fember-pouch.svg)](https://badge.fury.io/gh/pouchdb-community%2Fember-pouch) [![Ember Observer Score](https://emberobserver.com/badges/ember-pouch.svg)](https://emberobserver.com/addons/ember-pouch)\n\n-  [**Changelog**](#changelog)\n-  [**Upgrading**](#upgrading)\n\nEmber Pouch is a PouchDB/CouchDB adapter for Ember Data 3.16+. For older Ember Data versions down to 2.0+ use Ember Pouch version 7.0 For Ember Data versions lower than 2.0+ use Ember Pouch version 3.2.2.\n\nWith Ember Pouch, all of your app's data is automatically saved on the client-side using IndexedDB or WebSQL, and you just keep using the regular [Ember Data `store` API](http://emberjs.com/api/data/classes/DS.Store.html#method_all). This data may be automatically synced to a remote CouchDB (or compatible servers) using PouchDB replication.\n\nWhat's the point?\n\n1. You don't need to write any server-side logic. Just use CouchDB.\n\n2. Data syncs automatically.\n\n3. Your app works offline, and requests are super fast, because they don't need the network.\n\nFor more on PouchDB, check out [pouchdb.com](http://pouchdb.com).\n\n## Install and setup\n\n```bash\nember install ember-pouch\n```\n\nFor ember-data \u003c 2.0:\n\n```bash\nember install ember-pouch@3.2.2\n```\n\nFor ember-cli \u003c 1.13.0:\n\n```bash\nnpm install ember-pouch@3.2.2 --save-dev\n```\n\nThis provides\n\n- `import {Model, Adapter, Serializer} from 'ember-pouch'`\n\n`Ember-Pouch` requires you to add a `@attr('string') rev` field to all your models. This is for PouchDB/CouchDB to handle revisions:\n\n```javascript\n// app/models/todo.js\n\nimport Model, { attr } from '@ember-data/model';\n\nexport default class TodoModel extends Model {\n  @attr('string') title;\n  @attr('boolean') isCompleted;\n  @attr('string') rev; // \u003c-- Add this to all your models\n}\n```\n\nIf you like, you can also use `Model` from `Ember-Pouch` that ships with the `rev` attribute:\n\n```javascript\n// app/models/todo.js\n\nimport { attr } from '@ember-data/model';\nimport { Model } from 'ember-pouch';\n\nexport default class TodoModel extends Model {\n  @attr('string') title;\n  @attr('boolean') isCompleted;\n}\n```\n\nThe installation creates a file `adapters/application.js` that you can use by default to setup the database connection. Look at the [Adapter blueprint](#adapter) section to see the settings that you have to set in your config file to work with this adapter.  \nIt also installs the required packages.\n\n## Configuring /app/adapters/application.js\n\nA local PouchDB that syncs with a remote CouchDB looks like this:\n\n```javascript\n// app/adapters/application.js\n\nimport PouchDB from 'ember-pouch/pouchdb';\nimport { Adapter } from 'ember-pouch';\n\nlet remote = new PouchDB('http://localhost:5984/my_couch');\nlet db = new PouchDB('local_pouch');\n\ndb.sync(remote, {\n  live: true, // do a live, ongoing sync\n  retry: true, // retry if the connection is lost\n});\n\nexport default class ApplicationAdapter extends Adapter {\n  db = db;\n}\n```\n\nYou can also turn on debugging:\n\n```javascript\nimport PouchDB from 'ember-pouch/pouchdb';\n\n// For v7.0.0 and newer you must first load the 'pouchdb-debug' plugin\n// see https://github.com/pouchdb/pouchdb/tree/39ac9a7a1f582cf7a8d91c6bf9caa936632283a6/packages/node_modules/pouchdb-debug\nimport pouchDebugPlugin from 'pouchdb-debug'; // (assumed available via ember-auto-import or shim)\nPouchDB.plugin(pouchDebugPlugin);\n\nPouchDB.debug.enable('*');\n```\n\nSee the [PouchDB sync API](http://pouchdb.com/api.html#sync) for full usage instructions.\n\n## EmberPouch Blueprints\n\n### Model\n\nIn order to create a model run the following command from the command line:\n\n```\nember g pouch-model \u003cmodel-name\u003e\n```\n\nReplace `\u003cmodel-name\u003e` with the name of your model and the file will automatically be generated for you.\n\n### Adapter\n\nYou can now create an adapter using ember-cli's blueprint functionality. Once you've installed `ember-pouch` into your ember-cli app you can run the following command to automatically generate an adapter.\n\n```\nember g pouch-adapter foo\n```\n\nNow you can store your localDb and remoteDb names in your ember-cli's config. Just add the following keys to the `ENV` object:\n\n```javascript\nENV.emberPouch.localDb = 'test';\nENV.emberPouch.remoteDb = 'http://localhost:5984/my_couch';\n```\n\nThis blueprint is run on installation for the `application` adapter.\n\nYou can use multiple adapters, but be warned that doing the `.plugin` calls in multiple adapter files will result in errors: `TypeError: Cannot redefine property: replicate`. In this case it is better to move the `PouchDB.plugin` calls to a separate file.\n\n## Relationships\n\nEmberPouch supports both `hasMany` and `belongsTo` relationships.\n\n### Don't save hasMany child ids\n\nTo be more in line with the normal ember data way of saving `hasMany` - `belongsTo` relationships, ember-pouch now has an option to not save the child ids on the `hasMany` side. This prevents the extra need to save the `hasMany` side as explained below. For a more detailed explanation please read the [relational-pouch documentation](https://github.com/pouchdb-community/relational-pouch#dont-save-hasmany)\n\nThis new mode can be disabled for a `hasMany` relationship by specifying the option `save: true` on the relationship. An application wide setting named `ENV.emberPouch.saveHasMany` can also be set to `true` to make all `hasMany` relationships behave the old way.\n\nUsing this mode does impose a slight runtime overhead, since this will use `db.find` and database indexes to search for the child ids. The indexes are created automatically for you. But large changes to the model might require you to clean up old, unused indexes.\n\nℹ️ This mode is the default from version 5 onwards. Before that it was called `dontsave` and `dontsavehasmany`\n\n### Saving child ids\n\nWhen you do save child ids on the `hasMany` side, you have to follow the directions below to make sure the data is saved correctly.\n\n#### Adding entries\n\nWhen saving a `hasMany` - `belongsTo` relationship, both sides of the relationship (the child and the parent) must be saved. Note that the parent needs to have been saved at least once prior to adding children to it.\n\n```javascript\n// app/controllers/posts/post.js\nimport Controller from '@ember/controller';\nimport { action } from '@ember/object';\n\nexport default class PostController extends Controller {\n  @action addComment(comment, author) {\n    //Create the comment\n    const comment = this.store.createRecord('comment', {\n      comment: comment,\n      author: author,\n    });\n    //Add our comment to our existing post\n    this.model.comments.pushObject(comment);\n    //Save the child then the parent\n    comment.save().then(() =\u003e this.model.save());\n  }\n}\n```\n\n#### Removing child ids\n\nWhen removing a `hasMany` - `belongsTo` relationship, the children must be removed prior to the parent being removed.\n\n```javascript\n// app/controller/posts/admin.js\nimport Controller from '@ember/controller';\nimport { action } from '@ember/object';\nimport { all } from 'rsvp';\n\nexport default class AdminController extends Controller {\n  @action deletePost(post) {\n    //collect the promises for deletion\n    let deletedComments = [];\n    //get and destroy the posts comments\n    post.comments.then((comments) =\u003e {\n      comments.map((comment) =\u003e {\n        deletedComments.push(comment.destroyRecord());\n      });\n    });\n    //Wait for comments to be destroyed then destroy the post\n    all(deletedComments).then(() =\u003e {\n      post.destroyRecord();\n    });\n  }\n}\n```\n\n### Query and QueryRecord\n\nquery and queryRecord are relying on [pouchdb-find](https://github.com/pouchdb/pouchdb/tree/master/packages/node_modules/pouchdb-find)\n\n### db.createIndex(index [, callback])\n\nCreate an index if it doesn't exist.\n\n```javascript\n// app/adapters/application.js\nfunction createDb() {\n  ...\n\n  db.createIndex({\n    index: {\n      fields: ['data.name']\n    }\n  }).then((result) =\u003e {\n    // {'result': 'created'} index was created\n  });\n\n  return db;\n};\n```\n\n### store.query(model, options)\n\nFind all docs where doc.name === 'Mario'\n\n```javascript\n// app/routes/smasher.js\nimport Route from '@ember/routing/route';\n\nexport default class SmasherRoute extends Route {\n  model() {\n    return this.store.query('smasher', {\n      filter: { name: 'Mario' },\n    });\n  }\n}\n```\n\nFind all docs where doc.name === 'Mario' and doc.debut \u003e 1990:\n\n```javascript\n// app/routes/smasher.js\nimport Route from '@ember/routing/route';\n\nexport default class SmasherRoute extends Route {\n  model() {\n    return this.store.query('smasher',  {\n      filter: {\n        name: 'Mario'\n        debut: { $gt: 1990 }\n      }\n    });\n  }\n}\n```\n\nSorted by doc.debut descending.\n\n```javascript\n// app/routes/smasher.js\nimport Route from '@ember/routing/route';\n\nexport default class SmasherRoute extends Route {\n  model() {\n    return this.store.query('smasher', {\n      filter: {\n        name: 'Mario',\n        debut: { $gte: null },\n      },\n      sort: [{ debut: 'desc' }],\n    });\n  }\n}\n```\n\nLimit to 5 documents.\n\n```javascript\n// app/routes/smasher.js\nimport Route from '@ember/routing/route';\n\nexport default class SmasherRoute extends Route {\n  model() {\n    return this.store.query('smasher', {\n      filter: {\n        name: 'Mario',\n        debut: { $gte: null },\n      },\n      sort: [{ debut: 'desc' }],\n      limit: 5,\n    });\n  }\n}\n```\n\nSkip the first 5 documents\n\n```javascript\n// app/routes/smasher.js\nimport Route from '@ember/routing/route';\n\nexport default class SmasherRoute extends Route {\n  model() {\n    return this.store.query('smasher', {\n      filter: {\n        name: 'Mario',\n        debut: { $gte: null },\n      },\n      sort: [{ debut: 'desc' }],\n      skip: 5,\n    });\n  }\n}\n```\n\nNote that this query would require a custom index including both fields `data.name` and `data.debut`. Any field in `sort` must also be included in `filter`. Only `$eq`, `$gt`, `$gte`, `$lt`, and `$lte` can be used when matching a custom index.\n\n### store.queryRecord(model, options)\n\nFind one document where doc.name === 'Mario'\n\n```javascript\n// app/routes/smasher.js\nimport Route from '@ember/routing/route';\n\nexport default class SmasherRoute extends Route {\n  model() {\n    return this.store.queryRecord('smasher', {\n      filter: { name: 'Mario' },\n    });\n  }\n}\n```\n\n## Attachments\n\n`Ember-Pouch` provides an `attachments` transform for your models, which makes working with attachments as simple as working with any other field.\n\nAdd a `DS.attr('attachments')` field to your model. Provide a default value for it to be an empty array.\n\n```javascript\n// myapp/models/photo-album.js\nimport { attr } from '@ember-data/model';\nimport { Model } from 'ember-pouch';\n\nexport default class PhotoAlbumModel extends Model {\n  @attr('attachments', {\n    defaultValue: function () {\n      return [];\n    },\n  })\n  photos;\n}\n```\n\nHere, instances of `PhotoAlbum` have a `photos` field, which is an array of plain `Ember.Object`s, which have a `.name` and `.content_type`. Non-stubbed attachment also have a `.data` field; and stubbed attachments have a `.stub` instead.\n\n```handlebars\n\u003cul\u003e\n  {{#each myalbum.photos as |photo|}}\n    \u003cli\u003e{{photo.name}}\u003c/li\u003e\n  {{/each}}\n\u003c/ul\u003e\n```\n\nAttach new files by adding an `Ember.Object` with a `.name`, `.content_type` and `.data` to array of attachments.\n\n```javascript\n// somewhere in your controller/component:\nmyAlbum.photos.addObject(\n  Ember.Object.create({\n    name: 'kitten.jpg',\n    content_type: 'image/jpg',\n    data: btoa('hello world'), // base64-encoded `String`, or a DOM `Blob`, or a `File`\n  })\n);\n```\n\n## Sample app\n\nTom Dale's blog example using Ember CLI and EmberPouch: [broerse/ember-cli-blog](https://github.com/broerse/ember-cli-blog)\n\n## Notes\n\n### LocalStorage\n\nCurrently PouchDB doesn't use LocalStorage unless you include an experimental plugin. Amazingly, this is only necessary to support IE ≤ 9.0 and Opera Mini. It's recommended you read more about this, what storage mechanisms modern browsers now support, and using SQLite in Cordova on [the PouchDB adapters page](http://pouchdb.com/adapters.html).\n\n### CouchDB\n\nFrom day one, CouchDB and its protocol have been designed to be always **A**vailable and handle **P**artitioning over the network well (AP in the CAP theorem). PouchDB/CouchDB gives you a solid way to manage conflicts. It is \"eventually consistent,\" but CouchDB has an API for listening to changes to the database, which can be then pushed down to the client in real-time.\n\nTo learn more about how CouchDB sync works, check out [the PouchDB guide to replication](http://pouchdb.com/guides/replication.html).\n\n### Sync and the ember-data store\n\nOut of the box, ember-pouch includes a PouchDB [change listener](http://pouchdb.com/guides/changes.html) that automatically updates any records your app has loaded when they change due to a sync. It also unloads records that are removed due to a sync.\n\nHowever, ember-pouch does not automatically load new records that arrive during a sync. The records are saved in the local database, but **ember-data is not told to load them into memory**. Automatically loading every new record works well with a small number of records and a limited number of models. As an app grows, automatically loading every record will negatively impact app responsiveness during syncs (especially the first sync). To avoid puzzling slowdowns, ember-pouch only automatically reloads records you have already used ember-data to load.\n\nIf you have a model or two that you know will always have a small number of records, you can tell ember-data to automatically load them into memory as they arrive. Your PouchAdapter subclass has a method `unloadedDocumentChanged`, which is called when a document is received during sync that has not been loaded into the ember-data store. In your subclass, you can implement the following to load it automatically:\n\n```javascript\n  unloadedDocumentChanged: function(obj) {\n    let recordTypeName = this.getRecordTypeName(this.store.modelFor(obj.type));\n    this.db.rel.find(recordTypeName, obj.id).then((doc) =\u003e {\n      this.store.pushPayload(recordTypeName, doc);\n    });\n  },\n```\n\n### Plugins\n\nWith PouchDB, you also get access to a whole host of [PouchDB plugins](http://pouchdb.com/external.html).\n\nFor example, to use the `pouchdb-authentication` plugin like this using `ember-auto-import`:\n\n```javascript\nimport PouchDB from 'ember-pouch/pouchdb';\nimport auth from 'pouchdb-authentication';\n\nPouchDB.plugin(auth);\n```\n\n### Relational Pouch\n\nEmber Pouch is really just a thin layer of Ember-y goodness over [Relational Pouch](https://github.com/pouchdb-community/relational-pouch). Before you file an issue, check to see if it's more appropriate to file over there.\n\n### Offline First\n\nSaving data locally using PouchDB is one part of making a web application [Offline First](http://offlinefirst.org/). However, you will also need to make your static assets available offline.\n\nThere are two possible approaches to this. The first one is using the Application Cache (AP) feature. The second one is using Service Workers (SW). The Application Cache specification has been [removed from the Web standards](https://developer.mozilla.org/en-US/docs/Web/HTML/Using_the_application_cache). Mozilla now recommends to use [Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers) instead.\n\nMost browser vendors still provide support for Application Cache and are in the process of implementing Service Workers. So depending on the browsers you target, you should go for one or the other. You can track the progress via [caniuse.com](https://caniuse.com/#feat=serviceworkers).\n\n#### 1. Application Cache\n\nYou can use [broccoli-manifest](https://github.com/racido/broccoli-manifest) to create an HTML5 `appcache.manifest` file. This By default, will allow your index.html and `assets` directory to load even if the user is offline.\n\n#### 2. Service Workers\n\nWe recommend using [Ember Service Worker](http://ember-service-worker.com) to get started with Service Workers for your web application. The website provide's an easy to follow guide on getting started with the addon.\n\nYou can also take a look at Martin Broerse his [ember-cli-blog](https://github.com/broerse/ember-cli-blog/blob/14b95b443b851afa3632be3cbe631f055664b340/ember-cli-build.js) configuration for the plugin.\n\n⚠️ iOS does not yet support Service Workers. If you want to make your assets available offline for an iPhone or iPad, you have to go for the Application Cache strategy. Since Jan 10, 2018, [Safari Technology Preview does support Service Workers](https://webkit.org/blog/8060/release-notes-for-safari-technology-preview-47/). It's expected to land in iOS 12, but there's no certainity about that.\n\n### Security\n\nAn easy way to secure your Ember Pouch-using app is to ensure that data can only be fetched from CouchDB \u0026ndash; not from some other server (e.g. in an [XSS attack](https://en.wikipedia.org/wiki/Cross-site_scripting)).\n\nYou can use the [content-security-policy](https://github.com/rwjblue/ember-cli-content-security-policy) plugin to enable Content Security Policy in Ember CLI. You also will have to set the CSP HTTP header on your backend in production.\n\nTo use, add a Content Security Policy whitelist entry to `/config/environment.js`:\n\n```js\nENV.contentSecurityPolicy = {\n  'connect-src': \"'self' http://your_couch_host.com:5984\",\n};\n```\n\n### CORS setup (important!)\n\nTo automatically set up your remote CouchDB to use CORS, you can use the plugin [add-cors-to-couchdb](https://github.com/pouchdb/add-cors-to-couchdb):\n\n```\nnpm install -g add-cors-to-couchdb\nadd-cors-to-couchdb http://your_couch_host.com:5984 -u your_username -p your_password\n```\n\n### Multiple models for the same data\n\nEmber-data can be slow to load large numbers of records which have lots of relationships. If you run into this problem, you can define multiple models and have them all point to the same set of records by defining `documentType` on the model class. Example (in an ember-cli app):\n\n```javascript\n// app/models/post.js\n\nimport { attr, belongsTo, hasMany } from '@ember-data/model';\nimport { Model } from 'ember-pouch';\n\nexport default class PostModel extends Model {\n  @attr('string') title;\n  @attr('string') text;\n\n  @belongsTo('author') author;\n  @hasMany('comments') comments;\n}\n\n// app/models/post-summary.js\n\nimport { attr } from '@ember-data/model';\nimport { Model } from 'ember-pouch';\n\nexport default class PostSummaryModel extends Model {\n  @attr('string') title;\n}\n\nPostSummary.reopenClass({\n  documentType: 'post'\n})\n\nexport default PostSummary;\n```\n\nThe value for `documentType` is the camelCase version of the primary model name.\n\nFor best results, only create/update records using the full model definition. Treat the others as read-only.\n\n## Multiple databases for the same model\n\nIn some cases it might be desirable (security related, where you want a given user to only have some informations stored on his computer) to have multiple databases for the same model of data.\n\n`Ember-Pouch` allows you to dynamically change the database a model is using by calling the function `changeDb` on the adapter.\n\n```javascript\nfunction changeProjectDatabase(dbName, dbUser, dbPassword) {\n  // CouchDB is serving at http://localhost:5455\n  let remote = new PouchDB('http://localhost:5455/' + dbName);\n  // here we are using pouchdb-authentication for credential supports\n  remote.login(dbUser, dbPassword).then(function (user) {\n    let db = new PouchDB(dbName);\n    db.sync(remote, { live: true, retry: true });\n    // grab the adapter, it can be any ember-pouch adapter.\n    let adapter = this.store.adapterFor('project');\n    // this is where we told the adapter to change the current database.\n    adapter.changeDb(db);\n  });\n}\n```\n\n## Eventually Consistent\n\nFollowing the CouchDB consistency model, we have introduced `ENV.emberPouch.eventuallyConsistent`. This feature is on by default. So if you want the old behavior you'll have to disable this flag.\n\n`findRecord` now returns a long running Promise if the record is not found. It only rejects the promise if a deletion of the record is found. Otherwise this promise will wait for eternity to resolve.\nThis makes sure that belongsTo relations that have been loaded in an unexpected order will still resolve correctly. This makes sure that ember-data does not set the belongsTo to null if the Pouch replicate would have loaded the related object later on. (This only works for async belongsTo, sync versions will need this to be implemented in relational-pouch)\n\n## Upgrading\n\n### Version 8\n\nVersion 8 introduces the custom PouchDB setup in the adapter instead of having a default setup in `addon/pouchdb.js`. So if you used `import PouchDB from 'ember-pouch/pouchdb'` in your files, you now have to make your own 'PouchDB bundle' in the same way we do it in the default adapter blueprint. The simplest way to do this is to run the blueprint by doing `ember g ember-pouch` (which will overwrite your application adapter, so make sure to commit that file first) and take the `import PouchDB from...` until the final `.plugin(...)` line and put that into your original adapter (or a separate file if you use more than one adapter).\nYou can also copy the lines from [the blueprint file in git](https://github.com/pouchdb-community/ember-pouch/blob/master/blueprints/pouch-adapter/files/__root__/adapters/__name__.js)\n\nWe also removed the pouchdb-browser package and relational-pouch as a package.json dependency, so you will have to install the packages since the lines above depend upon.  \n`npm install pouchdb-core pouchdb-adapter-indexeddb pouchdb-adapter-http pouchdb-mapreduce pouchdb-replication pouchdb-find relational-pouch --save-dev`\n\nThis way you can now decide for yourself which PouchDB plugins you want to use. You can even remove the http or indexeddb ones if you just want to work offline or online.\n\n## Installation\n\n- `git clone` this repository\n- `npm install`\n\n## Running\n\n- `ember server`\n- Visit your app at http://localhost:4200.\n\n## Running Tests\n\n- `ember test`\n- `ember test --server`\n\n## Building\n\n- `ember build`\n\nFor more information on using ember-cli, visit [http://www.ember-cli.com/](http://www.ember-cli.com/).\n\n## Credits\n\nThis project was originally based on the [ember-data-hal-adapter](https://github.com/locks/ember-data-hal-adapter) by [@locks](https://github.com/locks), and I really benefited from his guidance during its creation.\n\nAnd of course thanks to all our wonderful contributors, [here](https://github.com/pouchdb-community/ember-pouch/graphs/contributors) and [in Relational Pouch](https://github.com/pouchdb-community/relational-pouch/graphs/contributors)!\n\n## Changelog\n- **8.0.0-beta.2**\n  - Set PouchDb indexeddb adapter as default instead of idb adapter to use native views\n  - Generate adapters/application.js at installation\n  - move package.json dependencies to default blueprint\n  - removed Adapter `fixDeleteBug` flag. We now do a client side `destroyRecord` with custom `adapterOptions` to signal to the ember-data store that the record is deleted. So no more hacking ember-data is needed in the addon to support the server pushed deletes.\n- **8.0.0-beta.1**\n  - Updated to support latest Ember 4.x (fixed isDeleted issues)\n  - Switch to PouchDB 7.3.0. Getting ready to use the indexeddb-adapter\n  - Embroider safe and compatible scenarios supported. Ember Pouch works fine with Ember 4.x projects.\n  - Update application adapter example to use class property #262\n  - Fix Adapter Blueprint for Ember Octane #257\n- **7.0.0**\n  - Use ember-auto-import and pouchdb-browser to ease the installation process\n  - relational-pouch@4.0.0\n  - Use Octane Blueprints\n- **6.0.0**\n  - Switch to PouchDB 7.0.0\n- **5.1.0**\n  - Don't unloadRecord a deleted document in onChange, only mark as deleted. This fixes some bugs with hasMany arrays corrupting in newer ember-data versions. Not unloading records also seems safer for routes that have that model active.\n- **5.0.1**\n  - Adapter `fixDeleteBug` flag. Defaults to `true`. Fixes [https://github.com/emberjs/data/issues/4963](https://github.com/emberjs/data/issues/4963) and related issues that don't seem to work well with server side delete notifications.\n  - Track newly inserted records, so `unloadedDocumentChanged` is not called for those. Otherwise a race-condition can occur where onChange is faster than the save. This can result in the document being inserted in the store via `unloadedDocumentChanged` before the save returns to ember-data. This will result in an assert that the id is already present in the store.\n- **5.0.0**\n  - Add warning for old `dontsavehasmany` use [#216](https://github.com/pouchdb-community/ember-pouch/pull/216)\n  - forcing the default serializer [#215](https://github.com/pouchdb-community/ember-pouch/pull/215)\n  - test + flag + doc for eventually-consistent [#214](https://github.com/pouchdb-community/ember-pouch/pull/214)\n  - config changes [#213](https://github.com/pouchdb-community/ember-pouch/pull/213)\n  - Update pouchdb to version 6.4.2 [#211](https://github.com/pouchdb-community/ember-pouch/pull/211)\n- **5.0.0-beta.6**\n  - Add register-version.js to vendor/ember-pouch [#210](https://github.com/pouchdb-community/ember-pouch/pull/210)\n  - Update documentation about Offline First [#209](https://github.com/pouchdb-community/ember-pouch/pull/209)\n- **5.0.0-beta.5**\n  - Add pouchdb.find.js from pouchdb [#208](https://github.com/pouchdb-community/ember-pouch/pull/208)\n  - createIndex promises should be done before removing [#208](https://github.com/pouchdb-community/ember-pouch/pull/208)\n  - Change sudo to required (see travis-ci/travis-ci#8836) [#208](https://github.com/pouchdb-community/ember-pouch/pull/208)\n  - Ignore same revision changes [#189](https://github.com/pouchdb-community/ember-pouch/pull/189)\n- **5.0.0-beta.4**\n  - Resolve Ember.String.pluralize() deprecation [#206](https://github.com/pouchdb-community/ember-pouch/pull/206)\n  - allow usage of skip parameter in pouchdb adapter queries [#198](https://github.com/pouchdb-community/ember-pouch/pull/198)\n- **5.0.0-beta.3**\n  - Fix Ember Data canary ember-try scenario [#202](https://github.com/pouchdb-community/ember-pouch/pull/202)\n  - Restore ember-try configuration for Ember Data [#201](https://github.com/pouchdb-community/ember-pouch/pull/201)\n  - Fix some jobs on Travis Trusty [#187](https://github.com/pouchdb-community/ember-pouch/pull/187)\n  - clean up db changes listener [#195](https://github.com/pouchdb-community/ember-pouch/pull/195)\n  - filter results of pouch adapter query by correct type [#194](https://github.com/pouchdb-community/ember-pouch/pull/194)\n  - allow usage of limit parameter in pouchdb adapter queries [#193](https://github.com/pouchdb-community/ember-pouch/pull/193)\n- **5.0.0-beta.2**\n  - version fix [#196](https://github.com/pouchdb-community/ember-pouch/pull/196)\n- **5.0.0-beta.1**\n  - Eventually consistency added: documents that are not in the database will result in an 'eternal' promise. This promise will only resolve when an entry for that document is found. Deleted documents will also satisfy this promise. This mirrors the way that couchdb replication works, because the changes might not come in the order that ember-data expects. Foreign keys might therefor point to documents that have not been loaded yet. Ember-data normally resets these to null, but keeping the promise in a loading state will keep the relations intact until the actual data is loaded.\n- **4.3.0**\n  - Bundle pouchdb-find [#191](https://github.com/pouchdb-community/ember-pouch/pull/191)\n- **4.2.9**\n  - Lock relational-pouch version until pouchdb-find bugs are solved\n- **4.2.8**\n  - Update Ember CLI and PouchDB [#186](https://github.com/pouchdb-community/ember-pouch/pull/186)\n- **4.2.7**\n  - Fix `_shouldSerializeHasMany` deprecation [#185](https://github.com/pouchdb-community/ember-pouch/pull/185)\n- **4.2.6**\n  - Fixes queryRecord deprecation [#152](https://github.com/pouchdb-community/ember-pouch/pull/152)\n  - Change links to `pouchdb-community`\n  - Use npm for ember-source [#183](https://github.com/pouchdb-community/ember-pouch/pull/183)\n- **4.2.5**\n  - Correct Security documentation [#177](https://github.com/pouchdb-community/ember-pouch/pull/177)\n  - Fix sort documentation and add additional notes [#176](https://github.com/pouchdb-community/ember-pouch/pull/176)\n  - update ember-getowner-polyfill to remove deprecation warnings [#174](https://github.com/pouchdb-community/ember-pouch/pull/174)\n- **4.2.4**\n  - Fix attachments typo in README [#170](https://github.com/pouchdb-community/ember-pouch/pull/170)\n- **4.2.3**\n  - Update pouchdb to the latest version\n  - Minor typofix [#166](https://github.com/pouchdb-community/ember-pouch/pull/166)\n- **4.2.2**\n  - Update pouchdb to the latest version\n- **4.2.1**\n  - Fix `Init` some more\n  - Fix `Init` `_super.Init` error\n- **4.2.0**\n  - Switch to npm versions\n- **4.1.0**\n  - async is now true when not specified for relationships\n  - hasMany relationship can have option dontsave\n- **4.0.3**\n  - Fixes [#158](https://github.com/pouchdb-community/ember-pouch/pull/158)\n- **4.0.2**\n  - Updated ember-cli fixes and some minor changes [#147](https://github.com/pouchdb-community/ember-pouch/pull/147)\n  - Added Version badge and Ember Observer badge [#142](https://github.com/pouchdb-community/ember-pouch/pull/142)\n- **4.0.0**\n  - Add support for Attachments [#135](https://github.com/pouchdb-community/ember-pouch/pull/135)\n  - Implement glue code for query and queryRecord using pouchdb-find [#130](https://github.com/pouchdb-community/ember-pouch/pull/130)\n- **3.2.2**\n  - Update Bower dependencies [#137](https://github.com/pouchdb-community/ember-pouch/pull/137)\n  - Correct import of Ember Data model blueprint [#131](https://github.com/pouchdb-community/ember-pouch/pull/131)\n- **3.2.1**\n  - Fix(Addon): Call super in init [#129](https://github.com/pouchdb-community/ember-pouch/pull/129)\n- **3.2.0**\n  - Make adapter call a hook when encountering a change for a record that is not yet loaded [#108](https://github.com/pouchdb-community/ember-pouch/pull/108)\n- **3.1.1**\n  - Bugfix for hasMany relations by [@backspace](https://github.com/backspace) ([#111](https://github.com/pouchdb-community/ember-pouch/pull/111)).\n- **3.1.0**\n  - Database can now be dynamically switched on the adapter ([#89](https://github.com/pouchdb-community/ember-pouch/pull/89)). Thanks to [@olivierchatry](https://github.com/olivierchatry) for this!\n  - Various bugfixes by [@backspace](https://github.com/backspace), [@jkleinsc](https://github.com/jkleinsc), [@rsutphin](https://github.com/rsutphin), [@mattmarcum](https://github.com/mattmarcum), [@broerse](https://github.com/broerse), and [@olivierchatry](https://github.com/olivierchatry). See [the full commit log](https://github.com/pouchdb-community/ember-pouch/compare/7c216311ffacd2f08b57df4fe34d49f4e7c373f1...v3.1.0) for details. Thank you!\n- **3.0.1**\n  - Add blueprints for model and adapter (see above for details). Thanks [@mattmarcum](https://github.com/mattmarcum) ([#101](https://github.com/pouchdb-community/ember-pouch/issues/101), [#102](https://github.com/pouchdb-community/ember-pouch/issues/102)) and [@backspace](https://github.com/backspace) ([#103](https://github.com/pouchdb-community/ember-pouch/issues/103)).\n- **3.0.0**\n  - Update for compatibility with Ember \u0026 Ember-Data 2.0+. The adapter now supports Ember \u0026 Ember-Data 1.13.x and 2.x only.\n- **2.0.3**\n  - Use Ember.get to reference the PouchDB instance property in the adapter (`db`), allowing it to be injected ([#84](https://github.com/pouchdb-community/ember-pouch/issues/84)). Thanks to [@jkleinsc](https://github.com/jkleinsc)!\n  - Indicate to ember-data 1.13+ that reloading individual ember-pouch records is never necessary (due to the change\n    watcher that keeps them up to date as they are modified) ([#79](https://github.com/pouchdb-community/ember-pouch/issues/79), [#83](https://github.com/pouchdb-community/ember-pouch/issues/83)).\n- **2.0.2** - Use provide `findRecord` for ember-data 1.13 and later thanks to [@OleRoel](https://github.com/OleRoel) ([#72](https://github.com/pouchdb-community/ember-pouch/issues/72))\n- **2.0.1** - Fixed [#62](https://github.com/pouchdb-community/ember-pouch/issues/62) thanks to [@rsutphin](https://github.com/rsutphin) (deprecated `typekey` in Ember-Data 1.0.0-beta.18)\n- **2.0.0** - Ember CLI support, due to some amazing support by [@fsmanuel](https://github.com/fsmanuel)! Bower and npm support are deprecated now; you are recommended to use Ember CLI instead.\n- **1.2.5** - Last release with regular Bower/npm support via bundle javascript in the `dist/` directory.\n- **1.0.0** - First release\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpouchdb-community%2Fember-pouch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpouchdb-community%2Fember-pouch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpouchdb-community%2Fember-pouch/lists"}