{"id":23282426,"url":"https://github.com/medsaad/node-db-models","last_synced_at":"2026-04-19T04:38:26.861Z","repository":{"id":65460390,"uuid":"229465835","full_name":"Medsaad/node-db-models","owner":"Medsaad","description":"light-weighted NPM Package create an ORM for Databases queries (especially Relational Databases that performs complex where statements) ","archived":false,"fork":false,"pushed_at":"2020-04-11T10:44:33.000Z","size":122,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-27T15:57:42.781Z","etag":null,"topics":["models","mysql","orm","postgresql","query-builder"],"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/Medsaad.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}},"created_at":"2019-12-21T18:14:15.000Z","updated_at":"2020-04-11T11:05:42.000Z","dependencies_parsed_at":"2023-01-24T14:45:26.224Z","dependency_job_id":null,"html_url":"https://github.com/Medsaad/node-db-models","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/Medsaad/node-db-models","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Medsaad%2Fnode-db-models","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Medsaad%2Fnode-db-models/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Medsaad%2Fnode-db-models/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Medsaad%2Fnode-db-models/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Medsaad","download_url":"https://codeload.github.com/Medsaad/node-db-models/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Medsaad%2Fnode-db-models/sbom","scorecard":{"id":92371,"data":{"date":"2025-08-11","repo":{"name":"github.com/Medsaad/node-db-models","commit":"0ca2fe8df0502bd3acb0545f1f4e2dbdd24f8685"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","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":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"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":"Code-Review","score":0,"reason":"Found 0/30 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":"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":"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":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"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":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"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"}}]},"last_synced_at":"2025-08-15T08:09:38.518Z","repository_id":65460390,"created_at":"2025-08-15T08:09:38.518Z","updated_at":"2025-08-15T08:09:38.518Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279019059,"owners_count":26086512,"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-10-14T02:00:06.444Z","response_time":60,"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":["models","mysql","orm","postgresql","query-builder"],"created_at":"2024-12-20T00:17:14.523Z","updated_at":"2025-10-14T11:11:59.285Z","avatar_url":"https://github.com/Medsaad.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Node Relational Database Models (NRDBM)\n![npm](https://img.shields.io/npm/v/node-db-models)\n![npm](https://img.shields.io/npm/dw/node-db-models)\n![NPM](https://img.shields.io/npm/l/node-db-models)\n\n- [Summary](#summary)\n- [New \u0026 Future Features](#new--future-features)\n- [Get Started](#get-started)\n- [Code Examples](#code-examples)\n\n## Summary\n\nNRDBM is a light-weighted project aims to create an ORM for Databases queries (especially Relational Databases that performs complex where statements) to help developers create model classes for tables and query them using functions rather than plain string that is error-prune once the query start to gets a little long.\n\nNRDBM supports [postgres](https://www.npmjs.com/package/pg) and [mysql2](https://www.npmjs.com/package/mysql2) packages.\n\n## Current \u0026 Future Features\nThe package is consistently getting enhanced and updated. Your contributions are always welcome. Here are the functionality that are developed/being developed:\n- **Insert/Select/Update/Delete** Data from **Postgresql** and **MySQL** with complex nested where conditions.\n- Create **class passed models** for your tables.\n- Specify certain fields to be **selectable** by default instead of bringing everything in `SELECT *`.\n- Allow **HTML data** to be added in certain fields.\n- Extract data in various ways: **list, select one column, first item, slicing, chunking, pagination**.\n- Apply **joins** between tables.\n- **Soon**: Event Handling. Ex: onInsert(), onUpdate(), onSelect() functions within model classes.\n\n## Get Started\nInstall package using npm:\n```\n$ npm install --save node-db-models\n```\n\nConnect to your database using [pg](https://www.npmjs.com/package/pg) or [mysql2](https://www.npmjs.com/package/mysql2) package, then attach your connection with node-db-models:\n### For Postgres:\n\n```javascript\nconst Pg = require(\"pg\");\nconst { Connection, Model } = require('node-db-models');\n\nlet pgModConn = new Pg.Pool({\n        host: '127.0.0.1',\n        user: 'admin',\n        database: 'sampledb',\n        password: '*******',\n        port: 5432\n});\n\nlet conn = new Connection({\n        connection: pgModConn,\n        type: 'pg'\n});\n```\n\n### For MySQL:\n```javascript\n\nconst mysql = require('mysql2');\nconst { Connection, Model } = require('node-db-models');\n\nconst mysqlConn = mysql.createPool({\n        host: '127.0.0.1',\n        user: 'admin',\n        password: '*****',\n        database: 'sampledb',\n        waitForConnections: true,\n        connectionLimit: 10,\n        queueLimit: 0\n});\n\nlet conn = new Connection({\n        connection: mysqlConn,\n        type: 'mysql'\n});\n```\nThat's it. From now on everything will be the same across different connections. Let's create models for our databse tables that will extend `Model` class that we imported above:\n```javascript\nclass Post extends Model {\n        tableName = 'posts';\n        allowHtml = ['body'];\n        selectable = ['title', 'body', 'author_id', 'created_at::date'];\n        connection = conn; //the object created above\n}\n```\n- `tableName`: the table name in the database.\n- `allowHtml`: do not strip html tags from this column.\n- `selectable`: select those column by default when select() method is not invoked. If not used `SELECT *` will be implemented.\n- `connection`: pass the connection object after initiating `new Connection()`.\n\nCreate an object of that class and start building queries:\n```javascript\nlet post = new Post();\nlet postQuery = post.select(['title', 'body', 'created_at::date'])\n        .where([\"created_at\", \"\u003e\", \"2019-01-01\" ])\n        .orderBy([\n                {col: 'id', order: 'desc'}\n        ]);\n```\nYou can chain the following methods to your model object:\n- `select(columns):` passes an array of columns to your query builder.\n- `innerJoin(rightModel, leftField, rightField)`, `leftJoin(rightModel, leftField, rightField)` and `rightJoin(rightModel, leftField, rightField):`: the 3 methods performs inner, left and right joins (respectively) between the current model and another model. The first parameter should be an object from the model that you need join with. The second should be the column from the current model and third parameter should be the column from the model that was added in the first parameter.\n- `where(conditions)`: accept an array of query conditions that can be attached by 'AND' and 'OR' relations. Supported with comparisons are `=`, `≠`, `\u003e`, `≥`, `\u003c`, `≤`, `like`, `ilike`, `in` \u0026 `not in` where the last 2 - `in` \u0026 `not in`- expects to have array in its value `[\"id\", \"in\", [1, 2,3]]`.\n- `orderBy(orderList):` accepts an array of objects where you can add a list of order columns and order directions.\n- `groupBy(groupList)`: accepts a list of columns you can group by.\n- `set(values)`: a key value pairs of data that will be inserted or updated.\n\nAfter the query is built, you are expected to chain a method that tells the query execution class how do you want the data to be returned.\n```javascript\nlet postResults = await postQuery.list();\n```\nAll the following functions return a promise:\n- `list()`: lists all results found in the form of array of objects.\n- `col(column_name)`: returns an array of values of a certain column.\n- `listAfter(offset)`: skip an *offset* amount of  values and then list all values after it.\n- `firstOne()`: returns an object of the first row that meets conditions specified.\n- `find(id)`: returns an object of a certain model using it's *id*\n- `slice(skip, count)`: returns a *count* amount of rows after skipping another amount of rows.\n- `first(count)`: return the first amount of rows that meets conditions specified.\n- `paginate(perPage, currentPage)`: paginate through your results by passing rows per page and your current page.\n- `chunk(count, callback)`: instead of returning all elements in one chunk, you can process them in pieces using this method. You can pass the amount per chunk and the callback function to specify what you want to do for each chunk.\n- `insert()`: get chained after `set(data)` to insert data into database.\n- `update()`: get chained after `set(data)` and a group of `where()` conditions to update certain rows in database.\n- `delete()`: get chained after a group of `where()` conditions to delete certain rows in database.\n\n## Code Examples\n- Inserting new row to database:\n```javascript\nlet insertedRows = await post.set({title: 'blog post', body: '\u003cp\u003eHello World\u003c/p\u003e'}).insert();\nif(insertedRows !== 0){\n        //success\n}\n```\n- Updating certain rows in database:\n```javascript\nlet affectedRows = await post.set({title: 'another blog post'}).where(['id', '=', 25]).update();\nif(affectedRows !== 0){\n        //update successful\n}\n```\n- Deleting a row in database:\n```javascript\nlet rowDeleted = await post.where(['id', '=', 25]).delete();\nif(rowDeleted !== 0){\n        //delete successful\n}\n```\n- Find a row by id in database:\n```javascript\nlet row = await post.find(25);\n```\n- Perform a query with joins:\n```javascript\nlet userJoinQuery = user.innerJoin(post, 'id', 'post_author').select(['user_email']);\nlet userEmails = await userJoinQuery.list();\n```\n- Select query with conditions using AND \u0026 OR with grouping:\n```javascript\nlet post = new Post();\nlet conditions = {\n        relation: 'AND',\n        cond: []\n};\nconditions.cond.push([\"created_at::date\", \"\u003e\", \"2019-01-01\" ]);\nconditions.cond.push([\"author_id\", \"=\", 25 ]);\n//include a nested condition\nlet nestedConditions = {\n        relation: 'OR',\n        cond: []\n};\nnestedConditions.cond.push(['created_at::date', \"\u003e\", \"2019-05-01\"]);\nnestedConditions.cond.push(['created_at::date', \"\u003c\", \"2019-10-01\"]);\n//add nested condition into the list of conditions\nconditions.cond.push(nestedConditions);\nlet postQuery = post.select(['created_at::date', 'count(*) as posts'])\n       .where(conditions)\n       .groupBy(['created_at::date'])\n       .orderBy([{col: 'created_at::date', order: 'desc'}]);\n       \nlet postRes = await postQuery.list();\n```\nThe previous statement will produce a query like this:\n```sql\nSELECT created_at::date, count(*) as posts \nFROM posts \nWHERE (\n        created_at::date \u003e \"2019-01-01\" AND \n        author_id, \"=\", 25 AND\n        (\n                created_at::date \u003e \"2019-05-01\" OR\n                created_at::date \u003c \"2019-10-01\"\n        )\n) \nGROUP BY created_at::date \nORDER BY created_at::date desc;\n```\n\nCopyright (c) 2019-2020 Ahmed Saad Zaghloul (ahmedthegicoder@gmail.com) MIT License","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmedsaad%2Fnode-db-models","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmedsaad%2Fnode-db-models","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmedsaad%2Fnode-db-models/lists"}