[no publish] finish dot parser

This commit is contained in:
Timo Hocker 2020-02-21 11:29:50 +01:00
parent 74fed4363b
commit 33c34b18f7
3 changed files with 108 additions and 64 deletions

View File

@ -61,7 +61,7 @@ function get_table_info (str) {
columns.push (col); columns.push (col);
} }
return { name, columns }; return { name, columns, foreign_keys: [] };
} }
/** /**
@ -80,11 +80,35 @@ async function get_tables (file) {
curr.push (l); curr.push (l);
if ((/>.*?\]/u).test (l)) { if ((/>.*?\]/u).test (l)) {
tables.push (curr.join ('\n')); const val = curr.join ('\n');
if (val)
tables.push (get_table_info (val));
curr.splice (0, curr.length); curr.splice (0, curr.length);
} }
const fk = (/(?<col>\S+) -> (?<ref>\S+)/u).exec (l); get_foreign_key (l, foreign);
}
for (const fk of foreign) {
for (let i = 0; i < tables.length; i++) {
if (tables[i].name === fk.table) {
tables[i].foreign_keys.push (fk);
break;
}
}
}
return tables;
}
/**
* gets foreign keys from a line
*
* @param {string} line line to check
* @param {Array<object>} foreign_keys array to add to
*/
function get_foreign_key (line, foreign_keys) {
const fk = (/(?<col>\S+) -> (?<ref>\S+)/u).exec (line);
if (fk) { if (fk) {
const col = fk.groups.col.split (':'); const col = fk.groups.col.split (':');
const ref = fk.groups.ref.split (':'); const ref = fk.groups.ref.split (':');
@ -96,16 +120,8 @@ async function get_tables (file) {
ref_column: ref[1] ref_column: ref[1]
}; };
foreign.push (foreign_key); foreign_keys.push (foreign_key);
} }
}
return {
tables: tables
.filter ((val) => val)
.map ((val) => get_table_info (val)),
foreign_keys: foreign
};
} }
/** /**
@ -124,21 +140,75 @@ function create_table_function (table) {
function create_${table.name} (knex) { function create_${table.name} (knex) {
return knex.schema.createTable ('${table.name}', (table) => { return knex.schema.createTable ('${table.name}', (table) => {
${table.columns ${table.columns
.map ((col) => `table.${col.type}('${col.name}');`) .map ((col) => `table.${col.type} ('${col.name}');`)
.join ('\n ')} .join ('\n ')}
`; `;
const unique = table.columns.filter ((val) => val.unique); const unique = table.columns.filter ((val) => val.unique);
if (unique.length > 0) { if (unique.length > 0) {
func += `\n table.unique(${unique func += `\n table.unique (${unique
.map ((val) => `'${val.name}'`) .map ((val) => `'${val.name}'`)
.join (', ')});\n`; .join (', ')});\n`;
} }
if (table.foreign_keys.length > 0) {
func += '\n';
for (const fk of table.foreign_keys) {
func += ` table.foreign ('${fk.column}')
.references ('${fk.ref_column}')
.inTable ('${fk.ref_table}');\n`;
}
}
func += ` }); func += ` });
}`; }`;
return func; return func;
} }
module.exports = { get_tables, create_table_function }; /**
* creates the migration function
*
* @param {Array<object>} tables table array
* @returns {string} function
*/
function create_up_function (tables) {
const func = `async function up (knex) {
${tables.map ((val) => ` await create_${val.name} (knex);`)
.join ('\n')}
}`;
return func;
}
/**
* creates the complete migration file for a graph
*
* @param {string} file_path file to scan
* @returns {Promise<string>} file
*/
async function create_migration (file_path) {
const tables = await get_tables (file_path);
const functions = tables.map ((tab) => create_table_function (tab));
const file = `${functions.join ('\n\n')}
/*
* run migration
*
* @param {any} knex db connection
*/
${create_up_function (tables)}
/*
* revert migration
*
* @param {any} knex db connection
*/
function down () {}
module.exports = { up, down }
`;
return file;
}
module.exports = { get_tables, create_table_function, create_migration };

View File

@ -2,9 +2,10 @@
* Copyright (C) Sapphirecode - All Rights Reserved * Copyright (C) Sapphirecode - All Rights Reserved
* This file is part of snippeteer which is released under BSD-3-Clause. * This file is part of snippeteer which is released under BSD-3-Clause.
* See file 'LICENSE' for full license details. * See file 'LICENSE' for full license details.
* Created by Timo Hocker <timo@scode.ovh>, January 2020 * Created by Timo Hocker <timo@scode.ovh>, February 2020
*/ */
/* eslint-disable no-magic-numbers */
/* eslint-disable no-sync */ /* eslint-disable no-sync */
/* eslint-disable no-console */ /* eslint-disable no-console */
@ -12,6 +13,7 @@
const fs = require ('fs-extra'); const fs = require ('fs-extra');
const path = require ('path'); const path = require ('path');
const dot_parser = require ('./dot_parser');
/** /**
* copies the full template to a new folder named after arg[0] * copies the full template to a new folder named after arg[0]
@ -19,24 +21,12 @@ const path = require ('path');
* @param {string} folder folder to run in * @param {string} folder folder to run in
* @param {Array} args function arguments * @param {Array} args function arguments
*/ */
function run (folder, args) { async function run (folder, args) {
const snip_folder_path = [ folder ]; const graph = path.join (folder, args[0]);
if (args.length > 0) const migration = path.join (folder, args[1]);
snip_folder_path.push (args[0]);
const snip_folder = path.join (...snip_folder_path); const db_migration = dot_parser.create_migration (graph);
const template = path.join (__dirname, 'template'); await fs.writeFile (migration, db_migration, 'utf-8');
if (!fs.existsSync (snip_folder))
fs.mkdir (snip_folder);
for (const f of fs.readdirSync (template)) {
fs.copy (
path.join (template, f),
path.join (snip_folder, f),
{
recursive: true,
filter: (src, dest) => !fs.existsSync (dest)
}
);
}
} }
/** /**
@ -49,16 +39,10 @@ function run (folder, args) {
function assert (folder, args) { function assert (folder, args) {
const tests = [ const tests = [
{ {
f: () => (args.length < 2), f: () => (args.length === 2
reason: 'too many arguments' && typeof args[0] === 'string'
}, && typeof args[1] === 'string'),
{ reason: 'db [graph] [migration]'
f: () => (args.length === 0 || typeof args[0] === 'string'),
reason: 'name is not a string'
},
{
f: () => (args.length === 0 || (/^[a-z]+$/iu).test (args[0])),
reason: 'name can only contain [a-z]'
}, },
{ {
f: () => (typeof folder === 'string'), f: () => (typeof folder === 'string'),
@ -67,15 +51,6 @@ function assert (folder, args) {
{ {
f: () => (fs.existsSync (folder)), f: () => (fs.existsSync (folder)),
reason: 'cwd does not exist (internal error)' reason: 'cwd does not exist (internal error)'
},
{
f: () => (args.length === 1 || fs.readdirSync (folder).length === 0),
reason: 'folder is not empty'
},
{
f: () => (args.length === 0
|| !fs.existsSync (path.join (folder, args[0]))),
reason: 'folder already exists'
} }
]; ];
for (const test of tests) { for (const test of tests) {

View File

@ -7,8 +7,7 @@ const dot_parser = require ('../snippets/db/dot_parser');
* test * test
*/ */
async function test () { async function test () {
const data = await dot_parser.get_tables ('db_structure.dot'); const data = await dot_parser.create_migration ('db_structure.dot');
for (const table of data) console.log (data);
console.log (dot_parser.create_table_function (table));
} }
test (); test ();