{"id":15285373,"url":"https://github.com/noblemajo/al-sql","last_synced_at":"2026-03-04T03:00:35.798Z","repository":{"id":57175393,"uuid":"434685152","full_name":"NobleMajo/al-sql","owner":"NobleMajo","description":"Abstraction_Layer-Sql is a sql abstraction layer that can be used for every sql database to perform simple querys.","archived":false,"fork":false,"pushed_at":"2026-02-18T12:47:34.000Z","size":453,"stargazers_count":39,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-02-18T16:56:39.643Z","etag":null,"topics":["database","javascript-library","mariadb","mysql","mysqldb","node","node-js","nodejs","npm","npm-library","npm-package","postgres","postgresql","sql","sqlite","typescript","typescript-library"],"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/NobleMajo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","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":null,"dco":null,"cla":null}},"created_at":"2021-12-03T17:48:59.000Z","updated_at":"2026-02-18T12:47:37.000Z","dependencies_parsed_at":"2025-04-12T23:54:41.828Z","dependency_job_id":"cdc1564b-b9dd-4547-bc59-ebe746e1912c","html_url":"https://github.com/NobleMajo/al-sql","commit_stats":null,"previous_names":["majo418/al-sql"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/NobleMajo/al-sql","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NobleMajo%2Fal-sql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NobleMajo%2Fal-sql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NobleMajo%2Fal-sql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NobleMajo%2Fal-sql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NobleMajo","download_url":"https://codeload.github.com/NobleMajo/al-sql/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NobleMajo%2Fal-sql/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30070479,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-04T01:03:42.280Z","status":"online","status_checked_at":"2026-03-04T02:00:07.464Z","response_time":59,"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":["database","javascript-library","mariadb","mysql","mysqldb","node","node-js","nodejs","npm","npm-library","npm-package","postgres","postgresql","sql","sqlite","typescript","typescript-library"],"created_at":"2024-09-30T15:04:26.518Z","updated_at":"2026-03-04T03:00:35.780Z","avatar_url":"https://github.com/NobleMajo.png","language":"TypeScript","readme":"# al-sql\n\n![CI/CD](https://github.com/noblemajo/al-sql/actions/workflows/npm-publish.yml/badge.svg)\n![MIT](https://img.shields.io/badge/license-MIT-blue.svg)\n![typescript](https://img.shields.io/badge/dynamic/json?style=plastic\u0026color=blue\u0026label=Typescript\u0026prefix=v\u0026query=devDependencies.typescript\u0026url=https%3A%2F%2Fraw.githubusercontent.com%2Fnoblemajo%2Fal-sql%2Fmain%2Fpackage.json)\n![npm](https://img.shields.io/npm/v/al-sql.svg?style=plastic\u0026logo=npm\u0026color=red)\n\u003c!-- ![github](https://img.shields.io/badge/dynamic/json?style=plastic\u0026color=darkviolet\u0026label=GitHub\u0026prefix=v\u0026query=version\u0026url=https%3A%2F%2Fraw.githubusercontent.com%2Fnoblemajo%2Fal-sql%2Fmain%2Fpackage.json) --\u003e\n\n![](https://img.shields.io/badge/dynamic/json?color=green\u0026label=watchers\u0026query=watchers\u0026suffix=x\u0026url=https%3A%2F%2Fapi.github.com%2Frepos%2Fnoblemajo%2Fal-sql)\n![](https://img.shields.io/badge/dynamic/json?color=yellow\u0026label=stars\u0026query=stargazers_count\u0026suffix=x\u0026url=https%3A%2F%2Fapi.github.com%2Frepos%2Fnoblemajo%2Fal-sql)\n![](https://img.shields.io/badge/dynamic/json?color=navy\u0026label=forks\u0026query=forks\u0026suffix=x\u0026url=https%3A%2F%2Fapi.github.com%2Frepos%2Fnoblemajo%2Fal-sql)\n\u003c!-- ![](https://img.shields.io/badge/dynamic/json?color=darkred\u0026label=open%20issues\u0026query=open_issues\u0026suffix=x\u0026url=https%3A%2F%2Fapi.github.com%2Frepos%2Fnoblemajo%2Fal-sql)\n![](https://img.shields.io/badge/dynamic/json?color=orange\u0026label=subscribers\u0026query=subscribers_count\u0026suffix=x\u0026url=https%3A%2F%2Fapi.github.com%2Frepos%2Fnoblemajo%2Fal-sql) --\u003e\n\n\"al-sql\" is a Abstraction_Layer for sql databases to perform simple sql querys.\n\nYou create or use a sql dialect interface and a sql connection interface for your sql database.\nWith this you can create a SqlClient instance which provides full controll over a database and its table structure.\n\nThere is already a working postgres abstraction implementation that you can use for a postgres databases or as base to create a own abstraction implementation (see [here](#getting-started-postgres)).\n\n---\n\n- [al-sql](#al-sql)\n- [Getting started (postgres)](#getting-started-postgres)\n  - [1. Install package](#1-install-package)\n  - [2. Client cnnnections](#2-client-cnnnections)\n  - [3. Table definition](#3-table-definition)\n  - [4. Implement control functions](#4-implement-control-functions)\n  - [6. Use the table](#6-use-the-table)\n- [Debugging help](#debugging-help)\n- [Layer Implementation](#layer-implementation)\n  - [AbstractSqlDialect](#abstractsqldialect)\n  - [AbstractSqlConnection](#abstractsqlconnection)\n  - [Postgres connection via 'pg'](#postgres-connection-via-pg)\n- [NPM Scripts](#npm-scripts)\n  - [use](#use)\n  - [base scripts](#base-scripts)\n  - [watch mode](#watch-mode)\n- [Contributing](#contributing)\n- [License](#license)\n- [Disclaimer](#disclaimer)\n\n# Getting started (postgres)\n## 1. Install package\n```sh\nnpm i al-sql\n```\n\n## 2. Client cnnnections\nDon't worry, much of it is or can be copied and pasted or distributed across multiple files.\n\nImplement the base client connection:\n```ts\nimport { SqlClient } from \"al-sql\"\nimport { PostgresConnection } from \"al-sql/dist/pg\"\n\nexport const client = new SqlClient(\n    new PostgresConnection(\n        env.POSTGRES_HOST,\n        env.POSTGRES_PORT,\n        env.POSTGRES_USER,\n        env.POSTGRES_PASSWORD,\n        env.POSTGRES_DB,\n    )\n)\n```\n\n## 3. Table definition\nDefine your tables in the database, this tables can be created via al-sql:\n```ts\n// user table example:\nexport const accountTable = client.getTable(\n    \"account\",\n    [{ // column example:\n        name: \"id\",\n        type: \"SERIAL\",\n        primaryKey: true,\n        nullable: false,\n    },{\n        name: \"name\",\n        type: \"VARCHAR\",\n        unique: true,\n        nullable: false,\n        size: 32,\n    },{\n        name: \"email\",\n        type: \"VARCHAR\",\n        unique: true,\n        nullable: false,\n        size: 128,\n    },]\n)\n\n// friendship example:\nexport const friendshipTable = client.getTable(\n    \"friendship\",\n    [{ // column example:\n        name: \"id\",\n        type: \"SERIAL\",\n        primaryKey: true,\n        nullable: false,\n    },{\n        name: \"sender_id\",\n        type: \"INT\",\n        nullable: false,\n    },{\n        name: \"receiver_id\",\n        type: \"INT\",\n        nullable: false,\n    },{\n        name: \"accepted\",\n        type: \"BOOL\",\n        nullable: false,\n        default: false,\n    },],\n    [{ // foreign keys example:\n        columnName: \"sender_id\",\n        foreignColumnName: \"id\",\n        foreignTableName: \"account\",\n    },{\n        columnName: \"receiver_id\",\n        foreignColumnName: \"id\",\n        foreignTableName: \"account\",\n    },]\n)\n```\n\n## 4. Implement control functions\nThis way database entities feel like local objects with control functions.\nThis is just a example, there are better implementations depends on the codebase and coding style:\n```ts\nexport async function getAccountByName(\n    name: string\n): Promise\u003cnumber\u003e {\n    const result = await accountTable.selectOne(\n        [\"id\"], // SELECT \"id\" FROM \"account\" LIMIT 1\n        { // WHERE name = $1 (\"name\" is a prepared statement)\n            name: name,\n        }\n    )\n\n    if (!result || typeof result.id != \"number\") {\n        throw new Error(\"User with name '\" + name + \"' not exists!\")\n    }\n\n    return result.id\n}\n\nexport async function getAccountByEmail(\n    email: string\n): Promise\u003cnumber\u003e {\n    const result = await accountTable.selectOne( \n        [\"id\"], // SELECT \"id\" from \"account\" LIMIT 1\n        { // WHERE email = $1 (\"email\" is a prepared statement)\n            email: email,\n        }\n    )\n    if (!result || typeof result.id != \"number\") {\n        throw new Error(\"User with email '\" + email + \"' not exists!\")\n    }\n    return result.id\n}\n\nexport async function createAccount(\n    name: string,\n    email: string\n): Promise\u003cnumber\u003e {\n    const result = await accountTable.insert(\n        { // INSERT INTO \"account\" (name, email) VALUES ($1, $2)\n            name: name,\n            email: email,\n        },\n        [\"id\"] // RETURNING \"ID\"\n    )\n    if (!result || typeof result.id != \"number\") {\n        throw new Error(\"User with email '\" + email + \"' not exists!\")\n    }\n    return result.id\n}\n\nexport async function requestFriendship(\n    senderId: number,\n    receiverId: number\n): Promise\u003cvoid\u003e {\n    await removeFriendship(senderId, receiverId)\n    // INSERT INTO \"friendship\" (sender_id, receiver_id) VALUES ($1, $2)\n    await friendshipTable.insert({ \n        sender_id: senderId,\n        receiver_id: receiverId,\n    })\n}\n\nexport async function acceptFriendship(\n    senderId: number,\n    receiverId: number\n): Promise\u003cvoid\u003e {\n    await friendshipTable.update(\n        { // UPDATE SET accepted = $1\n            accepted: true,\n        },{ // WHERE sender_id = $1 AND receiver_id = $2\n            sender_id: senderId,\n            receiver_id: receiverId,\n        },\n    )\n}\n\nexport async function getFriends(\n    user: number\n): Promise\u003cnumber[]\u003e {\n    const result = await Promise.all([\n        friendshipTable.select(\n            [ // SELECT \"friendship\".sender_id from \"friendship\"\n                [\"friendship\", \"sender_id\"],\n            ],\n            { // WHERE receiver_id = $1\n                receiver_id: user,\n            },\n        ),\n        friendshipTable.select(\n            [ // SELECT \"friendship\".receiver_id from \"friendship\"\n                [\"friendship\", \"receiver_id\"],\n            ],\n            { // WHERE sender_id = $1\n                sender_id: user,\n            }\n        )\n    ])\n    // merge results together\n    const friends: number[] = []\n    result[0].forEach((f) =\u003e friends.push(f.sender_id as number))\n    result[1].forEach((f) =\u003e friends.push(f.receiver_id as number))\n\n    return friends\n}\n\nexport async function removeFriendship(\n    user1: number,\n    user2: number\n): Promise\u003cvoid\u003e {\n    await Promise.all([\n        friendshipTable.delete(\n            { // DELETE FROM \"friendship\" WHERE sender_id = $1 AND receiver_id = $2\n                sender_id: user1,\n                receiver_id: user2\n            }\n        ),\n        friendshipTable.delete(\n            { // DELETE FROM \"friendship\" WHERE sender_id = $1 AND receiver_id = $2\n                sender_id: user2,\n                receiver_id: user1\n            }\n        )\n    ])\n}\n```\n\n## 6. Use the table\nAfter defining the tables in code use \"createTable()\" on the client to create the tables if not exist:\n```ts\nawait client.createTables()\n```\n\nYou can use the \"dropAllTables()\" function to drop all (defined) tables.\nThis is handy for debug and tests: \n```ts\n// drops all tables (cascaded) in reversed order\nawait client.dropAllTables()\n\n// creates all tables in normal order\nawait client.createAllTables()\n```\n\nFrom here on your can use the tables or control function to manipulate the database data.\n\n# Debugging help\nExample:  \nshowResult(object, ...options) / showTable(table, ...options)  \n![showTables output](https://raw.githubusercontent.com/noblemajo/al-sql/main/docs/pics/showTables.png)\n\n# Layer Implementation\nIf you want to create a own abstraction layer implementation you need to implement this two interfaces:\n - AbstractSqlDialect\n - AbstractSqlConnection\n\n## AbstractSqlDialect\nFirst you implement the sql querys for your sql dialect.\nYou can checkout the postgres implementation for help:\n```ts\nexport interface AbstractSqlDialect {\n    getDialectName(): string\n\n    getTablesQuery(\n        client: SqlClient\n    ): ExecutableSqlQuery\n\n    createTableQuery(\n        table: SqlTable\n    ): ExecutableSqlQuery\n    dropTableQuery(\n        table: SqlTable\n    ): ExecutableSqlQuery\n\n    insertQuery(\n        table: SqlTable,\n        set: SqlSetValueMap,\n        returning?: SqlResultColumnSelector | undefined,\n    ): ExecutableSqlQuery\n    updateQuery(\n        table: SqlTable,\n        set: SqlSetValueMap,\n        where?: SqlWhereSelector,\n        returning?: SqlResultColumnSelector | undefined,\n    ): ExecutableSqlQuery\n    selectQuery(\n        table: SqlTable,\n        select?: SqlResultColumnSelector,\n        where?: SqlJoinWhereSelector,\n        join?: number | undefined,\n        ...joins: SqlJoin[]\n    ): ExecutableSqlQuery\n    deleteQuery(\n        table: SqlTable,\n        where?: SqlWhereSelector,\n        returning?: SqlResultColumnSelector | undefined,\n    ): ExecutableSqlQuery\n}\n```\n\n## AbstractSqlConnection\nNow you can implement the needed sql connection based on the sql driver/library.\nIf two sql databases share the same sql dialect but need a other connection driver/library you can reuse the AbstractSqlDialect and just implement a other AbstractSqlConnection for that driver/library.\n```ts\nexport interface AbstractSqlConnection {\n    getDialect(): AbstractSqlDialect // HERE YOU RETURN YOUR SQL DIALECT IMPLEMENTATION\n\n    execute(query: ExecutableSqlQuery): Promise\u003cSqlQueryExecuteResult\u003e\n\n    isConnected(): Promise\u003cboolean\u003e\n    connect(): Promise\u003cvoid\u003e\n    close(): Promise\u003cvoid\u003e\n}\n```\n\n## Postgres connection via 'pg'\nThe postgres connection implementation looks like this:\n```ts\nexport class PostgresConnection implements AbstractSqlConnection {\n    public readonly client: Client\n    public readonly dialect: PostgresSqlDialect\n    public connected: boolean = false\n\n    constructor(\n        public readonly host: string,\n        public readonly port: number,\n        public readonly username: string,\n        public readonly password: string,\n        public readonly database: string\n    ) {\n        this.client = new Client({ // \u003c- \"Client\" is a export of the \"pg\"-package (postgres-client)\n            host: host,\n            port: port,\n            user: username,\n            password: password,\n            database: database\n        })\n        this.dialect = new PostgresSqlDialect()\n    }\n\n    getDialect(): AbstractSqlDialect {\n        return this.dialect\n    }\n\n    async execute(query: ExecutableSqlQuery): Promise\u003cSqlQueryExecuteResult\u003e {\n        try{\n            return this.client.query(\n                query[0],\n                query.slice(1)\n            )\n        }catch(err: Error | any){\n            await this.client.end().catch(() =\u003e {})\n            this.connected = false\n            throw err\n        }\n    }\n\n    async isConnected(): Promise\u003cboolean\u003e {\n        return this.connected\n    }\n\n    async connect(): Promise\u003cvoid\u003e {\n        await this.client.connect()\n        this.connected = true\n    }\n\n    async close(): Promise\u003cvoid\u003e {\n        await this.client.end()\n        this.connected = false\n    }\n}\n```\n\n# NPM Scripts\nThe npm scripts are made for linux.\nBut your welcome to test them on macos and windows and create feedback.\n\n## use\nYou can run npm scripts in the project folder like this:\n```sh\nnpm run \u003cscriptname\u003e\n```\nHere is an example:\n```sh\nnpm run test\n```\n\n## base scripts\nYou can find all npm scripts in the `package.json` file.\nThis is a list of the most important npm scripts:\n - test // test the app\n - build // build the app\n - exec // run the app\n - start // build and run the app\n\n## watch mode\nLike this example you can run all npm scripts in watch mode:\n```sh\nnpm run start:watch\n```\n\n# Contributing\nContributions to this project are welcome!  \nInterested users can refer to the guidelines provided in the [CONTRIBUTING.md](CONTRIBUTING.md) file to contribute to the project and help improve its functionality and features.\n\n# License\nThis project is licensed under the [MIT license](LICENSE), providing users with flexibility and freedom to use and modify the software according to their needs.\n\n# Disclaimer\nThis project is provided without warranties.  \nUsers are advised to review the accompanying license for more information on the terms of use and limitations of liability.\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnoblemajo%2Fal-sql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnoblemajo%2Fal-sql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnoblemajo%2Fal-sql/lists"}