Compare commits
No commits in common. "285dbf2b5a853f558bf9481c2826d49aaeb5efdb" and "74fed4363b72fb06b99676c6e13155a2496c5bfa" have entirely different histories.
285dbf2b5a
...
74fed4363b
@ -61,7 +61,7 @@ function get_table_info (str) {
|
|||||||
columns.push (col);
|
columns.push (col);
|
||||||
}
|
}
|
||||||
|
|
||||||
return { name, columns, foreign_keys: [] };
|
return { name, columns };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -80,48 +80,32 @@ async function get_tables (file) {
|
|||||||
curr.push (l);
|
curr.push (l);
|
||||||
|
|
||||||
if ((/>.*?\]/u).test (l)) {
|
if ((/>.*?\]/u).test (l)) {
|
||||||
const val = curr.join ('\n');
|
tables.push (curr.join ('\n'));
|
||||||
if (val)
|
|
||||||
tables.push (get_table_info (val));
|
|
||||||
curr.splice (0, curr.length);
|
curr.splice (0, curr.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
get_foreign_key (l, foreign);
|
const fk = (/(?<col>\S+) -> (?<ref>\S+)/u).exec (l);
|
||||||
}
|
if (fk) {
|
||||||
|
const col = fk.groups.col.split (':');
|
||||||
|
const ref = fk.groups.ref.split (':');
|
||||||
|
|
||||||
for (const fk of foreign) {
|
const foreign_key = {
|
||||||
for (let i = 0; i < tables.length; i++) {
|
table: col[0],
|
||||||
if (tables[i].name === fk.table) {
|
column: col[1],
|
||||||
tables[i].foreign_keys.push (fk);
|
ref_table: ref[0],
|
||||||
break;
|
ref_column: ref[1]
|
||||||
}
|
};
|
||||||
|
|
||||||
|
foreign.push (foreign_key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tables;
|
return {
|
||||||
}
|
tables: tables
|
||||||
|
.filter ((val) => val)
|
||||||
/**
|
.map ((val) => get_table_info (val)),
|
||||||
* gets foreign keys from a line
|
foreign_keys: foreign
|
||||||
*
|
};
|
||||||
* @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) {
|
|
||||||
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_keys.push (foreign_key);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -136,81 +120,25 @@ function create_table_function (table) {
|
|||||||
*
|
*
|
||||||
* @param {any} knex database connection
|
* @param {any} knex database connection
|
||||||
* @returns {Promise} result
|
* @returns {Promise} result
|
||||||
*/
|
*/
|
||||||
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 = `'use strict';
|
|
||||||
|
|
||||||
${functions.join ('\n\n')}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* run migration
|
|
||||||
*
|
|
||||||
* @param {any} knex db connection
|
|
||||||
*/
|
|
||||||
${create_up_function (tables)}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* revert migration
|
|
||||||
*/
|
|
||||||
function down () {
|
|
||||||
// noop
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { up, down };
|
|
||||||
`;
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { get_tables, create_table_function, create_migration };
|
|
||||||
|
@ -2,10 +2,9 @@
|
|||||||
* 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>, February 2020
|
* Created by Timo Hocker <timo@scode.ovh>, January 2020
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* eslint-disable no-magic-numbers */
|
|
||||||
/* eslint-disable no-sync */
|
/* eslint-disable no-sync */
|
||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
|
|
||||||
@ -13,7 +12,6 @@
|
|||||||
|
|
||||||
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]
|
||||||
@ -21,12 +19,24 @@ const dot_parser = require ('./dot_parser');
|
|||||||
* @param {string} folder folder to run in
|
* @param {string} folder folder to run in
|
||||||
* @param {Array} args function arguments
|
* @param {Array} args function arguments
|
||||||
*/
|
*/
|
||||||
async function run (folder, args) {
|
function run (folder, args) {
|
||||||
const graph = path.join (folder, args[0]);
|
const snip_folder_path = [ folder ];
|
||||||
const migration = path.join (folder, args[1]);
|
if (args.length > 0)
|
||||||
|
snip_folder_path.push (args[0]);
|
||||||
const db_migration = await dot_parser.create_migration (graph);
|
const snip_folder = path.join (...snip_folder_path);
|
||||||
await fs.writeFile (migration, db_migration, 'utf-8');
|
const template = path.join (__dirname, 'template');
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,10 +49,16 @@ async function run (folder, args) {
|
|||||||
function assert (folder, args) {
|
function assert (folder, args) {
|
||||||
const tests = [
|
const tests = [
|
||||||
{
|
{
|
||||||
f: () => (args.length === 2
|
f: () => (args.length < 2),
|
||||||
&& typeof args[0] === 'string'
|
reason: 'too many arguments'
|
||||||
&& 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'),
|
||||||
@ -51,6 +67,15 @@ 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) {
|
||||||
|
@ -7,7 +7,8 @@ const dot_parser = require ('../snippets/db/dot_parser');
|
|||||||
* test
|
* test
|
||||||
*/
|
*/
|
||||||
async function test () {
|
async function test () {
|
||||||
const data = await dot_parser.create_migration ('db_structure.dot');
|
const data = await dot_parser.get_tables ('db_structure.dot');
|
||||||
console.log (data);
|
for (const table of data)
|
||||||
|
console.log (dot_parser.create_table_function (table));
|
||||||
}
|
}
|
||||||
test ();
|
test ();
|
||||||
|
191
test/test.js
191
test/test.js
@ -1,191 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* create table users
|
|
||||||
*
|
|
||||||
* @param {any} knex database connection
|
|
||||||
* @returns {Promise} result
|
|
||||||
*/
|
|
||||||
function create_users (knex) {
|
|
||||||
return knex.schema.createTable ('users', (table) => {
|
|
||||||
table.increments ('id');
|
|
||||||
table.string ('name');
|
|
||||||
table.string ('email');
|
|
||||||
table.string ('password');
|
|
||||||
table.string ('salt');
|
|
||||||
table.boolean ('deleted');
|
|
||||||
|
|
||||||
table.unique ('name', 'email');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* create table applications
|
|
||||||
*
|
|
||||||
* @param {any} knex database connection
|
|
||||||
* @returns {Promise} result
|
|
||||||
*/
|
|
||||||
function create_applications (knex) {
|
|
||||||
return knex.schema.createTable ('applications', (table) => {
|
|
||||||
table.increments ('id');
|
|
||||||
table.string ('name');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* create table permissions
|
|
||||||
*
|
|
||||||
* @param {any} knex database connection
|
|
||||||
* @returns {Promise} result
|
|
||||||
*/
|
|
||||||
function create_permissions (knex) {
|
|
||||||
return knex.schema.createTable ('permissions', (table) => {
|
|
||||||
table.increments ('id');
|
|
||||||
table.integer ('user_id');
|
|
||||||
table.boolean ('create_app');
|
|
||||||
table.boolean ('manage_users');
|
|
||||||
table.boolean ('manage_permissions');
|
|
||||||
table.boolean ('manage_apps');
|
|
||||||
table.boolean ('manage_keys');
|
|
||||||
table.boolean ('issue_key');
|
|
||||||
|
|
||||||
table.foreign ('user_id')
|
|
||||||
.references ('id')
|
|
||||||
.inTable ('users');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* create table user_access
|
|
||||||
*
|
|
||||||
* @param {any} knex database connection
|
|
||||||
* @returns {Promise} result
|
|
||||||
*/
|
|
||||||
function create_user_access (knex) {
|
|
||||||
return knex.schema.createTable ('user_access', (table) => {
|
|
||||||
table.increments ('id');
|
|
||||||
table.integer ('user_id');
|
|
||||||
table.integer ('app_id');
|
|
||||||
table.string ('crud');
|
|
||||||
|
|
||||||
table.foreign ('user_id')
|
|
||||||
.references ('id')
|
|
||||||
.inTable ('users');
|
|
||||||
table.foreign ('app_id')
|
|
||||||
.references ('id')
|
|
||||||
.inTable ('applications');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* create table auth_keys
|
|
||||||
*
|
|
||||||
* @param {any} knex database connection
|
|
||||||
* @returns {Promise} result
|
|
||||||
*/
|
|
||||||
function create_auth_keys (knex) {
|
|
||||||
return knex.schema.createTable ('auth_keys', (table) => {
|
|
||||||
table.increments ('id');
|
|
||||||
table.string ('key');
|
|
||||||
table.integer ('app_id');
|
|
||||||
table.boolean ('read_data');
|
|
||||||
table.string ('hash');
|
|
||||||
table.string ('name');
|
|
||||||
|
|
||||||
table.unique ('key', 'hash');
|
|
||||||
|
|
||||||
table.foreign ('app_id')
|
|
||||||
.references ('id')
|
|
||||||
.inTable ('applications');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* create table categories
|
|
||||||
*
|
|
||||||
* @param {any} knex database connection
|
|
||||||
* @returns {Promise} result
|
|
||||||
*/
|
|
||||||
function create_categories (knex) {
|
|
||||||
return knex.schema.createTable ('categories', (table) => {
|
|
||||||
table.increments ('id');
|
|
||||||
table.string ('name');
|
|
||||||
table.integer ('app_id');
|
|
||||||
|
|
||||||
table.unique ('name');
|
|
||||||
|
|
||||||
table.foreign ('app_id')
|
|
||||||
.references ('id')
|
|
||||||
.inTable ('applications');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* create table log
|
|
||||||
*
|
|
||||||
* @param {any} knex database connection
|
|
||||||
* @returns {Promise} result
|
|
||||||
*/
|
|
||||||
function create_log (knex) {
|
|
||||||
return knex.schema.createTable ('log', (table) => {
|
|
||||||
table.increments ('id');
|
|
||||||
table.integer ('key_id');
|
|
||||||
table.integer ('app_id');
|
|
||||||
table.integer ('timestamp');
|
|
||||||
table.integer ('category_id');
|
|
||||||
|
|
||||||
table.foreign ('key_id')
|
|
||||||
.references ('id')
|
|
||||||
.inTable ('auth_keys');
|
|
||||||
table.foreign ('app_id')
|
|
||||||
.references ('id')
|
|
||||||
.inTable ('applications');
|
|
||||||
table.foreign ('category_id')
|
|
||||||
.references ('id')
|
|
||||||
.inTable ('categories');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* create table data
|
|
||||||
*
|
|
||||||
* @param {any} knex database connection
|
|
||||||
* @returns {Promise} result
|
|
||||||
*/
|
|
||||||
function create_data (knex) {
|
|
||||||
return knex.schema.createTable ('data', (table) => {
|
|
||||||
table.increments ('id');
|
|
||||||
table.integer ('log_id');
|
|
||||||
table.string ('key');
|
|
||||||
table.string ('value');
|
|
||||||
|
|
||||||
table.foreign ('log_id')
|
|
||||||
.references ('id')
|
|
||||||
.inTable ('log');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* run migration
|
|
||||||
*
|
|
||||||
* @param {any} knex db connection
|
|
||||||
*/
|
|
||||||
async function up (knex) {
|
|
||||||
await create_users (knex);
|
|
||||||
await create_applications (knex);
|
|
||||||
await create_permissions (knex);
|
|
||||||
await create_user_access (knex);
|
|
||||||
await create_auth_keys (knex);
|
|
||||||
await create_categories (knex);
|
|
||||||
await create_log (knex);
|
|
||||||
await create_data (knex);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* revert migration
|
|
||||||
*/
|
|
||||||
function down () {
|
|
||||||
// noop
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { up, down };
|
|
Loading…
x
Reference in New Issue
Block a user