{"id":23246406,"url":"https://github.com/marianmeres/data-to-sql-params","last_synced_at":"2026-01-27T17:39:04.485Z","repository":{"id":254709214,"uuid":"847332153","full_name":"marianmeres/data-to-sql-params","owner":"marianmeres","description":"A helper function for extracting and converting data objects to various helper lists useful for programmatically creating SQL statements.","archived":false,"fork":false,"pushed_at":"2025-12-27T16:05:26.000Z","size":97,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-12-29T12:54:31.410Z","etag":null,"topics":["sql"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/marianmeres.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2024-08-25T14:24:21.000Z","updated_at":"2025-12-27T16:05:27.000Z","dependencies_parsed_at":"2025-08-22T01:01:25.480Z","dependency_job_id":null,"html_url":"https://github.com/marianmeres/data-to-sql-params","commit_stats":null,"previous_names":["marianmeres/data-to-sql-params"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/marianmeres/data-to-sql-params","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marianmeres%2Fdata-to-sql-params","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marianmeres%2Fdata-to-sql-params/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marianmeres%2Fdata-to-sql-params/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marianmeres%2Fdata-to-sql-params/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/marianmeres","download_url":"https://codeload.github.com/marianmeres/data-to-sql-params/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marianmeres%2Fdata-to-sql-params/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28817140,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-27T12:25:15.069Z","status":"ssl_error","status_checked_at":"2026-01-27T12:25:05.297Z","response_time":168,"last_error":"SSL_read: 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":["sql"],"created_at":"2024-12-19T07:14:51.119Z","updated_at":"2026-01-27T17:39:04.479Z","avatar_url":"https://github.com/marianmeres.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @marianmeres/data-to-sql-params\n\n[![NPM version](https://img.shields.io/npm/v/@marianmeres/data-to-sql-params.svg)](https://www.npmjs.com/package/@marianmeres/data-to-sql-params)\n[![JSR version](https://jsr.io/badges/@marianmeres/data-to-sql-params)](https://jsr.io/@marianmeres/data-to-sql-params)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA lightweight utility function for converting data objects into SQL parameter lists, making it easier to build dynamic SQL statements with parameterized queries.\n\nGenerates PostgreSQL-style placeholders (`$1`, `$2`, etc.) and properly quoted SQL identifiers, with support for value transformation and selective field extraction.\n\n## Features\n\n- 🔒 **SQL Injection Safe** - Properly escapes SQL identifiers (quotes are doubled per SQL standard)\n- 🎯 **Flexible Extraction** - Choose which fields to include via whitelist or transform map\n- 🔄 **Value Transformation** - Apply custom functions to transform values during extraction\n- 📦 **Zero Dependencies** - Lightweight and self-contained\n- 🎨 **Multiple Output Formats** - Keys, placeholders, values, pairs, and named parameters\n- 🔢 **PostgreSQL-Compatible** - Uses `$1`, `$2` style placeholders\n- 💪 **TypeScript Support** - Fully typed with JSDoc annotations\n\n## Installation\n\n```sh\ndeno add jsr:@marianmeres/data-to-sql-params\n```\n\n```sh\nnpm install @marianmeres/data-to-sql-params\n```\n\n## API\n\n\u003e **Full API documentation:** [API.md](API.md)\n\n```typescript\nfunction dataToSqlParams(\n  data: Record\u003cstring, any\u003e,\n  extractor?: string[] | Record\u003cstring, TransformFn | boolean\u003e\n): SqlParamsResult\n```\n\n### Parameters\n\n- **`data`** - Source object containing the data to extract\n- **`extractor`** _(optional)_ - Extraction strategy:\n  - `undefined` - Extract all defined keys (excludes `undefined` values)\n  - `string[]` - Whitelist of keys to extract\n  - `Record\u003cstring, TransformFn | boolean\u003e` - Map of keys to transform functions:\n    - `true` - Include key without transformation\n    - `false` - Exclude key from extraction\n    - `function` - Apply transformation to the value\n\n### Return Value (`SqlParamsResult`)\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `keys` | `string[]` | SQL-quoted identifiers for INSERT column lists |\n| `placeholders` | `string[]` | Numbered placeholders (`$1`, `$2`, ...) |\n| `values` | `any[]` | Extracted values in placeholder order |\n| `pairs` | `string[]` | `\"key\" = $N` strings for UPDATE SET clauses |\n| `map` | `Record\u003cstring, any\u003e` | Named parameters with `$` prefix |\n| `_next` | `number` | Next available placeholder number |\n| `_extractor` | `Record\u003cstring, TransformFn\u003e` | Transform functions for reuse |\n\n## Usage Examples\n\n```js\nimport { dataToSqlParams } from '@marianmeres/data-to-sql-params';\n```\n\n### Basic Usage - Extract All Keys\n\n```js\n// No extractor - all defined keys are extracted (undefined values are skipped)\nconst result = dataToSqlParams({ a: 1, x: undefined, b: 2, c: 3 });\n/* {\n    keys: [ '\"a\"', '\"b\"', '\"c\"' ],\n    placeholders: [ '$1', '$2', '$3' ],\n    pairs: [ '\"a\" = $1', '\"b\" = $2', '\"c\" = $3' ],\n    values: [ 1, 2, 3 ],\n    map: { $a: 1, $b: 2, $c: 3 },\n    _next: 4,\n    _extractor: { ... }\n} */\n```\n\n### Whitelist Specific Keys\n\n```js\n// Extract only specified keys (undefined values like \"x\" are skipped)\nconst result = dataToSqlParams(\n\t{ a: 1, x: undefined, b: 2, c: 3 },\n\t['b', 'c', 'x']\n);\n/* {\n    keys: [ '\"b\"', '\"c\"' ],\n    placeholders: [ '$1', '$2' ],\n    values: [ 2, 3 ],\n    pairs: [ '\"b\" = $1', '\"c\" = $2' ],\n    map: { $b: 2, $c: 3 },\n    _next: 3\n} */\n```\n\n### Transform Values During Extraction\n\n```js\n// Apply custom transformations (type casting, JSON stringify, etc.)\n// Use `true` to include a key without transformation\nconst result = dataToSqlParams(\n\t{ id: 1, name: 'alice', createdAt: new Date('2024-01-01') },\n\t{\n\t\tid: true,\n\t\tname: (v) =\u003e v.toUpperCase(),\n\t\tcreatedAt: (v) =\u003e v.toISOString(),\n\t}\n);\n/* {\n    keys: [ '\"id\"', '\"name\"', '\"createdAt\"' ],\n    placeholders: [ '$1', '$2', '$3' ],\n    values: [ 1, 'ALICE', '2024-01-01T00:00:00.000Z' ],\n    pairs: [ '\"id\" = $1', '\"name\" = $2', '\"createdAt\" = $3' ],\n    map: { $id: 1, $name: 'ALICE', $createdAt: '2024-01-01T00:00:00.000Z' },\n    _next: 4\n} */\n```\n\n### Exclude Specific Keys\n\n```js\n// Use `false` to explicitly exclude keys\nconst result = dataToSqlParams(\n\t{ id: 1, password: 'secret', email: 'user@example.com' },\n\t{\n\t\tid: true,\n\t\tpassword: false,  // Exclude from extraction\n\t\temail: true,\n\t}\n);\n// Only id and email are extracted, password is excluded\n```\n\n## Real-World Examples\n\n### Dynamic INSERT Statement\n\n```js\nconst userData = {\n\tname: 'John Doe',\n\temail: 'john@example.com',\n\trole: 'admin',\n\tcreatedAt: new Date(),\n};\n\nconst { keys, placeholders, values } = dataToSqlParams(userData, {\n\tname: true,\n\temail: true,\n\trole: true,\n\tcreatedAt: (d) =\u003e d.toISOString(),\n});\n\nconst sql = `INSERT INTO users (${keys.join(', ')}) VALUES (${placeholders.join(', ')})`;\n// INSERT INTO users (\"name\", \"email\", \"role\", \"createdAt\") VALUES ($1, $2, $3, $4)\n\nawait db.query(sql, values);\n```\n\n### Dynamic UPDATE Statement\n\n```js\nconst updates = {\n\tname: 'Jane Doe',\n\temail: 'jane@example.com',\n\tupdatedAt: new Date(),\n};\n\nconst { pairs, values, _next, _extractor } = dataToSqlParams(updates, {\n\tname: true,\n\temail: true,\n\tupdatedAt: (d) =\u003e d.toISOString(),\n});\n\n// Add WHERE condition using _next for the next placeholder number\nconst userId = 123;\nconst sql = `UPDATE users SET ${pairs.join(', ')} WHERE \"id\" = $${_next}`;\n// UPDATE users SET \"name\" = $1, \"email\" = $2, \"updatedAt\" = $3 WHERE \"id\" = $4\n\nawait db.query(sql, [...values, userId]);\n```\n\n### Conditional INSERT or UPDATE (Upsert Pattern)\n\n```js\nconst data = { id: 1, name: 'Alice', status: 'active' };\nconst exists = await checkIfExists(data.id);\n\nconst { keys, placeholders, values, pairs, _next, _extractor } = dataToSqlParams(\n\tdata,\n\t{\n\t\tid: true,\n\t\tname: true,\n\t\tstatus: true,\n\t}\n);\n\nlet sql;\nif (exists) {\n\t// UPDATE: use pairs and add WHERE clause\n\tconst pk = 'id';\n\tsql = `UPDATE users SET ${pairs.join(', ')} WHERE \"${pk}\" = $${_next}`;\n\t// UPDATE users SET \"id\" = $1, \"name\" = $2, \"status\" = $3 WHERE \"id\" = $4\n\tvalues.push(_extractor[pk](data[pk]));\n} else {\n\t// INSERT: use keys and placeholders\n\tsql = `INSERT INTO users (${keys.join(', ')}) VALUES (${placeholders.join(', ')})`;\n\t// INSERT INTO users (\"id\", \"name\", \"status\") VALUES ($1, $2, $3)\n}\n\nawait db.query(sql, values);\n```\n\n### Using Named Parameters\n\nSome database drivers support named parameters with the `$key` syntax:\n\n```js\nconst { map } = dataToSqlParams({\n\tuserId: 123,\n\tstatus: 'active',\n});\n\n// If your DB driver supports named parameters:\nawait db.run('UPDATE users SET status = $status WHERE id = $userId', map);\n// map = { $userId: 123, $status: 'active' }\n```\n\n### Reusing Transform Functions\n\n```js\nconst data = { createdAt: new Date(), updatedAt: new Date() };\nconst { _extractor } = dataToSqlParams(data, {\n\tcreatedAt: (d) =\u003e d.toISOString(),\n\tupdatedAt: (d) =\u003e d.toISOString(),\n});\n\n// Later, reuse the same transformations for consistency\nconst newDate = new Date();\nconst transformed = _extractor.createdAt(newDate);\n// Ensures dates are always formatted the same way\n```\n\n## Important Notes\n\n### SQL Identifier Escaping\n\nThe package properly escapes SQL identifiers according to the SQL standard (quotes are doubled). This protects against malformed identifiers:\n\n```js\nconst { keys } = dataToSqlParams({ 'user\"name': 'test' });\n// keys = ['\"user\"\"name\"'] - quotes are escaped\n```\n\n**Note:** Field names (keys) come from your code, not user input. Values are safely parameterized. The package does not protect against SQL injection in field names from untrusted sources.\n\n### Database Compatibility\n\n- **PostgreSQL** - Full compatibility (`$1`, `$2` style)\n- **SQLite** - Compatible with numbered parameters\n- **MySQL/MariaDB** - Requires `?` placeholders (you'll need to adapt)\n- **SQL Server** - Requires `@p1`, `@p2` style (you'll need to adapt)\n\n### The `map` Object\n\nThe `map` property uses `$` prefix for field names (e.g., `{$name: 'John', $age: 30}`), which differs from the numbered placeholders (`$1`, `$2`). This is intentional - it provides named parameter support for database drivers that support it (like `better-sqlite3`).\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarianmeres%2Fdata-to-sql-params","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarianmeres%2Fdata-to-sql-params","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarianmeres%2Fdata-to-sql-params/lists"}