Skip to content

Commit

Permalink
feat: generate .d.ts from db schema
Browse files Browse the repository at this point in the history
Closes: #34

PR-URL: #41
  • Loading branch information
tshemsedinov committed Sep 15, 2020
1 parent 4d0702f commit 9bef5d8
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 0 deletions.
12 changes: 12 additions & 0 deletions lib/schema-db.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,13 +164,25 @@ class DatabaseSchema {
async execute(sql) {
throw new Error(`Method is not implemented: execute(${sql})`);
}

async saveTypes(outputPath) {
const filePath = path.join(outputPath, 'database.d.ts');
console.log('Generating types ' + filePath);
const dts = [];
for (const name of this.order) {
const schema = this.entities.get(name);
dts.push(schema.toInterface());
}
await fs.writeFile(filePath, dts.join('\n\n') + '\n');
}
}

DatabaseSchema.implementations = {};

const create = async (schemaPath, outputPath) => {
const schema = await DatabaseSchema.load(schemaPath);
await schema.create(outputPath);
await schema.saveTypes(outputPath);
};

const generate = async schemaPath => {
Expand Down
29 changes: 29 additions & 0 deletions lib/schema.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
'use strict';

const vm = require('vm');
const path = require('path');
const fs = require('fs').promises;
const { toLowerCamel, isUpperCamel } = require('./utils.js');

const SCRIPT_OPTIONS = { timeout: 5000 };

const ES_TYPES = ['number', 'string', 'boolean'];

class Schema {
constructor(schemaPath) {
this.path = schemaPath;
this.name = path.basename(schemaPath, '.js');
this.entity = null;
return this.load();
}
Expand All @@ -26,6 +31,30 @@ class Schema {
}
return this;
}

toInterface() {
const { name, entity } = this;
const types = [];
types.push(`interface ${name} {`);
const pk = toLowerCamel(name) + 'Id';
types.push(` ${pk}: number;`);
const fields = Object.keys(entity);
for (const fieldName of fields) {
const def = entity[fieldName];
if (def.type) {
const q = def.required ? '' : '?';
const isEntity = isUpperCamel(def.type);
const isType = ES_TYPES.includes(def.type);
const field = def.name + (isEntity ? 'Id' : '');
let { type } = def;
if (isEntity) type = 'number';
else if (!isType) type = 'string';
types.push(` ${field}${q}: ${type};`);
}
}
types.push('}');
return types.join('\n');
}
}

module.exports = { Schema };

0 comments on commit 9bef5d8

Please sign in to comment.