Home

Awesome

<p align="center"> <img src="https://user-images.githubusercontent.com/33014/151277543-07b92bf4-6db7-4620-ad78-d0ce2e36d98b.png"/> </p>

oclif Version Downloads/month License

Generate runtime types and TypeScript from your database schema. Currently, this supports generating runtime type definitions as runtypes, or directly to TypeScript, from PostgreSQL, MySQL, and SQL Server.

Example

Given the following table:

CREATE TYPE gender AS ENUM ('male', 'female');

CREATE TABLE app.user (
    id serial NOT NULL,
    email text NOT NULL,
    availability tsrange NULL,
    gender gender NULL
);

and schemart YAML configuration file with type customizations:

databaseType: 'postgres'
schema: 'app'
outfile: './schema.ts'
runtimeType: 'runtypes'
enumsAsTypes: true
includeViews: false
extraInfo:
  indexes: false
  dataType: false
excludeTables:
  - schema_migrations
content:
  import { Interval } from 'luxon';

  function isInterval(value:unknown): value is Interval {
    return value instanceof Interval;
  }
  const IntervalRt = rt.Unknown.withGuard(isInterval);

typeMappings:
  'tsrange':
    runtype: IntervalRt

run command:

$ schemart -f ./schemart.yaml -u postgres://user@localhost/my_db

generated ts file:

// generated from schemart
import * as rt from 'runtypes';
import { Interval } from 'luxon';

function isInterval(value:unknown): value is Interval {
  return value instanceof Interval;
}
const IntervalRt = rt.Unknown.withGuard(isInterval);

export const GenderEnum = rt.Union(
  rt.Literal('male'),
  rt.Literal('female')
);
export type Gender = Static<typeof GenderEnum>;

export const User = rt.Record({
  id: rt.Number,
  email: rt.String,
  availability: rt.Optional(IntervalRt.Or(rt.Null)), // custom Interval type
  gender: rt.Optional(GenderEnum.Or(rt.Null))
});
export type User = rt.Static<typeof User>;

where the resulting type User is inferred as:

type Users = {
    id: number
    email: string
    availability?: Interval
    gender?: "male" | "female"
}

Why use this?

You want to have generated TypeScript types that match your database schema and you want to ensure that data you've retrieved from the database matches those types. Generated types won't matter if the data returned from your queries don't match those types at runtime. For example:

const User = Record({
    id: Number,
    name: String,
    phoneNumber: String
});
type User = Static<typeof User>;

const { rows } = db.query(' SELECT id, name, phone_number FROM users; ')

// fails because 'phone_number' does not match the expected 'phoneNumber' field in User.
const users:User[] = rows.map((row) => User.check(row));

Runtime Type Checking

A number of different runtime type checking libraries exist. runtypes is an excellent library that is used in many projects to perform runtime type validation. However, a newer breed of libraries have emerged that are able to utilize ahead-of-time compilation to greatly simplify usage and improve performance. A good example of this is typia. These libraries are able to utilize TypeScript types directly without the need to predefine a schema. In those cases, you just need to generate the TypeScript types, which SchemaRT supports.

Install

npm install --save-dev schemart

or

yarn add -D schemart

Dependencies

SchemaRT does not install driver dependencies. You must install one or more of the following drivers:

Configuration

Configuration options are stored in a YAML file.

postgres

Additional configurations:

mssql

Additional configurations:

CLI

USAGE
  $ schemart

OPTIONS
  -d, --dryRun                 Perform all operations but don't actually generate output
  -f, --configFile=configFile  (required) Path to configuration file
  -u, --dbUri=dbUri            Database URI. Overrides value in configuration files.

Debugging

This uses the debug library. To enable debug output set the DEBUG environment variable:

DEBUG=schemart* schemart -f ./foo.yaml -u postgres://localhost