mysqlsyncr 1.1.10 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +246 -186
- package/__tests__/acceptCurrent.test.js +117 -0
- package/__tests__/columnAttributes.test.js +101 -0
- package/__tests__/options.test.js +259 -0
- package/__tests__/parser.test.js +167 -166
- package/__tests__/parser2.test.js +155 -152
- package/__tests__/paths.test.js +21 -0
- package/__tests__/prompt.test.js +106 -0
- package/__tests__/sync.test.js +348 -0
- package/__tests__/templateDrift.test.js +72 -0
- package/__tests__/versions.test.js +138 -0
- package/dist/index.cjs +4070 -1730
- package/dist/index.js +4106 -1768
- package/package.json +66 -59
- package/rollup.config.js +25 -24
- package/src/DBStructureChecker.js +47 -0
- package/src/acceptCurrent.js +225 -0
- package/src/apply.js +481 -348
- package/src/cli.js +61 -34
- package/src/compare.js +106 -92
- package/src/differences.js +258 -212
- package/src/dump.js +63 -54
- package/src/getters.js +151 -139
- package/src/index.js +223 -170
- package/src/loggers.js +156 -139
- package/src/normalizers.js +28 -6
- package/src/options.js +133 -0
- package/src/parsers.js +197 -145
- package/src/paths.js +41 -0
- package/src/prompt.js +109 -0
- package/src/rebuild.js +106 -0
- package/src/rows.js +46 -0
- package/src/socketServer.js +311 -229
- package/src/templateDrift.js +93 -0
- package/src/versions.js +112 -0
- package/ui/README.md +55 -40
- package/ui/dist/spa/assets/KFOMCnqEu92Fr1ME7kSn66aGLdTylUAMQXC89YmC2DPNWuYjalmUiAw-k1h7X_-h.woff +0 -0
- package/ui/dist/spa/assets/KFOMCnqEu92Fr1ME7kSn66aGLdTylUAMQXC89YmC2DPNWuZtalmUiAw-B7du-70m.woff +0 -0
- package/ui/dist/spa/assets/KFOMCnqEu92Fr1ME7kSn66aGLdTylUAMQXC89YmC2DPNWuaabVmUiAw-CoAZ_DKt.woff +0 -0
- package/ui/dist/spa/assets/KFOMCnqEu92Fr1ME7kSn66aGLdTylUAMQXC89YmC2DPNWub2bVmUiAw-D0406B4n.woff +0 -0
- package/ui/dist/spa/assets/KFOMCnqEu92Fr1ME7kSn66aGLdTylUAMQXC89YmC2DPNWubEbFmUiAw-CnAg2DeQ.woff +0 -0
- package/ui/dist/spa/assets/KFOMCnqEu92Fr1ME7kSn66aGLdTylUAMQXC89YmC2DPNWubEbVmUiAw-BG9VWE5v.woff +0 -0
- package/ui/dist/spa/assets/MainLayout-DLH1Kfg-.js +1 -0
- package/ui/dist/spa/assets/axios-2hQ_j_Tz.js +1 -0
- package/ui/dist/spa/assets/flUhRq6tzZclQEJ-Vdg-IuiaDsNa-OUIwM9U8.woff +0 -0
- package/ui/dist/spa/assets/index-Cqrg985P.js +23 -0
- package/ui/dist/spa/assets/index-pOWtXlXQ.css +1 -0
- package/ui/dist/spa/index.html +2 -2
- package/ui/package.json +43 -42
- package/ui/src/components/DefinitionDiff.vue +169 -0
- package/ui/src/pages/MainComponent.vue +704 -78
- package/ui/dist/spa/assets/KFOkCnqEu92Fr1MmgVxIIzQ-Y2mpUUkw.woff +0 -0
- package/ui/dist/spa/assets/KFOlCnqEu92Fr1MmEU9fBBc--ViM7Ag4Q.woff +0 -0
- package/ui/dist/spa/assets/KFOlCnqEu92Fr1MmSU5fBBc--CrFzpgl6.woff +0 -0
- package/ui/dist/spa/assets/KFOlCnqEu92Fr1MmWUlfBBc--CW3_XjG_.woff +0 -0
- package/ui/dist/spa/assets/KFOlCnqEu92Fr1MmYUtfBBc--Dr8fnyGc.woff +0 -0
- package/ui/dist/spa/assets/KFOmCnqEu92Fr1Mu4mxM-DAYh6T4l.woff +0 -0
- package/ui/dist/spa/assets/MainLayout-CvQD3xKr.js +0 -1
- package/ui/dist/spa/assets/axios-C0XcclIb.js +0 -1
- package/ui/dist/spa/assets/flUhRq6tzZclQEJ-Vdg-IuiaDsNa-Dr0goTwe.woff +0 -0
- package/ui/dist/spa/assets/index-CwWo8xmP.js +0 -40
- package/ui/dist/spa/assets/index-kXpA8n8r.css +0 -5
package/src/getters.js
CHANGED
|
@@ -1,140 +1,152 @@
|
|
|
1
|
-
import { parseCreateTableSQL } from './parsers.js';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import fs from 'fs/promises';
|
|
4
|
-
import { logger } from './loggers.js';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
.
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
// Get the
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
//
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
//
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
1
|
+
import { parseCreateTableSQL } from './parsers.js';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import fs from 'fs/promises';
|
|
4
|
+
import { logger } from './loggers.js';
|
|
5
|
+
import { applyAutoIncrementOption, applyDefiner, getTableOptions } from './options.js';
|
|
6
|
+
|
|
7
|
+
export const getDatabases = async (connection) => {
|
|
8
|
+
const databases = await connection.query('SHOW DATABASES');
|
|
9
|
+
return databases
|
|
10
|
+
.map(db => db.Database)
|
|
11
|
+
.filter(db => !['information_schema', 'mysql', 'performance_schema', 'sys'].includes(db));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @param syncOptions options from syncOptions.json; when dumping, each table's
|
|
17
|
+
* autoIncrement option is applied to its saved CREATE TABLE,
|
|
18
|
+
* and the definer option to procedures, triggers and views
|
|
19
|
+
*/
|
|
20
|
+
export const getDatabaseStructure = async (connection, database, command, options, syncOptions = {}) => {
|
|
21
|
+
if (connection.state === 'disconnected') {
|
|
22
|
+
await connection.reconnect(); // Ensure the connection is open
|
|
23
|
+
}
|
|
24
|
+
await connection.query(`USE \`${database}\``); // Switch to the target database
|
|
25
|
+
const tables = {};
|
|
26
|
+
const procedures = [];
|
|
27
|
+
const views = {};
|
|
28
|
+
const dbDir = path.join(options.output, database); // Use argv.output for the base path
|
|
29
|
+
|
|
30
|
+
// Create the output directory for the database if it doesn't exist
|
|
31
|
+
if (command === 'dump') {
|
|
32
|
+
const tableDir = path.join(dbDir, 'tables'); // Subfolder for table SQL files
|
|
33
|
+
await fs.mkdir(tableDir, { recursive: true }); // Create the tables directory
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Get tables and their structures
|
|
37
|
+
const tableRows = await connection.query('SHOW FULL TABLES WHERE Table_Type != "VIEW"');
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
for (const row of tableRows) {
|
|
41
|
+
const tableName = Object.values(row)[0]; // Get the first value in the row object
|
|
42
|
+
if (!tableName) {
|
|
43
|
+
logger(`Undefined table name found in database ${database}`, row);
|
|
44
|
+
continue; // Skip undefined table names
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Get the CREATE TABLE statement
|
|
48
|
+
const createTableRow = await connection.query(`SHOW CREATE TABLE \`${tableName}\``);
|
|
49
|
+
const liveCreateTableSQL = createTableRow[0]['Create Table'];
|
|
50
|
+
const createTableSQL = command === 'dump'
|
|
51
|
+
? applyAutoIncrementOption(liveCreateTableSQL, getTableOptions(syncOptions, database, tableName).autoIncrement)
|
|
52
|
+
: liveCreateTableSQL;
|
|
53
|
+
|
|
54
|
+
const parsedTable = parseCreateTableSQL(createTableSQL);
|
|
55
|
+
|
|
56
|
+
// Structure the table object
|
|
57
|
+
tables[tableName] = {
|
|
58
|
+
columns: parsedTable.columns, // Array of columns
|
|
59
|
+
indexes: parsedTable.indexes, // Array of indexes
|
|
60
|
+
constraints: parsedTable.constraints, // Array of constraints
|
|
61
|
+
triggers: [], // Initialize triggers array
|
|
62
|
+
createSQL: createTableSQL // Store the CREATE TABLE SQL if needed
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// Save the CREATE TABLE statement to an individual SQL file for each table
|
|
66
|
+
if (command === 'dump') {
|
|
67
|
+
const tableDir = path.join(dbDir, 'tables'); // Subfolder for table SQL files
|
|
68
|
+
const filePath = path.join(tableDir, `${tableName}.sql`); // Use the table directory for file saving
|
|
69
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true }); // Create the tables directory if it doesn't exist
|
|
70
|
+
await fs.writeFile(filePath, `${createTableSQL}\n`, 'utf-8');
|
|
71
|
+
logger(`Table structure saved to: ${filePath}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Get stored procedures
|
|
76
|
+
const routineRows = await connection.query(`SHOW PROCEDURE STATUS WHERE Db = ?`, [database]);
|
|
77
|
+
|
|
78
|
+
for (const row of routineRows) {
|
|
79
|
+
let createSQLrow = await connection.query(`SHOW CREATE PROCEDURE \`${row.Name}\``);
|
|
80
|
+
let createSQL = createSQLrow[0]['Create Procedure'];
|
|
81
|
+
if (command === 'dump') createSQL = applyDefiner(createSQL, syncOptions.definer);
|
|
82
|
+
procedures.push({
|
|
83
|
+
Name: row.Name,
|
|
84
|
+
Definition: createSQL
|
|
85
|
+
}); // Add procedure names to the array
|
|
86
|
+
if (command === 'dump') {
|
|
87
|
+
const filePath = path.join(dbDir, 'procedures', `${row.Name}.sql`); // Use the table directory for file saving
|
|
88
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true }); // Create the procedures directory if it doesn't exist
|
|
89
|
+
await fs.writeFile(filePath, `${createSQL}\n`, 'utf-8');
|
|
90
|
+
logger(`Procedure definition saved to: ${filePath}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Get triggers
|
|
95
|
+
const triggerRows = await connection.query(`
|
|
96
|
+
SELECT TRIGGER_NAME, EVENT_OBJECT_TABLE
|
|
97
|
+
FROM INFORMATION_SCHEMA.TRIGGERS
|
|
98
|
+
WHERE TRIGGER_SCHEMA = ?
|
|
99
|
+
`, [database]);
|
|
100
|
+
|
|
101
|
+
for (const row of triggerRows) {
|
|
102
|
+
const triggerName = row.TRIGGER_NAME;
|
|
103
|
+
const tableName = row.EVENT_OBJECT_TABLE;
|
|
104
|
+
|
|
105
|
+
// Ensure triggerDefinition is defined before using it
|
|
106
|
+
const triggerDefinitionRow = await connection.query(`SHOW CREATE TRIGGER \`${triggerName}\``);
|
|
107
|
+
const liveTriggerDefinition = triggerDefinitionRow[0]['SQL Original Statement'];
|
|
108
|
+
const triggerDefinition = command === 'dump' ? applyDefiner(liveTriggerDefinition, syncOptions.definer) : liveTriggerDefinition;
|
|
109
|
+
|
|
110
|
+
if (triggerDefinition) {
|
|
111
|
+
|
|
112
|
+
tables[tableName].triggers.push({
|
|
113
|
+
Name: triggerName,
|
|
114
|
+
Definition: triggerDefinition
|
|
115
|
+
});
|
|
116
|
+
if (command === 'dump') {
|
|
117
|
+
const tableDir = path.join(dbDir, 'tables'); // Subfolder for table SQL files
|
|
118
|
+
const triggerFilePath = path.join(tableDir, 'triggers', `${triggerName}.sql`);
|
|
119
|
+
await fs.mkdir(path.dirname(triggerFilePath), { recursive: true }); // Create the triggers directory if it doesn't exist
|
|
120
|
+
await fs.writeFile(triggerFilePath, `${triggerDefinition}\n`, 'utf-8');
|
|
121
|
+
logger(`Trigger definition saved to: ${triggerFilePath}`);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
} else {
|
|
125
|
+
logger(`Trigger ${triggerName} has no action statement.`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Get views
|
|
130
|
+
const viewRows = await connection.query(`SHOW FULL TABLES IN \`${database}\` WHERE TABLE_TYPE LIKE 'VIEW'`);
|
|
131
|
+
for (const row of viewRows) {
|
|
132
|
+
let viewName = row[`Tables_in_${database.toLowerCase()}`];
|
|
133
|
+
if (!viewName) viewName = row[`Tables_in_${database}`];
|
|
134
|
+
logger(`getting view Tables_in_${database}`, viewName);
|
|
135
|
+
try {
|
|
136
|
+
const viewDefinition = await connection.query(`SHOW CREATE VIEW \`${viewName}\``);
|
|
137
|
+
const liveViewDefinition = viewDefinition[0]['Create View'];
|
|
138
|
+
views[viewName] = command === 'dump' ? applyDefiner(liveViewDefinition, syncOptions.definer) : liveViewDefinition;
|
|
139
|
+
if (command === 'dump') {
|
|
140
|
+
const filePath = path.join(dbDir, 'views', `${viewName}.sql`); // Use the table directory for file saving
|
|
141
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true }); // Create the views directory if it doesn't exist
|
|
142
|
+
await fs.writeFile(filePath, `${views[viewName]}\n`, 'utf-8');
|
|
143
|
+
logger(`View definition saved to: ${filePath}`);
|
|
144
|
+
}
|
|
145
|
+
} catch (error) {
|
|
146
|
+
logger(`Error retrieving definition for view ${viewName}:`, error.message);
|
|
147
|
+
logger(row)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return { tables, procedures, views };
|
|
140
152
|
}
|