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 🙏

© 2024 – Pkg Stats / Ryan Hefner

squealy-ts

v0.0.10

Published

## Usage

Downloads

12

Readme

Squealy TS

Usage

import {
  createSchema,
  setup,
  query,
  select,
  join,
  where,
  all,
} from "squealy-ts";
import { create } from "squealy-ts-adapter-bun-sqlite";
import { Database } from "bun:sqlite";

const schema = createSchema(
  // define your data
  {
    users: {
      id: ["text", "PRIMARY KEY"], // string
      name: ["text", "NOT NULL"], // string
      age: "integer", // number | null
    },
    account: {
      id: ["text", "PRIMARY KEY"],
    },
    transaction: {
      id: ["text", "PRIMARY KEY"],
      amount: ["real", "NOT NULL"],
    },
  },
  // define the relations
  {
    users: {
      account: ["maybe one", "account", "id"], // type safe strings
    },
    account: {
      transactions: ["many", "transaction", "id"],
    },
    transaction: {
      source: ["one", "account", "id"],
      target: ["one", "account", "id"],
    },
  },
);

const adapter = create(new Database());

await pipe(adapter, setup(schema)); // create tables

const getTransactions = (sourceAccount: string) =>
  pipe(
    query(schema),
    select("transaction"), // again, a typesafe string
    join({
      source: true,
      target: true,
    }),
    where((row) => `${row.source.id} = "${sourceAccount}"`), // typesafe column access based on current context
    all,
  );

const transactions = await pipe(adapter, getTransactions("foo")); // Array<{id: string, amount: number, source: {id: string}, target: {id: string}}>

Keep it simple, keep it functional

As you can see from the snippet above squealy-ts almost reads like regular SQL while avoiding the pitfalls of a fluent API. It also integrates nicely with other concepts such as reader monads and partial application, enabling you to simply define your operations as a series of smaller steps. I'd recommend using fp-ts for that, but of course you can use any functionally oriented library as well, such as lodash-fp or ramda.

A Typescript "ORM" that won't block you.

squealy-ts is built around a few core tenets that are supposed to provide a balance between seamless SQL integration and sensible use cases.

no ORM can abstract all of SQL without becoming a worse version of SQL itself

In the end SQL has been designed to arbitrarily query your data in an efficient manner. ORMs on the other hand have been designed for some common programmatic use cases. Trying to abstract everything SQL has to offer would just result in another version of SQL that is most likely worse. That means: if you need advanced stuff like window functions, recursive SQL, and even CTEs you should write those in SQL. After all there's not much gained if you have to spend the same effort googling "how to do CTEs in ORM X" compared to just "how to do CTEs in SQL".

easy, code-first schema definition

Schemas should be flexible without breaking your brain. Just say what your Data looks like and how it's connected and squealy-ts will take care of setting up the database.

precise typings that are still fast enough to use

"Typesafety" has many levels - from simply being explicit about nullability to inferring structure from a string. Many other ORMs seem to think modelling "entities" as classes is already enough while completely forgetting about things like object-relational impedance mismatch while others try to fully type any SQL query which makes things like autocomplete reeeeally slow.

easy integration with raw SQL

squealy-ts isn't even an "ORM" in the classical sense - it's more of a SQL wrapper geared towards common programmatic interactions.

"don't migrate, rebuild instead"

Anybody who tells you SQL migrations can be automated or supported so that they become painless is either lying or hasn't had to deal with larger migrations. IMHO migrating databases is always problematic - luckily employing architectures like event sourcing nicely circumvent these problems. So squealy-ts doesn't even try to solve a problem that can more completely and easily be solved outside of SQL.

A note on autoincrementing keys and such

While fine in theory you often want to control your ids from a programmatic perspective anyway. If you want to sort your primary keys in chronological order you should probably look at ULIDs or UUID-v7.

Comparison with other ORMs

Drizzle

Drizzle has been a great inspiration but its typings are too slow and some aspects break the "SQL abstraction" tenet.

Prisma

Why learn a new schema language when you already have typescript?

Sequelize

No typesafety in current version, classes in the next... to quote from object-relational impedance mismatch: Object orientation is a poor basis for schemas.

TypeORM

Class based and even flaunts that it goes nicely with the Active Record Pattern... as referenced above: object-relational impedance mismatch!