{"id":14989418,"url":"https://github.com/neonerd/puresql","last_synced_at":"2025-08-01T02:07:11.289Z","repository":{"id":6942323,"uuid":"55757405","full_name":"neonerd/puresql","owner":"neonerd","description":"ES6/7 ready SQL library for node.js inspired by Clojure's yesql","archived":false,"fork":false,"pushed_at":"2022-12-30T19:17:13.000Z","size":631,"stargazers_count":51,"open_issues_count":4,"forks_count":12,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-07-22T13:42:09.198Z","etag":null,"topics":["functional","koa","koajs","mssql","mysql","nodejs","postgresql","sql","sqlite","yesql"],"latest_commit_sha":null,"homepage":null,"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/neonerd.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":"2016-04-08T06:55:49.000Z","updated_at":"2024-05-15T14:29:55.000Z","dependencies_parsed_at":"2023-01-11T17:05:35.491Z","dependency_job_id":null,"html_url":"https://github.com/neonerd/puresql","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/neonerd/puresql","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neonerd%2Fpuresql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neonerd%2Fpuresql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neonerd%2Fpuresql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neonerd%2Fpuresql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/neonerd","download_url":"https://codeload.github.com/neonerd/puresql/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neonerd%2Fpuresql/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268157898,"owners_count":24204763,"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-08-01T02:00:08.611Z","response_time":67,"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":["functional","koa","koajs","mssql","mysql","nodejs","postgresql","sql","sqlite","yesql"],"created_at":"2024-09-24T14:18:20.283Z","updated_at":"2025-08-01T02:07:11.246Z","avatar_url":"https://github.com/neonerd.png","language":"JavaScript","readme":"# puresql\n\n[![npm version](https://badge.fury.io/js/puresql.svg)](https://badge.fury.io/js/puresql)\n[![Build Status](https://travis-ci.org/neonerd/puresql.svg?branch=master)](https://travis-ci.org/neonerd/puresql)\n[![Dependency Status](https://david-dm.org/neonerd/puresql.svg)](https://david-dm.org/neonerd/puresql)\n[![Coverage Status](https://coveralls.io/repos/github/neonerd/puresql/badge.svg?branch=master)](https://coveralls.io/github/neonerd/puresql?branch=master)\n[![JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/)\n\npuresql is a SQL library for node.js, heavily inspired by Clojure's [yesql](https://github.com/krisajenkins/yesql). It supports *MySQL*, *MariaDB*, *PostgreSQL*, *MS SQL Server* and *SQLite* from the box.\n\nNote: This README is aimed at Node 8.0.0 and higher and does not contain examples for generator-based workflow. See README_OLD.md for the previous version of documentation.\n\n## Intro\n\nSQL is a great [DSL](https://en.wikipedia.org/wiki/Domain-specific_language) itself. Why abstract it and do this:\n\n```js\nconst db = initDb(options)\nconst query = db.select('*').from('user').where('id', '=', 1)\n```\n\nWhen you can do this:\n\n```sql\n-- user.sql\n-- name: get_user_by_id\nSELECT *\nFROM user\nWHERE id = :id\n```\n\n```js\n// something.js\nconst db = puresql.loadQueries('user.sql')\n\nasync function foo() {\nconst rows = await db.get_user_by_id({id:1}, adapter)\n// do something with rows\n}\n```\n\n## Installation\n\n```\nnpm install puresql\n```\n\n## Usage\n\npuresql takes a path to a .sql file containing query definitions and turns them into promisified functions. You can then call them and either pass one of the provided adapters (mySQL), or your own adapter (see one of the existing ones on the structure).\n\nAlternatively, you can define individual queries manually via the exposed ```puresql.defineQuery(str)``` function.\n\n## Quickstart\n\nuser.sql\n```sql\n-- name: get_by_id\nSELECT *\nFROM user\nWHERE id = :id\n\n-- name: get_all\nSELECT *\nFROM user\n\n-- name: get_by_ids\nSELECT *\nFROM user\nWHERE id IN :ids\n\n-- name: get_or\nSELECT *\nFROM user\nWHERE id = :? OR id = :?\n```\n\nbasic.js\n```js\nconst mysql = require(\"mysql\")\nconst puresql = require(\"puresql\")\n\n// Create a connection the adapter will use\nconst connection = mysql.createConnection({\n  host : '192.168.99.100',\n  port : 3307,\n  user : 'test',\n  password : '',\n  database : 'test'\n})\n// Create the adapter\nconst adapter = puresql.adapters.mysql(connection)\n\n// Load our queries\nconst queries = puresql.loadQueries(\"user.sql\")\n\n// Do something\nasync function foo() {\n  const rows = await queries.get_all({}, adapter)\n  rows.map(row =\u003e {\n    console.log('Name: ' + row.name)\n  })\n}\nfoo()\n```\n\n## Parameters\n\npuresql query definitions can contain both named (:parameter) and anonymous (:?) parameters. These are later resolved by passing a parameters object into the query.\n\nArrays are automatically converted into their SQL representation.\n\nIf query function doesn't get all the parameters it needs, it throws an error.\n\nNamed parameters support modifiers. Cheatsheet:\n\n|Modifier|Name|Example|Input|Output|Is sanitized?|\n|---|---|---|---|---|---|\n|(blank)|Normal parameter|:id|1|1|Yes|\n|!|Dangerous parameter|:!order|ORDER ASC|ORDER ASC|No|\n|$|Object parameter (insert)|:$user{name,rights}|{name:'foo', rights:'bar'}|('foo', 'bar')|Yes|\n|@|Object parameter (update)|:@user{name,rights}|{name:'foo', rights:'bar'}|name = 'foo', rights = 'bar'|Yes|\n|$ or @|Object parameter (schemaless)|:$user|{name:'foo', rights:'bar', somethingElse: 'test'}|('foo', 'bar', 'test')|Yes|\n|*|Conditioned parameter|:\\*limit{LIMIT \\*}|10|LIMIT 10 (if '\\*limit' parameter is not undefined)|No|\n|~|Dynamic conditions|:~conditions|see bellow|see bellow|Not applicable|\n\nNamed parameter:\n```js\n// SELECT * FROM user WHERE id = :id\nqueries.get_by_id({id:1}, adapter)\n// SELECT * FROM user WHERE id = 1\n```\n\nUnnamed parameters:\n```js\n// SELECT * FROM user WHERE id = :? OR id = :?\nqueries.get_or({'?':[1, 2]}, adapter)\n// SELECT * FROM user WHERE id = 1 OR id = 2\n```\n\nArray:\n```js\n// SELECT * FROM user WHERE id IN :ids\nqueries.get_by_ids({ids:[1, 2, 3, 4]}, adapter)\n// SELECT * FROM user WHERE id IN (1, 2, 3, 4)\n```\n\nSub-arrays:\n```js\n// INSERT INTO user (name) VALUES :values\nqueries.create_users({values: [['john'], ['mark']]}, adapter)\n// INSERT INTO user (name) VALUES (\"john\"), (\"mark\")\n```\n\nParameter validation:\n```js\n// SELECT * FROM user WHERE position = :position AND division = :division\nqueries.get_by_position_and_division({position:'manager'}, adapter)\n// Throws an error\n```\n\nDangerous parameters (unescaped):\n```js\n// SELECT * FROM user ORDER BY :!order\nqueries.get_users({'!order': 'id ASC'}, adapter)\n// SELECT * FROM user ORDER BY id ASC\n```\n\nObject parameters (insert):\n```js\n// INSERT INTO user (name, surname) VALUES :$user\nqueries.insert_user({'$user': {name: 'John', surname: 'Doe'}}, adapter)\n// INSERT INTO user (name, surname) VALUES ('John', 'Doe')\n```\n\nObject parameters (update):\n```js\n// UPDATE user SET :@user\nqueries.insert_user({'@user': {name: 'John', surname: 'Doe'}}, adapter)\n// UPDATE user SET name = 'John', surname = 'Doe'\n```\n\nConcitioned parameters:\n```js\n// SELECT * FROM user ORDER BY name :*limit{LIMIT *!}\nqueries.get_users({'*limit': 10}, adapter)\nqueries.get_users({}, adapter)\n// SELECT * FROM user ORDER BY name LIMIT 10\n// SELECT * FROM user ORDER BY name\n```\n\n## Dynamic parameters\n\nWhen building parts of query dynamically (i.e. table filtering), you can use the dynamic (~) parameter type.\n\n```js\n// SELECT * FROM user WHERE :~conditions\nqueries.search_users({'~conditions':{\n  operator: 'AND',\n  parts: [\n    ['position = :position', {position: 'manager'}],\n    ['division = :division', {division: 'division'}]\n  ]\n}})\n// SELECT * FROM user WHERE position = \"manager\" AND division = \"division\"\n```\n\n## ES 6/7\n\nWith async/await, we can now take our SQL functions and use them in a sync-like way, avoiding the callback / .then() hell.\n\n```js\n// ES2015 (node.js \u003e8)\nasync function test () {\n  const rows = await queries.get_all({}, adapter)\n  console.log(rows)\n}\n```\n\n## Koa\n\nAs Koa (\u003e2.0.0) uses async/await workflow by default, puresql works out-of-box there too!\n\n```js\nconst koa = require(\"koa\")\n// Create a simple server\nconst app = koa()\n\napp.use(async function() {\n  // Like sync, but async!\n  const rows = await queries.get_all({}, adapter)\n  this.body = JSON.stringify(rows)\n})\n\napp.listen(3000)\n```\n\n## Security\n\npuresql automatically escapes the provided parameters using the adapter's escape function. The bundled adapters all use underlying drivers to escape safely. You should pay attention to properly implementing escaping when providing your own adapter.\n\n## Database support\n\npuresql provides its own default adapters for MySQL (MariaDB), PostgreSQL, MS SQL Server and sqlite. They are accessible through puresql.adapter.X functions as described below.\n\n### puresql.adapters.mysql(mysqlConnection, debugFn)\n\nReturns a mySQL adapter. Takes connection object from 'mysql' module as parameter.\n\n```js\n// dependencies\nconst mysql = require('mysql')\nconst puresql = require('puresql')\n// create a connection the adapter will use\nconst connection = mysql.createConnection({\n  host : '192.168.99.100',\n  port : 3307,\n  user : 'test',\n  password : '',\n  database : 'test'\n})\n// create the adapter\nconst adapter = puresql.adapters.mysql(connection)\n```\n\nThis adapter can optionally take debugFn function as a parameter. This function will receive the processed query before it runs.\n\nThis adapter exposes the lastInsertId value on itself.\n\n```js\nawait queries.insert({data:['foo', 'bar']}, mysqlAdapter)\nconsole.log(mysqlAdapter.lastInsertId)\n// should output the ID of the last inserted row if possible\n```\n\n### puresql.adapters.sqlite(db, debugFn)\n\nReturns an SQLite adapter. Takes a db object from 'sqlite3' module as parameter.\n\n```js\n// dependencies\nconst sqlite3 = require('sqlite3')\nconst puresql = require('puresql')\n// create the db adapter will use\nconst db = new sqlite3.Database(':memory:')\nconst adapter = puresql.adapters.sqlite(db)\n```\n\nThis adapter can optionally take debugFn function as a parameter. This function will receive the processed query before it runs.\n\n### puresql.adapters.mssql(mssqlConnection, debugFn)\n\nReturns a SQL Server adapter. Takes a connection object from 'mssql' module as parameter.\n\nNote: The mssql adapter currently only works with mssql version 3.x.x. The newest 4.x.x version is currently not supported.\n\n```js\n// dependencies\nconst mssql = require('mssql')\nconst puresql = require('puresql')\n// create a connection the adapter will use\nmssql.connect(CREDENTIALS)\n.then(function () {\n  // create the adapter\n  const adapter = puresql.adapters.mssql(mssql)\n})\n```\n\nThis adapter can optionally take debugFn function as a parameter. This function will receive the processed query before it runs.\n\n### puresql.adapters.pg(pgConnection, debugFn)\n\nReturns a PostgreSQL adapter. Takes a client instance from 'pg' module as parameter.\n\n```js\n// dependencies\nconst pg = require('pg')\nconst puresql = require('puresql')\n// create a connection the adapter will use\nconst client = new pg.Client(config)\n// create the adapter\nconst adapter = puresql.adapters.pg(client)\npg.connect((err) =\u003e {\n  // do something\n})\n```\n\nThis adapter can optionally take debugFn function as a parameter. This function will receive the processed query before it runs.\n\n## API\n\npuresql exposes these functions:\n\n### puresql.loadQueries(filePath)\n\nParses provided file and returns an object literal in {queryName:fn} format.\n\n```js\nconst queries = puresql.loadQueries('user.sql')\nconsole.log(queries)\n\n/*\n{\n  get_by_id : fn,\n  get_all : fn,\n  get_by_ids : fn,\n  get_or : fn\n}\n*/\n```\n\n### puresql.defineQuery(str)\n\nReturns a query function based on the provided string representation.\n\n```js\nconst query = puresql.defineQuery(\"SELECT * FROM user WHERE id = :id\")\n```\n\n### puresql.adapters.test()\n\nReturns a testing adapter. This adapter always returns the parsed SQL query (with parameters replaced by passed values) as a result.\n\n## License\n\nMIT\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneonerd%2Fpuresql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fneonerd%2Fpuresql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneonerd%2Fpuresql/lists"}