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

sql-mirror

v0.4.1

Published

Opiniated consistent SQL migrations using reusable raw SQL chunks

Downloads

13

Readme

🪞 sql-mirror

Opiniated consistent SQL migrations using reusable raw SQL chunks

✅ Requirements

  • NodeJS

⚙️ Features

  • Reusable raw SQL chunks
  • Generate up/down raw SQL migrations
  • Migration tool
  • Consistent table id naming & uuid_v4 value
  • Systematic created_at/updated_at columns
  • SQL chunks are automatically correctly sorted via topological order

✨ Usage

Installation

pnpm add -D sql-mirror

Input

import { sql, generateSqlFileContent } from "sql-mirror";
import fs from "fs";

const sqlMirrorConfig = {
  extensions: [sql.extension["uuid-ossp"]],
  tables: [
    {
      name: "user",
      columns: [
        sql.column.email("email"),
        "password_hash VARCHAR(255) NOT NULL",
        "password_reset_token VARCHAR(255)",
        "password_reset_token_generated_at TIMESTAMP",
        "email_confirmation_sent_at TIMESTAMP",
        "email_confirmed_at TIMESTAMP",
      ],
    },
    {
      name: "user_permission",
      columns: ["name VARCHAR(255) NOT NULL", "description TEXT"],
    },
    {
      name: "user_role",
      columns: ["name VARCHAR(255) NOT NULL", "description TEXT"],
    },
    {
      name: "user_role_permission",
      references: [
        {
          columnName: "user_role_id",
          tableNameRef: "user_role",
        },
        {
          columnName: "user_permission_id",
          tableNameRef: "user_permission",
        },
      ],
    },
    {
      name: "reward",
      columns: [
        "title VARCHAR NOT NULL",
        "img_url VARCHAR",
        "description TEXT NOT NULL",
        "points_price INT NOT NULL",
      ],
    },
    {
      name: "reward_user",
      references: [
        {
          columnName: "user_id",
          tableNameRef: "user",
        },
        {
          columnName: "reward_id",
          tableNameRef: "reward",
        },
      ],
    },
  ],
};

const newSqlFile = generateSqlFileContent(sqlMirrorConfig);

const dirPath = `./migrations/${new Date().toISOString()}`;

fs.mkdirSync(dirPath, { recursive: true });
fs.writeFileSync(`${dirPath}/up.sql`, newSqlFile.up);
fs.writeFileSync(`${dirPath}/down.sql`, newSqlFile.down);
fs.writeFileSync(
  `${dirPath}/sql-mirror-config.json`,
  JSON.stringify(sqlMirrorConfig, null, 2)
);

Output

migrations/2022-11-23T17:43:34.408Z/up.sql

-- This file was generated via sql-mirror at 2022-11-23T17:43:34.406Z
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

CREATE OR REPLACE FUNCTION updated_at_column()
RETURNS trigger AS
$BODY$
BEGIN
IF (NEW.updated_at IS NULL) THEN
NEW.updated_at = NOW();
END IF;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;

CREATE TABLE "user" (
    "user_id" uuid DEFAULT uuid_generate_v4 () PRIMARY KEY,
    "email" VARCHAR(255) UNIQUE NOT NULL,
    "password_hash" VARCHAR(255) NOT NULL,
    "password_reset_token" VARCHAR(255),
    "password_reset_token_generated_at" TIMESTAMP,
    "email_confirmation_sent_at" TIMESTAMP,
    "email_confirmed_at" TIMESTAMP,
    "created_at" TIMESTAMP DEFAULT (now()),
    "updated_at" TIMESTAMP
);
CREATE TRIGGER updated_at_on_user BEFORE UPDATE ON "user"
FOR EACH ROW
EXECUTE PROCEDURE updated_at_column();


CREATE TABLE "reward" (
    "reward_id" uuid DEFAULT uuid_generate_v4 () PRIMARY KEY,
    "title" VARCHAR NOT NULL,
    "img_url" VARCHAR,
    "description" TEXT NOT NULL,
    "points_price" INT NOT NULL,
    "created_at" TIMESTAMP DEFAULT (now()),
    "updated_at" TIMESTAMP
);
CREATE TRIGGER updated_at_on_reward BEFORE UPDATE ON "reward"
FOR EACH ROW
EXECUTE PROCEDURE updated_at_column();


CREATE TABLE "reward_user" (
    "reward_user_id" uuid DEFAULT uuid_generate_v4 () PRIMARY KEY,
    "user_id" uuid NOT NULL REFERENCES "user"(user_id),
    "reward_id" uuid NOT NULL REFERENCES "reward"(reward_id),
    "created_at" TIMESTAMP DEFAULT (now()),
    "updated_at" TIMESTAMP
);
CREATE TRIGGER updated_at_on_reward_user BEFORE UPDATE ON "reward_user"
FOR EACH ROW
EXECUTE PROCEDURE updated_at_column();


CREATE TABLE "user_role" (
    "user_role_id" uuid DEFAULT uuid_generate_v4 () PRIMARY KEY,
    "name" VARCHAR(255) NOT NULL,
    "description" TEXT,
    "created_at" TIMESTAMP DEFAULT (now()),
    "updated_at" TIMESTAMP
);
CREATE TRIGGER updated_at_on_user_role BEFORE UPDATE ON "user_role"
FOR EACH ROW
EXECUTE PROCEDURE updated_at_column();


CREATE TABLE "user_permission" (
    "user_permission_id" uuid DEFAULT uuid_generate_v4 () PRIMARY KEY,
    "name" VARCHAR(255) NOT NULL,
    "description" TEXT,
    "created_at" TIMESTAMP DEFAULT (now()),
    "updated_at" TIMESTAMP
);
CREATE TRIGGER updated_at_on_user_permission BEFORE UPDATE ON "user_permission"
FOR EACH ROW
EXECUTE PROCEDURE updated_at_column();


CREATE TABLE "user_role_permission" (
    "user_role_permission_id" uuid DEFAULT uuid_generate_v4 () PRIMARY KEY,
    "user_role_id" uuid NOT NULL REFERENCES "user_role"(user_role_id),
    "user_permission_id" uuid NOT NULL REFERENCES "user_permission"(user_permission_id),
    "created_at" TIMESTAMP DEFAULT (now()),
    "updated_at" TIMESTAMP
);
CREATE TRIGGER updated_at_on_user_role_permission BEFORE UPDATE ON "user_role_permission"
FOR EACH ROW
EXECUTE PROCEDURE updated_at_column();

migrations/2022-11-23T17:43:34.408Z/down.sql

-- This file was generated via sql-mirror at 2022-11-23T17:43:34.406Z
DROP TRIGGER IF EXISTS "updated_at_on_user" ON "user";
DROP TABLE IF EXISTS "user";

DROP TRIGGER IF EXISTS "updated_at_on_reward" ON "reward";
DROP TABLE IF EXISTS "reward";

DROP TRIGGER IF EXISTS "updated_at_on_reward_user" ON "reward_user";
DROP TABLE IF EXISTS "reward_user";

DROP TRIGGER IF EXISTS "updated_at_on_user_role" ON "user_role";
DROP TABLE IF EXISTS "user_role";

DROP TRIGGER IF EXISTS "updated_at_on_user_permission" ON "user_permission";
DROP TABLE IF EXISTS "user_permission";

DROP TRIGGER IF EXISTS "updated_at_on_user_role_permission" ON "user_role_permission";
DROP TABLE IF EXISTS "user_role_permission";

DROP FUNCTION updated_at_column();

DROP EXTENSION IF EXISTS "uuid-ossp";

🤔 Why ?

If you attempt to write raw SQL to make migrations, you will encounter these problems:

  • order carefully because of dependent table relations
  • rewrite same function/triggers usage
  • repeat writing created_at/updated_at table columns
  • writing consistent foreign keys is painful
  • ...

I wrote sql-mirror to be as close to raw SQL but with reusable raw SQL chunks

⚖️ License

MIT. Made with 💖