{"id":28365288,"url":"https://github.com/toolbuilder/pouchdb-paginated-query","last_synced_at":"2026-06-12T16:32:44.692Z","repository":{"id":57167189,"uuid":"316802777","full_name":"toolbuilder/pouchdb-paginated-query","owner":"toolbuilder","description":"Performs paginated PouchDB queries, and provides each result via an async iterable.","archived":false,"fork":false,"pushed_at":"2022-01-26T12:42:40.000Z","size":233,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-11-01T04:06:19.928Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/toolbuilder.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2020-11-28T19:01:57.000Z","updated_at":"2024-01-13T16:55:59.000Z","dependencies_parsed_at":"2022-08-30T15:10:14.566Z","dependency_job_id":null,"html_url":"https://github.com/toolbuilder/pouchdb-paginated-query","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/toolbuilder/pouchdb-paginated-query","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toolbuilder%2Fpouchdb-paginated-query","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toolbuilder%2Fpouchdb-paginated-query/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toolbuilder%2Fpouchdb-paginated-query/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toolbuilder%2Fpouchdb-paginated-query/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/toolbuilder","download_url":"https://codeload.github.com/toolbuilder/pouchdb-paginated-query/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toolbuilder%2Fpouchdb-paginated-query/sbom","scorecard":{"id":894225,"data":{"date":"2025-08-11","repo":{"name":"github.com/toolbuilder/pouchdb-paginated-query","commit":"4fc33ada3908c5ea23041b4cc95faeb209b2d81b"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.7,"checks":[{"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":"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":"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":"Code-Review","score":0,"reason":"Found 0/7 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":"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":9,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Warn: project license file does not contain an FSF or OSI license."],"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"}},{"name":"Vulnerabilities","score":0,"reason":"12 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-w7rc-rwvf-8q5r","Warn: Project is vulnerable to: GHSA-r683-j2x4-v87g","Warn: Project is vulnerable to: GHSA-gcx4-mw62-g8wm","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3","Warn: Project is vulnerable to: GHSA-j8xg-fqg3-53r7"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-24T13:03:44.792Z","repository_id":57167189,"created_at":"2025-08-24T13:03:44.792Z","updated_at":"2025-08-24T13:03:44.792Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34253930,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-12T02:00:06.859Z","response_time":109,"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-05-28T21:10:33.926Z","updated_at":"2026-06-12T16:32:44.672Z","avatar_url":"https://github.com/toolbuilder.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Pouchdb-Paginated-Query\n\n`Pouchdb-Paginated-Query` performs paginated PouchDB queries, and provides each result via an async iterable. It works well with [await-for-it](https://github.com/toolbuilder/await-for-it), which joins async iterables with event handling, transformations, and pub/sub.\n\nHere is a very simple example.\n\n```javascript\nimport { allRows } from '@toolbuilder/pouchdb-paginated-query'\n\nconst db = new PouchDB('db', { ..your options here.. })\n// allRows interprets 'limit' as the page size\nconst paginatedQuery = allRows(db, { startkey: '03', endkey: '16', limit: 5 })\nfor await (const row of paginatedQuery) {\n  // handle each returned row here\n}\n```\n\nHere is the simplest example with [await-for-it](https://github.com/toolbuilder/await-for-it).\n\n```javascript\nimport { allRows } from '@toolbuilder/pouchdb-paginated-query'\nimport { chainable } from '@toolbuilder/await-for-it'\n\nconst db = new PouchDB('db', { ..your options here.. })\n// allDocs interprets 'limit' as the page size\nconst paginatedQuery = allRows(db, { startkey: '03', endkey: '16', limit: 5, include_docs: true })\nchainable(paginatedQuery)\n  .map(row =\u003e row.doc)\n  .callAwait(async doc =\u003e /* your processing function here */)\n  .catch(error =\u003e { /* your exception handler here */ })\n  .finally(() =\u003e { /* your cleanup function here */ })\n  .run() // start asynchronous processing\n\n```\n\n## Installation\n\n```bash\nnpm install --save @toolbuilder/pouchdb-paginated-query\n```\n\n## API\n\n* [allDocs](#allDocs)\n* [allRows](#allRows)\n* [queries](#queries)\n\n### **allDocs**\n\nPaginated PouchDB query responses provided as an async iterator. If pagination is selected as an option, responses are provided until the response contains no entries or an error is thrown.\n\nBy default, pagination is performed if the `limit` field has a value. To turn it off, set options.paginate = false.\n\nPagination works by updating the 'startkey' field of the options parameter to query for the next batch of rows when 'options.limit' is less than the number\nof records specified by the query. It also updates the 'skip' field after the first page to prevent record skipping or duplicates. See \u003chttps://pouchdb.com/2014/04/14/pagination-strategies-with-pouchdb.html\u003e for more information on paginated queries.\n\n* `db` **PouchDB** An open PouchDB database. In case you wish to proxy the database for some reason, only `db.allDocs` will be called by this generator.\n* `options` **Object** Any valid `PouchDB.allDocs(options)` query parameter. For pagination to work you should at least set the 'limit' field. The startkey, and 'skip' option parameters will be changed as required by this generator to manage pagination. The query will NOT be paginated if `options.limit == null || options.paginate === false`\n\nThrows **PouchError** if any exception is thrown by PouchDB.\n\nReturns **AsyncIterable** where each value is an unmodified PouchDB.allDocs() return value.\n\n```javascript\nimport PouchDB from 'pouchdb'\nimport { allDocs } from '@toolbuilder/pouchdb-paginated-query'\n\nconst db = new PouchDB('db', { ..your options here.. })\nconst paginatedQuery = allDocs(db, { startkey: '03', endkey: '16', limit: 5 })\nfor await (const response of paginatedQuery) {\n  const rows = response.total_rows\n  for (const row of response.rows) {\n    // handle rows here\n  }\n}\n```\n\n### **allRows**\n\nThe rows from paginated queries provided as an async iterator. If pagination is selected as an option, rows are provided until the PouchDB response contains no entries or an error is thrown.\n\nThis function is a convenience wrapper around [allDocs](#allDocs) that returns just the rows.\n\n* `db` **PouchDB** An open PouchDB database. In case you wish to proxy the database for some reason, only `db.allDocs` will be called by this generator.\n* `options` **Object** Any valid `PouchDB.allDocs(options)` query parameter. For pagination to work you should at least set the 'limit' field. The startkey, and 'skip' option parameters will be changed as required by this generator to manage pagination. The query will NOT be paginated if `options.limit == null || options.paginate === false`.\n\nThrows **PouchError** if any exception is thrown by PouchDB.\n\nReturns **AsyncIterable** where each value is a row object from a PouchDB query.\n\n```javascript\nimport PouchDB from 'pouchdb'\nimport { allDocs } from '@toolbuilder/pouchdb-paginated-query'\n\nconst db = new PouchDB('db', { ..your options here.. })\nconst paginatedQuery = allRows(db, { startkey: '03', endkey: '16', limit: 5 })\nfor await (const response of paginatedQuery) {\n  const id = response.id\n  const doc = response.doc\n  // row processing here\n}\n```\n\n### **queries**\n\nIterate over a sequence of queries, using allDocs, allRows, or your own custom function as paginatedQueryFn.\n\n* `db` **PouchDB** An open PouchDB database. In case you wish to proxy the database for some reason, only `db.allDocs` will be called by this generator.\n* `paginatedQueryFn` **AsyncGeneratorFunction** any function that matches the signature of allDocs or allRows. The function will be called once for each query provided.\n\nThrows **PouchError** if any exception is thrown by PouchDB.\n\nReturns **AsyncIterable** where each value is yielded from a `paginatedQueryFn` iterable.\n\n```javascript\nimport PouchDB from 'pouchdb'\nimport { queries, allRows } from '@toolbuilder/paginated-pouchdb-query'\n\nconst db = new PouchDB('db', { ..your options here.. })\nconst someQueries = [{ /* query options */ }, { /* query options */ }]\n// Call allRows for each query and process the results\nfor await (const row of queries(db, allRows)(someQueries)) {\n  // process rows from both queries here\n}\n```\n\nThis example uses [await-for-it](https://github.com/toolbuilder/await-for-it) to query PouchDB in response to events.\n\n```javascript\nimport { chainable, Queue } from '@toolbuilder/await-for-it'\nimport { RingBuffer } from '@toolbuilder/ring-buffer'\nimport PouchDB from 'pouchdb'\nimport { queries, allRows } from '@toolbuilder/paginated-pouchdb-query'\n\n// Setup queue to keep only the most recent 100 data values.\n// Older values that have not been processed yet are quietly dropped.\n// This behavior is provided by RingBuffer. Other buffers behave differently.\n// For example, an Array will never drop anything, but could grow forever.\nconst queue = new Queue(new RingBuffer(100))\n\n// setup an async iterator to handle the input events\nconst controller = chainable(queue)\n  .filter(event =\u003e dropEventsThatYouDoNotWant(event))\n  .map(async (event) =\u003e generateQueryOptionsFromEvent(event))\n  // Perform query, and return rows for each event\n  .mapWith(queries(db, allRows))\n  .map(async (row) =\u003e processRow(row))\n  // An error stops all iteration\n  .catch(error =\u003e handleErrors(error))\n  .finally(async () =\u003e doSomeCleanup())\n  .run() // you could use 'publish' here if you want pub/sub\n\n// In your event handler, push events into the queue\nconst eventHandler = (event) =\u003e queue.push(event)\n// register your event handler of course\n\n// You can stop/resume the chainable iterator if you need to.\n// You can still push to the queue while chainable is stopped,\n// but the buffer might drop what you push depending on the buffer\n// you choose.\nif (controller.running) controller.stop()\ncontroller.start()\n\n// Somewhere else, such as an 'application done' event, tell the\n// Queue that it is done so that the chainable finally method is called\n// By default all values in the buffer are processed before iteration stops.\nqueue.done()\n\n// Elsewhere, you can also pass an exception to the queue, so that the async\n// iterator will handle it asynchronously.\nqueue.exception(new YourError(someData))\n// The .catch() method in the chainable above will now get\n// YourError, and iteration will stop\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftoolbuilder%2Fpouchdb-paginated-query","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftoolbuilder%2Fpouchdb-paginated-query","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftoolbuilder%2Fpouchdb-paginated-query/lists"}