Skip to content
On this page

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 } from './Country';
import 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.Schema<CityId> = z.number() as any;

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

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

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

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