Validate and auto-generate TypeScript types from raw SQL queries in PostgreSQL.

Overview

SafeQL

Write SQL Queries With Confidence • Get started

npm version

Install

I would first recommend follow the instructions in the documentation.

npm install --save-dev @ts-safeql/eslint-plugin libpg-query

Features

  • ⚡️ Automatic Type Inference & Validation:

    SafeQL automatically infers the type of the query result based on the query itself.

  • 🖖 Compatible With Popular SQL Libraries:

    SafeQL works with any PostgreSQL client, including Prisma, Sequelize, pg, postgres, and more.

  • 🛠️ Easy To Use

    SafeQL was built in mind to be easy to use and integrate with your existing codebase.

  • 📦 Built with Monorepos & Microservices in mind:

    SafeQL was built with monorepos and microservices in mind, and it's easy to use with multiple databases.

Comments
  • Unexpected error when doing conditional query

    Unexpected error when doing conditional query

    Describe the bug SafeQL throws an unsupported conditional expression error when doing a conditional query on Postgres. This is a feature in postgres.js but it seems like SafeQL doesn't allow for these kinds of queries. The queries below would throw this error Invalid Query: Unsupported conditional expression flags (true = 524288, false = 524288).

    type A = { a: number | null; b: string | null; c: string | null };
    export async function query(a: number) {
      return await sql<A[]>`
        SELECT
          *
        FROM
          try_safe_ql ${a ? sql`WHERE a = ${a}` : sql``}
    `;
    }
    
    export async function query3(a: number) {
      return await sql<A[]>`
      SELECT
       *
      FROM
        try_safe_ql
      WHERE
        c is not null ${a ? sql`AND a = ${a}` : sql``}
    `;
    }
    

    According to postgres.js, it is normal to do these kinds of queries

    To Reproduce Steps to reproduce the behavior:

    1. Setup SafeQL
    2. Use this code in .ts file
    type A = { a: number | null; b: string | null; c: string | null };
    export async function query(a: number) {
      return await sql<A[]>`
        SELECT
          *
        FROM
          try_safe_ql ${a ? sql`WHERE a = ${a}` : sql``}
    `;
    }
    

    Expected behavior I expected no error for these kinds of queries

    Screenshots Screenshot 2022-11-10 at 16 19 15 Screenshot 2022-11-10 at 16 19 39

    Desktop (please complete the following information):

    • OS: MAC OS
    • PostgreSQL version 14
    • Version [e.g. 22]

    Additional context Add any other context about the problem here.

    opened by Eprince-hub 12
  • Support for utility types

    Support for utility types

    Hi @Newbie012 , hope you are well! 👋

    Is your feature request related to a problem? Please describe.

    It would be great to be able to use generic utility types such as Pick and Omit with existing types to be able to transform existing types instead of copying them throughout the codebase:

    type User = {
      id: number;
      username: string;
    }
    
    export async function getUserByUsername(username: string) {
      const [user] = await sql<Pick<User, 'id'>[]>`
        SELECT
          id
        FROM
          users
        WHERE
          username = ${username}
      `;
      return user;
    }
    

    Right now, this leads to a confusing error message:

    Query has incorrect type annotation.
    	Expected: null[]`
    	Actual: { id: number; }[]
    eslint @ts-safeql/check-sql
    

    Describe the solution you'd like

    It would be great if the utility types worked

    Describe alternatives you've considered

    Workaround:

    Use the literal object type instead of the utility type (decreasing maintainability):

    export async function getUserByUsername(username: string) {
      const [user] = await sql<{ id: number }[]>`
        SELECT
          id
        FROM
          users
        WHERE
          username = ${username}
      `;
      return user;
    }
    

    Additional context

    --

    bug 
    opened by karlhorky 12
  • Support Idiomatic Postgres.js

    Support Idiomatic Postgres.js

    Hi @Newbie012 👋 First of all, thanks again for this library, so amazing!

    Is your feature request related to a problem? Please describe.

    Reading the first Before we begin section on the Postgres.js docs page, it becomes clear that idiomatic Postgres.js is not supported:

    SafeQL supports by design only the following pattern: ...

    Screen Shot 2022-09-11 at 17 39 15

    It would be nice to be able to keep the code simple when using SafeQL and not have to create an extra wrapper for every project using Postgres.js + SafeQL.

    For us, we would like to avoid any extra code / boilerplate because we are teaching beginners to programming.

    Describe the solution you'd like

    It would be great to remove this limitation and allow for idiomatic Postgres.js as in their docs:

    // db.js
    import postgres from 'postgres'
    
    const sql = postgres({ /* options */ }) // will use psql environment variables
    
    export default sql
    
    // users.js
    import sql from './db.js'
    
    async function getUsersOver(age) {
      const users = await sql`
        select
          name,
          age
        from users
        where age > ${ age }
      `
      // users = Result [{ name: "Walter", age: 80 }, { name: 'Murray', age: 68 }, ...]
      return users
    }
    

    If the "by design" limitation is about the ESLint AST, I guess there are a few different ways this could be approached, so that it can support await sql()...

    Describe alternatives you've considered

    Staying with the wrapper

    Additional context

    This would also help the plugin with its claim of "easy to use and integrate with your existing codebase":

    Screen Shot 2022-09-11 at 17 52 43

    opened by karlhorky 11
  • Failing interpolation

    Failing interpolation

    Describe the bug When using Postgres.js, interpolation causes SafeQL error

    To Reproduce Steps to reproduce the behavior:

    async function query(id: number) {
      type Animal = {
        id: number;
      };
    
    // Works
      await sql<Animal[]>`SELECT * FROM animals WHERE id = 1`;
    
    // Fail
      await sql<Animal[]>`SELECT * FROM animals WHERE id = ${id}`;
    }
    

    Expected behavior Shouldn't fail with interpolation

    Screenshots Screenshot 2022-09-26 at 16 37 10

    Screenshot 2022-09-26 at 16 24 08

    Desktop (please complete the following information):

    • OS: Mac OS
    • PostgreSQL version 13
    • Version [e.g. 22]

    Additional context Add any other context about the problem here.

    needs investigation 
    opened by Eprince-hub 10
  • Description of migrations is missing

    Description of migrations is missing

    Describe the bug

    On the Configuration page of the docs, the "2. A basic example of migrations folder" section is missing a description of what migrations are, both:

    1. In a general sense (general definition of migrations)
    2. In terms of SafeQL - what does SafeQL do with migrations and what behavior can the user expect / not expect?

    To Reproduce

    Steps to reproduce the behavior:

    1. Navigate to the docs page above
    2. Look for an explanation of migrations

    Expected behavior

    Migrations are explained

    Screenshots

    --

    Desktop (please complete the following information):

    • OS: n/a
    • PostgreSQL version: n/a
    • Version: n/a

    Additional context

    --

    documentation good first issue 
    opened by karlhorky 9
  • Remove unnecessary configuration options

    Remove unnecessary configuration options

    The configuration options on this page are confusing because they imply that Postgres.js and Sequelize can only be used with migrations instead of the simpler databaseUrl configuration.

    opened by karlhorky 4
  • `connections.transform` option conflicts with `no-template-curly-in-string`

    `connections.transform` option conflicts with `no-template-curly-in-string`

    Describe the bug

    When linting .eslintrc.js or .eslintrc.cjs, the built in no-template-curly-in-string rule reports a problem with the connections.transform syntax with a dollar sign in a non-template string:

    module.exports = {
      plugins: ['@ts-safeql/eslint-plugin'],
      rules: {
        '@ts-safeql/check-sql': [
          'error',
          {
            connections: [
              {
                databaseUrl: `postgres://postgres:postgres@localhost:5432/postgres`,
                tagName: 'sql',
                transform: '${type}[]', // 💥 Unexpected template string expression. (`no-template-curly-in-string`)
              },
            ],
          },
        ],
      },
    };
    

    To Reproduce

    Steps to reproduce the behavior:

    1. Enable the no-template-curly-in-string to be a warning or error
    2. Lint a .eslintrc.js file with the connections.transform option as specified in the code block above
    3. Observe the problem reported by ESLint

    Expected behavior

    The recommended connections.transform configuration shouldn't cause an error with a built-in ESLint rule.

    Maybe an alternative syntax that doesn't use the dollar?

    Screenshots

    --

    Desktop (please complete the following information):

    • OS: macOS Monterey 12.6 (21G115)
    • PostgreSQL version 14.2
    • Version @ts-safeql/[email protected]

    Additional context

    --

    opened by karlhorky 3
  • Switch from `Nullable` generic to `<type> | null`

    Switch from `Nullable` generic to ` | null`

    Is your feature request related to a problem? Please describe.

    It was confusing to me that this does not work:

    type Animal = {
      id: number;
      name: string | null;
    }
    
    // error: type of name `string | null` does not match `Nullable<string>`
    await sql<Animal[]>`
      SELECT * FROM animals
    `
    

    With this schema:

    CREATE TABLE animals (
      id integer PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
      name varchar(40)
    )
    

    Describe the solution you'd like

    Support the x | null union type when using a nullable database field

    Describe alternatives you've considered

    Apparently as shown in the examples, it shows that users can define their own Nullable generic type to achieve this:

    type Nullable<T> = T | null;
    
    type Animal = {
      id: number;
      name: Nullable<string>;
    }
    
    // no error
    await sql<Animal[]>`
      SELECT * FROM animals
    `
    

    But this seems less natural and discoverable than allowing | null unions

    Additional context

    --

    opened by karlhorky 3
  • ESLint server crash: `dyld[...]: missing symbol called`

    ESLint server crash: `dyld[...]: missing symbol called`

    Describe the bug

    Installing and running SafeQL on an M1 machine (process.arch === 'arm64') causes crashes in the VS Code ESLint Output panel that look like this:

    ...more...
    dyld[70673]: missing symbol called
    [Info  - 5:42:07 PM] Connection to server got closed. Server will restart.
    [Info  - 5:42:07 PM] ESLint server stopped.
    [Info  - 5:42:07 PM] ESLint server is starting
    [Info  - 5:42:07 PM] ESLint server running in node v16.11.0
    [Info  - 5:42:07 PM] ESLint server is running.
    [Info  - 5:42:07 PM] ESLint library loaded from: /Users/k/p/next-js-example-spring-2022/node_modules/eslint/lib/api.js
    dyld[70680]: missing symbol called
    [Error - 5:42:09 PM] The ESLint server crashed 5 times in the last 3 minutes. The server will not be restarted. See the output for more information.
    [Info  - 5:42:09 PM] ESLint server stopped.
    

    This also occurs on the command line:

    $ yarn eslint . --max-warnings 0
    yarn run v1.22.19
    $ /Users/k/p/next-js-example-spring-2022/node_modules/.bin/eslint . --max-warnings 0
    dyld[71873]: missing symbol called
    error Command failed with signal "SIGABRT".
    info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
    
    • I also tried upgrading Node.js from 16.11.0 to 18.10.0, but encountered a similar problem.
    • Switching to a Node.js v16 version that is using i386 architecture via Rosetta 2 (process.arch === 'x64') resolves the issue

    To Reproduce Steps to reproduce the behavior:

    1. Install and run SafeQL on an M1 / M2 (ARM - Apple Silicon) machine
    2. Open a file that causes a connection to the database
    3. Observe the crash in the VS Code Output -> ESLint panel

    Expected behavior

    It should run on Apple Silicon machines too.

    Screenshots

    --

    Desktop (please complete the following information):

    • OS: macOS Monterey 12.6 (21G115)
    • PostgreSQL version 14.2
    • Version @ts-safeql/[email protected]

    Additional context

    Also asked about this upstream in libpg-query here: https://github.com/pyramation/libpg-query-node/issues/9#issuecomment-1262491945

    opened by karlhorky 3
  • Fix `snake` documentation

    Fix `snake` documentation

    Thanks for #51!

    Just a quick fix for the documentation of the connections.fieldTransform: 'snake' option (at least, from what I'm understanding about the option)

    opened by karlhorky 3
  • Support for intersection types

    Support for intersection types

    Hi @Newbie012 👋 hope things are going great!

    Is your feature request related to a problem? Please describe.

    It would be great to be able to use intersection types with existing object type aliases to be able to transform existing types instead of copying them throughout the codebase:

    type User = {
      id: number;
      username: string;
    };
    
    type UserWithPasswordHash = User & {
      passwordHash: string;
    };
    
    export async function getUserWithPasswordHashById(id: number) {
      const [user] = await sql<UserWithPasswordHash[]>`
        SELECT
          id,
          username,
          password_hash
        FROM
          users
        WHERE
          id = ${id}
      `;
      return user;
    }
    

    Right now, this leads to a crash of ESLint with a confusing error message (as seen here: https://github.com/upleveled/security-vulnerability-examples-next-js-postgres/actions/runs/3330517524/jobs/5509108053):

    TypeError: Cannot read properties of undefined (reading 'members')
    Occurred while linting /home/runner/work/security-vulnerability-examples-next-js-postgres/security-vulnerability-examples-next-js-postgres/database/users.ts:24
    Rule: "@ts-safeql/check-sql"
        at tsTypeToText (/home/runner/work/security-vulnerability-examples-next-js-postgres/security-vulnerability-examples-next-js-postgres/node_modules/@ts-safeql/eslint-plugin/lib/utils/ts.utils.js:18:34)
        at tsTypeToText (/home/runner/work/security-vulnerability-examples-next-js-postgres/security-vulnerability-examples-next-js-postgres/node_modules/@ts-safeql/eslint-plugin/lib/utils/ts.utils.js:22:16)
        at getTypeAnnotationState (/home/runner/work/security-vulnerability-examples-next-js-postgres/security-vulnerability-examples-next-js-postgres/node_modules/@ts-safeql/eslint-plugin/lib/rules/check-sql.rule.js:271:49)
        at /home/runner/work/security-vulnerability-examples-next-js-postgres/security-vulnerability-examples-next-js-postgres/node_modules/@ts-safeql/eslint-plugin/lib/rules/check-sql.rule.js:206:37
        at /home/runner/work/security-vulnerability-examples-next-js-postgres/security-vulnerability-examples-next-js-postgres/node_modules/fp-ts/lib/Either.js:863:60
        at pipe (/home/runner/work/security-vulnerability-examples-next-js-postgres/security-vulnerability-examples-next-js-postgres/node_modules/fp-ts/lib/function.js:300:20)
        at reportCheck (/home/runner/work/security-vulnerability-examples-next-js-postgres/security-vulnerability-examples-next-js-postgres/node_modules/@ts-safeql/eslint-plugin/lib/rules/check-sql.rule.js:173:29)
        at checkConnectionByTagExpression (/home/runner/work/security-vulnerability-examples-next-js-postgres/security-vulnerability-examples-next-js-postgres/node_modules/@ts-safeql/eslint-plugin/lib/rules/check-sql.rule.js:236:16)
        at /home/runner/work/security-vulnerability-examples-next-js-postgres/security-vulnerability-examples-next-js-postgres/node_modules/@ts-safeql/eslint-plugin/lib/rules/check-sql.rule.js:160:16
        at e.run (/home/runner/work/security-vulnerability-examples-next-js-postgres/security-vulnerability-examples-next-js-postgres/node_modules/ts-pattern/dist/index.cjs:1:4927)
    error Command failed with exit code 2.
    

    Describe the solution you'd like

    It would be great if the intersection types worked

    Describe alternatives you've considered

    Workaround:

    Copy the properties from the other type to the new type (decreasing maintainability):

    type User = {
      id: number;
      username: string;
    };
    
    type UserWithPasswordHash = {
      id: number;
      username: string;
      passwordHash: string;
    };
    
    export async function getUserWithPasswordHashById(id: number) {
      const [user] = await sql<UserWithPasswordHash[]>`
        SELECT
          id,
          username,
          password_hash
        FROM
          users
        WHERE
          id = ${id}
      `;
      return user;
    }
    

    Additional context

    --

    opened by karlhorky 2
Releases(@ts-safeql/[email protected])
ORM for TypeScript and JavaScript (ES7, ES6, ES5). Supports MySQL, PostgreSQL, MariaDB, SQLite, MS SQL Server, Oracle, SAP Hana, WebSQL databases. Works in NodeJS, Browser, Ionic, Cordova and Electron platforms.

TypeORM is an ORM that can run in NodeJS, Browser, Cordova, PhoneGap, Ionic, React Native, NativeScript, Expo, and Electron platforms and can be used

null 30.1k Jan 3, 2023
Next-generation ORM for Node.js & TypeScript | PostgreSQL, MySQL, MariaDB, SQL Server & SQLite

Prisma Quickstart • Website • Docs • Examples • Blog • Slack • Twitter • Prisma 1 What is Prisma? Prisma is a next-generation ORM that consists of the

Prisma 28k Jan 2, 2023
Conjure SQL from GraphQL queries 🧙🔮✨

Sqlmancer Conjure SQL from your GraphQL queries ?? ?? ✨ ⚠️ This project is currently on hiatus. I am hoping to resume working on Sqlmancer once I have

Daniel Rearden 132 Oct 30, 2022
Run SPARQL/SQL queries directly on Virtuoso database with connection pool support.

?? virtuoso-connector Package that allows you to create a direct connection to the Virtuoso database and run queries on it. Connection can be used to

Tomáš Dvořák 6 Nov 15, 2022
Connect to private Google Cloud SQL instance through Cloud SQL Auth Proxy running in Kubernetes.

⛅ google-cloud-sql A CLI app which establishes a connection to a private Google Cloud SQL instance and port-forwards it to a local machine. Connection

Dinko Osrecki 10 Oct 16, 2022
A PostgreSQL client with strict types, detailed logging and assertions.

Slonik A battle-tested PostgreSQL client with strict types, detailed logging and assertions. (The above GIF shows Slonik producing query logs. Slonik

Gajus Kuizinas 3.6k Jan 3, 2023
A simple url shorter API built with nodejs running on Kubernetes in Google Cloud, using PostgreSQL for storage and cloud sql proxy.

Simple URL Shorter - Google Cloud - Kubernetes A simple url shorter API built with nodejs running on Kubernetes in Google Cloud, using PostgreSQL for

null 3 Nov 25, 2021
Database manager for MySQL, PostgreSQL, SQL Server, MongoDB, SQLite and others. Runs under Windows, Linux, Mac or as web application

Database manager for MySQL, PostgreSQL, SQL Server, MongoDB, SQLite and others. Runs under Windows, Linux, Mac or as web application

DbGate 2k Dec 30, 2022
Ultimate Script to complete PostgreSQL-to-PostgreSQL Migration right after AWS DMS task done

Ultimate Script to complete PostgreSQL-to-PostgreSQL Migration right after AWS DMS task done

방신우 22 Dec 23, 2022
TypeScript clients for databases that prevent SQL Injection

Safe From HTML Injection Using tagged template literals for queries, e.g. db.query(sql`SELECT * FROM users WHERE id=${userID}`); makes it virtually im

Forbes Lindesay 478 Dec 21, 2022
TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, MariaDB, PostgreSQL and SQLite databases.

TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, MariaDB, PostgreSQL and SQLite datab

MikroORM 5.4k Dec 31, 2022
just a graphql example created by typescript + fastify + mikro-orm(postgresql) + mercurius(graphql adaptor) + type-graphql

fastify-mikro-orm-mercurius-graphql-example A MikroORM boilerplate for GraphQL made with Fastify, Mercurius, Typescript using TypeGraphQL ?? Packages

Vigen 10 Aug 28, 2022
A tiny wrapper around pg that makes PostgreSQL a lot of fun to use. Written in TypeScript.

A tiny wrapper around pg that makes PostgreSQL a lot of fun to use. Written in TypeScript.

Mojolicious 8 Nov 29, 2022
Nodeparse - A lightweight, vanilla replacement for Express framework when parsing the HTTP body's data or parsing the URL parameters and queries with NodeJS.

nodeparse A lightweight, vanilla replacement for Express framework when parsing the HTTP body's data or parsing the URL parameters and queries with No

Trần Quang Kha 1 Jan 8, 2022
StashQL is a light-weight, open-source npm package that improves the speed of your GraphQL queries in your application.

Table of Contents What is StashQL? Install Getting Started Queries Mutations refillCache clearRelatedFields Logging The Team What is StashQL? StashQL

OSLabs Beta 67 Sep 30, 2022
A joi extension to validate MongoDB's ObjectIDs

@marsup/joi-objectid This is a simple joi extension to validate MongoDB's ObjectIDs. Installation npm install --save @marsup/joi-objectid Usage const

Nicolas Morel 2 Dec 15, 2022
AlaSQL.js - JavaScript SQL database for browser and Node.js. Handles both traditional relational tables and nested JSON data (NoSQL). Export, store, and import data from localStorage, IndexedDB, or Excel.

Please use version 1.x as prior versions has a security flaw if you use user generated data to concat your SQL strings instead of providing them as a

Andrey Gershun 6.1k Jan 9, 2023
Lovefield is a relational database for web apps. Written in JavaScript, works cross-browser. Provides SQL-like APIs that are fast, safe, and easy to use.

Lovefield Lovefield is a relational database written in pure JavaScript. It provides SQL-like syntax and works cross-browser (currently supporting Chr

Google 6.8k Jan 3, 2023