{"id":15156338,"url":"https://github.com/cmtv/sqlean","last_synced_at":"2025-09-30T04:32:19.763Z","repository":{"id":57368320,"uuid":"399406287","full_name":"CMTV/sqlean","owner":"CMTV","description":"Simple SQLite database manager. Focus on writing code, rather then messing with queries.","archived":true,"fork":false,"pushed_at":"2021-09-21T09:39:07.000Z","size":79,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-01-14T03:36:21.635Z","etag":null,"topics":["database","db","entity","sql","sql-entity","sqlite"],"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/CMTV.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-08-24T09:23:04.000Z","updated_at":"2023-01-28T00:25:04.000Z","dependencies_parsed_at":"2022-09-05T20:51:23.504Z","dependency_job_id":null,"html_url":"https://github.com/CMTV/sqlean","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CMTV%2Fsqlean","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CMTV%2Fsqlean/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CMTV%2Fsqlean/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CMTV%2Fsqlean/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CMTV","download_url":"https://codeload.github.com/CMTV/sqlean/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234702069,"owners_count":18873824,"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":["database","db","entity","sql","sql-entity","sqlite"],"created_at":"2024-09-26T19:04:06.377Z","updated_at":"2025-09-30T04:32:14.480Z","avatar_url":"https://github.com/CMTV.png","language":"TypeScript","readme":"\u003cdiv align=\"center\"\u003e\n  \u003cp\u003e\u003c/p\u003e\n  \u003ca href=\"https://github.com/CMTV/sqlean\"\u003e\n    \u003cimg height=\"70\" src=\"sqlean.svg\"\u003e\n  \u003c/a\u003e\n  \u003cp\u003e\u003c/p\u003e\n  \u003ch1\u003eSQLean\u003cp\u003e\u003c/p\u003e\u003c/h1\u003e\n\u003c/div\u003e\n\n\u003cp\u003e\u003c/p\u003e\n\nSQLean (*/s_clean/*) is a simple SQLite database manager built on top of [better-sqlite3](https://www.npmjs.com/package/better-sqlite3) package. It's main purpose is to allow you to focus on writing **code** rather then messing with **queries**.\n\nWorking with a database on a low level is a nightmare since you have to convert your data to database format, then to query strings and vice verca.\n\nWith SQLean you can easily perform basic operations with database (select, insert, update, delete) passing data as objects and constructing `WHERE` clauses with code constructions instead of mixing strings with data.\n\nSQLean also supports **entity system** allowing you to create relations between TypeScript classes with SQLite columns using modern decorator syntax. With this system you can forget about SQL-stuff at all and work directly with classes and instances, letting SQLean to do all insert, update, select, delete job behind the scenes.\n\nBefore you start:\n\n* SQLean is intended to be used in TypeScript projects\n* SQLean is synchronous (just as [better-sqlite3](https://www.npmjs.com/package/better-sqlite3))\n* SQLean does not protect you from SQL-injections\n* SQLean **always** automatically converts `camelCase` (code side) to `snake_case` (db side) and vice verca\n\n## Quick links\n\n1. [Install](#install)\n2. [Opening database](#opening-database)\n3. [Simple Queries](#simple-queries)\n    * [Insert](#insert)\n    * [Building `WHERE` clauses](#building-where-clauses)\n    * [Select](#select)\n    * [Update and Delete](#update-and-delete)\n4. [Entity system](#entity-system)\n    * [Creating entity](#creating-entity)\n    * [Saving and Updating entity](#saving-and-updating-entity)\n    * [Retrieving entity](#retrieving-entity)\n    * [Deleting entity](#deleting-entity)\n5. [Using better-sqlite3](#using-better-sqlite3)\n\n## Install\n\n```console\n$ npm i sqlean\n```\n\n## Opening database\n\nLet's assume you already have a SQLite database called `data.db` file with columns structure and maybe some data. A typical way  to create such databases is to use something like [DB4S](https://sqlitebrowser.org/).\n\nFirst of all, we need to open the database file. It must be done before calling any other SQLean methods!\n\n```typescript\nimport { Db } from \"sqlean\";\n\nDb.Open('data.db');\n\n// Do stuff with database\n// ...\n\nDb.Close(); // Optional. Can be omitted\n```\n\n## Simple Queries\n\nThe basic idea is simple. You just call a desired static method of `Db` class and pass data object which contains info about table, columns and where clauses.\n\n### Insert\n\n```typescript\nlet customerData = {\n    customerId: 'cmtv',\n    firstName: 'Peter',\n    //secondName: 'Radko' // Allowed to be null in database\n    age: 23,\n    isPro: 1 // SQLite does not support Boolean values\n};\n\nDb.Insert({\n    table: 'customer',\n    columnValues: customerData\n});\n```\n\n| customer_id | first_name | second_name | age | is_pro |\n|-------------|------------|-------------|-----|--------|\n| cmtv        | Peter      | *NULL*      | 23  | 1      |\n\n### Building `WHERE` clauses\n\nThere are three ways to build `WHERE` clauses:\n\n1 - Pure string clause:\n```typescript\nlet where = `@firstName = 'Peter' AND 5 = 2`;\n\n// first_name = 'Peter' AND 5 = 2\n```\n\n2 - Single array-clause:\n```typescript\nlet where: WhereClause;\n    \n    where = ['@firstName', '=', 'Peter'];\n            // WHERE first_name = $param0\n\n    where = [2, '\u003e=', 5];\n            // $param0 \u003e= $param1\n\n    where = ['@customerId', 'LIKE', 'c%'];\n            // customer_id LIKE $param0\n```\n\n3 - Group clauses in which you can combine all three ways:\n```typescript\nlet where = AND(\n    ['@firstName', '=', 'Peter'],\n    OR(\n        ['@customerId', 'LIKE', 'c%'],\n        '2 \u003e= 5'\n    )\n);\n\n// (first_name = $param0) AND ((customer_id LIKE $param1) OR (2 \u003e= 5))\n```\n\nThere are two important things you should keep in mind.\n\nFirst of all, everything prefixed with `@` will be converted to `snake_case` and left in query without quotes.\n\nSecondly, notice how strings and numbers are converted into `$paramX` references in array-clauses.\nWhen query run, the values will be automatically injected adding quotes for strings if needed. This works only in array-clauses.\n\n### Select\n\nSelecting one row:\n\n```typescript\nlet cmtv = Db.Select.Get({\n    table: 'customer',\n    columns: '*',\n    where: ['@firstName', '=', 'Peter']\n});\n```\n\n```\n{ customerId: 'cmtv', firstName: 'Peter', secondName: null, isPro: 1 }\n```\n\nSelecting multiple rows:\n\n```typescript\nlet rows = Db.Select.All({\n    table:      'customer',\n    columns:    ['customerId', 'age'],\n    where:      OR('2 = 2', [3, '\u003e', 20])\n});\n```\n\n```\n[\n  { customerId: 'nnagibin', age: 25 },\n  { customerId: 'cmtv', age: 23 }     \n]\n```\n\nNotice how came casel column names automatically convert to snake case database column names and vice versa.\n\nReturn values can be plucked:\n\n```typescript\nDb.Select.All({\n    table:      'customer',\n    columns:    ['firstName'],\n    pluck:      true\n});\n```\n\n```\n[ 'Nicholas', 'Peter' ]\n```\n\n### Update and Delete\n\nThe `UPDATE` and `DELETE` queries are built the same way we already discovered:\n\n```typescript\nDb.Update({\n    table:          'customer',\n    columnValues:   { firstName: 'Steve'},\n    where:          ['@customerId', '=', 'cmtv']\n});\n\nDb.Delete({\n    table:  'customer',\n    where:  ['@customerId', '=', 'cmtv']\n});\n```\n\n## Entity system\n\nThe Entity system utilizes JS decorators and since it is an experimental feature you need to enable them in `tsconfig.json`.\nMoreover you also have to enable a feature for correct type casting from db values to class properties. \n\n```json\n\"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true\n}\n```\n\n### Creating entity\n\nThe entity is just a class extending `Entity` abstract class with some decorators on class and properties:\n\n```typescript\nimport { Column, Entity, PrimaryKey, Table } from \"sqlean\"\n\n@Table('customer')\nclass Customer extends Entity \n{\n    @PrimaryKey\n    @Column\n    customerId: string;\n\n    @Column\n    firstName: string;\n\n    @Column\n    secondName: string;\n\n    @Column\n    age: number;\n\n    @Column\n    isPro: boolean;\n}\n```\n\nYou can also override `pre/postSave/Delete/Get` methods to run additional queries when entity gets saved, deleted or retrieved from database.\n\n### Saving and Updating entity\n\nBoth saving (inserting) and updating entity is done via `save()` method. Calling it cause updating database values. Keep in mind that changing primary key columns will result in creating a new row in column when saving!\n\n```typescript\n// Creating entity instance\n\nlet cmtv = new Customer;\n    cmtv.customerId = 'CMTV';\n    cmtv.firstName = 'Peter';\n // cmtv.secondName = 'Radko' // `second_name` column allowed to be null  \n    cmtv.age = 23;\n    cmtv.isPro = true;\n\n// Inserting entity to database\n\ncmtv.save();\n```\n\n| customer_id | first_name | second_name | age | is_pro |\n|-------------|------------|-------------|-----|--------|\n| CMTV        | Peter      | *NULL*      | 23  | 1      |\n\n```typescript\n// Updating entity\n\ncmtv.secondName = 'Radko';\ncmtv.isPro = false;\n\ncmtv.save();\n```\n\n| customer_id | first_name | second_name | age | is_pro |\n|-------------|------------|-------------|-----|--------|\n| CMTV        | Peter      | Radko       | 23  | 0      |\n\n\n### Retrieving entity\n\nUse `getById()` static method of your entity class to retrieve rows from database. The return value is an instance of entity class or `null` if no rows were found.\n\nFirst argument can be a simple value for single primary key or an array of values for multi-column primary keys.\nOptional second argument accepts column names to retrieve in case you don't wont to load heavy data from database.\n\n```typescript\nlet cmtv = Customer.getById('CMTV');\n\nlet shortCmtv = Custom.getById('CMTV', ['customerId', 'age']);\n```\n\n```\nCustomer {\n  customerId: 'CMTV', \n  firstName: 'Peter', \n  secondName: 'Radko',\n  age: 23,\n  isPro: 0\n}\n\nCustomer { customerId: 'CMTV', age: 23 }\n```\n\n### Deleting entity\n\nThere are two ways to delete an entity: through its class or directly from instance:\n\n```typescript\nCustomer.delete('CMTV');\n\n/* OR */\n\nlet cmtv = Customer.getById('CMTV');\ncmtv.delete();\n```\n\n## Using better-sqlite3\n\nIf you need to build complex SQL queries or access low-level database settings you can always access [better-sqlite3](https://www.npmjs.com/package/better-sqlite3) database instance directly by accessing `_db` property:\n\n```typescript\nimport { Db, DB } from \"sqlean\";\n\nDb.Open('data.db');\n\nDB._db.pragma('cache_size = 32000');\nDB._db.pragma('journal_mode = WAL');\n\nDB._db.prepare('CREATE TABLE my_table (my_primary_key INTEGER NOT NULL, my_column TEXT, PRIMARY KEY(my_primary_key))').run();\n```\n\nNotice the small difference between `Db` class which is used to access SQLean static methods and `DB` singleton instance!\n\nFor more information about `_db` see official better-sqlite3 [docs](https://github.com/JoshuaWise/better-sqlite3/blob/master/docs/api.md).","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcmtv%2Fsqlean","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcmtv%2Fsqlean","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcmtv%2Fsqlean/lists"}