从 Typescript 接口生成数据库架构

ima*_*est 8 javascript database typescript

我正在尝试生成基于AWS SDK接口的架构。我们正在尝试建立多个帐户的所有资源的清单。这些 API 调用为我提供了大量 JSON,我需要一种简单的方法将其存储在关系数据库中。

所以我的问题是我可以基于接口生成 SQL 数据库模式(用于 postgresql 或 mysql)而不添加实体注释(例如 typeorm 需要这些注释)。

小智 0

Typescript 接口在运行时不存在。它们在开发和编译(是的,我知道它是转译)时间检查期间提供帮助。

可能有一种方法可以帮助您完成任务。

选项 1: 最简单的方法是让您的类实现接口。通过这样做,您可以确保您没有错过任何内容:

例子:

@Model()
export class MyDbModel implements TheAwsInterface {
}
Run Code Online (Sandbox Code Playgroud)

选项 2: 将 AWS 响应存储为单个 JSON 序列化对象,作为数据库中的 bson 或字符串列。

选项 3: 另一个选项是自己实现静态接口解析器和模型生成器。下面是一个非常基本的示例。该示例不适用于嵌套对象,并且无法识别哪一个是主键列。但通过一些努力和配置,它可能会被扩展。

游乐场链接在这里


const inputInterface = `
interface AwsUser {
  name: string;
  age: number;
  address: string;
}
`;

enum SupportedTypes {
  'string' = 'string',
  'number' = 'number',
}

type ParsedInterfaceResult = {
  interfaceName: string;
  props: Record<string, SupportedTypes>;
};

const removeNewLines = (input: string): string => {
  return input.replace('\n', '');
};

const extractInterfaceName = (input: string): string => {
  return input.substring(0, input.indexOf('{')).replace('interface', '').trim();
};

const parseInterfaceProps = (input: string): Record<string, SupportedTypes> => {
  const result = {};

  const props = input
    .substring(input.indexOf('{') + 1, input.indexOf('}') - 1)
    .split(';');

  props.forEach((prop) => {
    if (prop.trim() === '') {
      return;
    }
    const [key, value] = prop.split(':');
    result[key.trim()] = value.trim();
  });

  return result;
};

const parseInterface = (input: string): ParsedInterfaceResult => {
  const sanitizedInput = removeNewLines(input);
  return {
    interfaceName: extractInterfaceName(sanitizedInput),
    props: parseInterfaceProps(input),
  };
};

const convertToTypeOrmModel = (
  interfaceDefinittion: ParsedInterfaceResult
): string => {
  const lines: Array<string> = [
    'import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"',
    '',
  ];

  lines.push('@Entity()');
  lines.push(`export class ${interfaceDefinittion.interfaceName} {`);

  Object.keys(interfaceDefinittion.props).forEach((propName) => {
    lines.push(`  @Column()`);
    lines.push(`  ${propName}: ${interfaceDefinittion.props[propName]};`);
    lines.push(``);
  });

  lines.push('}', '');

  return lines.join('\n');
};

const result = parseInterface(inputInterface);

const generatedCode = convertToTypeOrmModel(result);

/*
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"

@Entity()
export class AwsUser {
  @Column()
  name: string;

  @Column()
  age: number;

  @Column()
  address: string;

}
*/
Run Code Online (Sandbox Code Playgroud)