npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

vite-plugin-postgres-import

v0.7.0

Published

Vite plugin for importing SQL files as JS modules with sqlc-style annotations

Readme

vite-plugin-postgres-import

Ever wanted to ditch those ORMs and finally learn SQL?

If you use PostgreSQL and Vite - this plugin is right for you!

Start importing .sql files with sqlc-style annotations right into your JavaScript code today!

Usage

module.sql:

-- name: Query :one
select id
from t
where id = :id;

-- name: UpdateQuery :execrows
update t
set foo = :newFoo
where id = :id;

-- name: QueryMany :many
select *
from t;

-- name: MultiStatement :many
select *
from t;
-- :one
select something
from t
limit 1;
-- :execrows
delete from t
where foo = :foo;

usage.js:

import { Pool } from "pg";
import { Query, UpdateQuery, QueryMany, MultiStatement } from "./module.sql";

const pool = new Pool("...");

const { id } = await Query(pool, { id: 1 });

const rowsUpdated = await UpdateQuery(pool, { id: 1, newFoo: "bar" });

const array = await QueryMany(pool);

// array, object, number respectively
const [all, something, deleted] = await MultiStatement(pool, { foo: "bar" });

[!Warning]

Postgres does NOT allow using parameters in multi-statement queries.

The current implementation for them is a hackaround that involes injecting escaped values into the SQL string.

Annotations

The only 4 sqlc annotations that are available are the following:

  • :execresult - default if neither of the 3 below are provided, returns QueryResult.

    ex.: Query<R extends QueryResultRow = { ... }>(c): Promise<QueryResult<R>>

  • :one - returns template argument, or the default-parsed ones from the select/returning clause.

    ex.: Query<R extends QueryResultRow = { ... }>(c): Promise<R>

  • :many - returns template argument as an array, or the default-parsed ones from the select/returning clause.

    ex.: Query<R extends QueryResultRow = { ... }>(c): Promise<R[]>

  • :execrows - returns number of affected rows.

    ex.: Query(c): Promise<number>

4 additional annotations not found in sqlc are available:

  • :prepare - prepares the statement by passing query's name to query config.

[!Warning]

Similarly to parameters, Postgres does NOT allow preparing multi-statement queries. Using :prepare on a multi-statement query will result in an error. I warned you!

[!Warning]

Don't use identical names for prepared queries, regardless whether they're in different .sql modules or not:

one.sql:

-- name: One :one :prepare
select *
from t

another-one.sql:

-- name: One :one :prepare
select id
from t
where id = :id;

script.js:

import { One } from "./one.sql";
import { One as AnotherOne } from "./another-one.sql";

// definitely don't do this
await One(c);
await AnotherOne(c, { id: ... });

At best, you'd get an error in the provided example, due to mismatch in provided values, and at worst, assuming different examples, you'd be getting obscure bugs related to incorrect data.

  • :array - sets rowMode to 'array'. Modifies to type declarations accordingly:

    ex. :execresult: Query<R extends any[] = [ ... ]>(c): Promise<QueryArrayResult<R>>

    ex. :one: Query<R extends any[] = [ ... ]>(c): Promise<R>

    ex. :many: Query<R extends any[] = [ ... ]>(c): Promise<R[]>

  • :iterable - returns an AsyncGenerator. Once Async Iterator Helpers are in the standard, you can use crazy piping as following:

const result = await IterableQuery<{ ... }>(c, { foo: 'bar' })
    .flatMap(superComplicatedCodeThatIsMoreUsefulToRunFromJS)
    .filter(Boolean)
    .toArray();

Well maybe that didn't look too crazy, but if some filtering forces your squeel to become convoluted, and you're fine with moving some of that computation to JS, you can finally do that! Or at least when that proposal is in the language, that is.

  • :cursor - returns an Cursor

ex.: Query<R extends QueryResultRow = { ... }>(c): Promise<Cursor<R>>

ex. `:array`: `Query<R extends any[] = [ ... ]>(c): Promise<Cursor<R>>`

Configuring

typesFolder

Path to a folder where all declaration are kept relative to rootFolder, i.e. a file at path src/sql/module.sql will have its .d.ts file generated into ${typesFolder}/src/sql/module.sql.d.ts. Make sure you include this one in your tsconfig.json as "${typesFolder}/**/*.sql.d.ts".

default: 'node_modules/@types/vite-plugin-postgres-import/'

rootFolder

Root folder relative to which path calculation will be happening. May be useful for some I guess.

default: process.cwd()

What this plugin does NOT do

This plugin does not connect to the database or scan a schema folder, instead naively parsing select or returning clauses to figure out potential response types.

In a real TypeScript project you should probably still roll your own types?

And JavaScript projects still get the benefits of completions.

SvelteKit use case

I primarily use this in a SvelteKit project. The only thing I modify is setting typesFolder to '.svelte-kit/types' directory, and adding a ".svelte-kit/types/**/*.sql.d.ts" record to my include array in tsconfig.json.

Also, when using SvelteKit aliases you can absolutely shove all your sql modules in a src/sql directory with a $sql alias and have module declarations generated for all of the files! Works automagically out of the box.

License

MIT.