Awesome
<p align="center"> <img src="https://user-images.githubusercontent.com/33014/151277543-07b92bf4-6db7-4620-ad78-d0ce2e36d98b.png"/> </p>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:
- 'pg' - for PostgreSQL
- 'mysql2' - for MySQL
- 'mssql' - for SQL Server
Configuration
Configuration options are stored in a YAML file.
databaseType
: required - Possible values:postgres
,mysql
,mssql
outfile
: required - path to the output file to write type definitions to. This can be a relative path (to the yaml file itself)runtimeType
: required - The type of runtime type system to target.runtypes
ortypescript
camelCase
: optional - Whether or not to convert database object names to camelCase. Default true.dbUri
: optional - Database connection string. This can be passed in through the command line.extraInfo
: optional - Whether or not to include additional information. Includes one of:indexes
: optional - include index names in field comments.dataType
: optional - include index names in field comments.
excludeTables
: optional array - A list of tables to exclude from type generation. Default is none.tables
: optional array - A list of tables (or views) to include for type generation. Is overridden byexcludeTables
.includeViews
must be enabled to allow specification of views. Default is all.enums
: optional array - A list of enums to include for type generation. Default is to include all. This is not supported in all databases.enumsAsTypes
: optional boolean - whether or not to generate enum values as a typescript enum or union literal type. This is not supported in all databases.includeViews
: optional boolean - Whether or not to include views when generating types. Defaults tofalse
.content
: optional - Custom content that will be inserted at the top of the generated ts file.typeMappings
: optional - Map of database type names to target type information. Use this to provide custom type mapping from some database type. For example:typeMappings: tsrange: runtype: Interval
{data type name}
:runtype: {type name}
postgres
Additional configurations:
schema
- The name of the schema to target. This defaults to 'public'.includeForeignTables
- whether or not to include foreign tables.
mssql
Additional configurations:
schema
- The name of the schema to target. This defaults to 'dbo'.
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