[no publish] progressing dot parser
This commit is contained in:
parent
8d665a3576
commit
74fed4363b
@ -1 +0,0 @@
|
||||
/snippets/
|
@ -1,17 +1,65 @@
|
||||
/* eslint-disable no-magic-numbers */
|
||||
|
||||
'use strict';
|
||||
|
||||
const fs = require ('fs-extra');
|
||||
|
||||
/**
|
||||
* @param str
|
||||
* 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.splice (0);
|
||||
const { name } = (/<b>(?<name>\S)<\/b>/u).exec (name_line).groups;
|
||||
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 };
|
||||
}
|
||||
@ -20,23 +68,77 @@ function get_table_info (str) {
|
||||
* get all tables from a structure file
|
||||
*
|
||||
* @param {string} file path to the structure file
|
||||
* @returns {Array<object>} tables
|
||||
* @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)) {
|
||||
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.map ((val) => get_table_info (val));
|
||||
return {
|
||||
tables: tables
|
||||
.filter ((val) => val)
|
||||
.map ((val) => get_table_info (val)),
|
||||
foreign_keys: foreign
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = { get_tables };
|
||||
/**
|
||||
* 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 };
|
||||
|
102
test/db_structure.dot
Normal file
102
test/db_structure.dot
Normal file
@ -0,0 +1,102 @@
|
||||
digraph {
|
||||
node [shape=box,margin=0,height=0]
|
||||
edge [arrowhead=open,style=dashed]
|
||||
rankdir="RL";
|
||||
|
||||
users [label=<
|
||||
<table border="0" cellborder="1" cellspacing="0">
|
||||
<tr><td border="2"><b>users</b></td></tr>
|
||||
<tr><td port="id">🔑 id</td></tr>
|
||||
<tr><td port="name">★ name ''</td></tr>
|
||||
<tr><td port="email">★ email ''</td></tr>
|
||||
<tr><td port="password">password ''</td></tr>
|
||||
<tr><td port="salt">salt ''</td></tr>
|
||||
<tr><td port="deleted">deleted ✓</td></tr>
|
||||
</table>
|
||||
>]
|
||||
|
||||
applications [label=<
|
||||
<table border="0" cellborder="1" cellspacing="0">
|
||||
<tr><td border="2"><b>applications</b></td></tr>
|
||||
<tr><td port="id">🔑 id</td></tr>
|
||||
<tr><td port="name">name ''</td></tr>
|
||||
</table>
|
||||
>]
|
||||
|
||||
permissions [label=<
|
||||
<table border="0" cellborder="1" cellspacing="0">
|
||||
<tr><td border="2"><b>permissions</b></td></tr>
|
||||
<tr><td port="id">🔑 id</td></tr>
|
||||
<tr><td port="user_id">user_id #</td></tr>
|
||||
<tr><td>create_app ✓</td></tr>
|
||||
<tr><td>manage_users ✓</td></tr>
|
||||
<tr><td>manage_permissions ✓</td></tr>
|
||||
<tr><td>manage_apps ✓</td></tr>
|
||||
<tr><td>manage_keys ✓</td></tr>
|
||||
<tr><td>issue_key ✓</td></tr>
|
||||
</table>
|
||||
>]
|
||||
|
||||
user_access [label=<
|
||||
<table border="0" cellborder="1" cellspacing="0">
|
||||
<tr><td border="2"><b>user_access</b></td></tr>
|
||||
<tr><td port="id">🔑 id</td></tr>
|
||||
<tr><td port="user_id">user_id #</td></tr>
|
||||
<tr><td port="app_id">app_id #</td></tr>
|
||||
<tr><td port="crud">crud ''</td></tr>
|
||||
</table>
|
||||
>]
|
||||
|
||||
auth_keys [label=<
|
||||
<table border="0" cellborder="1" cellspacing="0">
|
||||
<tr><td border="2"><b>auth_keys</b></td></tr>
|
||||
<tr><td port="id">🔑 id</td></tr>
|
||||
<tr><td port="key">★ key ''</td></tr>
|
||||
<tr><td port="app_id">app_id #</td></tr>
|
||||
<tr><td port="read_data">read_data ✓</td></tr>
|
||||
<tr><td port="hash">★ hash ''</td></tr>
|
||||
<tr><td port="name">name ''</td></tr>
|
||||
</table>
|
||||
>]
|
||||
|
||||
categories [label=<
|
||||
<table border="0" cellborder="1" cellspacing="0">
|
||||
<tr><td border="2"><b>categories</b></td></tr>
|
||||
<tr><td port="id">🔑 id</td></tr>
|
||||
<tr><td port="name">★ name ''</td></tr>
|
||||
<tr><td port="app_id">app_id #</td></tr>
|
||||
</table>
|
||||
>, shape=box, margin=0]
|
||||
|
||||
log [label=<
|
||||
<table border="0" cellborder="1" cellspacing="0">
|
||||
<tr><td border="2"><b>log</b></td></tr>
|
||||
<tr><td port="id">🔑 id</td></tr>
|
||||
<tr><td port="key_id">key_id #</td></tr>
|
||||
<tr><td port="app_id">app_id #</td></tr>
|
||||
<tr><td port="timestamp">timestamp #</td></tr>
|
||||
<tr><td port="category_id">category_id #</td></tr>
|
||||
</table>
|
||||
>]
|
||||
|
||||
data [label=<
|
||||
<table border="0" cellborder="1" cellspacing="0">
|
||||
<tr><td border="2"><b>data</b></td></tr>
|
||||
<tr><td port="id">🔑 id</td></tr>
|
||||
<tr><td port="log_id">log_id #</td></tr>
|
||||
<tr><td port="key">key ''</td></tr>
|
||||
<tr><td port="value">value ''</td></tr>
|
||||
</table>
|
||||
>]
|
||||
|
||||
data:log_id -> log:id [color=blue]
|
||||
permissions:user_id -> users:id [color=blue]
|
||||
log:key_id -> auth_keys:id [color=blue]
|
||||
auth_keys:app_id -> applications:id [color=blue]
|
||||
user_access:user_id -> users:id [color=red]
|
||||
user_access:app_id -> applications:id [color=red]
|
||||
log:app_id -> applications:id [color=blue]
|
||||
log:category_id -> categories:id [color=blue]
|
||||
categories:app_id -> applications:id [color=blue]
|
||||
}
|
||||
data_key [label=key]
|
14
test/index.js
Normal file
14
test/index.js
Normal file
@ -0,0 +1,14 @@
|
||||
/* eslint-disable no-console */
|
||||
'use strict';
|
||||
|
||||
const dot_parser = require ('../snippets/db/dot_parser');
|
||||
|
||||
/**
|
||||
* test
|
||||
*/
|
||||
async function test () {
|
||||
const data = await dot_parser.get_tables ('db_structure.dot');
|
||||
for (const table of data)
|
||||
console.log (dot_parser.create_table_function (table));
|
||||
}
|
||||
test ();
|
Loading…
x
Reference in New Issue
Block a user