mysqlsyncr 1.0.44 → 1.0.48

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.
Files changed (38) hide show
  1. package/package.json +44 -44
  2. package/src/compare.js +2 -2
  3. package/src/index.js +7 -2
  4. package/ui/.editorconfig +7 -7
  5. package/ui/.prettierrc.json +5 -5
  6. package/ui/README.md +40 -40
  7. package/ui/dist/spa/assets/{MainLayout-CJQ1jgg8.js → MainLayout-Cft1OeWe.js} +1 -1
  8. package/ui/dist/spa/assets/axios-CNk6rzlZ.js +1 -0
  9. package/ui/dist/spa/assets/index-DomDZ6ci.js +30 -0
  10. package/ui/dist/spa/assets/{index-BvnAI_tZ.css → index-kXpA8n8r.css} +2 -2
  11. package/ui/dist/spa/index.html +2 -2
  12. package/ui/eslint.config.js +73 -73
  13. package/ui/index.html +21 -21
  14. package/ui/jsconfig.json +2 -2
  15. package/ui/package.json +42 -42
  16. package/ui/postcss.config.js +29 -29
  17. package/ui/quasar.config.js +216 -216
  18. package/ui/src/App.vue +7 -7
  19. package/ui/src/assets/quasar-logo-vertical.svg +14 -14
  20. package/ui/src/boot/axios.js +6 -14
  21. package/ui/src/components/EssentialLink.vue +44 -44
  22. package/ui/src/components/FolderBrowser.vue +2 -3
  23. package/ui/src/css/app.scss +1 -1
  24. package/ui/src/css/quasar.variables.scss +25 -25
  25. package/ui/src/layouts/MainLayout.vue +13 -13
  26. package/ui/src/pages/ApplyChanges.vue +46 -46
  27. package/ui/src/pages/CompareDatabase.vue +57 -57
  28. package/ui/src/pages/DatabaseManager.vue +42 -42
  29. package/ui/src/pages/DumpDatabase.vue +41 -41
  30. package/ui/src/pages/ErrorNotFound.vue +27 -27
  31. package/ui/src/pages/MainComponent copy.vue +322 -322
  32. package/ui/src/pages/MainComponent.vue +36 -23
  33. package/ui/src/router/index.js +30 -30
  34. package/ui/src/router/routes.js +20 -20
  35. package/ui/src/stores/example-store.js +21 -21
  36. package/ui/src/stores/index.js +20 -20
  37. package/ui/dist/spa/assets/axios-DrqNXj9v.js +0 -1
  38. package/ui/dist/spa/assets/index-NGPmhjJD.js +0 -30
@@ -1,322 +1,322 @@
1
- <template>
2
- <q-page>
3
- <div class="q-mb-md">
4
- <q-btn @click="openSettings" label="Settings" color="primary" />
5
- <q-btn
6
- @click="Object.keys(existingDatabases).length === 0 ? createNewDump() : refreshDifferences"
7
- :label="Object.keys(existingDatabases).length === 0 ? 'Get New Dump' : 'Refresh Dump'"
8
- color="secondary"
9
- />
10
- </div>
11
-
12
- <q-card v-if="!isDbSetup" class="q-mb-md">
13
- <q-card-section>
14
- <div class="text-h6">Database Not Set Up</div>
15
- <div>Please configure your database settings.</div>
16
- <q-btn @click="openSettings" label="Open Settings" color="primary" />
17
- </q-card-section>
18
- </q-card>
19
-
20
- <q-card v-if="isDbSetup" class="q-mb-md">
21
- <q-card-section>
22
- <div class="text-h6">Database Differences</div>
23
- <q-table :rows="differences" :columns="columns" />
24
- <q-btn @click="refreshDifferences" label="Refresh Differences" color="secondary" />
25
- </q-card-section>
26
- </q-card>
27
-
28
- <q-card v-if="Object.keys(existingDatabases).length > 0" class="q-mb-md">
29
- <q-card-section>
30
- <div class="text-h6">Database Structure</div>
31
- <q-tree
32
- :nodes="databaseTree"
33
- node-key="id"
34
- v-model:expanded="expandedNodes"
35
- >
36
- <template v-slot:default-header="prop">
37
- <div class="row items-center">
38
- <div>{{ prop.node.label }}</div>
39
- <q-badge v-if="prop.node.type" color="primary" class="q-ml-sm">
40
- {{ prop.node.type }}
41
- </q-badge>
42
- </div>
43
- </template>
44
- </q-tree>
45
- </q-card-section>
46
- </q-card>
47
-
48
- <q-dialog v-model="settingsDialog" persistent>
49
- <q-card>
50
- <q-card-section>
51
- <div class="text-h6">Database Settings</div>
52
- <q-input v-model="host" label="Database Host" required />
53
- <q-input v-model="port" label="Database Port" type="number" required />
54
- <q-input v-model="user" label="Database User" required />
55
- <q-input
56
- v-model="password"
57
- label="Database Password"
58
- type="password"
59
- required
60
- autocomplete="off"
61
- />
62
- <q-input v-model="database" label="Database Name" required />
63
- <q-input v-model="dbFolder" label="Database Folder" required />
64
- </q-card-section>
65
- <q-card-actions>
66
- <q-btn @click="saveSettings" label="Save" color="primary" />
67
- <q-btn @click="closeSettings" label="Cancel" color="secondary" />
68
- </q-card-actions>
69
- </q-card>
70
- </q-dialog>
71
- </q-page>
72
- </template>
73
-
74
- <script>
75
- import axios from 'axios'
76
-
77
- export default {
78
- data() {
79
- return {
80
- isDbSetup: false,
81
- differences: [],
82
- columns: [
83
- { name: 'table', label: 'Table', align: 'left', field: 'table' },
84
- { name: 'difference', label: 'Difference', align: 'left', field: 'difference' },
85
- ],
86
- settingsDialog: false,
87
- host: '127.0.0.1',
88
- port: 3306,
89
- user: 'root',
90
- password: '',
91
- database: '',
92
- dbFolder: 'db-dump',
93
- existingDatabases: [],
94
- databaseColumns: [
95
- { name: 'name', label: 'Database Name', align: 'left', field: 'name' },
96
- { name: 'size', label: 'Size', align: 'left', field: 'size' },
97
- ],
98
- databaseTree: [],
99
- expandedNodes: [],
100
- }
101
- },
102
- methods: {
103
- openSettings() {
104
- this.settingsDialog = true
105
- },
106
- closeSettings() {
107
- this.settingsDialog = false
108
- },
109
- saveSettings() {
110
- const dbConfig = {
111
- host: this.host,
112
- port: this.port,
113
- user: this.user,
114
- password: this.password,
115
- database: this.database,
116
- output: this.dbFolder,
117
- }
118
- localStorage.setItem('dbConfig', JSON.stringify(dbConfig))
119
- this.isDbSetup = true
120
- this.closeSettings()
121
- this.refreshDifferences()
122
- },
123
- async refreshDifferences() {
124
- if (!this.isDbSetup) return
125
- try {
126
- const response = await axios.post('http://localhost:3000/api/compare', {
127
- config: {
128
- host: this.host,
129
- port: this.port,
130
- user: this.user,
131
- password: this.password,
132
- output: this.dbFolder,
133
- database: this.database,
134
- },
135
- })
136
- this.differences = response.data
137
- } catch (error) {
138
- console.error('Error fetching differences:', error)
139
- }
140
- },
141
- async getDatabasesFromExistingDumps() {
142
- try {
143
- const response = await axios.post(
144
- `http://localhost:3000/api/getDatabasesFromExistingDumps`,
145
- {
146
- config: {
147
- host: this.host,
148
- port: this.port,
149
- user: this.user,
150
- password: this.password,
151
- output: this.dbFolder,
152
- },
153
- },
154
- )
155
- if (response.data && typeof response.data === 'object') {
156
- this.existingDatabases = response.data
157
- this.buildDatabaseTree()
158
- }
159
- } catch (error) {
160
- console.error('Error fetching databases from existing dumps:', error)
161
- }
162
- },
163
- buildDatabaseTree() {
164
- this.databaseTree = Object.entries(this.existingDatabases).map(([dbName, db]) => ({
165
- id: `db-${dbName}`,
166
- label: dbName,
167
- type: 'database',
168
- children: [
169
- // Tables section
170
- {
171
- id: `${dbName}-tables`,
172
- label: 'Tables',
173
- type: 'category',
174
- children: Object.entries(db.tables).map(([tableName, table]) => ({
175
- id: `${dbName}-table-${tableName}`,
176
- label: tableName,
177
- type: 'table',
178
- children: [
179
- // Columns subsection
180
- {
181
- id: `${dbName}-table-${tableName}-columns`,
182
- label: 'Columns',
183
- type: 'subcategory',
184
- children: table.columns.map(column => ({
185
- id: `${dbName}-table-${tableName}-column-${column.Field}`,
186
- label: `${column.Field} (${column.Type})${column.NotNull ? ' NOT NULL' : ''}${column.AutoIncrement ? ' AUTO_INCREMENT' : ''}`,
187
- type: 'column',
188
- noChildren: true
189
- }))
190
- },
191
- // Indexes subsection (if present)
192
- table.indexes && table.indexes.length > 0 && {
193
- id: `${dbName}-table-${tableName}-indexes`,
194
- label: 'Indexes',
195
- type: 'subcategory',
196
- children: table.indexes.map(index => ({
197
- id: `${dbName}-table-${tableName}-index-${index.Name}`,
198
- label: `${index.Name}${index.Primary ? ' (Primary)' : ''}${index.Unique ? ' (Unique)' : ''}`,
199
- type: 'index',
200
- noChildren: true
201
- }))
202
- },
203
- // Triggers subsection (if present)
204
- table.triggers && table.triggers.length > 0 && {
205
- id: `${dbName}-table-${tableName}-triggers`,
206
- label: 'Triggers',
207
- type: 'subcategory',
208
- children: table.triggers.map(trigger => ({
209
- id: `${dbName}-table-${tableName}-trigger-${trigger.name}`,
210
- label: trigger.name,
211
- type: 'trigger',
212
- noChildren: true
213
- }))
214
- }
215
- ].filter(Boolean)
216
- }))
217
- },
218
- // Procedures section (if present)
219
- db.procedures && db.procedures.length > 0 && {
220
- id: `${dbName}-procedures`,
221
- label: 'Procedures',
222
- type: 'category',
223
- children: db.procedures.map(proc => ({
224
- id: `${dbName}-proc-${proc.Name}`,
225
- label: proc.Name,
226
- type: 'procedure',
227
- noChildren: true
228
- }))
229
- }
230
- ].filter(Boolean)
231
- }))
232
-
233
- // Only expand the first level (databases)
234
- this.expandedNodes = this.databaseTree.map(node => node.id)
235
- },
236
- async fetchAllDifferences() {
237
- const response = await axios.post('http://localhost:3000/api/compare', {
238
- config: {
239
- host: this.host,
240
- port: this.port,
241
- user: this.user,
242
- password: this.password,
243
- output: this.dbFolder,
244
- },
245
- })
246
- this.differences = response.data
247
- },
248
- async fetchDifferencesForSelectedDb() {
249
- if (Object.keys(this.existingDatabases).length > 0) {
250
- const selectedDbName = Object.keys(this.existingDatabases)[0]
251
- const response = await axios.post('http://localhost:3000/api/compare', {
252
- config: {
253
- host: this.host,
254
- port: this.port,
255
- user: this.user,
256
- password: this.password,
257
- output: this.dbFolder,
258
- database: selectedDbName,
259
- },
260
- })
261
- this.differences = response.data
262
- }
263
- },
264
- async createNewDump() {
265
- console.log('Creating a new dump...')
266
- let response = await axios.post('http://localhost:3000/api/dump', {
267
- config: {
268
- host: this.host,
269
- port: this.port,
270
- user: this.user,
271
- password: this.password,
272
- output: this.dbFolder,
273
- database: this.database,
274
- },
275
- }).catch((error) => {
276
- if (error.response.data.message) {
277
- this.$q.dialog({
278
- title: 'Error',
279
- message: error.response.data.message,
280
- })
281
- }
282
- console.error('Error creating new dump:', error)
283
- return
284
- })
285
-
286
- if (!response) return
287
- if (response.data.message) {
288
- this.$q.dialog({
289
- title: 'Error',
290
- message: response.data.message,
291
- })
292
- }
293
-
294
- if (response.data && typeof response.data === 'object' && Object.keys(response.data).length > 0) {
295
- this.existingDatabases = response.data
296
- this.buildDatabaseTree()
297
- } else {
298
- this.existingDatabases = {}
299
- this.$q.notify({
300
- message: 'Error creating new dump',
301
- color: 'red',
302
- })
303
- }
304
- },
305
- },
306
- mounted() {
307
- const dbConfig = localStorage.getItem('dbConfig')
308
- if (dbConfig) {
309
- const config = JSON.parse(dbConfig)
310
- this.host = config.host
311
- this.port = config.port
312
- this.user = config.user
313
- this.password = config.password
314
- this.database = config.database
315
- this.dbFolder = config.output
316
- this.isDbSetup = true
317
- this.getDatabasesFromExistingDumps()
318
- this.fetchAllDifferences()
319
- }
320
- },
321
- }
322
- </script>
1
+ <template>
2
+ <q-page>
3
+ <div class="q-mb-md">
4
+ <q-btn @click="openSettings" label="Settings" color="primary" />
5
+ <q-btn
6
+ @click="Object.keys(existingDatabases).length === 0 ? createNewDump() : refreshDifferences"
7
+ :label="Object.keys(existingDatabases).length === 0 ? 'Get New Dump' : 'Refresh Dump'"
8
+ color="secondary"
9
+ />
10
+ </div>
11
+
12
+ <q-card v-if="!isDbSetup" class="q-mb-md">
13
+ <q-card-section>
14
+ <div class="text-h6">Database Not Set Up</div>
15
+ <div>Please configure your database settings.</div>
16
+ <q-btn @click="openSettings" label="Open Settings" color="primary" />
17
+ </q-card-section>
18
+ </q-card>
19
+
20
+ <q-card v-if="isDbSetup" class="q-mb-md">
21
+ <q-card-section>
22
+ <div class="text-h6">Database Differences</div>
23
+ <q-table :rows="differences" :columns="columns" />
24
+ <q-btn @click="refreshDifferences" label="Refresh Differences" color="secondary" />
25
+ </q-card-section>
26
+ </q-card>
27
+
28
+ <q-card v-if="Object.keys(existingDatabases).length > 0" class="q-mb-md">
29
+ <q-card-section>
30
+ <div class="text-h6">Database Structure</div>
31
+ <q-tree
32
+ :nodes="databaseTree"
33
+ node-key="id"
34
+ v-model:expanded="expandedNodes"
35
+ >
36
+ <template v-slot:default-header="prop">
37
+ <div class="row items-center">
38
+ <div>{{ prop.node.label }}</div>
39
+ <q-badge v-if="prop.node.type" color="primary" class="q-ml-sm">
40
+ {{ prop.node.type }}
41
+ </q-badge>
42
+ </div>
43
+ </template>
44
+ </q-tree>
45
+ </q-card-section>
46
+ </q-card>
47
+
48
+ <q-dialog v-model="settingsDialog" persistent>
49
+ <q-card>
50
+ <q-card-section>
51
+ <div class="text-h6">Database Settings</div>
52
+ <q-input v-model="host" label="Database Host" required />
53
+ <q-input v-model="port" label="Database Port" type="number" required />
54
+ <q-input v-model="user" label="Database User" required />
55
+ <q-input
56
+ v-model="password"
57
+ label="Database Password"
58
+ type="password"
59
+ required
60
+ autocomplete="off"
61
+ />
62
+ <q-input v-model="database" label="Database Name" required />
63
+ <q-input v-model="dbFolder" label="Database Folder" required />
64
+ </q-card-section>
65
+ <q-card-actions>
66
+ <q-btn @click="saveSettings" label="Save" color="primary" />
67
+ <q-btn @click="closeSettings" label="Cancel" color="secondary" />
68
+ </q-card-actions>
69
+ </q-card>
70
+ </q-dialog>
71
+ </q-page>
72
+ </template>
73
+
74
+ <script>
75
+ import axios from 'axios'
76
+
77
+ export default {
78
+ data() {
79
+ return {
80
+ isDbSetup: false,
81
+ differences: [],
82
+ columns: [
83
+ { name: 'table', label: 'Table', align: 'left', field: 'table' },
84
+ { name: 'difference', label: 'Difference', align: 'left', field: 'difference' },
85
+ ],
86
+ settingsDialog: false,
87
+ host: '127.0.0.1',
88
+ port: 3306,
89
+ user: 'root',
90
+ password: '',
91
+ database: '',
92
+ dbFolder: 'db-dump',
93
+ existingDatabases: [],
94
+ databaseColumns: [
95
+ { name: 'name', label: 'Database Name', align: 'left', field: 'name' },
96
+ { name: 'size', label: 'Size', align: 'left', field: 'size' },
97
+ ],
98
+ databaseTree: [],
99
+ expandedNodes: [],
100
+ }
101
+ },
102
+ methods: {
103
+ openSettings() {
104
+ this.settingsDialog = true
105
+ },
106
+ closeSettings() {
107
+ this.settingsDialog = false
108
+ },
109
+ saveSettings() {
110
+ const dbConfig = {
111
+ host: this.host,
112
+ port: this.port,
113
+ user: this.user,
114
+ password: this.password,
115
+ database: this.database,
116
+ output: this.dbFolder,
117
+ }
118
+ localStorage.setItem('dbConfig', JSON.stringify(dbConfig))
119
+ this.isDbSetup = true
120
+ this.closeSettings()
121
+ this.refreshDifferences()
122
+ },
123
+ async refreshDifferences() {
124
+ if (!this.isDbSetup) return
125
+ try {
126
+ const response = await axios.post('http://localhost:3000/api/compare', {
127
+ config: {
128
+ host: this.host,
129
+ port: this.port,
130
+ user: this.user,
131
+ password: this.password,
132
+ output: this.dbFolder,
133
+ database: this.database,
134
+ },
135
+ })
136
+ this.differences = response.data
137
+ } catch (error) {
138
+ console.error('Error fetching differences:', error)
139
+ }
140
+ },
141
+ async getDatabasesFromExistingDumps() {
142
+ try {
143
+ const response = await axios.post(
144
+ `http://localhost:3000/api/getDatabasesFromExistingDumps`,
145
+ {
146
+ config: {
147
+ host: this.host,
148
+ port: this.port,
149
+ user: this.user,
150
+ password: this.password,
151
+ output: this.dbFolder,
152
+ },
153
+ },
154
+ )
155
+ if (response.data && typeof response.data === 'object') {
156
+ this.existingDatabases = response.data
157
+ this.buildDatabaseTree()
158
+ }
159
+ } catch (error) {
160
+ console.error('Error fetching databases from existing dumps:', error)
161
+ }
162
+ },
163
+ buildDatabaseTree() {
164
+ this.databaseTree = Object.entries(this.existingDatabases).map(([dbName, db]) => ({
165
+ id: `db-${dbName}`,
166
+ label: dbName,
167
+ type: 'database',
168
+ children: [
169
+ // Tables section
170
+ {
171
+ id: `${dbName}-tables`,
172
+ label: 'Tables',
173
+ type: 'category',
174
+ children: Object.entries(db.tables).map(([tableName, table]) => ({
175
+ id: `${dbName}-table-${tableName}`,
176
+ label: tableName,
177
+ type: 'table',
178
+ children: [
179
+ // Columns subsection
180
+ {
181
+ id: `${dbName}-table-${tableName}-columns`,
182
+ label: 'Columns',
183
+ type: 'subcategory',
184
+ children: table.columns.map(column => ({
185
+ id: `${dbName}-table-${tableName}-column-${column.Field}`,
186
+ label: `${column.Field} (${column.Type})${column.NotNull ? ' NOT NULL' : ''}${column.AutoIncrement ? ' AUTO_INCREMENT' : ''}`,
187
+ type: 'column',
188
+ noChildren: true
189
+ }))
190
+ },
191
+ // Indexes subsection (if present)
192
+ table.indexes && table.indexes.length > 0 && {
193
+ id: `${dbName}-table-${tableName}-indexes`,
194
+ label: 'Indexes',
195
+ type: 'subcategory',
196
+ children: table.indexes.map(index => ({
197
+ id: `${dbName}-table-${tableName}-index-${index.Name}`,
198
+ label: `${index.Name}${index.Primary ? ' (Primary)' : ''}${index.Unique ? ' (Unique)' : ''}`,
199
+ type: 'index',
200
+ noChildren: true
201
+ }))
202
+ },
203
+ // Triggers subsection (if present)
204
+ table.triggers && table.triggers.length > 0 && {
205
+ id: `${dbName}-table-${tableName}-triggers`,
206
+ label: 'Triggers',
207
+ type: 'subcategory',
208
+ children: table.triggers.map(trigger => ({
209
+ id: `${dbName}-table-${tableName}-trigger-${trigger.name}`,
210
+ label: trigger.name,
211
+ type: 'trigger',
212
+ noChildren: true
213
+ }))
214
+ }
215
+ ].filter(Boolean)
216
+ }))
217
+ },
218
+ // Procedures section (if present)
219
+ db.procedures && db.procedures.length > 0 && {
220
+ id: `${dbName}-procedures`,
221
+ label: 'Procedures',
222
+ type: 'category',
223
+ children: db.procedures.map(proc => ({
224
+ id: `${dbName}-proc-${proc.Name}`,
225
+ label: proc.Name,
226
+ type: 'procedure',
227
+ noChildren: true
228
+ }))
229
+ }
230
+ ].filter(Boolean)
231
+ }))
232
+
233
+ // Only expand the first level (databases)
234
+ this.expandedNodes = this.databaseTree.map(node => node.id)
235
+ },
236
+ async fetchAllDifferences() {
237
+ const response = await axios.post('http://localhost:3000/api/compare', {
238
+ config: {
239
+ host: this.host,
240
+ port: this.port,
241
+ user: this.user,
242
+ password: this.password,
243
+ output: this.dbFolder,
244
+ },
245
+ })
246
+ this.differences = response.data
247
+ },
248
+ async fetchDifferencesForSelectedDb() {
249
+ if (Object.keys(this.existingDatabases).length > 0) {
250
+ const selectedDbName = Object.keys(this.existingDatabases)[0]
251
+ const response = await axios.post('http://localhost:3000/api/compare', {
252
+ config: {
253
+ host: this.host,
254
+ port: this.port,
255
+ user: this.user,
256
+ password: this.password,
257
+ output: this.dbFolder,
258
+ database: selectedDbName,
259
+ },
260
+ })
261
+ this.differences = response.data
262
+ }
263
+ },
264
+ async createNewDump() {
265
+ console.log('Creating a new dump...')
266
+ let response = await axios.post('http://localhost:3000/api/dump', {
267
+ config: {
268
+ host: this.host,
269
+ port: this.port,
270
+ user: this.user,
271
+ password: this.password,
272
+ output: this.dbFolder,
273
+ database: this.database,
274
+ },
275
+ }).catch((error) => {
276
+ if (error.response.data.message) {
277
+ this.$q.dialog({
278
+ title: 'Error',
279
+ message: error.response.data.message,
280
+ })
281
+ }
282
+ console.error('Error creating new dump:', error)
283
+ return
284
+ })
285
+
286
+ if (!response) return
287
+ if (response.data.message) {
288
+ this.$q.dialog({
289
+ title: 'Error',
290
+ message: response.data.message,
291
+ })
292
+ }
293
+
294
+ if (response.data && typeof response.data === 'object' && Object.keys(response.data).length > 0) {
295
+ this.existingDatabases = response.data
296
+ this.buildDatabaseTree()
297
+ } else {
298
+ this.existingDatabases = {}
299
+ this.$q.notify({
300
+ message: 'Error creating new dump',
301
+ color: 'red',
302
+ })
303
+ }
304
+ },
305
+ },
306
+ mounted() {
307
+ const dbConfig = localStorage.getItem('dbConfig')
308
+ if (dbConfig) {
309
+ const config = JSON.parse(dbConfig)
310
+ this.host = config.host
311
+ this.port = config.port
312
+ this.user = config.user
313
+ this.password = config.password
314
+ this.database = config.database
315
+ this.dbFolder = config.output
316
+ this.isDbSetup = true
317
+ this.getDatabasesFromExistingDumps()
318
+ this.fetchAllDifferences()
319
+ }
320
+ },
321
+ }
322
+ </script>