{"id":27617616,"url":"https://github.com/olegnn/sql-template-builder","last_synced_at":"2026-03-05T07:01:50.714Z","repository":{"id":54859386,"uuid":"92466785","full_name":"olegnn/sql-template-builder","owner":"olegnn","description":"Complex SQL query builder","archived":false,"fork":false,"pushed_at":"2024-03-28T08:53:16.000Z","size":65,"stargazers_count":16,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-18T16:01:44.333Z","etag":null,"topics":["builder","sql","templates"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/olegnn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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}},"created_at":"2017-05-26T03:09:37.000Z","updated_at":"2025-10-06T09:01:36.000Z","dependencies_parsed_at":"2024-10-24T22:16:53.206Z","dependency_job_id":"a5dc43d7-d8ee-4901-bced-4fc03d611945","html_url":"https://github.com/olegnn/sql-template-builder","commit_stats":{"total_commits":28,"total_committers":1,"mean_commits":28.0,"dds":0.0,"last_synced_commit":"5e0e31e33c640c3177a98abfc67a319d3afa55c0"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/olegnn/sql-template-builder","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/olegnn%2Fsql-template-builder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/olegnn%2Fsql-template-builder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/olegnn%2Fsql-template-builder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/olegnn%2Fsql-template-builder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/olegnn","download_url":"https://codeload.github.com/olegnn/sql-template-builder/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/olegnn%2Fsql-template-builder/sbom","scorecard":{"id":704787,"data":{"date":"2025-08-11","repo":{"name":"github.com/olegnn/sql-template-builder","commit":"5e0e31e33c640c3177a98abfc67a319d3afa55c0"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.4,"checks":[{"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":"Code-Review","score":0,"reason":"Found 0/19 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":"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":"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":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","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":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codecov.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/olegnn/sql-template-builder/codecov.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/codecov.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/olegnn/sql-template-builder/codecov.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lints.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/olegnn/sql-template-builder/lints.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/olegnn/sql-template-builder/test.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/olegnn/sql-template-builder/test.yml/master?enable=pin","Warn: npmCommand not pinned by hash: .github/workflows/codecov.yml:19","Warn: npmCommand not pinned by hash: .github/workflows/lints.yml:20","Warn: npmCommand not pinned by hash: .github/workflows/test.yml:27","Info:   0 out of   4 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned","Info:   0 out of   3 npmCommand dependencies pinned"],"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":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/codecov.yml:1","Warn: no topLevel permission defined: .github/workflows/lints.yml:1","Warn: no topLevel permission defined: .github/workflows/test.yml:1","Info: no jobLevel write permissions found"],"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":"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":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"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":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"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":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 22 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-22T06:12:31.072Z","repository_id":54859386,"created_at":"2025-08-22T06:12:31.072Z","updated_at":"2025-08-22T06:12:31.072Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30113111,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-05T03:40:26.266Z","status":"ssl_error","status_checked_at":"2026-03-05T03:39:15.902Z","response_time":93,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["builder","sql","templates"],"created_at":"2025-04-23T04:12:12.050Z","updated_at":"2026-03-05T07:01:50.687Z","avatar_url":"https://github.com/olegnn.png","language":"JavaScript","readme":"# SQL template builder\n\n[![Build Status](https://travis-ci.org/olegnn/sql-template-builder.svg?branch=master)](https://travis-ci.org/olegnn/sql-template-builder)\n[![npm](https://img.shields.io/npm/v/sql-template-builder.svg)](https://www.npmjs.com/package/sql-template-builder)\n[![node](https://img.shields.io/node/v/sql-template-builder.svg)](https://nodejs.org)\n[![codecov](https://codecov.io/gh/olegnn/sql-template-builder/branch/master/graph/badge.svg)](https://codecov.io/gh/olegnn/sql-template-builder)\n\n## Installation\n\n```shell\nyarn add sql-template-builder\n```\n\nor\n\n```shell\nnpm i --save sql-template-builder\n```\n\n## Compatible with\n\n- [mysql](https://www.npmjs.com/package/mysql)\n- [mysql2](https://www.npmjs.com/package/mysql2)\n- [postgres](https://www.npmjs.com/package/pg)\n- [sequelize](https://www.npmjs.com/package/sequelize)\n\n## API and usage\n\n- **sql\\`Statements go here = ${\\`value goes here\\`}\\`** - create a new `SQLQuery`\n- **sql(sql\\`query\\`, 'value', 'other value', sql\\`other query\\`, ...)** - create a new `SQLQuery` from queries/values joined by `','`\n- **sql(sql\\`query\\`, 'value', sql\\`other query\\`).joinBy(string)** - create a new `SQLQuery` as a statement joined from the underlying queries/values with `.joinBy` argument as the delimiter\n- **sql.raw(string)** - create a new `SQLQuery` statement from raw value. **Be careful!**\n- query.joinBy(string) - create a new `SQLQuery` with the given string to be used to join the top-level statements\n- query.setName(string) - create a new `SQLQuery` with the given name set as the prepared statement name (for Postgres)\n- query.text - get template text for the Postgres query\n- query.sql - get template text for the SQL query\n- query.values - get values for the query\n\n```javascript\nconst sql = require(\"sql-template-builder\");\n\nconst tableName = sql`my_table`;\n\n// Or you could pass raw value (Be careful and use escape functions in this case!)\nconst rawTableName = sql.raw(\"my_table_1\");\n\nconst conditions = [sql`a = ${1}`, sql`c = ${2}`, sql`e = ${3}`];\n\nconst conditionQuery = sql(...conditions).joinBy(\" AND \"); // It will join all statements by ' AND '\n\nconst prepared =\n  sql`SELECT * FROM ${tableName} LEFT OUTER JOIN ${rawTableName} ON(${conditionQuery})`.setName(\n    \"my_statement\"\n  );\n// text: SELECT * FROM my_table LEFT OUTER JOIN my_table_1 ON(a = $1 AND c = $2 AND e = $3)\n// sql: SELECT * FROM my_table LEFT OUTER JOIN my_table_1 ON(a = ? AND c = ? AND e = ?)\n// values: [ 1, 2, 3 ]\n\n// Do something like this\npg.query(prepared);\n```\n\n## Examples\n\nIf you like template strings and crazy things, you are welcome.\n\n```javascript\n// So, let's start from simple query\nconst sql = require(\"sql-template-builder\");\n\nconst query = sql`SELECT * from my_table`;\n\npg.query(query);\n\n// You can use query parts inside query\n\nconst complexQuery = sql`SELECT ${sql`name, age`} FROM ${sql`people`} WHERE ${sql`name = ${\"Andrew\"}`}`;\n// =\u003e text: SELECT name, age FROM people WHERE name = $0\n// =\u003e sql: SELECT name, age FROM people WHERE name = ?\n// =\u003e values: [ 'Andrew' ]\n\nconst superComplexQuery = sql`\n  WITH q1 as (${complexQuery}), q2 as (${complexQuery}), q3 as (${complexQuery}) select 1\n`;\n// =\u003e text: WITH q1 as(SELECT name, age FROM people WHERE name = $1), q2 as (SELECT name, age FROM people WHERE name = $2), q3 as (SELECT name, age FROM people WHERE name = $3) select 1\n// =\u003e values: [ 'Andrew', 'Andrew', 'Andrew' ]\n```\n\nBut sorry, that were so simple things. I hope you didn't fall asleep.\nTime to build some dynamic query system, yep?\n\n```javascript\nconst pg = require(\"pg\");\nconst sql = require(\"../src\");\n\nconst pool = new pg.Pool(/** Your PG config, please */);\n\nconst tableName = sql`people`;\n\nconst columns = [sql`name varchar`, sql`age int2`];\n\nconst createTableQuery = sql`\n  CREATE TABLE IF NOT EXISTS ${tableName}(${sql(...columns)});\n`;\n\nconst data = [\n  [\"Peter\", \"25\"],\n  [\"Wendy\", \"24\"],\n  [\"Andrew\", \"32\"],\n];\n\nconst insertStatement = sql`\n  INSERT INTO ${tableName} VALUES ${sql(\n  ...data.map((row) =\u003e sql`(${sql(...row)})`)\n)}\n`;\n// =\u003e text: INSERT INTO people VALUES ($1,$2),($3,$4),($5,$6)\n// =\u003e sql: INSERT INTO people VALUES (?,?),(?,?),(?,?)\n// =\u003e values: [ 'Peter', '25', 'Wendy', '24', 'Andrew', '32' ]\n\n// Lazy evaluated :)\nconst getNameCondition = (query) =\u003e {\n  switch (query) {\n    case firstQuery:\n      return \"Andrew\";\n    case secondQuery:\n      return sql`ANY(${[\"Peter\", \"Wendi\"]})`;\n    default:\n      return null;\n  }\n};\n\nconst firstQuery = sql`SELECT * FROM people where name = ${getNameCondition}`;\nconst secondQuery = sql`SELECT * FROM people where name = ${getNameCondition}`;\n\nconst me = sql`me`;\nconst myFriends = sql`my_friends`;\n\nconst fullQuery = sql`\n  WITH ${me} AS (${firstQuery}), ${myFriends} AS (${secondQuery})\n  SELECT name, (SELECT count(*) from ${myFriends}) as friend_count FROM ${me}\n`;\n// =\u003e text: WITH me AS (SELECT * FROM people where name = $1), my_friends AS (SELECT * FROM people where name = ANY($2))  SELECT name, (SELECT count(*) from my_friends) as friend_count FROM me\n// =\u003e sql: WITH me AS (SELECT * FROM people where name = ?), my_friends AS (SELECT * FROM people where name = ANY(?))  SELECT name, (SELECT count(*) from my_friends) as friend_count FROM me\n// =\u003e values: [ 'Andrew', [ 'Peter', 'Wendi' ] ]\n\nconst complexQuery = sql`SELECT ${sql`name, age`} FROM ${sql`people`} WHERE name = ${\"Andrew\"}`;\n// =\u003e text: SELECT name, age FROM people WHERE name = $0\n// =\u003e sql: SELECT name, age FROM people WHERE name = ?\n// =\u003e values: [ 'Andrew' ]\n\nconst superComplexQuery = sql`\n  WITH q1 as(${complexQuery}), q2 as (${complexQuery}), q3 as (${complexQuery}) select 1\n`;\n\nconst makeQuery = (query) =\u003e async () =\u003e\n  void console.log(await pool.query(query));\n\nmakeQuery(createTableQuery)()\n  .then(makeQuery(insertStatement))\n  .then(makeQuery(superComplexQuery))\n  .then(makeQuery(fullQuery))\n  .catch(console.log.bind(console, \":C\"));\n```\n\nMore examples in tests.\n\n## Motivation\n\nUsing [node-sql-template-strings](https://github.com/felixfbecker/node-sql-template-strings) you could do things like this\n\n```javascript\nconst query = SQL`SELECT * FROM my_table WHERE name = ${\"Andrew\"}`;\n\npg.query(query);\n```\n\nThat's so cool, but what if you need more complex query? For instance, you want to build query from several parts or wrap one query into another.\n\n```javascript\nconst query = SQL`SELECT * FROM people`;\nquery.append(SQL` WHERE name = ${name}`).append(` AND age = ${age}`);\nconst withQuery = SQL`WITH my_select AS (`\n  .append(query)\n  .append(\") SELECT * FROM my_select\");\n// :C\n```\n\n## Original idea\n\n[node-sql-template-strings](https://github.com/felixfbecker/node-sql-template-strings)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Folegnn%2Fsql-template-builder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Folegnn%2Fsql-template-builder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Folegnn%2Fsql-template-builder/lists"}