javascript - Generera databasschema från Typescript-gränssnitt
Jag försöker generera ett schema baserat på AWS SDK-gränssnitten. Vi försöker bygga ett inventarium över alla resurser över flera konton. Dessa API-anrop ger mig mycket JSON, och jag behöver ett enkelt sätt att lagra det i en relationsdatabas.
Så min fråga är om jag kan generera ett SQL-databaseschema (för postgresql eller mysql) baserat på gränssnitt utan att lägga till enhetsanteckningar (dessa behövs till exempel för typeorm).
Svar #1
Typescript-gränssnitt finns inte vid körning. De hjälper under utveckling och kompilering (ja, jag vet att det är transpilering) tidkontroller.
Det kan finnas ett tillvägagångssätt som kan hjälpa dig med uppgiften.
Alternativ 1: Det enklaste sättet är att låta dina klasser implementera gränssnitten. Genom att göra detta försäkrar du dig om att du inte har missat något:
Exempel :
@Model()
export class MyDbModel implements TheAwsInterface {
}
Alternativ 2: Spara AWS-svaret som ett enda JSON-serialiserat objekt som en bson- eller strängkolumn i databasen.
Alternativ 3: Det andra alternativet är att själv implementera en statisk gränssnittstolk och modellgenerator. Ett mycket grundläggande exempel följer. Exemplet fungerar inte med inbäddade objekt, och det kan inte identifiera vilken som är primärnyckelkolumnen. Men med lite ansträngning och konfiguration kan det utökas.
Länk till lekplats här
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;
}
*/
