{"id":13458975,"url":"https://github.com/felixfbecker/node-sql-template-strings","last_synced_at":"2025-05-14T04:07:27.127Z","repository":{"id":1626062,"uuid":"42783737","full_name":"felixfbecker/node-sql-template-strings","owner":"felixfbecker","description":"ES6 tagged template strings for prepared SQL statements 📋","archived":false,"fork":false,"pushed_at":"2025-03-15T18:43:51.000Z","size":343,"stargazers_count":616,"open_issues_count":66,"forks_count":41,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-10T22:34:56.956Z","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":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/felixfbecker.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2015-09-19T17:57:38.000Z","updated_at":"2025-03-23T01:57:20.000Z","dependencies_parsed_at":"2024-12-25T22:05:55.557Z","dependency_job_id":"a051d994-aad1-4165-8c73-21785e1ac624","html_url":"https://github.com/felixfbecker/node-sql-template-strings","commit_stats":{"total_commits":104,"total_committers":11,"mean_commits":9.454545454545455,"dds":"0.27884615384615385","last_synced_commit":"7e6cad0c5cee072275ecd11340a01dc03f990582"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felixfbecker%2Fnode-sql-template-strings","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felixfbecker%2Fnode-sql-template-strings/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felixfbecker%2Fnode-sql-template-strings/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felixfbecker%2Fnode-sql-template-strings/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/felixfbecker","download_url":"https://codeload.github.com/felixfbecker/node-sql-template-strings/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254068962,"owners_count":22009464,"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":[],"created_at":"2024-07-31T09:01:00.469Z","updated_at":"2025-05-14T04:07:27.067Z","avatar_url":"https://github.com/felixfbecker.png","language":"JavaScript","readme":"# SQL Template Strings\n\n[![npm](https://img.shields.io/npm/v/sql-template-strings.svg?maxAge=2592000)](https://www.npmjs.com/package/sql-template-strings)\n[![downloads](https://img.shields.io/npm/dm/sql-template-strings.svg?maxAge=2592000)](https://www.npmjs.com/package/sql-template-strings)\n[![build](https://travis-ci.org/felixfbecker/node-sql-template-strings.svg?branch=master)](https://travis-ci.org/felixfbecker/node-sql-template-strings)\n[![codecov](https://codecov.io/gh/felixfbecker/node-sql-template-strings/branch/master/graph/badge.svg)](https://codecov.io/gh/felixfbecker/node-sql-template-strings)\n[![dependencies](https://david-dm.org/felixfbecker/node-sql-template-strings.svg)](https://david-dm.org/felixfbecker/node-sql-template-strings)\n![node](http://img.shields.io/node/v/sql-template-strings.svg)\n[![license](https://img.shields.io/npm/l/sql-template-strings.svg?maxAge=2592000)](https://github.com/felixfbecker/node-sql-template-strings/blob/master/LICENSE.txt)\n[![chat: on gitter](https://badges.gitter.im/felixfbecker/node-sql-template-strings.svg)](https://gitter.im/felixfbecker/node-sql-template-strings?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier)\n[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)\n\n[API Documentation](http://node-sql-template-strings.surge.sh/)\n\nA simple yet powerful module to allow you to use ES6 tagged template strings for prepared/escaped statements.  \nWorks with [mysql](https://www.npmjs.com/package/mysql), [mysql2](https://www.npmjs.com/package/mysql2), [postgres](https://www.npmjs.com/package/pg) and [sequelize](https://www.npmjs.com/package/sequelize).\n\nExample for escaping queries (callbacks omitted):\n\n```js\nconst SQL = require('sql-template-strings')\n\nconst book = 'harry potter'\nconst author = 'J. K. Rowling'\n\n// mysql:\nmysql.query('SELECT author FROM books WHERE name = ? AND author = ?', [book, author])\n// is equivalent to\nmysql.query(SQL`SELECT author FROM books WHERE name = ${book} AND author = ${author}`)\n\n// postgres:\npg.query('SELECT author FROM books WHERE name = $1 AND author = $2', [book, author])\n// is equivalent to\npg.query(SQL`SELECT author FROM books WHERE name = ${book} AND author = ${author}`)\n\n// sequelize:\nsequelize.query('SELECT author FROM books WHERE name = ? AND author = ?', {replacements: [book, author]})\n// is equivalent to\nsequelize.query(SQL`SELECT author FROM books WHERE name = ${book} AND author = ${author}`)\n```\n\nThis might not seem like a big deal, but when you do an INSERT with a lot columns writing all the placeholders becomes a nightmare:\n\n```js\ndb.query(\n  'INSERT INTO books (name, author, isbn, category, recommended_age, pages, price) VALUES (?, ?, ?, ?, ?, ?, ?)',\n  [name, author, isbn, category, recommendedAge, pages, price]\n)\n// is better written as\ndb.query(SQL`\n  INSERT\n  INTO    books\n          (name, author, isbn, category, recommended_age, pages, price)\n  VALUES  (${name}, ${author}, ${isbn}, ${category}, ${recommendedAge}, ${pages}, ${price})\n`)\n```\nAlso template strings support line breaks, while normal strings do not.\n\n## How it works\nThe SQL template string tag transforms the template string and returns an _object_ that is understood by both mysql and postgres:\n\n```js\nconst query = SQL`SELECT author FROM books WHERE name = ${book} AND author = ${author}`\ntypeof query // =\u003e 'object'\nquery.text   // =\u003e 'SELECT author FROM books WHERE name = $1 AND author = $2'\nquery.sql    // =\u003e 'SELECT author FROM books WHERE name = ? AND author = ?'\nquery.values // =\u003e ['harry potter', 'J. K. Rowling']\n```\n\n## Building complex queries with `append()`\nIt is also possible to build queries by appending another query or a string with the `append()` method (returns `this` for chaining):\n\n```js\nquery.append(SQL`AND genre = ${genre}`).append(' ORDER BY rating')\nquery.text   // =\u003e 'SELECT author FROM books WHERE name = $1 AND author = $2 AND genre = $3 ORDER BY rating'\nquery.sql    // =\u003e 'SELECT author FROM books WHERE name = ? AND author = ? AND genre = ? ORDER BY rating'\nquery.values // =\u003e ['harry potter', 'J. K. Rowling', 'Fantasy'] ORDER BY rating\n```\n\nThis allows you to build complex queries without having to care about the placeholder index or the values array:\n\n```js\nconst query = SQL`SELECT * FROM books`\nif (params.name) {\n  query.append(SQL` WHERE name = ${params.name}`)\n}\nquery.append(SQL` LIMIT 10 OFFSET ${params.offset || 0}`)\n```\n\n## Raw values\nSome values cannot be replaced by placeholders in prepared statements, like table names.\n`append()` replaces the `SQL.raw()` syntax from version 1, just pass a string and it will get appended raw.\n\n \u003e Please note that when inserting raw values, you are responsible for quoting and escaping these values with proper escaping functions first if they come from user input (E.g. `mysql.escapeId()` and `pg.escapeIdentifier()`).\n \u003e Also, executing many prepared statements with changing raw values in a loop will quickly overflow the prepared statement buffer (and destroy their performance benefit), so be careful.\n\n```js\nconst table = 'books'\nconst order = 'DESC'\nconst column = 'author'\n\ndb.query(SQL`SELECT * FROM \"`.append(table).append(SQL`\" WHERE author = ${author} ORDER BY ${column} `).append(order))\n\n// escape user input manually\nmysql.query(SQL`SELECT * FROM `.append(mysql.escapeId(someUserInput)).append(SQL` WHERE name = ${book} ORDER BY ${column} `).append(order))\npg.query(SQL`SELECT * FROM `.append(pg.escapeIdentifier(someUserInput)).append(SQL` WHERE name = ${book} ORDER BY ${column} `).append(order))\n```\n\n## Binding Arrays\n\nTo bind the array dynamically as a parameter use ANY (PostgreSQL only):\n```js\nconst authors = ['J. K. Rowling', 'J. R. R. Tolkien']\nconst query = SQL`SELECT name FROM books WHERE author = ANY(${authors})`\nquery.text   // =\u003e 'SELECT name FROM books WHERE author = ANY($1)'\nquery.values // =\u003e ['J. K. Rowling', 'J. R. R. Tolkien']\n```\n\n## Named Prepared Statements in Postgres\nPostgres has the option of naming prepared statements, which allows parsing and other work to be reused (and requires the SQL associated with the name to stay the same, with only the parameters changing).\nYou can set the name with the `setName()` method:\n\n```js\n// old way\npg.query({name: 'my_query', text: 'SELECT author FROM books WHERE name = $1', values: [book]})\n\n// with template strings\npg.query(SQL`SELECT author FROM books WHERE name = ${book}`.setName('my_query'))\n```\nYou can also set the name property on the statement object directly or use `Object.assign()`.\n\n## Bound Statements in sequelize\nBy default, Sequelize will escape replacements on the client.\nTo switch to using a bound statement in Sequelize, call `useBind()`.\nThe boolean parameter defaults to `true`.\nLike all methods, returns `this` for chaining.\nPlease note that as long as the bound mode is active, the statement object only supports Sequelize, not the other drivers.\n\n```js\n// old way\nsequelize.query('SELECT author FROM books WHERE name = ? AND author = ?', {bind: [book, author]})\n\n// with template strings\nsequelize.query(SQL`SELECT author FROM books WHERE name = ${book}`.useBind(true))\nsequelize.query(SQL`SELECT author FROM books WHERE name = ${book}`.useBind()) // the same\n\n// works with append (you can call useBind at any time)\nconst query = SQL`SELECT * FROM books`.useBind(true)\nif (params.name) {\n  query.append(SQL` WHERE name = ${params.name}`)\n}\nquery.append(SQL` LIMIT 10 OFFSET ${params.offset || 0}`)\n```\n\n## Editor Integration\n\n- **Sublime Text**: [javascript-sql-sublime-syntax](https://github.com/AsterisqueDigital/javascript-sql-sublime-syntax)\n- **Vim**: [vim-javascript-sql](https://github.com/statico/vim-javascript-sql)\n\n## Contributing\n - Tests are written using [mocha](https://www.npmjs.com/package/mocha)\n - You can use `npm test` to run the tests and check coding style\n - Since this module is only compatible with ES6 versions of node anyway, use all the ES6 goodies\n - Pull requests are welcome :)\n","funding_links":[],"categories":["JavaScript","Packages","Libraries"],"sub_categories":["SQL"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffelixfbecker%2Fnode-sql-template-strings","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffelixfbecker%2Fnode-sql-template-strings","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffelixfbecker%2Fnode-sql-template-strings/lists"}