Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PG Migrations #99

Open
droganov opened this issue Apr 28, 2023 · 0 comments
Open

PG Migrations #99

droganov opened this issue Apr 28, 2023 · 0 comments
Assignees

Comments

@droganov
Copy link
Contributor

Это эпик и его нужно разбить на задачи

Что мы хотим
Создать модуль pg который создавать имграции из типов тс

что-то вроде

import { createMigrations, runMigrations } from '@yobta/pg'

import schema from './schema'

const migrations = createMigrations(schema)
await runMigrations()

кроме методов будут служебные типы для того чтобы делать тс-модели типы которые мапятся в схемы pg

Это пока наработки которые нужно будет проработать

export type FixedString<N extends number> = string & { _length: N };
export type VaryingString<N extends number> = string & { _maxLength: N };
export type DeprecatedField<FieldName extends string, FieldType> = {
  type: FieldType;
  deprecated: true;
  useInstead: FieldName;
};

Предполагаемый пример использования

export interface User {
  id: number;
  name: DeprecatedField<'fullName', FixedString<50>>;
  fullName: FixedString<50>;
  email: VaryingString<100>;
  createdAt: Date;
}

createMigrations должна собрать из типов миграции при помощи ts-morph

import { Project } from 'ts-morph';
import * as fs from 'fs';

function getTypeScriptTypes(fileName: string): Map<string, Map<string, string>> {
  const project = new Project();
  const sourceFile = project.addSourceFileAtPath(fileName);
  const interfaces = sourceFile.getInterfaces();
  const types = new Map<string, Map<string, string>>();

  interfaces.forEach((i) => {
    const properties = i.getProperties();
    const propertyMap = new Map<string, string>();

    properties.forEach((p) => {
      const type = p.getType().getText(p);
      propertyMap.set(p.getName(), type);
    });

    types.set(i.getName(), propertyMap);
  });

  return types;
}

function mapTypeScriptTypeToPg(type: string): string {
  if (type.startsWith('FixedString')) {
    const length = type.match(/<(\d+)>/)?.[1];
    return `char(${length})`;
  }

  if (type.startsWith('VaryingString')) {
    const maxLength = type.match(/<(\d+)>/)?.[1];
    return `varchar(${maxLength})`;
  }

  switch (type) {
    case 'number':
      return 'integer';
    case 'string':
      return 'text';
    case 'Date':
      return 'timestamp';
    default:
      throw new Error(`Unsupported type: ${type}`);
  }
}

function createMigrations(types: Map<string, Map<string, string>>): void {
  let migrationSql = '';

  types.forEach((properties, tableName) => {
    migrationSql += `CREATE TABLE ${tableName.toLowerCase()} (\n`;

    properties.forEach((type, columnName) => {
      const pgType = mapTypeScriptTypeToPg(type);
      migrationSql += `  ${columnName} ${pgType},\n`;
    });

    migrationSql = migrationSql.slice(0, -2); // remove the trailing comma
    migrationSql += `\n);\n\n`;
  });

  return [
    {tableName, migration}
  ]
}

runMigrations должна при помощи db-migrate db-migrate-pg выполнить необходимые миграции

Вообщем нужен стабильный и надежный механизм автоматизирующий управление таблицами на основе информации о типах моделей

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants