{"id":18656753,"url":"https://github.com/optimalbits/fowl","last_synced_at":"2025-10-13T11:09:49.851Z","repository":{"id":10922860,"uuid":"13224555","full_name":"OptimalBits/fowl","owner":"OptimalBits","description":"A NodeJS Document Model and Query Layer for FoundationDB","archived":false,"fork":false,"pushed_at":"2014-06-01T10:26:53.000Z","size":282,"stargazers_count":48,"open_issues_count":4,"forks_count":6,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-08-21T03:06:44.991Z","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/OptimalBits.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}},"created_at":"2013-09-30T19:14:04.000Z","updated_at":"2024-07-28T20:02:51.000Z","dependencies_parsed_at":"2022-08-30T02:30:34.956Z","dependency_job_id":null,"html_url":"https://github.com/OptimalBits/fowl","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/OptimalBits/fowl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OptimalBits%2Ffowl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OptimalBits%2Ffowl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OptimalBits%2Ffowl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OptimalBits%2Ffowl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OptimalBits","download_url":"https://codeload.github.com/OptimalBits/fowl/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OptimalBits%2Ffowl/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273156867,"owners_count":25055583,"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-09-01T02:00:09.058Z","response_time":120,"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-11-07T07:25:06.659Z","updated_at":"2025-10-13T11:09:44.821Z","avatar_url":"https://github.com/OptimalBits.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"#Fowl - NodeJS Document and Query Layer for FDB\n\nA NodeJS Layer for [FoundationDB](http://www.foundationdb.com) that provides documents and queries\nwith similar capabilities to MongoDB but providing support for \nmultidocument transactions.\n\nTransaction support is an incredile powerful feature that simplifies\nserver logic and helps avoiding difficult to solve race conditions.\n\nFowl provides a low level API based on keypaths for describing documents and its\nproperties following CRUD semantics.\n\nFowl aims to be a low level document layer that can be used by others to provide\nhigher level features such as schemas, models, validation, etc.\n\nAll asynchronous operations return A+ compliant promises (provided by bluebirdjs).\n\n##Contribute\n\nDo you like Fowl and want to bring it up to the next level? Do not hesitate to\nclone the project and start contributing to it! :)\n\n##Install\n\n```\nnpm install fowl\n```\n\n##Test\n\n```\nnpm test\n```\n\n##Features\n- Clean API based on promises\n- Complete transaction support for all available operations.\n- Supports: create, get, update, remove, and find.\n- Access of documents and subdocuments seamless due to a keypath based design.\n\n##Roadmap\n- namespaces\n- Advanced queries (implement all mongodb query operators)\n- Joins\n- Profile and optimize\n\n##Documentation\n\n* [open](#open)\n* [create](#create)\n* [put](#put)\n* [get](#get)\n* [remove](#remove)\n* [find](#remove)\n* [transaction](#transaction)\n* [addIndex](#addindex)\n* [query](#query)\n\n##Example\n\n\n```\n// Open a foundationDB database\nfowl.open();\n\n// Create a document (if _id not specify a GUID will be generated)\nvar john = fowl.create('people', {\n  _id: 'john',\n  name: 'John',\n  lastname: 'Smith',\n  balance: 100\n});\n\nvar lisa = fowl.create('people', {\n  _id: 'lisa',\n  name: 'Lisa',\n  lastname: 'Jones',\n  balance: 80\n});\n\n// Use transactions to transfer money from one account to another\nvar tr = fowl.transaction()\n\ntr.get(['people', 'john', 'balance']).then(function(johnBalance){\n  tr.put(['people', 'john', 'balance'], johnBalance - 10);\n});\n\ntr.get(['people', 'lisa', 'balance']).then(function(lisaBalance){\n  tr.put(['people','lisa', 'balance'], lisaBalance + 10);\n})\n\ntr.commit().then(function(){\n  // We need to wait for the commit to complete since we are finding the\n  // same keypaths.\n  \n  fowl.find('people', {balance: 90}, ['lastname']).then(function(docs){\n    // docs = [{lastname: 'Jones'}, {lastname: 'Smith'}]\n  })\n})\n```\n\nIn order to accelerate queries you should use indexes on the most common\nfields in a document. Just add indexes specifying a base key path and the\nfields to index:\n\n```\nfowl.addIndex('people',  ['name', 'balance']);\n```\n\nIt is possible to perform more advanced queries using the Query object:\n\n```\nvar query = fowl.query('people');\nquery\n  .eql('lastname', 'Andersson')\n  .gt('balance', 15)\n  .lte('balance', 45)\n  .exec(tr).then(function(results){\n    // results -\u003e array of documents matching the query.\n  })\n```\n\n## About atomicity\n\nAll CRUD functions are atomic. Meaning that updating or getting a document is\nfully atomic and you either update or get a full document or nothing at all.\n\nThe transaction object provides this same CRUD operations as atomic operations\nspawning multiple documents.\n\n\n## About Key Paths\n\nKey paths are used in fowl to represent the location of some document or \nsubdocument. It is just an array of strings (or numbers) that maps to a \nkey or key range inside FoundationDB.\nKey paths are more flexible than bucket based collections, as used for example\nin mongoDB, since it allows you to specify a document or subdocument in a \ngeneric way.\n\nFor example:\n\n```\n// Specify a document for some user in bucket 'people'\n['people', '60abd640-2d98-11e3-a7d8-bd61eca52c5c']\n\n// Specify a location of all the songs in a playlist\n['playlist', '60af31a0-2d98-11e3-a7d8-bd61eca52c5c', 'songs']\n\n```\n\nAll methods accepting a key path as parameter also accept a string that will just\nbe converted to an array:\n\n```\n'people' -\u003e ['people']\n```\n\n## About  the _id property\n\nAs in MongoDB, we generate a unique *_id* property as a primary key for all the \ncreated documents.\n\nThis property can be overrided if required by providing it explicitly in the\ndocument object.\n\nIt is also possible skip the use of the *_id* property by just using the put \nmethod directly and never calling create.\n\n## Methods\n\n\u003ca name=\"open\"/\u003e\n### open([clusterFile, dbName])\n\nOpens a FoundationDB database. This function is just a wrapper on top of\nfdb##open\nYou need to call this method before you can start using the rest of the API.\n\n__Arguments__\n \n```javascript\n    clusterFile {String} Optional path to a cluster file.\n    dbName {String} Optional database name.\n```\n\n---------------------------------------\n\n\u003ca name=\"create\"/\u003e\n### create(keyPath, doc)\n\nCreates a new document in the given key path. The document must be a plain\nobject without any circular dependencies.\nReturns a promise that will resolve to the document *_id* property.\n\n__Arguments__\n \n```javascript\n    keyPath {Array|String} Keypath with the target location for the document.\n    doc {Object} A plain object representing the document to store.\n    returns {Promise} A promise that resolves to the document _id property.\n```\n\n---------------------------------------\n\n\u003ca name=\"put\"/\u003e\n### put(keyPath, doc)\n\nUpdates a document. Similar to *create* but will not generate any _id property\nautomatically.\n\n__Arguments__\n \n```javascript\n    keyPath {Array|String} Keypath with the target location for the document.\n    doc {Object} A plain object representing the document to store.\n    returns {Promise} A promise that resolves after the document has been updated.\n```\n\n---------------------------------------\n\n\u003ca name=\"get\"/\u003e\n### get(keyPath)\n\nRetrieves the document at the given key path.\n\n__Arguments__\n \n```javascript\n    keyPath {Array|String} Keypath with the target location for the document.\n    returns {Promise} A promise that resolves with the retrieved document.\n```\n\n---------------------------------------\n\n\u003ca name=\"remove\"/\u003e\n### remove(keyPath)\n\nRemoves the document/subdocument at the given key path.\n\n__Arguments__\n \n```javascript\n  keyPath {Array|String} Keypath with the target location for the document to remove.\n  returns {Promise} A promise that resolves after the removal.  \n```\n\n---------------------------------------\n\n\u003ca name=\"find\"/\u003e\n### find(keyPath, filter, [fields])\n\nFinds documents in the given keypath that meets certain criteria. \n\n__Arguments__\n \n```javascript\n  keyPath {Array|String} Keypath with the target location of the documents to find\n  filter {Object} An object mapping properties to their values.\n  fields {Array} An optiona array of property names that should be returned.\n  returns {Promise} A promise that resolves with the found documents.\n```\n\n---------------------------------------\n\n\n\u003ca name=\"transaction\"/\u003e\n### transaction()\n\nCreates a new transaction. A transaction is an object that provides methods \nto access the database as an atomic operation.\n\n\n---------------------------------------\n\n\u003ca name=\"open\"/\u003e\n#### transaction##commit()\n\nCommits this transaction by executing all the operations and resolving their \npromises. It returns a promise that is resolved when all operations have been\nexecuted.\n\n__Arguments__\n \n```javascript\n    returns {Promise} A promise resolved when the commit has been executed.\n```\n\n#### transaction##create()\n\nA transactional equivalent to [fowl##create](#create)\n\n#### transaction##put()\n\nA transactional equivalent to [fowl##put](#put)\n\n#### transaction##get()\n\nA transactional equivalent to [fowl##get](#get)\n\n#### transaction##remove()\n\nA transactional equivalent to [fowl##remove](#remove)\n\n#### transaction##find()\n\nA transactional equivalent to [fowl##find](#find)\n\n\u003ca name=\"addIndex\"/\u003e\n### addIndex(keyPath, fields)\n\nAdds an index for the given key path and fields. After calling this method,\neverytime the key paths with the given fields are updated, an index is also\nupdated so that queries on such fields can be performed much faster.\n\n__Arguments__\n \n```javascript\n  keyPath {Array|String} base key path for the index.\n  fields {String|Array} A field or array of fields to index.\n  returns {Promise} A promise that resolves after the index has been added.\n```\n\n---------------------------------------\n\n\u003ca name=\"query\"/\u003e\n### query(keyPath, fields, opts)\n\nCreates a query object that can be used to retrieve documents that matches\nthe given criteria. The returned query object provides several operators\nto perform different kind of queries. The query object will use indexes to accelerate\nqueries if possible. Note that the order of the operators can affect performance,\nit is always better to use indexed properties first.\n\n__Arguments__\n \n```javascript\n  keyPath {Array|String} base key path for the query.\n  fields {String|Array} A field or array of fields to return on the matched documents.\n  opts {Options} Available options are \"limit\", \"skip\" and \"sort\".\n  returns {Query} A query object with several operators to match the documents.\n```\n\n#### query##eql(property, value)\nMatches documents where the given property is equal to the given value.\n\n#### query##gt(property, value)\nMatches documents where the given property is greather than the given value.\n\n#### query##gte(property, value)\nMatches documents where the given property is greater or equal than the given value.\n\n#### query##lt(property, value)\nMatches documents where the given property is less than the given value.\n\n#### query##lte(property, value)\nMatches documents where the given property is less or equal than the given value.\n\n#### query##exec(transaction)\nExecutes the query. Returns a promise that resolves to the result of the query.\n\n\n##License \n\n(The MIT License)\n\nCopyright (c) 2013 Manuel Astudillo \u003cmanuel@optimalbits.com\u003e\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foptimalbits%2Ffowl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foptimalbits%2Ffowl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foptimalbits%2Ffowl/lists"}