{"id":13659267,"url":"https://github.com/featurist/sworm","last_synced_at":"2025-04-07T06:13:28.144Z","repository":{"id":19507256,"uuid":"22753872","full_name":"featurist/sworm","owner":"featurist","description":"a write-only ORM for Node.js","archived":false,"fork":false,"pushed_at":"2022-05-27T07:17:16.000Z","size":406,"stargazers_count":147,"open_issues_count":10,"forks_count":32,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-03-31T04:07:47.057Z","etag":null,"topics":["mssql","mysql","nodejs","oracle-db","orm","postgresql","sql","sqlite3"],"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/featurist.png","metadata":{"files":{"readme":"readme.md","changelog":"changelog.md","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":"2014-08-08T10:07:41.000Z","updated_at":"2025-03-29T06:44:38.000Z","dependencies_parsed_at":"2022-07-27T00:32:17.371Z","dependency_job_id":null,"html_url":"https://github.com/featurist/sworm","commit_stats":null,"previous_names":["featurist/mssql-orm"],"tags_count":48,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/featurist%2Fsworm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/featurist%2Fsworm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/featurist%2Fsworm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/featurist%2Fsworm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/featurist","download_url":"https://codeload.github.com/featurist/sworm/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247601449,"owners_count":20964864,"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","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":["mssql","mysql","nodejs","oracle-db","orm","postgresql","sql","sqlite3"],"created_at":"2024-08-02T05:01:06.892Z","updated_at":"2025-04-07T06:13:28.121Z","avatar_url":"https://github.com/featurist.png","language":"JavaScript","readme":"# SWORM [![npm version](https://img.shields.io/npm/v/sworm.svg)](https://www.npmjs.com/package/sworm) [![npm](https://img.shields.io/npm/dm/sworm.svg)](https://www.npmjs.com/package/sworm) [![Build Status](https://travis-ci.org/featurist/sworm.svg?branch=master)](https://travis-ci.org/featurist/sworm)\n\nA very lightweight **write only** Node.js ORM, with support for:\n\n* Microsoft SQL Server (MSSQL)\n* PostgreSQL\n* MySQL\n* Oracle DB\n* Sqlite 3\n* Browser Web SQL\n\n## Changelog\n\nSee [changelog.md](changelog.md)\n\n## NPM\n\n    npm install sworm\n\nThen install a database driver, one of:\n\n    npm install mssql\n    npm install pg\n    npm install mysql\n    npm install oracledb\n    npm install sqlite3\n\nThere's no need to install a driver for Web SQL, sworm will pick it up from the `window` object.\n\nSee [sworm](https://www.npmjs.org/package/sworm) in NPM.\n\n## Write Only?\n\nThe features in this module are mostly for **writing graphs of related entities**. Querying, on the other hand, is done with raw SQL so you can do it fast. See the [query API](#queries) for details.\n\nThis ORM avoids some of the largest issues experienced in other ORMs:\n\n* query performance is too opaque\n* N+1 queries are frequently the default\n* configuring eager and lazy loading is tricky\n* one-to-many, many-to-one, many-to-many relationships are notoriously difficult to get right\n* lifecycle management of sessions and identity maps is rarely pleasant\n* check out the massive generated SQL statements!\n\nJust write SQL, you know how.\n\n## Example\n\n```js\nvar person = db.model({table: 'people'});\nvar address = db.model({table: 'addresses'});\n\nvar bob = person({\n  name: 'bob',\n  address: address({\n    address: 'Fremantle'\n  })\n});\n\nbob.save()\n```\n\nProduces:\n\n    -------- people ----------\n    | id | name | address_id |\n    --------------------------\n    | 11 | bob  | 22         |\n    --------------------------\n\n    ------- addresses ------\n    | id | address         |\n    ------------------------\n    | 22 | Fremantle       |\n    ------------------------\n\n## Connection\n\nConnect:\n\n```js\ndb.connect(config? : {}, fn? : () -\u003e Promise);\n```\n\n* `config` database connection configuration, see below\n* `fn` if passed, `connect()` will connect to the database, run the function, then disconnect. Ensure that `fn` returns a promise.\n\nYou can pass connection configuration to the `sworm.db()` function, or to the `db.connect()` function.\n\n```js\nvar sworm = require('sworm');\n\nvar db = sworm.db({\n  driver: 'pg',\n  config: {\n    user: 'user',\n    password: 'password',\n    host: 'localhost',\n    database: 'databasename'\n  }\n});\n\nvar person = db.model({table: 'people'});\n\nvar bob = person({name: 'Bob'});\n\n// sworm connects at the first database interaction\nbob.save();\n```\n\nOr define models then connect:\n\n```js\nvar sworm = require('sworm');\n\nvar db = sworm.db();\n\nvar person = db.model({table: 'people'});\n\ndb.connect({\n  driver: 'mssql',\n  config: {\n    user: 'user',\n    password: 'password',\n    server: 'localhost',\n    database: 'databasename'\n  }\n}).then(function () {\n\n  ...\n\n});\n```\n\nOr connect, run some code and then disconnect:\n\n```js\nvar sworm = require('sworm');\n\nvar db = sworm.db(config);\n\nvar person = db.model({table: 'people'});\n\ndb.connect(function () {\n\n  // connected\n\n  var bob = person({name: 'bob'});\n  return bob.save().then(function () {\n    ...\n  });\n}).then(function () {\n  \n  // disconnected\n\n});\n```\n\n## Connection options:\n\n```js\nsworm.db(options)\nsworm.db(url)\n```\n\n  * `url`, see urls for databases in respective section below\n\n  * `options.driver`, one of `'mssql'`, `'mysql'`, `'pg'`, `'oracle'`, `'sqlite'` or `'websql'`.\n  * `options.config` see configuration for databases in respective section below\n\n  * `url` a connection URL, the following are supported\n    * `pg` - `postgres://user:password@host:5432/database`. See the [`pg` url format](https://github.com/brianc/node-postgres/wiki/pg#connectstring-connectionstring-function-callback).\n    * `oracle` - `oracle://user:password@host:1521/sid\u0026maxRows=100000\u0026pool=true`\n  * `setupSession` a function that is passed the `db` to setup the session before any queries are run.\n\n    ```js\n    setupSession: function (db) {\n      return db.query(\"alter session set time_zone = 'UTC'\");\n    }\n    ```\n\n  * `log`: either `true` to log SQL statements with `console.log()`\n\n    Can also be a function for custom logging:\n\n    ```js\n    function (sql, params) {\n      // sql == 'select * from people where name = @name'\n      // params == {name: 'bob'}\n    }\n    ```\n\n    Defaults to `false`, no logging.\n\n### Driver Connection Config\n\n* **mysql**\n\n  See: [https://github.com/felixge/node-mysql#connection-options](https://github.com/felixge/node-mysql#connection-options)\n\n  ```js\n  {\n    driver: 'mysql',\n    config: {\n      user: 'username',\n      password: 'password',\n      host: 'localhost',\n      database: 'database name'\n    }\n  }\n  ```\n\n* **mssql**\n\n  See: [https://github.com/patriksimek/node-mssql#configuration-1](https://github.com/patriksimek/node-mssql#configuration-1)\n\n  ```js\n  {\n    driver: 'mssql',\n    config: {\n      user: 'username',\n      password: 'password',\n      server: 'localhost',\n      database: 'databaseName'\n    }\n  }\n  ```\n\n* **postgres**\n\n  URL: `postgres://user:password@host:5432/database`. See the [`pg` url format](https://github.com/brianc/node-postgres/wiki/pg#connectstring-connectionstring-function-callback).\n\n  See: [https://github.com/brianc/node-postgres/wiki/pg#connectstring-connectionstring-function-callback](https://github.com/brianc/node-postgres/wiki/pg#connectstring-connectionstring-function-callback)\n\n  The driver will use connection pooling if you pass `pool: true`.\n\n  ```js\n  {\n    driver: 'pg',\n    config: {\n      user: 'username',\n      password: 'password',\n      host: 'localhost',\n      database: 'database name',\n      pool: true\n    }\n  }\n  ```\n\n* **oracle**\n\n  URL: `oracle://user:password@host:port/sid\u0026maxRows=100000\u0026pool=true`\n\n  See: [getConnection()](https://github.com/oracle/node-oracledb/blob/master/doc/api.md#-332-getconnection)\n  For `options` see [Oracledb Properties](https://github.com/oracle/node-oracledb/blob/master/doc/api.md#oracledbproperties)\n\n  The driver fetches `maxRows` rows at a time, defaulting to 100. You may want to adjust this value if you expect large result sets, higher values can be faster but use more memory.\n\n  The driver will use connection pooling if you pass `pool: true`.\n\n  By default the driver is set to `autoCommit = true`, you can pass `options: { autoCommit: false}` to turn this off again.\n\n  ```js\n  {\n    driver: 'oracle',\n    config: {\n      user: 'username',\n      password: 'password',\n      connectString: 'localhost/XE',\n      pool: true,\n\n      options: {\n        // options to set on `oracledb`\n        maxRows: 1000\n      }\n    }\n  }\n  ```\n\n  The driver can also use an existing pool:\n\n  ```js\n  {\n    driver: 'oracle',\n    config: {\n      pool: pool // from oracledb.createPool(config, cb),\n\n      options: {\n        // options to set on `oracledb`\n        maxRows: 1000\n      }\n    }\n  }\n  ```\n\n* **sqlite**\n\n  URL: `file:///absolute/path/to/database.db` or `relative/path/to/database.db`\n\n  See: [https://github.com/mapbox/node-sqlite3/wiki/API#new-sqlite3databasefilename-mode-callback](https://github.com/mapbox/node-sqlite3/wiki/API#new-sqlite3databasefilename-mode-callback)\n\n  ```js\n  {\n    driver: 'sqlite',\n    config: {\n      filename: 'filename or :memory:'\n    }\n  }\n  ```\n\n* **websql**\n\n  URL: `websql:///db-name` or `db-name`\n\n  ```js\n  {\n    driver: 'websql',\n    config: {\n      name: 'db-name',\n\n      // the `openDatabase` function to connect to the DB, defaulting to `window.openDatabase`\n      openDatabase: window.openDatabase,\n\n      // dababase size, defaulting to 5M\n      size: 5 * 1024 * 1024\n    }\n  }\n  ```\n\n### Close\n\nClose the connection after use:\n\n```js\ndb.close()\n```\n\n### Debug\n\nThis module uses [debug](https://www.npmjs.com/package/debug), so you can easily see what's happening under the hood by setting a `DEBUG` environment variable.\n\n```js\nDEBUG=sworm node myapp.js\n```\n\nThere are various schemes you can use:\n\n* `sworm` all queries\n* `sworm:results` all results\n* `sworm:mssql` exact query passed to mssql\n* `sworm:mysql` exact query passed to mysql\n* `sworm:pg` exact query passed to postgres\n* `sworm:oracle` exact query passed to oracle\n* `sworm:sqlite` exact query passed to sqlite3\n* `sworm:websql` exact query passed to websql\n\n## Models\n\n```js\nvar createEntity = db.model(options);\n```\n\n`createEntity` is a function that can be used to create entities from the model.\n\n`options` can contain the following:\n\n  * `table` (`undefined`) the name of the table to save entities to\n  * `id` (`'id'`) the name of the identity column. This can be an array of id columns for compound keys, or `false` if there is no id column.\n  * `foreignKeyFor` a function that returns a foreign key field name for a member (see [Relationships](#relationships)), defaults to:\n\n    ```js\n    function foreignKeyFor(fieldName) {\n      return fieldName + '_id';\n    }\n    ```\n\n  * for oracle `idType` (`oracledb.NUMBER`) is the type of the identity column, for e.g. `oracledb.STRING`.\n  * for mssql `generatedId` (`scope_identity`) is the method to get the generated id for insert statements:\n\n    * `scope_identity` uses `scope_identity()` to get the generated id, this is the default.\n    * `output` uses `output inserted.id` to get the generated id. This will work for `uniqueidentifier` column types but is not compatible with tables that have triggers.\n\n### Model Methods\n\nAny other properties or functions on the `options` object are accessible by entities.\n\n```js\nvar address = db.model({\n  table: 'addresses',\n\n  addPerson: function(person) {\n    this.people = this.people || [];\n    person.address = this;\n    this.people.push(person);\n  }\n});\n\nvar fremantle = address({address: 'Fremantle'});\nfremantle.addPerson(person({name: 'bob'}));\n```\n\n## Entities\n\nThe entity constructor takes an object with fields to be saved to the database.\n\n```js\nvar person = db.model({...});\n\nvar bob = person({\n  name: 'bob'\n}, [options]);\n```\n\nWhere options can have:\n  * `saved`: if `true` will `update` the entity (if modified) on the next `save()`, if `false` will `insert` the entity on the next `save()`. Default `false`.\n  * `modified`: if `true` (and if `saved` is true), will `update` the entity on the next `save()` regardless if it has been modified.\n\n### Save\n\n```js\nvar promise = entity.save([options]);\n```\n\nInserts or updates the entity into the table. If the entity already has a value for its identity column, then it is updated, if not, it is inserted.\n\nObjects know when they've been modified since their last insert or update, so they won't update unless a field is modified. You can force an update by passing `{force: true}`.\n\n`save()` returns a promise.\n\n### Identity\n\n```js\nentity.identity()\n```\n\nReturns the ID of the entity, based on the identity column specified in the model.\n\n### Changed\n\n```js\nentity.changed()\n```\n\nReturns true if the object has been modified since the last `save()`.\n\n## Relationships\n\nEntities can contain fields that are other entities. This way you can build up graphs of entities and save them all in one go.\n\n### Many to One\n\nWhen entity A contains a field that is entity B, then B will be saved first and B's ID will be set and saved with A.\n\nThe foreign key of the member will be saved on the field name `member_id`. So `address` will have a foreign key of `address_id`. See the `foreignKeyFor` option in [Models](#models).\n\n```js\nvar person = db.model({table: 'people'});\nvar address = db.model({table: 'addresses'});\n\nvar bob = person({\n  name: 'bob',\n  address: address({\n    address: \"15 Rue d'Essert\"\n  })\n});\n\nbob.save().then(function () {\n  assert(bob.address_id == address.id);\n});\n```\n\nAlternatively, you can specify the objects the other way around, the address on the outside (see [one-to-many](#one-to-many) for how this works):\n\n```js\nvar essert = address({\n  address: \"15 Rue d'Essert\",\n  person: (address) =\u003e [\n    person({\n      name: 'bob',\n      address: address\n    })\n  ]\n})\n\nessert.save()\n```\n\nIn SQL:\n\n    -------- people ----------\n    | id | name | address_id |\n    --------------------------\n    | 11 | bob  | 22         |\n    --------------------------\n\n    ------- addresses ------\n    | id | address         |\n    ------------------------\n    | 22 | 15 Rue d'Essert |\n    ------------------------\n\n### One to Many\n\nWhen entity A contains a field that is an array that contains entities B and C. Then entity A will be saved first, followed by all entities B and C.\n\nThis allows entities B and C to refer to entity A, as they would in their tables.\n\n```js\nvar person = db.model({ table: 'people' });\nvar address = db.model({ table: 'addresses' });\n\nvar bob = person({name: 'bob'});\nvar jane = person({name: 'jane'});\n\nvar essert = address({\n  address: \"15 Rue d'Essert\",\n  people: [bob, jane]\n});\n\nbob.address = essert;\njane.address = essert;\n\nessert.save().then(function () {\n  // all objects saved.\n});\n```\n\nAlternatively, we can return the people in the address using a function. When the address is saved, the `people` function will be called with the owner address as the first argument, then we can set the foreign key for the people. Following the `save()` the results of the function will be saved as an array on the object.\n\n```js\nvar person = db.model({ table: 'people' });\nvar address = db.model({ table: 'addresses' });\n\nvar essert = address({\n  address: \"15 Rue d'Essert\",\n  people: (addr) =\u003e [\n    person({ name: 'bob', address: addr }),\n    person({ name: 'jane', address: addr })\n  ]\n});\n\nessert.save().then(function () {\n  // all objects saved.\n  // essert.people == [{name: 'bob', ...}, {name: 'jane', ...}]\n});\n```\n\nNotice that whether we use an array or a function, the field itself is never saved to the database, only the entities inside the array.\n\nIn SQL:\n\n    -------- people ----------\n    | id | name | address_id |\n    --------------------------\n    | 11 | bob  | 22         |\n    | 12 | jane | 22         |\n    --------------------------\n\n    ------- addresses ------\n    | id | address         |\n    ------------------------\n    | 22 | 15 Rue d'Essert |\n    ------------------------\n\n### Many to Many\n\nMany-to-many is just a combination of one-to-many and many-to-one:\n\n```js\nvar db = sworm.db('test/test.db')\nvar person = db.model({ table: 'people' });\nvar personAddress = db.model({ table: 'people_addresses', id: ['address_id', 'person_id'] });\nvar address = db.model({ table: 'addresses' });\n\nvar bob = person({name: 'bob'});\nvar jane = person({name: 'jane'});\n\nvar fremantle = address({\n  address: 'Fremantle',\n  personAddresses: (address) =\u003e [\n    personAddress({ person: bob, address: address }),\n    personAddress({ person: jane, address: address })\n  ]\n});\nvar essert = address({\n  address: \"15 Rue d'Essert\",\n  personAddresses: (address) =\u003e [\n    personAddress({ person: jane, address: address })\n  ]\n});\n\nPromise.all([essert.save(), fremantle.save()]);\n```\n\nIn SQL:\n\n    -- people ---\n    | id | name |\n    -------------\n    | 11 | bob  |\n    | 12 | jane |\n    -------------\n\n    ------- addresses ------\n    | id | address         |\n    ------------------------\n    | 22 | 15 Rue d'Essert |\n    | 23 | Fremantle       |\n    ------------------------\n\n    ---- people_addresses ----\n    | address_id | person_id |\n    --------------------------\n    | 22         | 12        |\n    | 23         | 12        |\n    | 23         | 11        |\n    --------------------------\n\n## Relationships Summary\n\nIn summary, a relationship can be a field containing one of the following:\n\n* a sworm entity\n\n  ```js\n    outer({\n      field: inner({ ... })\n    })\n  ```\n\n  1. the entity is saved\n  2. the ID is placed in the outer entity's `field_id` field. (See `foreignKeyFor`)\n  3. the outer entity is saved\n* an array of sworm entities\n\n  ```js\n    outer({\n      field: [\n        inner({ ... }),\n        inner({ ... })\n      ]\n    })\n  ```\n\n  1. the outer entity is saved\n  2. each of the entities in the array are saved\n* a function that returns an array of sworm entities\n\n  ```js\n    outer({\n      field: (outer) =\u003e [\n        inner({ outer: outer, ... }),\n        inner({ outer: outer, ... })\n      ]\n    })\n  ```\n\n  1. the outer entity is saved\n  2. the function is called, passing the outer entity as the first argument\n  3. the function returns an array of entities\n  4. each of those entities are saved\n  5. the array is assigned to the outer entity's field\n\n# Unescaping\n\nIt's sometimes useful to pass in some real unescaped SQL, for this you can use `sworm.unescape()` for model values or query parameters.\n\nUsual qualifiers apply here: when using this feature, make sure to protect your application from SQL injection by properly escaping strings with `sworm.escape()` or by being extra careful!\n\nFor example, you can pass in an array of values for an `in (...)` statement:\n\n```js\ndb.query('select * from people where names in (@names)', {names: sworm.unescape(\"'bob', 'jane'\")})\n```\n\nwill become\n\n```sql\nselect * from people where names in ('bob', 'jane')\n```\n\nThese parameters are not passed to the database driver.\n\nThis is also useful for handling differences in database drivers, such as `sysdate` or `now`:\n\n```js\ndb.query(\n  'select * from people where subscription_date \u003c @now',\n  {now: sworm.unescape(usingSqlite? \"date('now')\": \"now()\")},\n)\n```\n\nOr, to refer to SQL features when inserting, such as sequences in oracle:\n\n```js\nperson({id: sworm.unescape('sequence.nextVal'), name: 'bob'}).save()\n```\n\n## Escaping\n\nUse `sworm.escape(string)` to escape strings.\n\n# Queries\n\n```js\ndb.query(sql, [parameters]).then(function (records) {\n});\n```\n\nWhere:\n\n  * `sql` is the SQL query, can be a query (i.e. select), or a command (update, insert, stored proc)\n  * `parameters`. If `sql` contains parameters in the form of `@paramName` the corresponding property on the `parameters` object will be substituted into the SQL, doing any escaping necessary.\n\nFor select queries, returns an array of objects, containing the fields of each record.\n\n```js\ndb.query('select * from people where name = @name', {name: 'Bob'}).then(function (results) {\n  console.log(results);\n\n  /*\n     [\n       {id: 2, name: 'Bob'}\n     ]\n   */\n}); \n```\n\n## Stored Procedure Example\n\n```js\ndb.query('myProcName @param1, @param2', {param1: 'a', param2: 'b'});\n```\n\n## Model Queries\n\n```js\nmodel.query(sql, [parameters]).then(function (entities) {\n});\n```\n\nSame as `db.query()` but records returned are turned into entities of the model that can subsequently be modified and saved.\n\n```js\nperson.query('select * from people where id = @id', {id: 1}, function (people) {\n  var bob = people[0];\n  bob.name = 'Jack';\n  return bob.save();\n});\n```\n\n# Statements\n\nStatements are just like queries but they don't bother to parse or log the results.\n\n```js\ndb.statement(query, [params, [options]]);\n```\n\n# update, insert, upsert\n\nYou can explicitly `insert`, `update` or `upsert` a record:\n\n```js\nvar bob = person({name: 'bob'})\nbob.insert()\n// insert into people (name) values ('bob')\n```\n\n```js\nvar bob = person({name: 'bob', id: 4})\nbob.update()\n// update people set name = 'bob' where id = 4\n```\n\nUpsert works by detecting the presence of an id, if there is an id, it updates the record, if not it inserts it.\n\n```js\nvar bob = person({name: 'bob'})\nbob.upsert()\n// insert into people (name) values ('bob')\n```\n\n```js\nvar bob = person({name: 'bob', id: 4})\nbob.upsert()\n// update people set name = 'bob' where id = 4\n```\n\nFor updates, an error is thrown if there are no records found with that id, or indeed if no id is given.\n\n# Transactions\n\nYou can insert update or query the database using transactions. Transactions can be used in two forms, explicitly running `db.begin()`, `db.commit()` and `db.rollback()`, or by calling `db.transaction(fn)` with a function that will commit automatically if it didn't fail.\n\nThe explicit form:\n\n```js\ndb.begin().then(() =\u003e {\n  var bob = person({name: 'bob'});\n  return bob.save();\n}).then(() =\u003e {\n  db.rollback();\n  // or\n  db.commit();\n});\n```\n\nThe implicit form:\n\n```js\ndb.transaction(() =\u003e {\n  var bob = person({name: 'bob'});\n  return bob.save();\n});\n```\n\n```js\ndb.begin([options]);\n```\n\nBegin the transaction\n\n* `options` a string that is appended to the database's `begin` command, for e.g. `db.begin('isolation level read committed')` will result in the sql `begin isolation level read committed`.\n\n```js\ndb.rollback();\n```\n\nRollback the transaction\n\n```js\ndb.commit();\n```\n\nCommit the transaction\n\n```js\ndb.transaction(options? : String, fn : () =\u003e Promise)\n```\n\n* `options` a string that is appended to the database's `begin` command, for e.g. `db.begin('isolation level read committed')` will result in the sql `begin isolation level read committed`.\n* `fn` a function that is executed after the transaction has begun. The function is expected to return a promise, if resolved, the transaction will be committed, if rejected, the transaction will be rolled back.\n\n```js\ndb.transaction(() =\u003e {\n  // this transaction will be rolled back\n  return db.query('update people set name = @name', {name: 'jane'}).then(() =\u003e {\n    throw new Error('uh oh!');\n  });\n});\n\ndb.transaction(() =\u003e {\n  // this transaction will be committed\n  return db.query('update people set name = @name', {name: 'jane'});\n});\n```\n\n# Accessing the Connection\n\nYou can access the underlying driver's connection after the database has connected of course through `db.driver.connection`.\n\n## Options\n\nYou can pass options to the database driver when executing a query\n\n```js\ndb.query(sql, parameters, [options])\n```\n\n* SQLite3\n  * `multiline` or `exec` runs the `exec()` method on the connection which executes multiple lines, see [exec](https://github.com/mapbox/node-sqlite3/wiki/API#databaseexecsql-callback). Note that this method ignores any query `parameters` passed in.\n* Oracle\n  * `formatRows` if `false` will not format rows as lower case and will return the raw `oracledb` results. Formatting rows may be a performance issue for large result sets.\n  * any other options are passed to `oracledb`'s [`execute` method](https://github.com/oracle/node-oracledb/blob/master/doc/api.md#-4233-execute-options).\n\n# Development\n\n## Tests\n\nThe only thing slightly awkward about this project are the test environments for each database. I've tried to make this as easy as possible however:\n\n* sqlite3 works out of the box on most if not all platforms\n* mysql, postgres and oracle instances can be found in the `docker-compose.yml` file. Install docker, make it run somehow, then run `docker-compose up -d`. This will download and start each of the databases necessary to run the tests. The tests look for the `$DOCKER_HOST` environment variable to see where the docker host is, if it's in a VM or somewhere else, otherwise the databases are expected to be on localhost, running on their default ports.\n* mssql is less friendly, and all I ask is that it's running on a machine called `windows` (hack your `/etc/hosts` file if necessary), with a fresh database called `sworm`, with user `user` and password `password`.\n\nEach database can be tested individually by running `mocha test/{mssql,mysql,postgres,oracle,sqlite}Spec.js`. All of them with simply `npm test`.\n\nNevertheless, this project is almost entirely covered with tests and I expect any pull request to have tests that demonstrate any new feature or bugfix.\n","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffeaturist%2Fsworm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffeaturist%2Fsworm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffeaturist%2Fsworm/lists"}