Skip to content

kanel

Source of truth: PostgreSQL

Turn your Postgres schema into Typescript types that look like this:

ts
// @generated
// This file is automatically generated by Kanel. Do not modify manually.

import { countryId, type CountryId } from './Country';
import { z } from 'zod';

/** Identifier type for city */
export type CityId = number & { __flavor?: 'CityId' };

/** Represents the table public.city */
export default interface City {
  /** Database type: pg_catalog.int4 */
  city_id: CityId;

  /** Database type: pg_catalog.varchar */
  city: string;

  /** Database type: pg_catalog.int2 */
  country_id: CountryId;

  /** Database type: pg_catalog.timestamp */
  last_update: Date;
}

/** Represents the initializer for the table public.city */
export interface CityInitializer {
  /**
   * Database type: pg_catalog.int4
   * Default value: nextval('city_city_id_seq'::regclass)
   */
  city_id?: CityId;

  /** Database type: pg_catalog.varchar */
  city: string;

  /** Database type: pg_catalog.int2 */
  country_id: CountryId;

  /**
   * Database type: pg_catalog.timestamp
   * Default value: now()
   */
  last_update?: Date;
}

/** Represents the mutator for the table public.city */
export interface CityMutator {
  /** Database type: pg_catalog.int4 */
  city_id?: CityId;

  /** Database type: pg_catalog.varchar */
  city?: string;

  /** Database type: pg_catalog.int2 */
  country_id?: CountryId;

  /** Database type: pg_catalog.timestamp */
  last_update?: Date;
}

export const cityId = z.number() as unknown as z.Schema<CityId>;

export const city = z.object({
  city_id: cityId,
  city: z.string(),
  country_id: countryId,
  last_update: z.date(),
}) as unknown as z.Schema<City>;

export const cityInitializer = z.object({
  city_id: cityId.optional(),
  city: z.string(),
  country_id: countryId,
  last_update: z.date().optional(),
}) as unknown as z.Schema<CityInitializer>;

export const cityMutator = z.object({
  city_id: cityId.optional(),
  city: z.string().optional(),
  country_id: countryId.optional(),
  last_update: z.date().optional(),
}) as unknown as z.Schema<CityMutator>;

It does this by inspecting a live PostgreSQL database, sort of like a reverse object/relations mapper.

You check the generated code into your repository and work with it using Knex.js or similar.

The idea is introduced in this blog post.


Copyright © 2018 Kristian Dupont, licensed under the MIT License

Cinnamon