snippeteer/snippets/db/dot_parser.js

145 lines
3.2 KiB
JavaScript

/* eslint-disable no-magic-numbers */
'use strict';
const fs = require ('fs-extra');
/**
* convert short type notation to knex notation
*
* @param {string} short short type
* @returns {string} type
*/
function get_type (short) {
switch (short) {
case '\'\'':
return 'string';
case '#':
return 'integer';
case '#.#':
return 'double';
case '✓':
return 'boolean';
case '🖹':
return 'text';
default:
return '';
}
}
/**
* returns columns and attributes for a table
*
* @param {string} str table definition
* @returns {object} table info
*/
function get_table_info (str) {
const lines = str.split (/\n/ug);
lines.splice (0, 2);
lines.splice (lines.length - 2, 2);
const name_line = lines.shift ();
const { name } = (/<b>(?<name>\S+)<\/b>/u).exec (name_line).groups;
const columns = [];
while (lines.length > 0) {
const col = {};
const l = lines.shift ();
const regex = /<tr><td.*?>(?<props>.*?)<\/td><\/tr>/u;
const data = regex.exec (l).groups.props.split (/\s+/gu);
if (data.length === 3 || data[0] === '🔑') {
const opt = data.shift ();
if (opt === '★')
col.unique = true;
if (opt === '🔑')
col.type = 'increments';
}
col.name = data.shift ();
if (data.length > 0)
col.type = get_type (data.shift ());
columns.push (col);
}
return { name, columns };
}
/**
* get all tables from a structure file
*
* @param {string} file path to the structure file
* @returns {Promise<object>} tables and foreign keys
*/
async function get_tables (file) {
const lines = (await fs.readFile (file, 'utf-8')).split (/\n/gu);
const curr = [];
const tables = [];
const foreign = [];
for (const l of lines) {
if (curr.length > 0 || (/\S+ \[label=</u).test (l))
curr.push (l);
if ((/>.*?\]/u).test (l)) {
tables.push (curr.join ('\n'));
curr.splice (0, curr.length);
}
const fk = (/(?<col>\S+) -> (?<ref>\S+)/u).exec (l);
if (fk) {
const col = fk.groups.col.split (':');
const ref = fk.groups.ref.split (':');
const foreign_key = {
table: col[0],
column: col[1],
ref_table: ref[0],
ref_column: ref[1]
};
foreign.push (foreign_key);
}
}
return {
tables: tables
.filter ((val) => val)
.map ((val) => get_table_info (val)),
foreign_keys: foreign
};
}
/**
* creates a function for creating a table
*
* @param {object} table table to create a function for
* @returns {string} function
*/
function create_table_function (table) {
let func = `/**
* create table ${table.name}
*
* @param {any} knex database connection
* @returns {Promise} result
*/
function create_${table.name} (knex) {
return knex.schema.createTable ('${table.name}', (table) => {
${table.columns
.map ((col) => `table.${col.type}('${col.name}');`)
.join ('\n ')}
`;
const unique = table.columns.filter ((val) => val.unique);
if (unique.length > 0) {
func += `\n table.unique(${unique
.map ((val) => `'${val.name}'`)
.join (', ')});\n`;
}
func += ` });
}`;
return func;
}
module.exports = { get_tables, create_table_function };