Compare commits

..

358 Commits

Author SHA1 Message Date
SPRINX0\prochazka a4876f6f14 v6.3.2 2025-04-02 14:08:24 +02:00
SPRINX0\prochazka 9835ae7e50 v6.3.2-premium-beta.4 2025-04-02 13:35:11 +02:00
SPRINX0\prochazka 59f763162c SYNC: fixed zoom 2025-04-02 11:34:18 +00:00
SPRINX0\prochazka a9412b418f changelog 2025-04-02 12:58:58 +02:00
SPRINX0\prochazka 742c5b76fe v6.3.2-premium-beta.3 2025-04-02 12:45:53 +02:00
SPRINX0\prochazka 7a85fc0179 fixed startup theme 2025-04-02 12:36:42 +02:00
SPRINX0\prochazka 73e73ffe58 SYNC: column search test+screenshot 2025-04-02 10:17:41 +00:00
SPRINX0\prochazka 3c5523894d v6.3.2-beta.2 2025-04-02 11:59:27 +02:00
SPRINX0\prochazka 4b9c76d3db Merge branch 'master' of https://github.com/dbgate/dbgate 2025-04-02 11:59:01 +02:00
SPRINX0\prochazka 0a694eea8a SYNC: fix 2025-04-02 09:58:53 +00:00
SPRINX0\prochazka 87f48dad79 v6.3.2-beta.1 2025-04-02 10:54:58 +02:00
SPRINX0\prochazka 68ef50ca46 real-time system theme switch #1084 2025-04-02 10:52:17 +02:00
SPRINX0\prochazka 8b1da33ffe ability to use dark mode from system #1084 2025-04-02 10:44:40 +02:00
SPRINX0\prochazka 9a9b18a3ef clickhouse: load views for users with limited permissions #1076 2025-04-02 09:48:35 +02:00
SPRINX0\prochazka 0bd7d23114 SYNC: highlight columne header search controls 2025-04-01 12:55:33 +00:00
SPRINX0\prochazka 9b860a6aa6 SYNC: uniqied form and grid search in columns 2025-04-01 12:51:20 +00:00
SPRINX0\prochazka 4812519a4c SYNC: search in columns - show filtered column in grid 2025-04-01 12:41:35 +00:00
SPRINX0\prochazka f3ce6ad467 SYNC: #1077 set custom connection prop from ENV vars 2025-04-01 10:47:43 +00:00
SPRINX0\prochazka 78d9b48854 SYNC: scrollable exported diagram 2025-04-01 10:37:15 +00:00
SPRINX0\prochazka b37d0eba04 diagram export scirpt 2025-04-01 12:16:27 +02:00
CI workflows 5289b3f54c chore: auto-update github workflows 2025-04-01 08:41:47 +00:00
CI workflows 5c08fe0611 Update pro ref 2025-04-01 08:41:28 +00:00
SPRINX0\prochazka 4bc9b70882 SYNC: configurable export watermark 2025-04-01 08:41:16 +00:00
CI workflows 3f98f9ff39 chore: auto-update github workflows 2025-04-01 08:02:15 +00:00
CI workflows e78a7bfbf1 Update pro ref 2025-04-01 08:01:56 +00:00
SPRINX0\prochazka b8b1412bf8 SYNC: diagram improvements 2025-04-01 08:01:44 +00:00
CI workflows a81d66ace3 chore: auto-update github workflows 2025-03-31 15:04:42 +00:00
CI workflows dcfd72b7e7 Update pro ref 2025-03-31 15:04:25 +00:00
SPRINX0\prochazka 6467db4a21 SYNC: show diagram table counts WIP 2025-03-31 15:04:11 +00:00
SPRINX0\prochazka f2570c97f3 SYNC: diagram - persist scroll when zooming 2025-03-31 12:42:43 +00:00
SPRINX0\prochazka 98ad518b5d SYNC: designer right-mouse drag scroll implementation 2025-03-31 12:20:01 +00:00
SPRINX0\prochazka 7a5e17a345 SYNC: fixed selecting in diagrams with zoom 2025-03-31 11:29:53 +00:00
SPRINX0\prochazka fde257c722 SYNC: fixes 2025-03-31 11:14:59 +00:00
SPRINX0\prochazka 97357f082d removed diagramsettings 2025-03-31 12:24:12 +02:00
CI workflows 6875bd82fc chore: auto-update github workflows 2025-03-31 10:23:04 +00:00
CI workflows b1f6cad741 Update pro ref 2025-03-31 10:22:44 +00:00
CI workflows fb28fec60d chore: auto-update github workflows 2025-03-31 10:18:36 +00:00
CI workflows 500130be59 Update pro ref 2025-03-31 10:18:15 +00:00
SPRINX0\prochazka 101173c87c SYNC: diagram settings in premium 2025-03-31 10:16:12 +00:00
SPRINX0\prochazka 4fb1b0dbd1 SYNC: zoom diagram by wheel 2025-03-31 10:12:28 +00:00
SPRINX0\prochazka 4270d5e8ec SYNC: most important tables diagram setting 2025-03-31 08:37:23 +00:00
SPRINX0\prochazka 6fce43a122 SYNC: fixed diagram references when using zoom 2025-03-28 15:24:33 +00:00
CI workflows a8a8f9b3e5 chore: auto-update github workflows 2025-03-28 14:43:05 +00:00
SPRINX0\prochazka 0dd0125e9f SYNC: test for parseName + fix 2025-03-28 14:42:43 +00:00
SPRINX0\prochazka d3d97b5924 SYNC: support OR in filterName 2025-03-28 14:09:05 +00:00
SPRINX0\prochazka c8462fb50b SYNC: diagram column filter 2025-03-28 13:29:09 +00:00
SPRINX0\prochazka c99ca9edcc SYNC: diagram style 2025-03-28 11:59:29 +00:00
CI workflows fc7e96feb9 chore: auto-update github workflows 2025-03-28 11:50:55 +00:00
CI workflows 31dd7be296 Update pro ref 2025-03-28 11:50:38 +00:00
SPRINX0\prochazka 2899373e42 SYNC: diagram settings more visible 2025-03-28 11:50:28 +00:00
CI workflows 7640c3d0ef chore: auto-update github workflows 2025-03-28 08:57:26 +00:00
CI workflows af7772f617 Update pro ref 2025-03-28 08:57:09 +00:00
SPRINX0\prochazka a1670caf06 fix export diagram - body - overflow - scroll 2025-03-28 09:31:45 +01:00
SPRINX0\prochazka 61e35b9773 Redis - ability to skip SETNAME #1077 2025-03-28 08:55:01 +01:00
SPRINX0\prochazka e4671ffdb3 exit connectProcess after connection test 2025-03-28 08:44:56 +01:00
SPRINX0\prochazka 3035f923cb Merge branch 'master' of https://github.com/dbgate/dbgate 2025-03-28 08:22:02 +01:00
SPRINX0\prochazka 97e83def48 end tab preview mode when change grid config 2025-03-28 08:21:57 +01:00
SPRINX0\prochazka ba31deaebf SYNC: missing gitkeep file 2025-03-27 15:24:27 +00:00
SPRINX0\prochazka bd571dc93d SYNC: slightly better dropdownmanu-layout algorithm 2025-03-26 15:13:31 +00:00
SPRINX0\prochazka c1da8321ac themeshot name 2025-03-26 13:09:11 +01:00
SPRINX0\prochazka 0a1972b854 themeshot name 2025-03-26 12:59:08 +01:00
SPRINX0\prochazka 96f387e90b SEO friendly screenshot names 2025-03-26 12:46:33 +01:00
SPRINX0\prochazka e034fc1019 SYNC: new themeshot 2025-03-26 09:08:26 +00:00
SPRINX0\prochazka d539912762 SYNC: fragment shots 2025-03-26 08:13:02 +00:00
SPRINX0\prochazka 85b72af3bb Merge branch 'master' of https://github.com/dbgate/dbgate 2025-03-26 08:00:21 +01:00
SPRINX0\prochazka 3004f4b583 malformed changelog 2025-03-26 08:00:18 +01:00
SPRINX0\prochazka 78dbd7eacd SYNC: screenshot 2025-03-25 16:13:02 +00:00
SPRINX0\prochazka add73e6f16 SYNC: filter - error 2025-03-25 15:53:59 +00:00
SPRINX0\prochazka 2c5a7d103d premium info in community 2025-03-25 15:10:59 +01:00
SPRINX0\prochazka f8f855d5d2 changed web 2025-03-25 14:02:44 +01:00
Jan Prochazka f2c109116c Merge branch 'master' of github.com:dbgate/dbgate 2025-03-24 17:34:42 +01:00
Jan Prochazka 41c63fab96 readme 2025-03-24 17:34:38 +01:00
Jan Prochazka de94651fca SYNC: data duplicator screenshot+test 2025-03-24 13:07:40 +00:00
Jan Prochazka 611c468b70 changed URLs 2025-03-24 10:30:14 +01:00
CI workflows fd2207e39e chore: auto-update github workflows 2025-03-23 13:37:52 +00:00
Jan Prochazka 10564442e2 try to fix process templates 2025-03-23 14:37:31 +01:00
Jan Prochazka a44307ca2d SYNC: fix 2025-03-23 11:57:11 +00:00
CI workflows cfea2ed954 Update pro ref 2025-03-23 11:57:05 +00:00
Jan Prochazka 62e59605ed SYNC: tableyaml screenshot 2025-03-23 11:56:53 +00:00
CI workflows 2644b1b7ac chore: auto-update github workflows 2025-03-23 10:18:52 +00:00
Jan Prochazka 6e4c6d0c54 condition for pushing e2e screenshots 2025-03-23 11:18:36 +01:00
Jan Prochazka 2b7d950a9f SYNC: next screenshots 2025-03-23 09:06:51 +00:00
CI workflows 5ece8d67f9 chore: auto-update github workflows 2025-03-23 08:31:04 +00:00
Jan Prochazka 8511b67811 Merge branch 'master' of github.com:dbgate/dbgate 2025-03-23 09:30:46 +01:00
Jan Prochazka a0a444e476 ammend commit in images 2025-03-23 09:30:43 +01:00
Jan Prochazka 6fec92926d SYNC: ai assistant test - try to increase timeout 2025-03-23 07:47:24 +00:00
Jan Prochazka 2cbefb261b skip ai assistant test 2025-03-22 15:01:17 +01:00
CI workflows 4bebbb158c chore: auto-update github workflows 2025-03-22 13:34:42 +00:00
Jan Prochazka 8fe2172c0a Merge branch 'master' of github.com:dbgate/dbgate 2025-03-22 14:34:28 +01:00
Jan Prochazka f52ef2d57e push to image repo 2025-03-22 14:34:25 +01:00
Jan Prochazka 3f1c005548 SYNC: switch on all tests 2025-03-22 10:47:58 +00:00
Jan Prochazka 821bd2b2d8 SYNC: filter themeshot 2025-03-22 09:11:13 +00:00
SPRINX0\prochazka bd94437c05 v6.3.1 2025-03-18 13:49:28 +01:00
SPRINX0\prochazka b290bdb473 v6.3.1-packer-beta.1 2025-03-18 13:42:48 +01:00
SPRINX0\prochazka f8e2af4fd4 SYNC: set current version for azure build 2025-03-18 12:39:46 +00:00
SPRINX0\prochazka 97c8dfa5b9 changelog 2025-03-18 12:56:09 +01:00
SPRINX0\prochazka 37cce68e2e v6.3.0 2025-03-18 12:13:15 +01:00
SPRINX0\prochazka 1f87a71b98 changelog 2025-03-18 12:12:08 +01:00
SPRINX0\prochazka 5511ea1887 dark theme detect, startup with dark theme 2025-03-17 15:43:33 +01:00
SPRINX0\prochazka e371081a1d Merge branch 'master' of https://github.com/dbgate/dbgate 2025-03-17 15:07:10 +01:00
SPRINX0\prochazka 70816b48e8 changelog 2025-03-17 15:07:08 +01:00
SPRINX0\prochazka 2c9fc7b4a7 SYNC: health 2025-03-17 13:11:59 +00:00
SPRINX0\prochazka 3bb4652a49 SYNC: health status 2025-03-17 12:57:47 +00:00
SPRINX0\prochazka d5f8e01dd8 changelog for 6.3.0 2025-03-17 10:50:17 +01:00
CI workflows 27e0517f9a chore: auto-update github workflows 2025-03-14 14:44:48 +00:00
CI workflows f59aeda28e Update pro ref 2025-03-14 14:44:35 +00:00
Jan Prochazka a8a69f8c36 v6.2.2-beta.10 2025-03-14 15:33:23 +01:00
Jan Prochazka 4ae6b8328e v6.2.2-premium-beta.9 2025-03-14 15:33:09 +01:00
Jan Prochazka 6d4337e4ce Merge branch 'master' of github.com:dbgate/dbgate 2025-03-14 15:31:35 +01:00
Jan Prochazka 3df928caf4 deleted obsolete file 2025-03-14 15:31:31 +01:00
Jan Prochazka faeb33fdc0 SYNC: libsql volatile package 2025-03-14 14:30:00 +00:00
Jan Prochazka bacdeb20eb libSQL - premium only 2025-03-14 15:26:28 +01:00
Jan Prochazka 781c426b2f libSQL - targetType 2025-03-14 15:25:15 +01:00
Jan Prochazka d5c9fb8dec refactor 2025-03-14 15:04:53 +01:00
CI workflows 78c372b9d8 chore: auto-update github workflows 2025-03-14 13:52:44 +00:00
Jan Prochazka ea31069609 fix 2025-03-14 14:52:28 +01:00
CI workflows 3f9a3e8f64 chore: auto-update github workflows 2025-03-14 13:45:28 +00:00
Jan Prochazka 2f02715efd Merge pull request #1069 from dbgate/feature/libsql
feat: libsql basic support
2025-03-14 14:45:14 +01:00
Jan Prochazka c94fa64a33 v6.2.2-premium-beta.8 2025-03-14 14:40:58 +01:00
CI workflows e2cb666b3c chore: auto-update github workflows 2025-03-14 13:40:22 +00:00
CI workflows 9f24e0145b Update pro ref 2025-03-14 13:40:10 +00:00
Jan Prochazka 41413471aa v6.2.2-premium-beta.7 2025-03-14 14:26:07 +01:00
CI workflows f8a11166f0 chore: auto-update github workflows 2025-03-14 13:25:42 +00:00
CI workflows 27517b3b47 Update pro ref 2025-03-14 13:25:29 +00:00
Jan Prochazka 834c0d92b4 v6.2.2-premium-beta.6 2025-03-14 14:01:39 +01:00
Jan Prochazka e04215f0e1 commented out localization 2025-03-14 14:01:20 +01:00
Jan Prochazka 9fa8d98ae8 Merge branch 'master' of github.com:dbgate/dbgate 2025-03-14 12:09:31 +01:00
Jan Prochazka 31621f273b SYNC: commented dump tests 2025-03-14 11:07:13 +00:00
Jan Prochazka 41f158dac1 v6.2.2-premium-beta.5 2025-03-14 11:47:11 +01:00
CI workflows e5687f3a7c chore: auto-update github workflows 2025-03-14 10:44:44 +00:00
CI workflows 1a5b684e1f Update pro ref 2025-03-14 10:44:30 +00:00
CI workflows bf70c487ca chore: auto-update github workflows 2025-03-14 10:38:22 +00:00
CI workflows 4e1d34ba77 Update pro ref 2025-03-14 10:38:10 +00:00
Jan Prochazka 3a75ad61f3 SYNC: Merge branch 'feature/backup-restore' 2025-03-14 10:37:58 +00:00
Nybkox c7db9ef481 fix: default options for libsql drive .script 2025-03-13 10:19:25 +01:00
Nybkox fb709c9eb0 fix(libSql): support useTransaction flag for scripts 2025-03-13 09:44:39 +01:00
Nybkox dfe4d2811a fix(ScriptDrivedDeployer): avoid nested transactions 2025-03-13 09:44:21 +01:00
Nybkox 6e4d16749b feat: lib sql server tests 2025-03-12 09:54:13 +01:00
Nybkox 75b2debf0a feat: libsql basic support 2025-03-11 15:11:35 +01:00
Jan Prochazka ba9e124527 Merge pull request #1064 from nyaaao/cassandra-auth
feat: add support for plain-text auth for Cassandra
2025-03-11 12:29:28 +01:00
SPRINX0\prochazka d684ab0e5e translation extractor 2025-03-07 17:33:51 +01:00
SPRINX0\prochazka 2e8205f458 fixed translation extractor 2025-03-07 17:33:07 +01:00
SPRINX0\prochazka 35855297eb SYNC: fix 2025-03-06 07:59:33 +00:00
SPRINX0\prochazka d365ecce46 translations 2025-03-06 08:52:17 +01:00
SPRINX0\prochazka f4edc45507 localization 2025-03-05 18:36:31 +01:00
SPRINX0\prochazka d165d81df0 renamed some lang keys 2025-03-05 18:27:05 +01:00
SPRINX0\prochazka ba0eba7132 SYNC: mognodb - correct handle stream errors 2025-03-05 17:09:48 +00:00
SPRINX0\prochazka 2b7f4281c2 SYNC: mongo import tests 2025-03-05 16:53:29 +00:00
SPRINX0\prochazka 0046575a4f SYNC: test CSV import 2025-03-05 16:10:52 +00:00
SPRINX0\prochazka 58b88d66be catch errors in base bulk importer 2025-03-05 16:56:18 +01:00
SPRINX0\prochazka 57f1019e51 SYNC: CSV with error import test 2025-03-05 15:35:34 +00:00
SPRINX0\prochazka b40168182a SYNC: fixed SQLite E2E tests (use absolute folder) 2025-03-05 14:25:40 +00:00
SPRINX0\prochazka 0ece662d8c SYNC: CSV import test 2025-03-05 13:21:47 +00:00
SPRINX0\prochazka 9265e52d68 SYNC: backup table, truncate, drop table - tests for all DBs 2025-03-05 12:33:16 +00:00
SPRINX0\prochazka 3a04166747 fixed bulk import 2025-03-05 12:55:37 +01:00
SPRINX0\prochazka 75bf58359c import error reporting 2025-03-05 12:51:44 +01:00
SPRINX0\prochazka e7f63e0460 confirm reload 2025-03-05 10:56:29 +01:00
SPRINX0\prochazka 1fdd1c6e88 Merge branch 'feature/localization' 2025-03-05 10:49:08 +01:00
SPRINX0\prochazka 391b9e91e9 gitignore 2025-03-05 10:44:08 +01:00
Nybkox 1e67ca3794 feat: default value for language select 2025-03-04 22:05:04 +01:00
Nybkox ceebf6dbe1 chore: add logging to translations:check ok scenario 2025-03-04 22:05:04 +01:00
Nybkox 8d4f9fd953 fix: use simple languagnes names 2025-03-04 22:05:04 +01:00
Nybkox 1c3032068e feat: remove unused by default when extracting 2025-03-04 21:17:01 +01:00
Nybkox 7b4b72166f chore: move sortJsonKeys helper 2025-03-04 20:54:42 +01:00
Nybkox 707e5bb8b0 chore: update git ignore 2025-03-04 20:53:53 +01:00
Nybkox ad5d364c57 chore: extract translations 2025-03-04 20:53:53 +01:00
Nybkox 138fadf672 feat: compile messages 2025-03-04 20:53:53 +01:00
Nybkox 82eabc41fe feat: sort translation json keys alphabetically 2025-03-04 20:53:52 +01:00
Nybkox 3e6aab6b00 feat: basic translations to ui 2025-03-04 20:53:52 +01:00
Nybkox 5396b3f1fb feat: add translations:check command 2025-03-04 20:53:52 +01:00
Nybkox b1ba887922 feat: separate remove-unused command 2025-03-04 20:53:52 +01:00
Nybkox 93a1c593fe feat: add basic language switch to settings 2025-03-04 20:53:52 +01:00
Nybkox b7044248cb feat: add translations api for fe 2025-03-04 20:53:52 +01:00
Nybkox ea5e2f660b feat: add --removeUnused flag to extract translations 2025-03-04 20:53:52 +01:00
Nybkox e9779a3d2f feat: add add-missing command to translations cli 2025-03-04 20:53:52 +01:00
Nybkox 1c6ec0f8e3 refactor: add index.js to translations-cli, add translations:extract to package.json 2025-03-04 20:53:52 +01:00
Nybkox 84bd81e525 feat: throw when found the same translation key with different default values 2025-03-04 20:53:52 +01:00
Nybkox a84cbee9db feat: basic translations extract 2025-03-04 20:53:52 +01:00
CI workflows 97b16c8c0c chore: auto-update github workflows 2025-03-04 15:43:56 +00:00
CI workflows 0a6a35b022 Update pro ref 2025-03-04 15:43:43 +00:00
SPRINX0\prochazka 6565b4101b SYNC: try to fix local e2e tests 2025-03-04 15:43:27 +00:00
nyaaao fbbcc1172d feat: add support for plain-text auth for Cassandra 2025-03-04 16:58:05 +02:00
SPRINX0\prochazka 53dc50c0dd Merge branch 'feature/impexp' 2025-03-04 15:55:10 +01:00
SPRINX0\prochazka 7b56485c74 report progress for quick exports 2025-03-04 15:51:43 +01:00
SPRINX0\prochazka cfc9b809fc key hack - correct reporting progress rows 2025-03-04 15:30:18 +01:00
SPRINX0\prochazka 4015e2566e import/export progress reporter 2025-03-04 15:21:22 +01:00
SPRINX0\prochazka 1d474a967c report read row count, if written row count not available 2025-03-04 15:17:58 +01:00
SPRINX0\prochazka bffc34485a report wwritten rows 2025-03-04 15:08:24 +01:00
SPRINX0\prochazka 3bf22a8606 import/export log messages 2025-03-04 14:29:52 +01:00
SPRINX0\prochazka 257ffa3cc4 show import/export error 2025-03-04 14:26:11 +01:00
SPRINX0\prochazka 0c104d5d29 progress indicator in exports 2025-03-04 13:55:36 +01:00
Jan Prochazka 2a59faec17 Merge pull request #1063 from nyaaao/cassandra-local-data-center-env
feat: configure cassandra local datacenter via environment variable
2025-03-04 12:55:20 +01:00
nyaaao 00534f7edd feat: allow specifying cassandra local datacenter via environment variable 2025-03-04 13:28:29 +02:00
SPRINX0\prochazka 4006f03444 removed invalid param 2025-03-04 10:06:05 +01:00
SPRINX0\prochazka beca5c6e45 using stream.pipeline for better handling errors 2025-03-04 09:51:29 +01:00
SPRINX0\prochazka 69f781d3de handle copyStreamError 2025-03-04 08:58:04 +01:00
SPRINX0\prochazka 3f3160406f propagate error in mongo stream 2025-03-03 16:05:12 +01:00
CI workflows 8067cff9bd chore: auto-update github workflows 2025-03-03 14:15:13 +00:00
CI workflows 7d776bb2af Update pro ref 2025-03-03 14:14:57 +00:00
SPRINX0\prochazka 880bb0d7cb SYNC: Change or add option to disable Shift + Space for AI Assistant #1060 2025-03-03 14:14:41 +00:00
SPRINX0\prochazka 3aea01fb78 v6.2.2-packer-beta.4 2025-03-03 10:34:57 +01:00
SPRINX0\prochazka 7025f4701d Merge branch 'master' of https://github.com/dbgate/dbgate 2025-03-03 10:34:32 +01:00
CI workflows 9d98b06132 chore: auto-update github workflows 2025-03-03 09:34:17 +00:00
SPRINX0\prochazka 47cb83c1ff Merge branch 'master' of https://github.com/dbgate/dbgate 2025-03-03 10:34:12 +01:00
CI workflows 6ff8847251 Update pro ref 2025-03-03 09:34:01 +00:00
SPRINX0\prochazka 9d9367d127 v6.2.2-packer-beta.3 2025-03-03 10:21:24 +01:00
SPRINX0\prochazka ae7c1ae666 Merge branch 'master' of https://github.com/dbgate/dbgate 2025-03-03 10:21:08 +01:00
CI workflows 44fe3cb7bd chore: auto-update github workflows 2025-03-03 09:16:39 +00:00
CI workflows bc783eb511 Update pro ref 2025-03-03 09:16:24 +00:00
SPRINX0\prochazka 0491bd5364 v6.2.2-packer-beta.2 2025-03-03 09:42:30 +01:00
SPRINX0\prochazka cf47cccc97 v6.2.2-packer.1 2025-03-03 09:35:47 +01:00
CI workflows c65ab35107 chore: auto-update github workflows 2025-03-03 08:33:14 +00:00
CI workflows b8ea16f4d4 Update pro ref 2025-03-03 08:32:57 +00:00
Jan Prochazka b40b5f0c1c v6.2.1 2025-02-28 10:55:29 +01:00
Jan Prochazka b193e29fdb changelog 2025-02-28 10:55:07 +01:00
Jan Prochazka 1b602c134f v6.2.1-premium-beta.11 2025-02-28 10:31:38 +01:00
Jan Prochazka e462c6d412 v6.2.1-premium-beta.10 2025-02-28 10:28:55 +01:00
Jan Prochazka d0c83f3c96 Merge pull request #1058 from dbgate/feature/xml-fixes
Feature/xml fixes
2025-02-28 10:28:21 +01:00
Jan Prochazka 0547aa2095 xml format indent 2025-02-28 10:20:18 +01:00
Nybkox 322907b972 feat: add themes to xml view 2025-02-27 17:12:27 +01:00
Nybkox 189b9a7ad6 feat: add xml-formatter 2025-02-27 15:55:06 +01:00
SPRINX0\prochazka 1d02927f6b scroll in xml cell data view 2025-02-27 12:44:34 +01:00
CI workflows 2ad739419a chore: auto-update github workflows 2025-02-27 09:06:11 +00:00
SPRINX0\prochazka 093ace1a89 updated build version 2025-02-27 10:05:45 +01:00
SPRINX0\prochazka 4c982a762b v6.2.1-premium-beta.9 2025-02-27 09:33:08 +01:00
SPRINX0\prochazka a30efd6e81 allow SQLite on web #956 2025-02-27 09:26:38 +01:00
SPRINX0\prochazka 1c0fc0bff2 removed onsolete code 2025-02-27 08:21:13 +01:00
SPRINX0\prochazka 7da0c204df Merge branch 'feature/impexp' 2025-02-27 08:20:05 +01:00
SPRINX0\prochazka a35421d8ab import fixed 2025-02-27 08:19:49 +01:00
SPRINX0\prochazka 450ce53dcf import WIP 2025-02-26 16:43:24 +01:00
SPRINX0\prochazka e80ccfcb19 fixed open query from datagrid 2025-02-26 13:37:21 +01:00
SPRINX0\prochazka 9ad612bd78 Merge branch 'master' of https://github.com/dbgate/dbgate 2025-02-26 10:26:03 +01:00
CI workflows 288857999f Update pro ref 2025-02-26 09:25:50 +00:00
SPRINX0\prochazka 217823652c v6.2.1-beta.8 2025-02-26 10:24:32 +01:00
SPRINX0\prochazka 268e1670c7 v6.2.1-premium-beta.7 2025-02-26 10:23:53 +01:00
SPRINX0\prochazka ce7b155f72 remove armv7l app build 2025-02-26 10:20:56 +01:00
SPRINX0\prochazka 2a71d84580 Merge branch 'master' of https://github.com/dbgate/dbgate 2025-02-26 10:14:03 +01:00
CI workflows 8f73dce934 chore: auto-update github workflows 2025-02-26 09:13:58 +00:00
CI workflows 5953e32988 Update ref to 6b5b092b9da447d89e64b30bfa2910833bf73312 2025-02-26 09:13:38 +00:00
SPRINX0\prochazka df74322b05 v6.2.1-premium-beta.6 2025-02-26 10:02:05 +01:00
SPRINX0\prochazka 22d941ae45 v6.2.1-beta.5 2025-02-26 08:37:19 +01:00
CI workflows 4fd7c1c4e9 chore: auto-update github workflows 2025-02-26 07:37:04 +00:00
SPRINX0\prochazka ee1aa6d42c workflow change 2025-02-26 08:36:39 +01:00
SPRINX0\prochazka 1343aba26e try to fix docker build 2025-02-26 08:33:50 +01:00
SPRINX0\prochazka 1483d84d8c v6.2.1-beta.4 2025-02-25 18:38:49 +01:00
CI workflows 02d58d66c9 chore: auto-update github workflows 2025-02-25 17:38:32 +00:00
SPRINX0\prochazka 2eb6ca28f7 full container - removed linux/arm/v7 docker platform 2025-02-25 18:38:12 +01:00
SPRINX0\prochazka 7575a9ce02 v6.2.1-beta.3 2025-02-25 18:17:00 +01:00
CI workflows 039b832be2 chore: auto-update github workflows 2025-02-25 17:16:32 +00:00
SPRINX0\prochazka e0ed025507 added setup qemu 2025-02-25 18:15:52 +01:00
SPRINX0\prochazka f2bd08f02a mixed mongoDB export #1044 2025-02-25 17:59:31 +01:00
SPRINX0\prochazka 63314b54bc v6.2.1-premium-beta.2 2025-02-25 17:24:36 +01:00
SPRINX0\prochazka 65165cd15f v6.2.1-beta.1 2025-02-25 16:58:44 +01:00
SPRINX0\prochazka d5ddbca067 Merge branch 'master' of https://github.com/dbgate/dbgate 2025-02-25 15:20:07 +01:00
SPRINX0\prochazka 517027e1fe SYNC: clearTestingData 2025-02-25 15:19:58 +01:00
SPRINX0\prochazka b843ccc898 SYNC: skip AI test 2025-02-25 14:11:43 +00:00
SPRINX0\prochazka fffd81267d SYNC: sqlite - passed transaction test 2025-02-25 14:11:41 +00:00
SPRINX0\prochazka 7d26dd5348 upgraded better-sqlite3 2025-02-25 14:33:56 +01:00
Jan Prochazka a4d3189dac import models tests fixed 2025-02-25 13:58:03 +01:00
SPRINX0\prochazka ec02743f83 SYNC: test fix 2025-02-25 11:38:55 +00:00
CI workflows 10e807751a chore: auto-update github workflows 2025-02-25 11:18:31 +00:00
SPRINX0\prochazka a8e827b5e2 fixed port for e2e-mssql 2025-02-25 12:18:11 +01:00
CI workflows f0eaba5857 chore: auto-update github workflows 2025-02-25 11:13:14 +00:00
SPRINX0\prochazka 7516b056a5 fixed workflow 2025-02-25 12:12:56 +01:00
CI workflows 312c3b8295 chore: auto-update github workflows 2025-02-25 11:09:55 +00:00
SPRINX0\prochazka 0a777dc909 fix 2025-02-25 12:09:36 +01:00
CI workflows ec24376608 chore: auto-update github workflows 2025-02-25 11:06:08 +00:00
SPRINX0\prochazka c9f45da217 fix 2025-02-25 12:05:10 +01:00
SPRINX0\prochazka 34cfbabf51 fix 2025-02-25 11:05:29 +01:00
SPRINX0\prochazka f7e7a4c99c fix 2025-02-25 11:02:09 +01:00
SPRINX0\prochazka 58c318b5cf process templates fix 2025-02-25 11:00:31 +01:00
SPRINX0\prochazka 10b1644d8d fix 2025-02-25 10:57:22 +01:00
SPRINX0\prochazka 599f59fc39 test change 2025-02-25 10:55:35 +01:00
SPRINX0\prochazka da4b8f6cb9 Merge branch 'master' of https://github.com/dbgate/dbgate 2025-02-25 10:53:19 +01:00
SPRINX0\prochazka 5f2e882ed9 process templates 2025-02-25 10:53:13 +01:00
CI workflows f20abe8878 Update ref to 83c1c85eb2761a642c17b2f0f882970718e0afca 2025-02-25 09:45:10 +00:00
SPRINX0\prochazka a6ab37f21c SYNC: transaction test works for oracle 2025-02-25 09:28:12 +00:00
SPRINX0\prochazka 13fc3ee25e SYNC: fixed test 2025-02-25 09:28:11 +00:00
SPRINX0\prochazka 2268086eac SYNC: autocommit icons 2025-02-25 09:28:10 +00:00
SPRINX0\prochazka 9e9dec5389 SYNC: autocommit for Oracle 2025-02-25 09:28:08 +00:00
SPRINX0\prochazka 11d193a6dd SYNC: commit/rollback - control commands 2025-02-25 09:28:07 +00:00
SPRINX0\prochazka f81207737c SYNC: INSERT SQL template 2025-02-25 09:28:06 +00:00
SPRINX0\prochazka 191c25a26b SYNC: autocommit WIP 2025-02-24 16:13:12 +00:00
Jan Prochazka 9c7727b7f3 oracle insert bulk inserts fix 2025-02-24 16:28:19 +01:00
Jan Prochazka 8bea9b8312 import data fixes 2025-02-24 16:14:51 +01:00
SPRINX0\prochazka 805a063fa1 SYNC: fixes 2025-02-24 15:14:22 +00:00
SPRINX0\prochazka 20a1cc89ae SYNC: import model+data test 2025-02-24 14:27:20 +00:00
SPRINX0\prochazka 963994b1e5 SYNC: some fixes 2025-02-24 14:19:17 +00:00
SPRINX0\prochazka afcb226111 SYNC: mutli-sql tests 2025-02-24 13:18:52 +00:00
SPRINX0\prochazka 5b246fe44c SYNC: multi tests 2025-02-24 12:46:20 +00:00
SPRINX0\prochazka d79f82e9b8 SYNC: fixed test 2025-02-24 12:27:03 +00:00
SPRINX0\prochazka bdd9dc8c9d SYNC: multi-sql 2025-02-24 11:21:02 +00:00
Veronika Kincova 8bdd24aa1e SYNC: [skip ci] Drop table test 2025-02-24 10:23:50 +00:00
Veronika Kincova 13c0da5c8a SYNC: [skip ci] Only fix 2025-02-24 10:07:07 +00:00
Veronika Kincova d31cfb15db SYNC: [skip ci] Backup - Truncate table test 2025-02-24 10:07:02 +00:00
SPRINX0\prochazka 8453bd3c26 SYNC: [skip ci] cy:open in root 2025-02-24 08:25:41 +00:00
SPRINX0\prochazka 457bf311c3 Commit/rollback in query editor #1039 2025-02-21 17:30:16 +01:00
SPRINX0\prochazka ea2ec9ef54 refresh testid 2025-02-21 16:50:59 +01:00
SPRINX0\prochazka d0c84ea469 better workflow for askUser, when closing window 2025-02-21 16:11:23 +01:00
SPRINX0\prochazka cdec56b661 SYNC: [skip ci] Show server name alongside database name in title of the tab group #1041 2025-02-21 14:08:32 +00:00
SPRINX0\prochazka 8bc2d7cb05 update ref 2025-02-21 13:42:11 +01:00
SPRINX0\prochazka 21f3de0a18 Merge branch 'master' of https://github.com/dbgate/dbgate 2025-02-21 13:30:42 +01:00
SPRINX0\prochazka 65b497c9f1 update pro ref 2025-02-21 13:30:40 +01:00
SPRINX0\prochazka f37f1e794e SYNC: [skip ci] fixed FK joining #1051 2025-02-21 12:04:30 +00:00
SPRINX0\prochazka 0096a40132 removed obsolete query designer 2025-02-21 12:50:53 +01:00
SPRINX0\prochazka b6b9b67836 fixed crash after filtering mongo array columns #1049 2025-02-21 12:38:22 +01:00
SPRINX0\prochazka 2b80a98a96 fix 2025-02-21 12:28:15 +01:00
SPRINX0\prochazka 8c5d47bfa0 run with push 2025-02-21 10:37:18 +01:00
SPRINX0\prochazka 00c0a0505f run with push 2025-02-21 10:28:17 +01:00
SPRINX0\prochazka 01ba8b4f3f commit info 2025-02-21 10:24:42 +01:00
SPRINX0\prochazka 919249215b fix 2025-02-21 10:20:41 +01:00
SPRINX0\prochazka a62394a67c changed used secret 2025-02-21 10:13:56 +01:00
SPRINX0\prochazka 332fff279b fix 2025-02-21 09:53:20 +01:00
SPRINX0\prochazka 27df4c435f use different secret 2025-02-21 09:52:30 +01:00
SPRINX0\prochazka a9998ebca7 tmp 2025-02-21 09:38:23 +01:00
SPRINX0\prochazka 82a8baabef fix 2025-02-21 09:37:17 +01:00
SPRINX0\prochazka 2af6d4ef29 fix 2025-02-21 09:35:56 +01:00
SPRINX0\prochazka c2526c1e2d diflow config 2025-02-21 09:31:35 +01:00
SPRINX0\prochazka 6021fa721e diflow CI 2025-02-19 16:44:13 +01:00
SPRINX0\prochazka 0bd59dc0f8 filter by column data type fix 2025-02-17 11:29:31 +01:00
Jan Prochazka 1af0c34ac0 Merge branch 'master' of github.com:dbgate/dbgate 2025-02-15 09:35:28 +01:00
Jan Prochazka 77f5b6d0c8 cassandra in readme 2025-02-15 09:34:53 +01:00
SPRINX0\prochazka cb3fdf1112 changelog 2025-02-14 15:05:45 +01:00
SPRINX0\prochazka 482d3d9188 v6.2.0 2025-02-14 14:56:52 +01:00
SPRINX0\prochazka bb4c64f478 v6.1.7-premium-beta.10 2025-02-14 14:34:52 +01:00
SPRINX0\prochazka a9d6e42add changelog 2025-02-14 14:34:08 +01:00
SPRINX0\prochazka 5fa6cf8eca Revert "build zip for mac (for autoupgrade)"
This reverts commit 6388129e27.
2025-02-14 14:27:19 +01:00
SPRINX0\prochazka 7c0de7b634 v6.1.7-beta.9 2025-02-14 14:06:13 +01:00
SPRINX0\prochazka 691f3238c5 v6.1.7-premium-beta.8 2025-02-14 14:05:56 +01:00
SPRINX0\prochazka 43163c787d renamed file 2025-02-14 14:04:25 +01:00
SPRINX0\prochazka a86693d950 v6.1.7-premium-beta.7 2025-02-14 13:56:07 +01:00
SPRINX0\prochazka 6388129e27 build zip for mac (for autoupgrade) 2025-02-14 13:55:47 +01:00
SPRINX0\prochazka 7788806a8d update pro ref 2025-02-14 13:50:07 +01:00
SPRINX0\prochazka 30037dad83 better connection error reporting 2025-02-14 13:27:56 +01:00
SPRINX0\prochazka d49c7d5e45 workflows 2025-02-14 12:49:11 +01:00
SPRINX0\prochazka 502109cdcb publish new plugins 2025-02-14 12:48:17 +01:00
SPRINX0\prochazka 3de775a163 ai assistant UX 2025-02-14 12:28:02 +01:00
SPRINX0\prochazka d4de917895 AI UX 2025-02-14 08:57:20 +01:00
SPRINX0\prochazka 35cb718f1f last used actions changed in switch button 2025-02-13 16:23:18 +01:00
SPRINX0\prochazka 60a72f4d45 fix data grid join problem #565 2025-02-13 15:54:40 +01:00
SPRINX0\prochazka 6ae536d035 datagrid: open real query in case of error 2025-02-13 15:47:55 +01:00
SPRINX0\prochazka 23daa7a91c fixes 2025-02-13 15:32:36 +01:00
SPRINX0\prochazka 771f93b5fa updated pro ref 2025-02-13 14:35:31 +01:00
SPRINX0\prochazka 19826636c7 uncommented builds 2025-02-12 14:03:49 +01:00
SPRINX0\prochazka 57ba9b52ba v6.1.7-packer-beta.6 2025-02-12 13:57:26 +01:00
SPRINX0\prochazka 38c0d9bbc3 pro update 2025-02-12 13:57:01 +01:00
SPRINX0\prochazka 5fb3e0b941 v6.1.7-packer-beta.5 2025-02-12 13:43:41 +01:00
SPRINX0\prochazka 9aa09d138a update pro ref 2025-02-12 13:43:19 +01:00
SPRINX0\prochazka f48efcc02d fix 2025-02-12 13:42:58 +01:00
SPRINX0\prochazka 1703e9e8c6 v6.1.7-packer-beta.4 2025-02-12 12:05:53 +01:00
SPRINX0\prochazka 940cf02935 build cloud 2025-02-12 12:05:40 +01:00
SPRINX0\prochazka 355aefc62a delete old azure VMs 2025-02-12 12:02:06 +01:00
SPRINX0\prochazka 0c0c9b2dad v6.1.7-packer-beta.3 2025-02-12 10:38:00 +01:00
SPRINX0\prochazka d3df844917 update pro ref 2025-02-12 10:37:36 +01:00
SPRINX0\prochazka e227f1f182 build script 2025-02-12 10:36:54 +01:00
SPRINX0\prochazka f97b49bc53 Merge branch 'master' of https://github.com/dbgate/dbgate 2025-02-12 09:47:50 +01:00
SPRINX0\prochazka 788b6def6c azure ubuntu support 2025-02-12 09:47:44 +01:00
Jan Prochazka 8550707485 Merge pull request #1038 from dbgate/feature/xml-preview
feat: add xml preview
2025-02-11 17:03:18 +01:00
275 changed files with 6506 additions and 2059 deletions
+17 -17
View File
@@ -5,10 +5,10 @@ name: Electron app BETA
'on':
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+-beta.[0-9]+'
- v[0-9]+.[0-9]+.[0-9]+-beta.[0-9]+
jobs:
build:
runs-on: '${{ matrix.os }}'
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
@@ -24,7 +24,7 @@ jobs:
echo "PYTHON=/opt/homebrew/bin/python3.11" >> $GITHUB_ENV
- name: Context
env:
GITHUB_CONTEXT: '${{ toJson(github) }}'
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
@@ -58,7 +58,7 @@ jobs:
yarn printSecrets
env:
GIST_UPLOAD_SECRET: '${{secrets.GIST_UPLOAD_SECRET}}'
GIST_UPLOAD_SECRET: ${{secrets.GIST_UPLOAD_SECRET}}
- name: fillPackagedPlugins
run: |
@@ -71,16 +71,16 @@ jobs:
yarn run build:app
env:
GH_TOKEN: '${{ secrets.GH_TOKEN }}'
WIN_CSC_LINK: '${{ secrets.WINCERT_2025 }}'
WIN_CSC_KEY_PASSWORD: '${{ secrets.WINCERT_2025_PASSWORD }}'
CSC_LINK: '${{ secrets.APPLECERT_CERTIFICATE }}'
CSC_KEY_PASSWORD: '${{ secrets.APPLECERT_PASSWORD }}'
APPLE_ID: '${{ secrets.APPLE_ID }}'
APPLE_TEAM_ID: '${{ secrets.APPLE_TEAM_ID }}'
APPLE_ID_PASSWORD: '${{ secrets.APPLE_ID_PASSWORD }}'
SNAPCRAFT_STORE_CREDENTIALS: '${{secrets.SNAPCRAFT_LOGIN}}'
APPLE_APP_SPECIFIC_PASSWORD: '${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}'
GH_TOKEN: ${{ secrets.GH_TOKEN }}
WIN_CSC_LINK: ${{ secrets.WINCERT_2025 }}
WIN_CSC_KEY_PASSWORD: ${{ secrets.WINCERT_2025_PASSWORD }}
CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }}
CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
- name: Copy artifacts
run: |
mkdir artifacts
@@ -111,16 +111,16 @@ jobs:
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: '${{ matrix.os }}'
name: ${{ matrix.os }}
path: artifacts
- name: Release
uses: softprops/action-gh-release@v1
if: 'startsWith(github.ref, ''refs/tags/'')'
if: startsWith(github.ref, 'refs/tags/')
with:
files: artifacts/**
prerelease: true
env:
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Print content of notarization-error.log
if: failure() && matrix.os == 'macos-14'
run: |
+19 -19
View File
@@ -5,10 +5,10 @@ name: Electron app PREMIUM BETA
'on':
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+-premium-beta.[0-9]+'
- v[0-9]+.[0-9]+.[0-9]+-premium-beta.[0-9]+
jobs:
build:
runs-on: '${{ matrix.os }}'
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
@@ -24,7 +24,7 @@ jobs:
echo "PYTHON=/opt/homebrew/bin/python3.11" >> $GITHUB_ENV
- name: Context
env:
GITHUB_CONTEXT: '${{ toJson(github) }}'
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
@@ -37,9 +37,9 @@ jobs:
uses: actions/checkout@v2
with:
repository: dbgate/dbgate-pro
token: '${{ secrets.GH_TOKEN }}'
token: ${{ secrets.GH_TOKEN }}
path: dbgate-pro
ref: ca1a1664e4c45945d7afe9534c43ca6cbb0b06e3
ref: 5cc577af44faaf6ec61cff778cae6fbe35a6c510
- name: Merge dbgate/dbgate-pro
run: |
mkdir ../dbgate-pro
@@ -88,7 +88,7 @@ jobs:
yarn printSecrets
env:
GIST_UPLOAD_SECRET: '${{secrets.GIST_UPLOAD_SECRET}}'
GIST_UPLOAD_SECRET: ${{secrets.GIST_UPLOAD_SECRET}}
- name: fillPackagedPlugins
run: |
cd ..
@@ -102,16 +102,16 @@ jobs:
yarn run build:app
env:
GH_TOKEN: '${{ secrets.GH_TOKEN }}'
WIN_CSC_LINK: '${{ secrets.WINCERT_2025 }}'
WIN_CSC_KEY_PASSWORD: '${{ secrets.WINCERT_2025_PASSWORD }}'
CSC_LINK: '${{ secrets.APPLECERT_CERTIFICATE }}'
CSC_KEY_PASSWORD: '${{ secrets.APPLECERT_PASSWORD }}'
APPLE_ID: '${{ secrets.APPLE_ID }}'
APPLE_TEAM_ID: '${{ secrets.APPLE_TEAM_ID }}'
APPLE_ID_PASSWORD: '${{ secrets.APPLE_ID_PASSWORD }}'
SNAPCRAFT_STORE_CREDENTIALS: '${{secrets.SNAPCRAFT_LOGIN}}'
APPLE_APP_SPECIFIC_PASSWORD: '${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}'
GH_TOKEN: ${{ secrets.GH_TOKEN }}
WIN_CSC_LINK: ${{ secrets.WINCERT_2025 }}
WIN_CSC_KEY_PASSWORD: ${{ secrets.WINCERT_2025_PASSWORD }}
CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }}
CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
- name: Copy artifacts
run: |
mkdir artifacts
@@ -142,16 +142,16 @@ jobs:
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: '${{ matrix.os }}'
name: ${{ matrix.os }}
path: artifacts
- name: Release
uses: softprops/action-gh-release@v1
if: 'startsWith(github.ref, ''refs/tags/'')'
if: startsWith(github.ref, 'refs/tags/')
with:
files: artifacts/**
prerelease: true
env:
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Print content of notarization-error.log
if: failure() && matrix.os == 'macos-14'
run: |
+19 -19
View File
@@ -5,10 +5,10 @@ name: Electron app PREMIUM
'on':
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
- v[0-9]+.[0-9]+.[0-9]+
jobs:
build:
runs-on: '${{ matrix.os }}'
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
@@ -24,7 +24,7 @@ jobs:
echo "PYTHON=/opt/homebrew/bin/python3.11" >> $GITHUB_ENV
- name: Context
env:
GITHUB_CONTEXT: '${{ toJson(github) }}'
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
@@ -37,9 +37,9 @@ jobs:
uses: actions/checkout@v2
with:
repository: dbgate/dbgate-pro
token: '${{ secrets.GH_TOKEN }}'
token: ${{ secrets.GH_TOKEN }}
path: dbgate-pro
ref: ca1a1664e4c45945d7afe9534c43ca6cbb0b06e3
ref: 5cc577af44faaf6ec61cff778cae6fbe35a6c510
- name: Merge dbgate/dbgate-pro
run: |
mkdir ../dbgate-pro
@@ -88,7 +88,7 @@ jobs:
yarn printSecrets
env:
GIST_UPLOAD_SECRET: '${{secrets.GIST_UPLOAD_SECRET}}'
GIST_UPLOAD_SECRET: ${{secrets.GIST_UPLOAD_SECRET}}
- name: fillPackagedPlugins
run: |
cd ..
@@ -102,16 +102,16 @@ jobs:
yarn run build:app
env:
GH_TOKEN: '${{ secrets.GH_TOKEN }}'
WIN_CSC_LINK: '${{ secrets.WINCERT_2025 }}'
WIN_CSC_KEY_PASSWORD: '${{ secrets.WINCERT_2025_PASSWORD }}'
CSC_LINK: '${{ secrets.APPLECERT_CERTIFICATE }}'
CSC_KEY_PASSWORD: '${{ secrets.APPLECERT_PASSWORD }}'
APPLE_ID: '${{ secrets.APPLE_ID }}'
APPLE_TEAM_ID: '${{ secrets.APPLE_TEAM_ID }}'
APPLE_ID_PASSWORD: '${{ secrets.APPLE_ID_PASSWORD }}'
SNAPCRAFT_STORE_CREDENTIALS: '${{secrets.SNAPCRAFT_LOGIN}}'
APPLE_APP_SPECIFIC_PASSWORD: '${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}'
GH_TOKEN: ${{ secrets.GH_TOKEN }}
WIN_CSC_LINK: ${{ secrets.WINCERT_2025 }}
WIN_CSC_KEY_PASSWORD: ${{ secrets.WINCERT_2025_PASSWORD }}
CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }}
CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
- name: Copy artifacts
run: |
mkdir artifacts
@@ -142,16 +142,16 @@ jobs:
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: '${{ matrix.os }}'
name: ${{ matrix.os }}
path: artifacts
- name: Release
uses: softprops/action-gh-release@v1
if: 'startsWith(github.ref, ''refs/tags/'')'
if: startsWith(github.ref, 'refs/tags/')
with:
files: artifacts/**
prerelease: false
env:
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Print content of notarization-error.log
if: failure() && matrix.os == 'macos-14'
run: |
+17 -17
View File
@@ -5,10 +5,10 @@ name: Electron app
'on':
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
- v[0-9]+.[0-9]+.[0-9]+
jobs:
build:
runs-on: '${{ matrix.os }}'
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
@@ -24,7 +24,7 @@ jobs:
echo "PYTHON=/opt/homebrew/bin/python3.11" >> $GITHUB_ENV
- name: Context
env:
GITHUB_CONTEXT: '${{ toJson(github) }}'
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
@@ -54,7 +54,7 @@ jobs:
yarn printSecrets
env:
GIST_UPLOAD_SECRET: '${{secrets.GIST_UPLOAD_SECRET}}'
GIST_UPLOAD_SECRET: ${{secrets.GIST_UPLOAD_SECRET}}
- name: fillPackagedPlugins
run: |
@@ -67,16 +67,16 @@ jobs:
yarn run build:app
env:
GH_TOKEN: '${{ secrets.GH_TOKEN }}'
WIN_CSC_LINK: '${{ secrets.WINCERT_2025 }}'
WIN_CSC_KEY_PASSWORD: '${{ secrets.WINCERT_2025_PASSWORD }}'
CSC_LINK: '${{ secrets.APPLECERT_CERTIFICATE }}'
CSC_KEY_PASSWORD: '${{ secrets.APPLECERT_PASSWORD }}'
APPLE_ID: '${{ secrets.APPLE_ID }}'
APPLE_TEAM_ID: '${{ secrets.APPLE_TEAM_ID }}'
APPLE_ID_PASSWORD: '${{ secrets.APPLE_ID_PASSWORD }}'
SNAPCRAFT_STORE_CREDENTIALS: '${{secrets.SNAPCRAFT_LOGIN}}'
APPLE_APP_SPECIFIC_PASSWORD: '${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}'
GH_TOKEN: ${{ secrets.GH_TOKEN }}
WIN_CSC_LINK: ${{ secrets.WINCERT_2025 }}
WIN_CSC_KEY_PASSWORD: ${{ secrets.WINCERT_2025_PASSWORD }}
CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }}
CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}}
APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}}
- name: generatePadFile
run: |
yarn generatePadFile
@@ -114,16 +114,16 @@ jobs:
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: '${{ matrix.os }}'
name: ${{ matrix.os }}
path: artifacts
- name: Release
uses: softprops/action-gh-release@v1
if: 'startsWith(github.ref, ''refs/tags/'')'
if: startsWith(github.ref, 'refs/tags/')
with:
files: artifacts/**
prerelease: false
env:
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Print content of notarization-error.log
if: failure() && matrix.os == 'macos-14'
run: |
@@ -1,15 +1,15 @@
# --------------------------------------------------------------------------------------------
# This file is generated. Do not edit manually
# --------------------------------------------------------------------------------------------
name: AWS image PREMIUM
name: Cloud images PREMIUM
'on':
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+-packer-beta.[0-9]+'
- v[0-9]+.[0-9]+.[0-9]+
- v[0-9]+.[0-9]+.[0-9]+-packer-beta.[0-9]+
jobs:
build:
runs-on: '${{ matrix.os }}'
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
@@ -17,7 +17,7 @@ jobs:
steps:
- name: Context
env:
GITHUB_CONTEXT: '${{ toJson(github) }}'
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
@@ -26,6 +26,9 @@ jobs:
uses: actions/setup-node@v1
with:
node-version: 18.x
- name: Install jq
run: |
sudo apt-get install jq -y
- name: Setup `packer`
uses: hashicorp/setup-packer@main
with:
@@ -34,9 +37,9 @@ jobs:
uses: actions/checkout@v2
with:
repository: dbgate/dbgate-pro
token: '${{ secrets.GH_TOKEN }}'
token: ${{ secrets.GH_TOKEN }}
path: dbgate-pro
ref: ca1a1664e4c45945d7afe9534c43ca6cbb0b06e3
ref: 5cc577af44faaf6ec61cff778cae6fbe35a6c510
- name: Merge dbgate/dbgate-pro
run: |
mkdir ../dbgate-pro
@@ -69,7 +72,7 @@ jobs:
cd dbgate-merged
yarn printSecrets
env:
GIST_UPLOAD_SECRET: '${{secrets.GIST_UPLOAD_SECRET}}'
GIST_UPLOAD_SECRET: ${{secrets.GIST_UPLOAD_SECRET}}
- name: Prepare packer build
run: |
cd ..
@@ -84,41 +87,56 @@ jobs:
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: '${{ matrix.os }}'
name: ${{ matrix.os }}
path: artifacts
- name: Release
uses: softprops/action-gh-release@v1
if: 'startsWith(github.ref, ''refs/tags/'')'
if: startsWith(github.ref, 'refs/tags/')
with:
files: artifacts/**
prerelease: true
env:
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
- name: Run `packer init`
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Run `packer init` for Azure
run: |
cd ../dbgate-merged/packer
packer init ./azure-ubuntu.pkr.hcl
- name: Run `packer build` for Azure
run: |
cd ../dbgate-merged/packer
packer build ./azure-ubuntu.pkr.hcl
- name: Run `packer init` for AWS
run: |
cd ../dbgate-merged/packer
packer init ./aws-ubuntu.pkr.hcl
env:
AWS_ACCESS_KEY_ID: '${{secrets.AWS_ACCESS_KEY_ID}}'
AWS_SECRET_ACCESS_KEY: '${{secrets.AWS_SECRET_ACCESS_KEY}}'
AWS_DEFAULT_REGION: '${{secrets.AWS_DEFAULT_REGION}}'
- name: Run `packer build`
AWS_ACCESS_KEY_ID: ${{secrets.AWS_ACCESS_KEY_ID}}
AWS_SECRET_ACCESS_KEY: ${{secrets.AWS_SECRET_ACCESS_KEY}}
AWS_DEFAULT_REGION: ${{secrets.AWS_DEFAULT_REGION}}
- name: Run `packer build` for AWS
run: |
cd ../dbgate-merged/packer
packer build ./aws-ubuntu.pkr.hcl
env:
AWS_ACCESS_KEY_ID: '${{secrets.AWS_ACCESS_KEY_ID}}'
AWS_SECRET_ACCESS_KEY: '${{secrets.AWS_SECRET_ACCESS_KEY}}'
AWS_DEFAULT_REGION: '${{secrets.AWS_DEFAULT_REGION}}'
- name: Install jq
AWS_ACCESS_KEY_ID: ${{secrets.AWS_ACCESS_KEY_ID}}
AWS_SECRET_ACCESS_KEY: ${{secrets.AWS_SECRET_ACCESS_KEY}}
AWS_DEFAULT_REGION: ${{secrets.AWS_DEFAULT_REGION}}
- name: Delete old Azure VMs
run: |
sudo apt-get install jq -y
- name: Delete old AMIs
cd ../dbgate-merged/packer
chmod +x delete-old-azure-images.sh
./delete-old-azure-images.sh
env:
AZURE_CLIENT_ID: ${{secrets.AZURE_CLIENT_ID}}
AZURE_CLIENT_SECRET: ${{secrets.AZURE_CLIENT_SECRET}}
AZURE_TENANT_ID: ${{secrets.AZURE_TENANT_ID}}
AZURE_SUBSCRIPTION_ID: ${{secrets.AZURE_SUBSCRIPTION_ID}}
- name: Delete old AMIs (AWS)
run: |
cd ../dbgate-merged/packer
chmod +x delete-old-amis.sh
./delete-old-amis.sh
env:
AWS_ACCESS_KEY_ID: '${{secrets.AWS_ACCESS_KEY_ID}}'
AWS_SECRET_ACCESS_KEY: '${{secrets.AWS_SECRET_ACCESS_KEY}}'
AWS_DEFAULT_REGION: '${{secrets.AWS_DEFAULT_REGION}}'
AWS_ACCESS_KEY_ID: ${{secrets.AWS_ACCESS_KEY_ID}}
AWS_SECRET_ACCESS_KEY: ${{secrets.AWS_SECRET_ACCESS_KEY}}
AWS_DEFAULT_REGION: ${{secrets.AWS_DEFAULT_REGION}}
+15 -13
View File
@@ -5,11 +5,11 @@ name: Docker image PREMIUM
'on':
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+-premium-beta.[0-9]+'
- v[0-9]+.[0-9]+.[0-9]+
- v[0-9]+.[0-9]+.[0-9]+-premium-beta.[0-9]+
jobs:
build:
runs-on: '${{ matrix.os }}'
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
@@ -17,7 +17,7 @@ jobs:
steps:
- name: Context
env:
GITHUB_CONTEXT: '${{ toJson(github) }}'
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
@@ -34,17 +34,17 @@ jobs:
type=match,pattern=\d+.\d+.\d+,enable=${{ !contains(github.ref_name, '-docker.') && !contains(github.ref_name, '-beta.') }}
type=raw,value=latest,enable=${{ !contains(github.ref_name, '-docker.') && !contains(github.ref_name, '-beta.') }}
- name: Use Node.js 18.x
- name: Use Node.js 22.x
uses: actions/setup-node@v1
with:
node-version: 18.x
node-version: 22.x
- name: Checkout dbgate/dbgate-pro
uses: actions/checkout@v2
with:
repository: dbgate/dbgate-pro
token: '${{ secrets.GH_TOKEN }}'
token: ${{ secrets.GH_TOKEN }}
path: dbgate-pro
ref: ca1a1664e4c45945d7afe9534c43ca6cbb0b06e3
ref: 5cc577af44faaf6ec61cff778cae6fbe35a6c510
- name: Merge dbgate/dbgate-pro
run: |
mkdir ../dbgate-pro
@@ -83,24 +83,26 @@ jobs:
yarn printSecrets
env:
GIST_UPLOAD_SECRET: '${{secrets.GIST_UPLOAD_SECRET}}'
GIST_UPLOAD_SECRET: ${{secrets.GIST_UPLOAD_SECRET}}
- name: Prepare docker image
run: |
cd ..
cd dbgate-merged
yarn run prepare:docker
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: '${{ secrets.DOCKER_USERNAME }}'
password: '${{ secrets.DOCKER_PASSWORD }}'
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v3
with:
push: true
context: ../dbgate-merged/docker
tags: '${{ steps.meta.outputs.tags }}'
platforms: 'linux/amd64,linux/arm64'
tags: ${{ steps.meta.outputs.tags }}
platforms: linux/amd64,linux/arm64
+15 -13
View File
@@ -5,11 +5,11 @@ name: Docker image Community
'on':
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+-beta.[0-9]+'
- v[0-9]+.[0-9]+.[0-9]+
- v[0-9]+.[0-9]+.[0-9]+-beta.[0-9]+
jobs:
build:
runs-on: '${{ matrix.os }}'
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
@@ -17,7 +17,7 @@ jobs:
steps:
- name: Context
env:
GITHUB_CONTEXT: '${{ toJson(github) }}'
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
@@ -47,10 +47,10 @@ jobs:
type=match,pattern=\d+.\d+.\d+,suffix=-alpine,enable=${{ !contains(github.ref_name, '-docker.') && !contains(github.ref_name, '-beta.') }}
type=raw,value=alpine,enable=${{ !contains(github.ref_name, '-docker.') && !contains(github.ref_name, '-beta.') }}
- name: Use Node.js 18.x
- name: Use Node.js 22.x
uses: actions/setup-node@v1
with:
node-version: 18.x
node-version: 22.x
- name: adjustPackageJson
run: |
@@ -70,30 +70,32 @@ jobs:
yarn printSecrets
env:
GIST_UPLOAD_SECRET: '${{secrets.GIST_UPLOAD_SECRET}}'
GIST_UPLOAD_SECRET: ${{secrets.GIST_UPLOAD_SECRET}}
- name: Prepare docker image
run: |
yarn run prepare:docker
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: '${{ secrets.DOCKER_USERNAME }}'
password: '${{ secrets.DOCKER_PASSWORD }}'
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v3
with:
push: true
context: ./docker
tags: '${{ steps.meta.outputs.tags }}'
platforms: 'linux/amd64,linux/arm64,linux/arm/v7'
tags: ${{ steps.meta.outputs.tags }}
platforms: linux/amd64,linux/arm64,linux/arm/v7
- name: Build and push alpine
uses: docker/build-push-action@v3
with:
push: true
context: ./docker
file: ./docker/Dockerfile-alpine
tags: '${{ steps.alpmeta.outputs.tags }}'
platforms: 'linux/amd64,linux/arm64,linux/arm/v7'
tags: ${{ steps.alpmeta.outputs.tags }}
platforms: linux/amd64,linux/arm64,linux/arm/v7
+8 -8
View File
@@ -5,11 +5,11 @@ name: NPM packages PREMIUM
'on':
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+'
- v[0-9]+.[0-9]+.[0-9]+
- v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+
jobs:
build:
runs-on: '${{ matrix.os }}'
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
@@ -17,7 +17,7 @@ jobs:
steps:
- name: Context
env:
GITHUB_CONTEXT: '${{ toJson(github) }}'
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
@@ -30,9 +30,9 @@ jobs:
uses: actions/checkout@v2
with:
repository: dbgate/dbgate-pro
token: '${{ secrets.GH_TOKEN }}'
token: ${{ secrets.GH_TOKEN }}
path: dbgate-pro
ref: ca1a1664e4c45945d7afe9534c43ca6cbb0b06e3
ref: 5cc577af44faaf6ec61cff778cae6fbe35a6c510
- name: Merge dbgate/dbgate-pro
run: |
mkdir ../dbgate-pro
@@ -51,7 +51,7 @@ jobs:
node adjustNpmPackageJsonPremium
- name: Configure NPM token
env:
NPM_TOKEN: '${{ secrets.NPM_TOKEN }}'
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
cd ..
cd dbgate-merged
@@ -77,7 +77,7 @@ jobs:
cd dbgate-merged
yarn printSecrets
env:
GIST_UPLOAD_SECRET: '${{secrets.GIST_UPLOAD_SECRET}}'
GIST_UPLOAD_SECRET: ${{secrets.GIST_UPLOAD_SECRET}}
- name: Publish dbgate-api-premium
run: |
cd ..
+14 -6
View File
@@ -5,11 +5,11 @@ name: NPM packages
'on':
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+'
- v[0-9]+.[0-9]+.[0-9]+
- v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+
jobs:
build:
runs-on: '${{ matrix.os }}'
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
@@ -17,7 +17,7 @@ jobs:
steps:
- name: Context
env:
GITHUB_CONTEXT: '${{ toJson(github) }}'
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- uses: actions/checkout@v2
with:
@@ -28,7 +28,7 @@ jobs:
node-version: 18.x
- name: Configure NPM token
env:
NPM_TOKEN: '${{ secrets.NPM_TOKEN }}'
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}"
- name: yarn install
@@ -41,7 +41,7 @@ jobs:
run: |
yarn printSecrets
env:
GIST_UPLOAD_SECRET: '${{secrets.GIST_UPLOAD_SECRET}}'
GIST_UPLOAD_SECRET: ${{secrets.GIST_UPLOAD_SECRET}}
- name: Publish types
working-directory: packages/types
run: |
@@ -123,3 +123,11 @@ jobs:
working-directory: plugins/dbgate-plugin-clickhouse
run: |
npm publish
- name: Publish dbgate-plugin-dbf
working-directory: plugins/dbgate-plugin-dbf
run: |
npm publish
- name: Publish dbgate-plugin-cassandra
working-directory: plugins/dbgate-plugin-cassandra
run: |
npm publish
+2 -2
View File
@@ -30,8 +30,8 @@ jobs:
uses: docker/login-action@v2
with:
registry: ghcr.io
username: '${{ github.actor }}'
password: '${{ secrets.GITHUB_TOKEN }}'
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Push mysql-ssh-login to GHCR
run: |
docker tag dbgate/mysql-ssh-login:latest ghcr.io/dbgate/mysql-ssh-login:latest
+36
View File
@@ -0,0 +1,36 @@
# --------------------------------------------------------------------------------------------
# This file is generated. Do not edit manually
# --------------------------------------------------------------------------------------------
name: Diflow merge
'on':
push:
branches:
- master
jobs:
merge:
runs-on: ubuntu-latest
steps:
- name: Use Node.js 22.x
uses: actions/setup-node@v1
with:
node-version: 22.x
- name: Checkout dbgate/diflow
uses: actions/checkout@v2
with:
repository: dbgate/diflow
path: diflow
- name: Diflow install
run: |
cd diflow
npm install
npm run build
- name: Git config
run: |
git config --global user.email "info@dbgate.io"
git config --global user.name "Diflow"
- name: Diflow run
run: |
cd diflow
node dist/diflow.js sync -r https://DIFLOW_GIT_SECRET@github.com/dbgate/dbgate-diflow-config.git -b master
env:
DIFLOW_GIT_SECRET: ${{ secrets.DIFLOW_GIT_SECRET }}
+32 -7
View File
@@ -24,9 +24,9 @@ jobs:
uses: actions/checkout@v2
with:
repository: dbgate/dbgate-pro
token: '${{ secrets.GH_TOKEN }}'
token: ${{ secrets.GH_TOKEN }}
path: dbgate-pro
ref: ca1a1664e4c45945d7afe9534c43ca6cbb0b06e3
ref: 5cc577af44faaf6ec61cff778cae6fbe35a6c510
- name: Merge dbgate/dbgate-pro
run: |
mkdir ../dbgate-pro
@@ -69,6 +69,17 @@ jobs:
with:
name: screenshots
path: screenshots
- name: Push E2E screenshots
if: ${{ github.ref_name == 'master' }}
run: |
git config --global user.email "info@dbgate.info"
git config --global user.name "GitHub Actions"
git clone https://${{ secrets.DIFLOW_GIT_SECRET }}@github.com/dbgate/dbgate-img.git
cp ../dbgate-merged/e2e-tests/screenshots/*.png dbgate-img/static/img
cd dbgate-img/static/img
git add .
git commit --amend --no-edit
git push --force
services:
postgres-cypress:
image: postgres
@@ -78,25 +89,25 @@ jobs:
ports:
- '16000:5432'
mysql-cypress:
image: 'mysql:8.0.18'
image: mysql:8.0.18
ports:
- '16004:3306'
env:
MYSQL_ROOT_PASSWORD: Pwd2020Db
mysql-ssh-login:
image: 'ghcr.io/dbgate/mysql-ssh-login:latest'
image: ghcr.io/dbgate/mysql-ssh-login:latest
ports:
- '16012:22'
mysql-ssh-keyfile:
image: 'ghcr.io/dbgate/mysql-ssh-keyfile:latest'
image: ghcr.io/dbgate/mysql-ssh-keyfile:latest
ports:
- '16008:22'
dex:
image: 'ghcr.io/dbgate/dex:latest'
image: ghcr.io/dbgate/dex:latest
ports:
- '16009:5556'
mongo:
image: 'mongo:4.0.12'
image: mongo:4.0.12
env:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: Pwd2020Db
@@ -106,3 +117,17 @@ jobs:
image: redis
ports:
- '16011:6379'
mssql:
image: mcr.microsoft.com/mssql/server
ports:
- '16014:1433'
env:
ACCEPT_EULA: 'Y'
SA_PASSWORD: Pwd2020Db
MSSQL_PID: Express
oracle:
image: gvenzl/oracle-xe:21-slim
env:
ORACLE_PASSWORD: Pwd2020Db
ports:
- '16013:1521'
+51
View File
@@ -0,0 +1,51 @@
# --------------------------------------------------------------------------------------------
# This file is generated. Do not edit manually
# --------------------------------------------------------------------------------------------
name: Update Workflows
'on':
push:
branches:
- master
paths:
- workflow-templates/**
jobs:
update-workflows:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v3
with:
token: ${{ secrets.WORKFLOW_CHANGE_ACCESS_TOKEN }}
- name: git pull
run: |
git pull
- name: Set up Node
uses: actions/setup-node@v3
with:
node-version: 22
- name: Install dependencies
run: |
rm package.json
rm yarn.lock
yarn add -W js-yaml lodash
- name: Run workflow generation
run: |
node common/processWorkflows.js
- name: Git config
run: |
git config --global user.email "info@dbgate.io"
git config --global user.name "CI workflows"
- name: Commit changes
run: |
# Only commit if there are changes
if [[ -n "$(git status --porcelain)" ]]; then
git add .github/workflows
git commit -m "chore: auto-update github workflows"
else
echo "No changes to commit"
fi
- name: Push changes
uses: ad-m/github-push-action@v0.6.0
with:
github_token: ${{ secrets.WORKFLOW_CHANGE_ACCESS_TOKEN }}
branch: master
+16 -7
View File
@@ -37,22 +37,27 @@ jobs:
run: |
cd packages/datalib
yarn test:ci
- name: Tools tests
if: always()
run: |
cd packages/tools
yarn test:ci
- uses: tanmen/jest-reporter@v1
if: always()
with:
github-token: '${{ secrets.GITHUB_TOKEN }}'
github-token: ${{ secrets.GITHUB_TOKEN }}
result-file: integration-tests/result.json
action-name: Integration tests
- uses: tanmen/jest-reporter@v1
if: always()
with:
github-token: '${{ secrets.GITHUB_TOKEN }}'
github-token: ${{ secrets.GITHUB_TOKEN }}
result-file: packages/filterparser/result.json
action-name: Filter parser test results
- uses: tanmen/jest-reporter@v1
if: always()
with:
github-token: '${{ secrets.GITHUB_TOKEN }}'
github-token: ${{ secrets.GITHUB_TOKEN }}
result-file: packages/datalib/result.json
action-name: Datalib (perspectives) test results
services:
@@ -64,7 +69,7 @@ jobs:
ports:
- '15000:5432'
mysql-integr:
image: 'mysql:8.0.18'
image: mysql:8.0.18
env:
MYSQL_ROOT_PASSWORD: Pwd2020Db
ports:
@@ -78,18 +83,22 @@ jobs:
ports:
- '15002:1433'
clickhouse-integr:
image: 'bitnami/clickhouse:24.8.4'
image: bitnami/clickhouse:24.8.4
env:
CLICKHOUSE_ADMIN_PASSWORD: Pwd2020Db
ports:
- '15005:8123'
oracle-integr:
image: 'gvenzl/oracle-xe:21-slim'
image: gvenzl/oracle-xe:21-slim
env:
ORACLE_PASSWORD: Pwd2020Db
ports:
- '15006:1521'
cassandradb:
image: 'cassandra:5.0.2'
image: cassandra:5.0.2
ports:
- '15942:9042'
libsql:
image: ghcr.io/tursodatabase/libsql-server:latest
ports:
- '8080:8080'
+3 -1
View File
@@ -32,4 +32,6 @@ packages/api/src/packagedPluginsContent.js
.VSCodeCounter
packages/web/public/*.html
e2e-tests/screenshots/*.png
e2e-tests/screenshots/*.png
my_guitar_shop.db
.aider*
+48 -1
View File
@@ -8,6 +8,53 @@ Builds:
- linux - application for linux
- win - application for Windows
### 6.3.2
- ADDED: "Use system theme" switch, use changed system theme without restart #1084
- ADDED: "Skip SETNAME instruction" option for Redis #1077
- FIXED: Clickhouse views are now available even for user with limited permissions #1076
- ADDED: Multiple-token search delimited with comma (=OR) in structure search boxes
- CHANGED: When filtering columns in data browser, data view shows only filtered columns
- ADDED: Advanced settings for diagrams (Premium)
- ADDED: Diagrams - zoom with Ctrl+mouse wheel
- FIXED: Scrollable diagram exports + scroll by mouse drag
- FIXED: Fixed many problems in diagrams when zoom is applied
- FIXED: Correctly end connection process after succesful/unsuccesful connect
### 6.3.0
- ADDED: Support for libSQL and Turso (Premium)
- ADDED: Native backup and restore database for MySQL and PostgreSQL (Premium)
- REMOVED: DbGate internal dump export for MySQL (replaced with call of mysqldump)
- REMOVED: Import SQL dump with internal DbGate capabilities (replaced by calling of mysql and psql utilities)
- FIXED: Many fixes in stream processing (imoprt/export), especialy for MongoDB
- ADDED: Indicating progress of import/export tasks, better error reporting
- CHANGED: #1060 - Changed shortcut for AI assistant
- ADDED: /health endpoint with diagnostic info
- FIXED: Linux Appimage crash => A JavaScript error occurred in the main process #1065 , #1067
### 6.2.1
- ADDED: Commit/rollback and autocommit in scripts #1039
- FIXED: Doesn't import all the records from MongoDB #1044
- ADDED: Show server name alongside database name in title of the tab group #1041
- ADDED: Can't open Sqlite through web #956
- FIXED: Crashed after text input at columns search #1049
- FIXED: Incorrect autojoin for foreign keys with more columns #1051
- FIXED: Scroll in XML cell view, XML view respect themes
- REMOVED: armv7l build for Linux (because of problems with glibc compatibility)
- CHANGED: Upgraded to node:22 for docker builds
- CHANGED: Upgraded SQLite engine version
### 6.2.0
- ADDED: Query AI Assistant (Premium)
- ADDED: Cassandra database support
- ADDED: XML cell data view
- FIXED: Filtering by value in Oracle #1009
- FIXED: Operand type clash: uniqueidentifier is incompatible with int #565
- FIXED: UX in administration
- FIXED: Error reporting of broken connections (sometimes it caused infinite loading of data grid)
- ADDED: Azure managed identity support (Team Premium)
- ADDED: Expanded JSON cell view
- CHANGED: Open real executed query, when datagrid shows loading error
### 6.1.6
- FIXED: Hotfix build process for premium edition
@@ -306,7 +353,7 @@ Builds:
- FIXED: Creating SQLite autoincrement column
- FIXED: Better error reporting from exports/import/dulicator
- CHANGED: Optimalizede OracleDB analysing algorithm
- ADDED: Mutli column filter for perspectives
- ADDED: Multi column filter for perspectives
- FIXED: Fixed some scenarios using tables from different DBs
- FIXED: Sessions with long-running queries are not killed
+5 -5
View File
@@ -15,9 +15,10 @@ But there are also many advanced features like schema compare, visual query desi
DbGate is licensed under GPL-3.0 license and is free to use for any purpose.
* Try it online - [demo.dbgate.org](https://demo.dbgate.org) - online demo application
* **Download** application for Windows, Linux or Mac from [dbgate.org](https://dbgate.org/download/)
* **Download** application for Windows, Linux or Mac from [dbgate.io](https://dbgate.io/download/)
* Looking for DbGate Community? **Download** from [dbgate.org](https://dbgate.org/download/)
* Run web version as [NPM package](https://www.npmjs.com/package/dbgate-serve) or as [docker image](https://hub.docker.com/r/dbgate/dbgate)
* Use nodeJs [scripting interface](https://dbgate.org/docs/scripting) ([API documentation](https://dbgate.org/docs/apidoc))
* Use nodeJs [scripting interface](https://docs.dbgate.io/scripting) ([API documentation](https://docs.dbgate.io/apidoc))
* [Recommend DbGate](https://testimonial.to/dbgate) | [Rate on G2](https://www.g2.com/products/dbgate/reviews)
## Supported databases
@@ -33,8 +34,7 @@ DbGate is licensed under GPL-3.0 license and is free to use for any purpose.
* MariaDB
* CosmosDB (Premium)
* ClickHouse
<!-- Learn more about DbGate features at the [DbGate website](https://dbgate.org/), or try our online [demo application](https://demo.dbgate.org) -->
* Apache Cassandra
<a href="https://raw.githubusercontent.com/dbgate/dbgate/master/img/screenshot1.png">
@@ -89,7 +89,7 @@ Any contributions are welcome. If you want to contribute without coding, conside
* Create issue, if you find problem in app, or you have idea to new feature. If issue already exists, you could leave comment on it, to prioritise most wanted issues
* Create some tutorial video on [youtube](https://www.youtube.com/playlist?list=PLCo7KjCVXhr0RfUSjM9wJMsp_ShL1q61A)
* Become a backer on [GitHub sponsors](https://github.com/sponsors/dbgate) or [Open collective](https://opencollective.com/dbgate)
* Where a small coding is acceptable for you, you could [create plugin](https://dbgate.org/docs/plugin-development). Plugins for new themes can be created actually without JS coding
* Where a small coding is acceptable for you, you could [create plugin](https://docs.dbgate.io/plugin-development). Plugins for new themes can be created actually without JS coding
Thank you!
-1
View File
@@ -51,7 +51,6 @@
"target": "AppImage",
"arch": [
"x64",
"armv7l",
"arm64"
]
},
+1
View File
@@ -357,6 +357,7 @@ function createWindow() {
title: isProApp() ? 'DbGate Premium' : 'DbGate',
frame: useNativeMenu,
titleBarStyle: useNativeMenu ? undefined : 'hidden',
backgroundColor: electron.nativeTheme.shouldUseDarkColors ? '#111111' : undefined,
...bounds,
icon: os.platform() == 'win32' ? 'icon.ico' : path.resolve(__dirname, '../icon.png'),
partition: isProApp() ? 'persist:dbgate-premium' : 'persist:dbgate',
-9
View File
@@ -1,9 +0,0 @@
// this file is generated automatically by script fillNativeModules.js, do not edit it manually
const content = {};
content['better-sqlite3'] = () => require('better-sqlite3');
content['oracledb'] = () => require('oracledb');
module.exports = content;
+43
View File
@@ -0,0 +1,43 @@
//@ts-check
const { getDefaultTranslations, getLanguageTranslations } = require('./helpers');
/**
* @param {string} language
*/
function getMissingTranslations(language) {
const source = getDefaultTranslations();
/** @type {Record<string, string>} */
let target;
try {
target = getLanguageTranslations(language);
} catch {
console.log(`Language ${language} not found, creating a new one`);
target = {};
}
let added = 0;
let removed = 0;
for (const key in source) {
if (!target[key]) {
target[key] = `*** ${source[key]}`;
added++;
}
}
for (const key in target) {
if (!source[key]) {
delete target[key];
removed++;
}
}
const newLength = Object.keys(target).length;
return { result: target, stats: { added, removed, newLength } };
}
module.exports = {
getMissingTranslations,
};
+16
View File
@@ -0,0 +1,16 @@
// @ts-check
//
const defaultLanguage = 'en';
/** @typedef {{ extensions: string[], directories: string[] }} ExtractConfig
/** @type {ExtractConfig} */
const defaultExtractConfig = {
extensions: ['.js', '.ts', '.svelte'],
directories: ['app', 'packages/web'],
};
module.exports = {
defaultLanguage,
defaultExtractConfig,
};
+84
View File
@@ -0,0 +1,84 @@
//@ts-check
const fs = require('fs');
const { promisify } = require('util');
const { getFiles } = require('./helpers');
const readFilePromise = promisify(fs.readFile);
const translationRegex = /_t\(\s*['"]([^'"]+)['"]\s*,\s*\{\s*defaultMessage\s*:\s*['"]([^'"]+)['"]\s*\}/g;
/**
* @param {string} file
*
* @returns {Promise<Record<string, string>>}
*/
async function extractTranslationsFromFile(file) {
/** @type {Record<string, string>} */
const translations = {};
const content = await readFilePromise(file, 'utf-8');
let match;
while ((match = translationRegex.exec(content)) !== null) {
const [_, key, defaultText] = match;
translations[key] = defaultText;
}
return translations;
}
/** @typedef {{ ignoreDuplicates?: boolean }} ExtractOptions */
/**
* @param {string[]} directories
* @param {string[]} extensions
* @param {ExtractOptions} options
*
* @returns {Promise<Record<string, string>>}
*/
async function extractAllTranslations(directories, extensions, options = {}) {
const { ignoreDuplicates } = options;
try {
/** @type {Record<string, string>} */
const allTranslations = {};
/** @type {Record<string, string[]>} */
const translationKeyToFiles = {};
for (const dir of directories) {
const files = await getFiles(dir, extensions);
for (const file of files) {
const fileTranslations = await extractTranslationsFromFile(file);
for (const key in fileTranslations) {
if (!translationKeyToFiles[key]) {
translationKeyToFiles[key] = [];
}
translationKeyToFiles[key].push(file);
if (!ignoreDuplicates && allTranslations[key] && allTranslations[key] !== fileTranslations[key]) {
console.error(
`Different translations for the same key [${key}] found. ${file}: ${
fileTranslations[key]
}. Previous value: ${allTranslations[key]} was found in ${translationKeyToFiles[key].join(', ')}`
);
throw new Error(`Duplicate translation key found: ${key}`);
}
allTranslations[key] = fileTranslations[key];
}
}
}
return allTranslations;
} catch (error) {
console.error('Error extracting translations:', error);
throw error;
}
}
module.exports = {
extractTranslationsFromFile,
extractAllTranslations,
};
+198
View File
@@ -0,0 +1,198 @@
//@ts-check
const path = require('path');
const fs = require('fs');
const { defaultLanguage } = require('./constants');
const sortJsonKeysAlphabetically = require('./sortJsonKeysAlphabetically');
/**
* @param {string} file
* @param {string[]} extensions
*
* @returns {boolean}
*/
function hasValidExtension(file, extensions) {
return extensions.includes(path.extname(file).toLowerCase());
}
/**
* @param {string} dir
* @param {string[]} extensions
*
* @returns {Promise<string[]>}
*/
async function getFiles(dir, extensions) {
const files = await fs.promises.readdir(dir);
const allFiles = await Promise.all(
files.map(async file => {
const filePath = path.join(dir, file);
const stats = await fs.promises.stat(filePath);
if (stats.isDirectory()) {
return getFiles(filePath, extensions);
} else if (stats.isFile() && hasValidExtension(file, extensions)) {
const slashPath = filePath.replace(/\\/g, '/');
if (slashPath.includes('/node_modules/') || slashPath.includes('/build/') || slashPath.includes('/dist/')) {
return null;
}
return filePath;
}
return null;
})
);
const validFiles = /** @type {string[]} */ (allFiles.flat().filter(file => file !== null));
return validFiles;
}
/**
* @param {string | string[]} value
*
* @returns {string}
*/
function formatDefaultValue(value) {
if (Array.isArray(value)) {
return value.join(', ');
}
return value;
}
const scriptDir = getScriptDir();
/** @param {string} file
*
* @returns {string}
*/
function resolveFile(file) {
if (path.isAbsolute(file)) {
return file;
}
return path.resolve(scriptDir, '..', '..', file);
}
/** @param {string[]} dirs
*
* @returns {string[]}
*/
function resolveDirs(dirs) {
return dirs.map(resolveFile);
}
/**
* @param {string[]} extensions
*
* @returns {string[]}
*/
function resolveExtensions(extensions) {
return extensions.map(ext => (ext.startsWith('.') ? ext : `.${ext}`));
}
function getScriptDir() {
if (require.main?.filename) {
return path.dirname(require.main.filename);
}
if ('pkg' in process && process.pkg) {
return path.dirname(process.execPath);
}
return __dirname;
}
/**
* @param {string} file
*/
function ensureFileDirExists(file) {
const dir = path.dirname(file);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
}
/**
* @param {Record<string, string>} existingTranslations - Previously extracted translations
* @param {Record<string, string>} newTranslations - Newly extracted translations
* @returns {{ added: string[], removed: string[], updated: string[] }} Translation changes
*/
const getTranslationChanges = (existingTranslations, newTranslations) => {
const existingKeys = new Set(Object.keys(existingTranslations || {}));
const newKeys = new Set(Object.keys(newTranslations));
const added = [...newKeys].filter(key => !existingKeys.has(key));
const removed = [...existingKeys].filter(key => !newKeys.has(key));
const updated = [...newKeys].filter(
key => existingKeys.has(key) && existingTranslations[key] !== newTranslations[key]
);
return { added, removed, updated };
};
function getDefaultTranslations() {
return getLanguageTranslations(defaultLanguage);
}
/**
* @param {string} language
*
* @returns {Record<string, string>}
*/
function getLanguageTranslations(language) {
const file = resolveFile(`translations/${language}.json`);
const content = fs.readFileSync(file, 'utf-8');
return JSON.parse(content);
}
/**
* @param {string} language
* @param {Record<string, string>} translations
*/
function setLanguageTranslations(language, translations) {
const file = resolveFile(`translations/${language}.json`);
const sorted = sortJsonKeysAlphabetically(translations);
fs.writeFileSync(file, JSON.stringify(sorted, null, 2));
}
/**
* @param {string} language
* @param {Record<string, string>} newTranslations
*/
function updateLanguageTranslations(language, newTranslations) {
const translations = getLanguageTranslations(language);
const updatedTranslations = { ...translations, ...newTranslations };
const sorted = sortJsonKeysAlphabetically(updatedTranslations);
setLanguageTranslations(language, sorted);
}
function getAllLanguages() {
const dir = resolveFile('translations');
const files = fs.readdirSync(dir);
const languages = files.filter(file => file.endsWith('.json')).map(file => file.replace('.json', ''));
return languages;
}
function getAllNonDefaultLanguages() {
return getAllLanguages().filter(language => language !== defaultLanguage);
}
module.exports = {
hasValidExtension,
getFiles,
formatDefaultValue,
resolveFile,
resolveDirs,
resolveExtensions,
ensureFileDirExists,
getTranslationChanges,
getDefaultTranslations,
getLanguageTranslations,
setLanguageTranslations,
updateLanguageTranslations,
getAllLanguages,
getAllNonDefaultLanguages,
};
+3
View File
@@ -0,0 +1,3 @@
const { program } = require('./program');
program.parse();
+163
View File
@@ -0,0 +1,163 @@
//@ts-check
const fs = require('fs');
const { program } = require('commander');
const {
resolveDirs,
resolveExtensions,
getTranslationChanges,
setLanguageTranslations,
getAllNonDefaultLanguages,
updateLanguageTranslations,
getDefaultTranslations,
} = require('./helpers');
const { extractAllTranslations } = require('./extract');
const { getMissingTranslations } = require('./addMissing');
const { defaultLanguage, defaultExtractConfig } = require('./constants');
const { removeUnusedAllTranslations, removeUnusedForSignelLanguage } = require('./removeUnused');
/**
* @typedef {import('./constants').ExtractConfig & { verbose?: boolean, ignoreUnused?: boolean }} ExtractOptions
*/
program.name('dbgate-translations-cli').description('CLI tool for managing translation').version('1.0.0');
program
.command('extract')
.description('Extract translation keys from source files')
.option('-d, --directories <directories...>', 'directories to search', defaultExtractConfig.directories)
.option('-e, --extensions <extensions...>', 'file extensions to process', defaultExtractConfig.extensions)
.option('-r, --ignoreUnused', 'Ignore unused keys in the output file')
.option('-v, --verbose', 'verbose mode')
.action(async (/** @type {ExtractOptions} */ options) => {
try {
const { directories, extensions, verbose, ignoreUnused } = options;
const resolvedRirectories = resolveDirs(directories);
const resolvedExtensions = resolveExtensions(extensions);
const extractedTranslations = await extractAllTranslations(resolvedRirectories, resolvedExtensions);
const defaultTranslations = getDefaultTranslations();
const { added, removed, updated } = getTranslationChanges(defaultTranslations, extractedTranslations);
console.log('\nTranslation changes:');
console.log(`- Added: ${added.length} keys`);
console.log(`- ${ignoreUnused ? 'Unused' : 'Removed'}: ${removed.length} keys`);
console.log(`- Updated: ${updated.length} keys`);
console.log(`- Total: ${Object.keys(extractedTranslations).length} keys`);
if (verbose) {
if (added.length > 0) {
console.log('\nNew keys:');
added.forEach(key => console.log(` + ${key}`));
}
if (removed.length > 0) {
console.log('\nRemoved keys:');
removed.forEach(key => console.log(` - ${key}`));
}
if (updated.length > 0) {
console.log('\nUpdated keys:');
updated.forEach(key => {
console.log(` ~ ${key}`);
console.log(` Old: ${defaultLanguage[key]}`);
console.log(` New: ${extractedTranslations[key]}`);
});
}
}
if (ignoreUnused) {
console.log('New translations were saved. Unused keys are kept.\n');
updateLanguageTranslations(defaultLanguage, extractedTranslations);
if (verbose) {
console.log('\nUnused keys:');
for (const key of removed) {
console.log(`${key}: "${defaultTranslations[key]}"`);
}
}
} else {
console.log('Unused keys were removed.\n');
setLanguageTranslations(defaultLanguage, extractedTranslations);
}
} catch (error) {
console.error(error);
console.error('Error during extraction:', error.message);
process.exit(1);
}
});
const ALL_LANGUAGES = 'all';
/**
* @param {string} target
*/
function addMissingTranslations(target) {
console.log(`Adding missing keys for language: ${target}`);
const { result, stats } = getMissingTranslations(target);
console.log(`Added: ${stats.added}, Removed: ${stats.removed}, Total: ${stats.newLength}`);
setLanguageTranslations(target, result);
console.log(`New translations for ${target} were saved.`);
}
program
.command('add-missing')
.description('Add missing keys for a langauge to the translation file')
.option('-t, --target <target>', 'language to add missing translations to', ALL_LANGUAGES)
.action(options => {
try {
const { target } = options;
const languages = getAllNonDefaultLanguages();
if (target === ALL_LANGUAGES) {
console.log('Adding missing keys for all languages\n');
for (const language of languages) {
addMissingTranslations(language);
console.log();
}
} else {
addMissingTranslations(target);
}
} catch (error) {
console.error(error);
console.error('Error during add-missing:', error.message);
process.exit(1);
}
});
program
.command('remove-unused')
.description('Remove unused keys from the translation files')
.option('-t, --target <target>', 'language to add missing translations to', ALL_LANGUAGES)
.action(async options => {
try {
const { target } = options;
if (target === ALL_LANGUAGES) {
console.log('Removing unused keys from all languages\n');
await removeUnusedAllTranslations();
} else {
await removeUnusedForSignelLanguage(target);
}
} catch (error) {
console.error(error);
console.error('Error during add-missing:', error.message);
process.exit(1);
}
});
program
.command('check')
.description('Check if there are multiple default values for the same key')
.action(async () => {
try {
await extractAllTranslations(defaultExtractConfig.directories, defaultExtractConfig.extensions);
console.log('No problems found while extracting translations.');
} catch (error) {
console.error(error);
console.error('Error during check:', error.message);
process.exit(1);
}
});
module.exports = { program };
+46
View File
@@ -0,0 +1,46 @@
// @ts-check
const { defaultExtractConfig } = require('./constants');
const { extractAllTranslations } = require('./extract');
const { getLanguageTranslations, getAllLanguages, setLanguageTranslations } = require('./helpers');
const { directories, extensions } = defaultExtractConfig;
/**
* @param {string} language
* @param {Record<string, string>} source
*/
function getUsedTranslations(language, source) {
const languageTranslations = getLanguageTranslations(language);
for (const key in languageTranslations) {
if (!(key in source)) {
delete languageTranslations[key];
}
}
return languageTranslations;
}
async function removeUnusedAllTranslations() {
const source = await extractAllTranslations(directories, extensions);
const languages = getAllLanguages();
for (const language of languages) {
const newTranslations = getUsedTranslations(language, source);
setLanguageTranslations(language, newTranslations);
}
}
/**
* @param {string} language
*/
async function removeUnusedForSignelLanguage(language) {
const source = await extractAllTranslations(directories, extensions);
const newTranslations = getUsedTranslations(language, source);
setLanguageTranslations(language, newTranslations);
}
module.exports = {
removeUnusedAllTranslations,
removeUnusedForSignelLanguage,
};
@@ -0,0 +1,24 @@
// @ts-check
/**
* @param {object|string} json
* @returns {object}
*/
function sortJsonKeysAlphabetically(json) {
const obj = typeof json === 'string' ? JSON.parse(json) : json;
if (obj === null || typeof obj !== 'object' || Array.isArray(obj)) {
return obj;
}
const sortedObj = Object.keys(obj)
.sort()
.reduce((result, key) => {
result[key] = obj[key];
return result;
}, {});
return sortedObj;
}
module.exports = sortJsonKeysAlphabetically;
+1
View File
@@ -14,6 +14,7 @@ const volatilePackages = [
'ioredis',
'node-redis-dump2',
'better-sqlite3',
'libsql',
'@azure/cosmos',
'@aws-sdk/rds-signer',
'activedirectory2',
+2 -13
View File
@@ -1,21 +1,10 @@
FROM ubuntu:22.04
FROM node:22
RUN apt-get update && apt-get install -y \
curl \
gnupg \
iputils-ping \
iproute2 \
unixodbc \
gcc \
g++ \
make
RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | gpg --dearmor -o /usr/share/keyrings/nodesource-archive-keyring.gpg \
&& echo "deb [signed-by=/usr/share/keyrings/nodesource-archive-keyring.gpg] https://deb.nodesource.com/node_18.x jammy main" | tee /etc/apt/sources.list.d/nodesource.list \
&& echo "deb-src [signed-by=/usr/share/keyrings/nodesource-archive-keyring.gpg] https://deb.nodesource.com/node_18.x jammy main" | tee -a /etc/apt/sources.list.d/nodesource.list \
&& apt-get update && apt-get install -y nodejs \
&& rm -rf /var/lib/apt/lists/* \
&& npm install -g yarn
&& rm -rf /var/lib/apt/lists/*
WORKDIR /home/dbgate-docker
+8
View File
@@ -0,0 +1,8 @@
module.exports = {
mysql: true,
postgres: true,
mssql: true,
oracle: true,
sqlite: true,
mongo: true
};
+25
View File
@@ -0,0 +1,25 @@
const path = require('path');
const os = require('os');
const fs = require('fs');
const baseDir = path.join(os.homedir(), '.dbgate');
function clearTestingData() {
if (fs.existsSync(path.join(baseDir, 'connections-e2etests.jsonl'))) {
fs.unlinkSync(path.join(baseDir, 'connections-e2etests.jsonl'));
}
if (fs.existsSync(path.join(baseDir, 'settings-e2etests.json'))) {
fs.unlinkSync(path.join(baseDir, 'settings-e2etests.json'));
}
if (fs.existsSync(path.join(baseDir, 'files-e2etests'))) {
fs.rmdirSync(path.join(baseDir, 'files-e2etests'), { recursive: true });
}
if (fs.existsSync(path.join(baseDir, 'archive-e2etests'))) {
fs.rmdirSync(path.join(baseDir, 'archive-e2etests'), { recursive: true });
}
if (fs.existsSync(path.join(__dirname, 'tmpdata', 'my_guitar_shop.db'))) {
fs.unlinkSync(path.join(__dirname, 'tmpdata', 'my_guitar_shop.db'));
}
}
clearTestingData();
+3 -2
View File
@@ -1,6 +1,5 @@
const { defineConfig } = require('cypress');
const killPort = require('kill-port');
const { clearTestingData } = require('./e2eTestTools');
const waitOn = require('wait-on');
const { exec } = require('child_process');
const fs = require('fs');
@@ -14,7 +13,6 @@ module.exports = defineConfig({
// implement node event listeners here
on('before:spec', async details => {
await clearTestingData();
// console.log('********************* DETAILS *********************', JSON.stringify(details));
if (config.isInteractive) {
@@ -39,6 +37,9 @@ module.exports = defineConfig({
case 'team':
serverProcess = exec('yarn start:team');
break;
case 'multi-sql':
serverProcess = exec('yarn start:multi-sql');
break;
}
await waitOn({ resources: ['http://localhost:3000'] });
+8 -2
View File
@@ -13,16 +13,22 @@ describe('Add connection', () => {
it('adds connection', () => {
// cy.get('[data-testid=ConnectionList_buttonNewConnection]').click();
cy.get('[data-testid=ConnectionDriverFields_connectionType]').select('MySQL');
cy.themeshot('connection');
cy.themeshot('new-connection');
cy.get('[data-testid=ConnectionDriverFields_user]').clear().type('root');
cy.get('[data-testid=ConnectionDriverFields_password]').clear().type('Pwd2020Db');
cy.get('[data-testid=ConnectionDriverFields_port]').clear().type('16004');
cy.get('[data-testid=ConnectionDriverFields_displayName]').clear().type('test-mysql-1');
// test connection
cy.get('[data-testid=ConnectionTab_buttonTest]').click();
cy.testid('ConnectionTab_buttonTest').click();
cy.contains('Connected:');
cy.testid('ConnectionTab_tabSshTunnel').click();
cy.testid('ConnectionTab_tabControlContent').themeshot('connection-sshtunnel-window', { padding: 50 });
cy.testid('ConnectionTab_tabSsl').click();
cy.testid('ConnectionTab_tabControlContent').themeshot('connection-ssl-window', { padding: 50 });
// save and connect
cy.get('[data-testid=ConnectionTab_buttonSave]').click();
cy.get('[data-testid=ConnectionTab_buttonConnect]').click();
+110 -34
View File
@@ -15,18 +15,23 @@ beforeEach(() => {
describe('Data browser data', () => {
it('Export window', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').rightclick();
cy.contains('MyChinook').click();
cy.contains('Album').rightclick();
cy.contains('Export').click();
cy.contains('Export advanced').click();
cy.wait(1000);
// cy.testid('SourceTargetConfig_buttonCurrentArchive_target').click();
cy.testid('FormTablesSelect_buttonAll_tables').click();
// cy.testid('FormTablesSelect_buttonAll_tables').click();
// cy.testid('SourceTargetConfig_tablesSelect_source').click();
// cy.find('.listContainer').contains('Album').click();
// cy.find('.listContainer').contains('Track').click();
// cy.wait(4000);
// cy.contains('All tables').click();
cy.contains('Run').click();
cy.contains('Finished job script');
cy.contains('Album.csv');
cy.testid('WidgetIconPanel_database').click();
cy.themeshot('exportcsv');
cy.themeshot('configure-export-csv');
});
it('Data archive editor - macros', () => {
@@ -37,7 +42,7 @@ describe('Data browser data', () => {
cy.contains('Out Of Exile').click({ shiftKey: true });
cy.contains('Change text case').click();
cy.contains('AUDIOSLAVE');
cy.themeshot('freetable');
cy.themeshot('data-archive-macros');
});
it('Load table data', () => {
@@ -76,11 +81,25 @@ describe('Data browser data', () => {
cy.contains('Aerosmith').should('not.exist');
});
it('Data filter', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.contains('Album').click();
cy.testid('DataFilterControl_input_Title').type('Rock{enter}');
cy.contains('Rows: 7');
cy.testid('DataFilterControl_input_AlbumId').type('>10xxx{enter}');
cy.contains('Rows: 7');
cy.testid('DataFilterControl_filtermenu_Title').click();
// hide what is not needed
cy.testid('WidgetIconPanel_database').click();
cy.testid('DataGrid_itemReferences').click();
cy.themeshot('data-browser-filter');
cy.testid('DataGridCore_button_clearFilters').click();
cy.contains('Rows: 347');
});
it('Data grid screenshots', () => {
cy.contains('MySql-connection').click();
cy.window().then(win => {
win.__changeCurrentTheme('theme-dark');
});
cy.contains('MyChinook').click();
@@ -95,16 +114,25 @@ describe('Data browser data', () => {
cy.contains('PgChinook').click();
cy.contains('customer').click();
cy.contains('Leonie').click();
cy.themeshot('datagrid');
cy.themeshot('common-data-browser');
cy.contains('invoice').click();
cy.contains('invoice_line (invoice_id)').click();
cy.themeshot('masterdetail');
cy.themeshot('data-browser-master-detail');
cy.contains('9, Place Louis Barthou').click();
cy.contains('Switch to form').click();
cy.contains('Switch to table'); // test that we are in form view
cy.themeshot('formview');
cy.themeshot('data-browser-form-view');
});
it.only('Column search', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.contains('Customer').click();
cy.testid('ColumnManager_searchColumns').clear().type('name,id{enter}');
cy.contains('Company').should('not.exist');
cy.themeshot('data-browser-column-search');
});
it('SQL Gen', () => {
@@ -112,7 +140,7 @@ describe('Data browser data', () => {
cy.contains('PgChinook').rightclick();
cy.contains('SQL Generator').click();
cy.contains('Check all').click();
cy.themeshot('sqlgen');
cy.themeshot('sql-generator');
});
it('Macros in DB', () => {
@@ -127,7 +155,7 @@ describe('Data browser data', () => {
cy.testid('DataGrid_itemMacros').click();
cy.contains('Change text case').click();
cy.contains('NIELSEN');
cy.themeshot('macros');
cy.themeshot('data-browser-macros');
});
it('Perspectives', () => {
@@ -143,7 +171,7 @@ describe('Data browser data', () => {
// check track is loaded
cy.contains('Put The Finger On You');
cy.themeshot('perspective1');
cy.themeshot('perspective-designer');
});
it('Query editor - code completion', () => {
@@ -152,11 +180,12 @@ describe('Data browser data', () => {
cy.contains('Customer').rightclick();
cy.contains('SQL template').click();
cy.contains('CREATE TABLE').click();
cy.wait(1000);
cy.get('body').realPress('PageDown');
cy.get('body').realType('select * from Album where Album.');
// code completion
cy.contains('ArtistId');
cy.themeshot('query');
cy.themeshot('query-editor-code-completion');
});
it('Query editor - join wizard', () => {
@@ -169,7 +198,7 @@ describe('Data browser data', () => {
cy.get('body').realPress(['Control', 'j']);
// JOIN wizard
cy.contains('INNER JOIN Customer ON Invoice.CustomerId = Customer.CustomerId');
cy.themeshot('joinwizard');
cy.themeshot('query-editor-join-wizard');
});
it('Mongo JSON data view', () => {
@@ -186,7 +215,7 @@ describe('Data browser data', () => {
cy.testid('WidgetIconPanel_cell-data').click();
// test JSON view
cy.contains('Country: "Brazil"');
cy.themeshot('mongoquery');
cy.themeshot('mongo-query-json-view');
});
it('SQL preview', () => {
@@ -196,7 +225,7 @@ describe('Data browser data', () => {
cy.contains('Show SQL').click();
// index should be part of create script
cy.contains('CREATE INDEX `IFK_CustomerSupportRepId`');
cy.themeshot('sqlpreview');
cy.themeshot('sql-preview-create-index');
});
it('Query designer', () => {
@@ -205,7 +234,7 @@ describe('Data browser data', () => {
cy.testid('WidgetIconPanel_file').click();
cy.contains('customer').click();
// cy.contains('left join').rightclick();
cy.themeshot('querydesigner');
cy.themeshot('query-designer');
});
it('Database diagram', () => {
@@ -216,7 +245,7 @@ describe('Data browser data', () => {
cy.testid('WidgetIconPanel_file').click();
// check diagram is shown
cy.contains('MediaTypeId');
cy.themeshot('diagram');
cy.themeshot('database-diagram');
});
it('Charts', () => {
@@ -225,7 +254,7 @@ describe('Data browser data', () => {
cy.contains('line-chart').click();
cy.testid('TabsPanel_buttonSplit').click();
cy.testid('WidgetIconPanel_file').click();
cy.themeshot('charts');
cy.themeshot('view-split-charts');
});
it('Keyboard configuration', () => {
@@ -233,7 +262,7 @@ describe('Data browser data', () => {
cy.contains('Keyboard shortcuts').click();
cy.contains('dataForm.refresh').click();
cy.testid('CommandModal_keyboardButton').click();
cy.themeshot('keyboard');
cy.themeshot('keyboard-configuration');
});
it('Command palette', () => {
@@ -244,7 +273,7 @@ describe('Data browser data', () => {
// cy.realPress('F1');
cy.realPress('PageDown');
cy.realPress('PageDown');
cy.testid('CommandPalette_main').themeshot('commandpalette', { padding: 50 });
cy.testid('CommandPalette_main').themeshot('command-palette', { padding: 50 });
});
it('Show map', () => {
@@ -257,7 +286,7 @@ describe('Data browser data', () => {
cy.contains('13.9').click({ shiftKey: true });
cy.testid('WidgetIconPanel_cell-data').click();
cy.wait(2000);
cy.themeshot('map');
cy.themeshot('cell-map-view');
});
it('Search in connections', () => {
@@ -269,7 +298,7 @@ describe('Data browser data', () => {
cy.contains('Album').click();
cy.testid('SqlObjectList_searchMenuDropDown').click();
cy.contains('Column name').click();
cy.themeshot('connsearch');
cy.themeshot('search-in-connections');
});
it('Plugin tab', () => {
@@ -279,7 +308,7 @@ describe('Data browser data', () => {
cy.contains('Total white theme');
// wait for load logos
cy.wait(2000);
cy.themeshot('plugin');
cy.themeshot('view-plugin-tab');
});
it('Edit mongo data JSON', () => {
@@ -306,7 +335,7 @@ describe('Data browser data', () => {
cy.contains('Helena').rightclick();
cy.contains('Delete document').click();
cy.contains('Save').click();
cy.themeshot('mongosave');
cy.themeshot('save-changes-mongodb');
});
it('Edit mongo data JSON', () => {
@@ -320,7 +349,7 @@ describe('Data browser data', () => {
cy.testid('ColumnManagerRow_checkbox__id').click();
cy.testid('DataFilterControl_input_countries.1').type('EXISTS{enter}');
cy.testid('WidgetIconPanel_cell-data').click();
cy.themeshot('collection');
cy.themeshot('mongodb-json-cell-view');
});
it('Table structure editor', () => {
@@ -329,10 +358,10 @@ describe('Data browser data', () => {
cy.contains('Customer').rightclick();
cy.contains('Open structure').click();
cy.contains('varchar(40)');
cy.themeshot('structure');
cy.themeshot('table-structure-editor');
cy.contains('EmployeeId').click();
cy.contains('Ref column - Employee');
cy.themeshot('fkeditor');
cy.themeshot('foreign-key-editor');
});
it('Compare database', () => {
@@ -344,10 +373,10 @@ describe('Data browser data', () => {
cy.testid('CompareModelTab_gridObjects_Customer_Customer').click();
cy.testid('WidgetIconPanel_database').click();
cy.testid('CompareModelTab_tabDdl').click();
cy.themeshot('dbcompare');
cy.themeshot('compare-database-models');
cy.contains('Settings').click();
cy.testid('CompareModelTab_tabOperations').click();
cy.themeshot('comparesettings');
cy.themeshot('compare-database-settings');
});
it('Query editor - AI assistant', () => {
@@ -359,10 +388,10 @@ describe('Data browser data', () => {
cy.testid('ConfirmModal_okButton').click();
cy.testid('QueryAiAssistant_promptInput').type('album names');
cy.testid('QueryAiAssistant_queryFromQuestionButton').click();
cy.contains('Use this').click();
cy.contains('Use this', { timeout: 10000 }).click();
cy.testid('QueryTab_executeButton').click();
cy.contains('Balls to the Wall');
cy.themeshot('aiassistant');
cy.themeshot('ai-assistant');
});
it('Modify data', () => {
@@ -388,7 +417,7 @@ describe('Data browser data', () => {
cy.contains('INSERT INTO `Employee`');
cy.contains("SET `FirstName`='Jane'");
cy.contains('DELETE FROM `Employee`');
cy.themeshot('modifydata');
cy.themeshot('data-browser-save-changes');
// cy.testid('ConfirmSqlModal_okButton').click();
// cy.contains('Cannot delete or update a parent row')
@@ -403,4 +432,51 @@ describe('Data browser data', () => {
cy.contains('Novak');
cy.contains('Rows: 8');
});
it('Export menu', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.contains('Album').click();
cy.testid('DataFilterControl_input_ArtistId').type('22{enter}');
// cy.contains('Presence').rightclick();
// cy.contains('Coda').rightclick();
// cy.testid('DropDownMenu-container-0').contains('Export').click();
cy.contains('Export').click();
// cy.wait(1000);
cy.themeshot('data-browser-export-menu');
});
it('MySQL native backup', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').rightclick();
cy.contains('Create database backup').click();
cy.contains('Customer');
cy.themeshot('mysql-backup-configuration');
});
it('View table YAML model', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').rightclick();
cy.contains('Export DB model').click();
cy.testid('ExportDbModelModal_archiveFolder').select('(Create new)');
cy.testid('InputTextModal_value').clear().type('test-model');
cy.testid('InputTextModal_ok').click();
cy.testid('ModalBase_window').themeshot('export-database-model-window', { padding: 50 });
cy.testid('ExportDbModelModal_exportButton').click();
cy.contains('Album').click();
cy.contains('autoIncrement');
cy.themeshot('database-model-table-yaml');
});
it('Data duplicator', () => {
cy.contains('MySql-connection').click();
cy.contains('MyChinook').click();
cy.testid('WidgetIconPanel_archive').click();
cy.contains('chinook-archive').rightclick();
cy.contains('Data duplicator').click();
cy.contains('Dry run').click();
cy.testid('DataDuplicatorTab_importIntoDb').click();
cy.contains('Duplicated Album, inserted 347 rows, mapped 0 rows, missing 0 rows, skipped 0 rows');
cy.themeshot('data-duplicator');
});
});
+202
View File
@@ -0,0 +1,202 @@
const localconfig = require('../../.localconfig');
const { formatQueryWithoutParams } = require('dbgate-tools');
global.DBGATE_PACKAGES = {
'dbgate-tools': require('dbgate-tools'),
};
function requireEngineDriver(engine) {
const [shortName, packageName] = engine.split('@');
const plugin = require(`../../../plugins/${packageName}/src/frontend/index`);
if (plugin.drivers) {
return plugin.drivers.find(x => x.engine == engine);
}
throw new Error(`Could not find engine driver ${engine}`);
}
Cypress.on('uncaught:exception', (err, runnable) => {
// if the error message matches the one about WorkerGlobalScope importScripts
if (err.message.includes("Failed to execute 'importScripts' on 'WorkerGlobalScope'")) {
// return false to let Cypress know we intentionally want to ignore this error
return false;
}
// otherwise let Cypress throw the error
});
beforeEach(() => {
cy.visit('http://localhost:3000');
cy.viewport(1250, 900);
});
function multiTest(testProps, testDefinition) {
if (localconfig.mysql) {
it('MySQL', () => testDefinition('MySql-connection', 'my_guitar_shop', 'mysql@dbgate-plugin-mysql'));
}
if (localconfig.postgres) {
it('Postgres', () => testDefinition('Postgres-connection', 'my_guitar_shop', 'postgres@dbgate-plugin-postgres'));
}
if (localconfig.mssql) {
it('Mssql', () => testDefinition('Mssql-connection', 'my_guitar_shop', 'mssql@dbgate-plugin-mssql'));
}
if (localconfig.oracle) {
it('Oracle', () =>
testDefinition('Oracle-connection', 'C##MY_GUITAR_SHOP', 'oracle@dbgate-plugin-oracle', {
implicitTransactions: true,
}));
}
if (localconfig.sqlite) {
it('Sqlite', () => testDefinition('Sqlite-connection', null, 'sqlite@dbgate-plugin-sqlite'));
}
if (localconfig.mongo && !testProps.skipMongo) {
it('MongoDB', () => testDefinition('Mongo-connection', 'my_guitar_shop', 'mongo@dbgate-plugin-mongo'));
}
}
describe('Transactions', () => {
multiTest({ skipMongo: true }, (connectionName, databaseName, engine, options = {}) => {
const driver = requireEngineDriver(engine);
const implicitTransactions = options.implicitTransactions ?? false;
cy.contains(connectionName).click();
if (databaseName) cy.contains(databaseName).click();
cy.testid('TabsPanel_buttonNewQuery').click();
cy.wait(1000);
cy.get('body').type(
formatQueryWithoutParams(driver, "INSERT INTO ~categories (~category_id, ~category_name) VALUES (5, 'test');")
);
// rollback
if (!implicitTransactions) {
cy.testid('QueryTab_beginTransactionButton').click();
cy.contains('Begin Transaction finished');
}
cy.testid('QueryTab_executeButton').click();
cy.contains('Query execution finished');
cy.testid('QueryTab_rollbackTransactionButton').click();
cy.contains('Rollback Transaction finished');
// should contain 4 rows
cy.testid('SqlObjectList_container').contains('categories').click();
cy.contains('Guitars').click();
cy.testid('TableDataTab_refreshGrid').click();
cy.contains('Rows: 4');
// commit
cy.contains('Query #1').click();
if (!implicitTransactions) {
cy.testid('QueryTab_beginTransactionButton').click();
cy.contains('Begin Transaction finished');
}
cy.testid('QueryTab_executeButton').click();
cy.contains('Query execution finished');
cy.testid('QueryTab_commitTransactionButton').click();
cy.contains('Commit Transaction finished');
// should contain 5 rows
cy.testid('SqlObjectList_container').contains('categories').click();
cy.contains('Guitars').click();
cy.testid('TableDataTab_refreshGrid').click();
cy.contains('Rows: 5');
});
});
describe('Backup table', () => {
multiTest({ skipMongo: true }, (connectionName, databaseName, engine, options = {}) => {
cy.contains(connectionName).click();
if (databaseName) cy.contains(databaseName).click();
cy.contains('customers').rightclick();
cy.contains('Create table backup').click();
cy.testid('ConfirmSqlModal_okButton').click();
cy.contains('_customers').click();
cy.contains('Rows: 8').should('be.visible');
});
});
describe('Truncate table', () => {
multiTest({ skipMongo: true }, (connectionName, databaseName, engine, options = {}) => {
cy.contains(connectionName).click();
if (databaseName) cy.contains(databaseName).click();
cy.contains('order_items').rightclick();
cy.contains('Truncate table').click();
cy.testid('ConfirmSqlModal_okButton').click();
cy.contains('order_items').click();
cy.contains('No rows loaded').should('be.visible');
});
});
describe('Drop table', () => {
multiTest({ skipMongo: true }, (connectionName, databaseName, engine, options = {}) => {
cy.contains(connectionName).click();
if (databaseName) cy.contains(databaseName).click();
cy.contains('order_items').rightclick();
cy.contains('Drop table').click();
cy.testid('ConfirmSqlModal_okButton').click();
cy.contains('order_items').should('not.exist');
});
});
describe('Import CSV', () => {
multiTest({}, (connectionName, databaseName, engine, options = {}) => {
cy.contains(connectionName).click();
if (databaseName) cy.contains(databaseName).click();
cy.testid('ConnectionList_container')
.contains(databaseName ?? connectionName)
.rightclick();
cy.contains('Import').click();
cy.get('input[type=file]').selectFile('cypress/fixtures/customers-20.csv', { force: true });
cy.contains('customers-20');
cy.testid('ImportExportTab_preview_content').contains('50ddd99fAdF48B3').should('be.visible');
cy.testid('ImportExportTab_executeButton').click();
cy.contains('20 rows written').should('be.visible');
cy.testid('SqlObjectList_refreshButton').click();
cy.testid('SqlObjectList_container').contains('customers-20').click();
cy.contains('Rows: 20').should('be.visible');
// cy.get('table tbody tr')
// .eq(1)
// .within(() => {
// cy.get('select').select('Append data');
// });
});
});
describe('Import CSV - source error', () => {
multiTest({}, (connectionName, databaseName, engine, options = {}) => {
cy.contains(connectionName).click();
if (databaseName) cy.contains(databaseName).click();
cy.testid('ConnectionList_container')
.contains(databaseName ?? connectionName)
.rightclick();
cy.contains('Import').click();
cy.get('input[type=file]').selectFile('cypress/fixtures/customers-20-err.csv', { force: true });
cy.contains('customers-20-err');
cy.testid('ImportExportTab_preview_content').contains('Invalid Closing Quote').should('be.visible');
cy.testid('ImportExportTab_executeButton').click();
cy.testid('ImportExportConfigurator_errorInfoIcon_customers-20-err').click();
cy.testid('ErrorMessageModal_message').contains('Invalid Closing Quote').should('be.visible');
});
});
describe('Import CSV - target error', () => {
multiTest({}, (connectionName, databaseName, engine, options = {}) => {
cy.contains(connectionName).click();
if (databaseName) cy.contains(databaseName).click();
cy.testid('ConnectionList_container')
.contains(databaseName ?? connectionName)
.rightclick();
cy.contains('Import').click();
cy.get('input[type=file]').selectFile('cypress/fixtures/customers-20.csv', { force: true });
cy.contains('customers-20');
cy.testid('ImportExportConfigurator_targetName_customers-20').clear().type('system."]`');
cy.testid('ImportExportTab_executeButton').click();
cy.testid('ImportExportConfigurator_errorInfoIcon_customers-20').click();
cy.testid('ErrorMessageModal_message').should('be.visible');
});
});
+30 -30
View File
@@ -45,36 +45,36 @@ describe('Run as portal', () => {
cy.get('[data-testid=InputTextModal_ok]').click();
});
it('Import Chinook MySQL', () => {
cy.visit('http://localhost:3000');
cy.contains('MySql-connection').click();
cy.get('[data-testid=DatabaseAppObject_Chinook]').rightclick();
cy.contains('Chinook').rightclick();
cy.contains('Restore/import SQL dump').click();
cy.get('#uploadFileButton').selectFile('data/chinook-mysql.sql', { force: true });
cy.wait(500);
cy.get('[data-testid=ImportDatabaseDumpModal_runImport]').click();
cy.contains('Importing database');
cy.contains('Finished job script');
cy.get('[data-testid=RunScriptModal_close]').click();
cy.contains('Chinook').click();
cy.contains('Album');
});
// it('Import Chinook MySQL', () => {
// cy.visit('http://localhost:3000');
// cy.contains('MySql-connection').click();
// cy.get('[data-testid=DatabaseAppObject_Chinook]').rightclick();
// cy.contains('Chinook').rightclick();
// cy.contains('Restore/import SQL dump').click();
// cy.get('#uploadFileButton').selectFile('data/chinook-mysql.sql', { force: true });
// cy.wait(500);
// cy.get('[data-testid=ImportDatabaseDumpModal_runImport]').click();
// cy.contains('Importing database');
// cy.contains('Finished job script');
// cy.get('[data-testid=RunScriptModal_close]').click();
// cy.contains('Chinook').click();
// cy.contains('Album');
// });
it('Import Chinook Postgres', () => {
cy.visit('http://localhost:3000');
cy.contains('Postgres-connection').click();
cy.get('[data-testid=DatabaseAppObject_Chinook]').rightclick();
cy.contains('Restore/import SQL dump').click();
cy.get('#uploadFileButton').selectFile('data/chinook-postgres.sql', { force: true });
cy.wait(500);
cy.get('[data-testid=ImportDatabaseDumpModal_runImport]').click();
cy.contains('Importing database');
cy.contains('Finished job script');
cy.get('[data-testid=RunScriptModal_close]').click();
cy.contains('Chinook').click();
cy.contains('album');
});
// it('Import Chinook Postgres', () => {
// cy.visit('http://localhost:3000');
// cy.contains('Postgres-connection').click();
// cy.get('[data-testid=DatabaseAppObject_Chinook]').rightclick();
// cy.contains('Restore/import SQL dump').click();
// cy.get('#uploadFileButton').selectFile('data/chinook-postgres.sql', { force: true });
// cy.wait(500);
// cy.get('[data-testid=ImportDatabaseDumpModal_runImport]').click();
// cy.contains('Importing database');
// cy.contains('Finished job script');
// cy.get('[data-testid=RunScriptModal_close]').click();
// cy.contains('Chinook').click();
// cy.contains('album');
// });
it('Open ask pwd connection', () => {
cy.visit('http://localhost:3000');
@@ -83,7 +83,7 @@ describe('Run as portal', () => {
cy.testid('DatabaseLoginModal_password').clear().type('Pwd2020Db');
cy.testid('DatabaseLoginModal_connect').click();
cy.contains('Chinook').click();
cy.contains('album');
// cy.contains('album');
});
// it('import chinook DB', () => {
+3 -3
View File
@@ -14,18 +14,18 @@ describe('Team edition tests', () => {
cy.contains('New connection').click();
cy.contains('New connection').click();
cy.testid('ConnectionDriverFields_connectionType').select('PostgreSQL');
cy.themeshot('connadmin');
cy.themeshot('connection-administration');
cy.testid('AdminMenuWidget_itemRoles').click();
cy.contains('Permissions').click();
cy.themeshot('roleadmin');
cy.themeshot('role-administration');
cy.testid('AdminMenuWidget_itemAuthentication').click();
cy.contains('Add authentication').click();
cy.contains('Use database login').click();
cy.contains('Add authentication').click();
cy.contains('OAuth 2.0').click();
cy.themeshot('authadmin');
cy.themeshot('authentication-administration');
});
it('OAuth authentication', () => {
@@ -0,0 +1,21 @@
Index,Customer Id,First Name,Last Name,Company,City,Country,Phone 1,Phone 2,Email,Subscription Date,Website
1,50ddd99fAdF48B3,Jessica,Navarro,"Tran, Odom and Graham",Port Terranceview,Jersey,(883)287-7947,479-044-3187,wmcintyre@myers.net,2023-03-11,http://pennington.com/
"2,BD1AB97979DDcDe,Preston,Andrews,"Townsend, Lawrence and Davenport",Harringtonmouth,Croatia,188-270-5676x63873,001-428-148-4270,bradley63@jacobs.net,2023-11-15,http://burke.com/
3,0FDDD9aCa501acE,Melissa,Mckay,Rivas-Cooke,Oliviabury,Cook Islands,8257631531,001-650-689-5600x927,ugalloway@maxwell-mcclain.com,2025-01-25,https://patrick.com/
4,A7dA284B7c4AfaD,Frank,Livingston,"Lambert, Garner and Mathews",Mallorytown,Faroe Islands,766.182.6201x689,+1-476-912-2027x4370,tracie00@webster.biz,2021-03-27,https://www.hart.com/
5,38bb1624e4f8211,Ross,Mendoza,Cook and Sons,New Perry,Bolivia,001-440-468-2236,165.562.4328x9274,austincarmen@abbott.com,2024-12-12,http://harmon.com/
6,55c9Fda2BABFE1a,Jane,Tate,Knapp PLC,West Kathyshire,Morocco,001-606-447-0584x07975,(003)872-1307x285,carlosgomez@mcpherson-ramos.biz,2021-09-13,http://www.yu.com/
7,A15eccAc67cCc5b,Tanya,Chung,Frost Inc,South Julieburgh,United States of America,778-360-8301x268,+1-034-169-4237,onewton@crosby.com,2024-10-01,http://www.gill-velez.biz/
8,aFdab04acACaf90,Jackson,Moyer,Bowen Ltd,Port Triciabury,Bahrain,001-187-882-2891x169,154.903.2525,gabriela16@mejia.org,2023-06-20,http://www.david.biz/
9,A2EaeAd3c6529B9,Kelly,Douglas,Phillips PLC,Weissberg,Qatar,767.177.3199x5576,5156730935,wigginsmercedes@tanner.com,2021-06-30,https://gonzalez.net/
10,188175A5641d080,Mariah,Riddle,"Mata, Fuller and Good",Choiton,Namibia,092-993-3559x342,190.937.3937,eileen32@greer.biz,2021-04-17,http://www.bowen.info/
11,B2BA817C7bC09f0,Kristine,Pennington,"Koch, Diaz and Valdez",Port Rachael,Suriname,877.152.6488x921,790-804-9979x3290,tonya00@flynn.com,2024-03-28,https://www.rocha.net/
12,fFAD70B5Febc43a,Robert,Adams,Bender-Wolfe,Billfort,Tanzania,219-696-1912x93626,518-969-4058,jeffersoncolton@moss-ashley.com,2022-07-31,https://www.alvarez.com/
13,9a44524E1261Ed6,Franklin,Costa,Werner Group,North Bradley,Cook Islands,(895)448-4681x1999,648-345-3083x88242,marksmith@novak.com,2024-12-03,http://thornton.com/
14,0C360EfE17D06cc,Dan,Ballard,Sampson-Huff,Michaelchester,Sao Tome and Principe,+1-803-469-5237x2580,(729)574-6101x0605,molly54@acevedo.info,2022-10-24,https://www.sloan-gonzales.biz/
15,fb5cE8cb1eF2954,Clifford,Moyer,Fry-Whitehead,Lake Gary,Japan,(504)263-0450,247.514.1614x551,rhonda34@orr.com,2020-03-08,https://norton.com/
16,3e53DcaD1cB0054,Tonya,Durham,"Lowe, West and Reynolds",South Sylviaton,Brunei Darussalam,(613)893-8183,(461)399-6120,kiara96@meadows.biz,2022-08-04,https://www.reeves.com/
17,83fDDE5812EbEde,Dale,Bishop,Shaw-Ray,Lake Miranda,Congo,(082)202-9241,+1-413-610-1854x79378,bhoward@hodges.biz,2023-05-08,http://www.escobar.com/
18,8dB7ACe2C5758cE,Priscilla,Mills,Pope PLC,North Cliffordshire,South Georgia and the South Sandwich Islands,+1-465-802-4573x30191,044-393-6049x598,nathaniel28@hess.com,2020-09-08,https://www.watts.org/
19,c1092ebDaF2ceED,Alice,Bond,Chan-Liu,West Wesley,Lithuania,+1-333-285-8515,(715)759-3158x77103,jose92@peters.com,2024-05-30,http://www.marquez.com/
20,4d0c95579D095aF,Cole,Compton,Calderon PLC,Robertaville,Saudi Arabia,029.862.3387x470,001-319-474-2394,sspence@dorsey.com,2020-08-02,http://hamilton.net/
Can't render this file because it contains an unexpected character in line 3 and column 36.
@@ -0,0 +1,21 @@
Index,Customer Id,First Name,Last Name,Company,City,Country,Phone 1,Phone 2,Email,Subscription Date,Website
1,50ddd99fAdF48B3,Jessica,Navarro,"Tran, Odom and Graham",Port Terranceview,Jersey,(883)287-7947,479-044-3187,wmcintyre@myers.net,2023-03-11,http://pennington.com/
2,BD1AB97979DDcDe,Preston,Andrews,"Townsend, Lawrence and Davenport",Harringtonmouth,Croatia,188-270-5676x63873,001-428-148-4270,bradley63@jacobs.net,2023-11-15,http://burke.com/
3,0FDDD9aCa501acE,Melissa,Mckay,Rivas-Cooke,Oliviabury,Cook Islands,8257631531,001-650-689-5600x927,ugalloway@maxwell-mcclain.com,2025-01-25,https://patrick.com/
4,A7dA284B7c4AfaD,Frank,Livingston,"Lambert, Garner and Mathews",Mallorytown,Faroe Islands,766.182.6201x689,+1-476-912-2027x4370,tracie00@webster.biz,2021-03-27,https://www.hart.com/
5,38bb1624e4f8211,Ross,Mendoza,Cook and Sons,New Perry,Bolivia,001-440-468-2236,165.562.4328x9274,austincarmen@abbott.com,2024-12-12,http://harmon.com/
6,55c9Fda2BABFE1a,Jane,Tate,Knapp PLC,West Kathyshire,Morocco,001-606-447-0584x07975,(003)872-1307x285,carlosgomez@mcpherson-ramos.biz,2021-09-13,http://www.yu.com/
7,A15eccAc67cCc5b,Tanya,Chung,Frost Inc,South Julieburgh,United States of America,778-360-8301x268,+1-034-169-4237,onewton@crosby.com,2024-10-01,http://www.gill-velez.biz/
8,aFdab04acACaf90,Jackson,Moyer,Bowen Ltd,Port Triciabury,Bahrain,001-187-882-2891x169,154.903.2525,gabriela16@mejia.org,2023-06-20,http://www.david.biz/
9,A2EaeAd3c6529B9,Kelly,Douglas,Phillips PLC,Weissberg,Qatar,767.177.3199x5576,5156730935,wigginsmercedes@tanner.com,2021-06-30,https://gonzalez.net/
10,188175A5641d080,Mariah,Riddle,"Mata, Fuller and Good",Choiton,Namibia,092-993-3559x342,190.937.3937,eileen32@greer.biz,2021-04-17,http://www.bowen.info/
11,B2BA817C7bC09f0,Kristine,Pennington,"Koch, Diaz and Valdez",Port Rachael,Suriname,877.152.6488x921,790-804-9979x3290,tonya00@flynn.com,2024-03-28,https://www.rocha.net/
12,fFAD70B5Febc43a,Robert,Adams,Bender-Wolfe,Billfort,Tanzania,219-696-1912x93626,518-969-4058,jeffersoncolton@moss-ashley.com,2022-07-31,https://www.alvarez.com/
13,9a44524E1261Ed6,Franklin,Costa,Werner Group,North Bradley,Cook Islands,(895)448-4681x1999,648-345-3083x88242,marksmith@novak.com,2024-12-03,http://thornton.com/
14,0C360EfE17D06cc,Dan,Ballard,Sampson-Huff,Michaelchester,Sao Tome and Principe,+1-803-469-5237x2580,(729)574-6101x0605,molly54@acevedo.info,2022-10-24,https://www.sloan-gonzales.biz/
15,fb5cE8cb1eF2954,Clifford,Moyer,Fry-Whitehead,Lake Gary,Japan,(504)263-0450,247.514.1614x551,rhonda34@orr.com,2020-03-08,https://norton.com/
16,3e53DcaD1cB0054,Tonya,Durham,"Lowe, West and Reynolds",South Sylviaton,Brunei Darussalam,(613)893-8183,(461)399-6120,kiara96@meadows.biz,2022-08-04,https://www.reeves.com/
17,83fDDE5812EbEde,Dale,Bishop,Shaw-Ray,Lake Miranda,Congo,(082)202-9241,+1-413-610-1854x79378,bhoward@hodges.biz,2023-05-08,http://www.escobar.com/
18,8dB7ACe2C5758cE,Priscilla,Mills,Pope PLC,North Cliffordshire,South Georgia and the South Sandwich Islands,+1-465-802-4573x30191,044-393-6049x598,nathaniel28@hess.com,2020-09-08,https://www.watts.org/
19,c1092ebDaF2ceED,Alice,Bond,Chan-Liu,West Wesley,Lithuania,+1-333-285-8515,(715)759-3158x77103,jose92@peters.com,2024-05-30,http://www.marquez.com/
20,4d0c95579D095aF,Cole,Compton,Calderon PLC,Robertaville,Saudi Arabia,029.862.3387x470,001-319-474-2394,sspence@dorsey.com,2020-08-02,http://hamilton.net/
1 Index Customer Id First Name Last Name Company City Country Phone 1 Phone 2 Email Subscription Date Website
2 1 50ddd99fAdF48B3 Jessica Navarro Tran, Odom and Graham Port Terranceview Jersey (883)287-7947 479-044-3187 wmcintyre@myers.net 2023-03-11 http://pennington.com/
3 2 BD1AB97979DDcDe Preston Andrews Townsend, Lawrence and Davenport Harringtonmouth Croatia 188-270-5676x63873 001-428-148-4270 bradley63@jacobs.net 2023-11-15 http://burke.com/
4 3 0FDDD9aCa501acE Melissa Mckay Rivas-Cooke Oliviabury Cook Islands 8257631531 001-650-689-5600x927 ugalloway@maxwell-mcclain.com 2025-01-25 https://patrick.com/
5 4 A7dA284B7c4AfaD Frank Livingston Lambert, Garner and Mathews Mallorytown Faroe Islands 766.182.6201x689 +1-476-912-2027x4370 tracie00@webster.biz 2021-03-27 https://www.hart.com/
6 5 38bb1624e4f8211 Ross Mendoza Cook and Sons New Perry Bolivia 001-440-468-2236 165.562.4328x9274 austincarmen@abbott.com 2024-12-12 http://harmon.com/
7 6 55c9Fda2BABFE1a Jane Tate Knapp PLC West Kathyshire Morocco 001-606-447-0584x07975 (003)872-1307x285 carlosgomez@mcpherson-ramos.biz 2021-09-13 http://www.yu.com/
8 7 A15eccAc67cCc5b Tanya Chung Frost Inc South Julieburgh United States of America 778-360-8301x268 +1-034-169-4237 onewton@crosby.com 2024-10-01 http://www.gill-velez.biz/
9 8 aFdab04acACaf90 Jackson Moyer Bowen Ltd Port Triciabury Bahrain 001-187-882-2891x169 154.903.2525 gabriela16@mejia.org 2023-06-20 http://www.david.biz/
10 9 A2EaeAd3c6529B9 Kelly Douglas Phillips PLC Weissberg Qatar 767.177.3199x5576 5156730935 wigginsmercedes@tanner.com 2021-06-30 https://gonzalez.net/
11 10 188175A5641d080 Mariah Riddle Mata, Fuller and Good Choiton Namibia 092-993-3559x342 190.937.3937 eileen32@greer.biz 2021-04-17 http://www.bowen.info/
12 11 B2BA817C7bC09f0 Kristine Pennington Koch, Diaz and Valdez Port Rachael Suriname 877.152.6488x921 790-804-9979x3290 tonya00@flynn.com 2024-03-28 https://www.rocha.net/
13 12 fFAD70B5Febc43a Robert Adams Bender-Wolfe Billfort Tanzania 219-696-1912x93626 518-969-4058 jeffersoncolton@moss-ashley.com 2022-07-31 https://www.alvarez.com/
14 13 9a44524E1261Ed6 Franklin Costa Werner Group North Bradley Cook Islands (895)448-4681x1999 648-345-3083x88242 marksmith@novak.com 2024-12-03 http://thornton.com/
15 14 0C360EfE17D06cc Dan Ballard Sampson-Huff Michaelchester Sao Tome and Principe +1-803-469-5237x2580 (729)574-6101x0605 molly54@acevedo.info 2022-10-24 https://www.sloan-gonzales.biz/
16 15 fb5cE8cb1eF2954 Clifford Moyer Fry-Whitehead Lake Gary Japan (504)263-0450 247.514.1614x551 rhonda34@orr.com 2020-03-08 https://norton.com/
17 16 3e53DcaD1cB0054 Tonya Durham Lowe, West and Reynolds South Sylviaton Brunei Darussalam (613)893-8183 (461)399-6120 kiara96@meadows.biz 2022-08-04 https://www.reeves.com/
18 17 83fDDE5812EbEde Dale Bishop Shaw-Ray Lake Miranda Congo (082)202-9241 +1-413-610-1854x79378 bhoward@hodges.biz 2023-05-08 http://www.escobar.com/
19 18 8dB7ACe2C5758cE Priscilla Mills Pope PLC North Cliffordshire South Georgia and the South Sandwich Islands +1-465-802-4573x30191 044-393-6049x598 nathaniel28@hess.com 2020-09-08 https://www.watts.org/
20 19 c1092ebDaF2ceED Alice Bond Chan-Liu West Wesley Lithuania +1-333-285-8515 (715)759-3158x77103 jose92@peters.com 2024-05-30 http://www.marquez.com/
21 20 4d0c95579D095aF Cole Compton Calderon PLC Robertaville Saudi Arabia 029.862.3387x470 001-319-474-2394 sspence@dorsey.com 2020-08-02 http://hamilton.net/
@@ -0,0 +1,13 @@
{"__isStreamHeader":true,"pureName":"addresses","tableRowCount":"12","tableEngine":"InnoDB","objectComment":"","modifyDate":"2025-02-03 02:56:32","objectId":"addresses","contentHash":"2025-02-03 02:56:32","columns":[{"notNull":true,"autoIncrement":true,"columnName":"address_id","columnComment":"","dataType":"int","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"customer_id","columnComment":"","dataType":"int","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"line1","columnComment":"","dataType":"varchar(60)","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":false,"autoIncrement":false,"columnName":"line2","columnComment":"","dataType":"varchar(60)","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"city","columnComment":"","dataType":"varchar(40)","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"state","columnComment":"","dataType":"varchar(2)","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"zip_code","columnComment":"","dataType":"varchar(10)","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"phone","columnComment":"","dataType":"varchar(12)","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"disabled","columnComment":"","dataType":"tinyint","defaultValue":"0","isUnsigned":false,"isZerofill":false}],"primaryKey":{"constraintName":"PRIMARY","pureName":"addresses","constraintType":"primaryKey","columns":[{"columnName":"address_id"}]},"foreignKeys":[{"constraintName":"addresses_fk_customers","constraintType":"foreignKey","pureName":"addresses","refTableName":"customers","updateAction":"NO ACTION","deleteAction":"NO ACTION","columns":[{"columnName":"customer_id","refColumnName":"customer_id"}]}],"indexes":[{"constraintName":"addresses_fk_customers","indexType":"BTREE","isUnique":false,"columns":[{"columnName":"customer_id","isDescending":0}]}],"uniques":[],"engine":"mysql@dbgate-plugin-mysql"}
{"address_id":1,"customer_id":1,"line1":"100 East Ridgewood Ave.","line2":"","city":"Paramus","state":"NJ","zip_code":"07652","phone":"201-653-4472","disabled":0}
{"address_id":2,"customer_id":1,"line1":"21 Rosewood Rd.","line2":"","city":"Woodcliff Lake","state":"NJ","zip_code":"07677","phone":"201-653-4472","disabled":0}
{"address_id":3,"customer_id":2,"line1":"16285 Wendell St.","line2":"","city":"Omaha","state":"NE","zip_code":"68135","phone":"402-896-2576","disabled":0}
{"address_id":4,"customer_id":3,"line1":"19270 NW Cornell Rd.","line2":"","city":"Beaverton","state":"OR","zip_code":"97006","phone":"503-654-1291","disabled":0}
{"address_id":5,"customer_id":4,"line1":"186 Vermont St.","line2":"Apt. 2","city":"San Francisco","state":"CA","zip_code":"94110","phone":"415-292-6651","disabled":0}
{"address_id":6,"customer_id":4,"line1":"1374 46th Ave.","line2":"","city":"San Francisco","state":"CA","zip_code":"94129","phone":"415-292-6651","disabled":0}
{"address_id":7,"customer_id":5,"line1":"6982 Palm Ave.","line2":"","city":"Fresno","state":"CA","zip_code":"93711","phone":"559-431-2398","disabled":0}
{"address_id":8,"customer_id":6,"line1":"23 Mountain View St.","line2":"","city":"Denver","state":"CO","zip_code":"80208","phone":"303-912-3852","disabled":0}
{"address_id":9,"customer_id":7,"line1":"7361 N. 41st St.","line2":"Apt. B","city":"New York","state":"NY","zip_code":"10012","phone":"212-335-2093","disabled":0}
{"address_id":10,"customer_id":7,"line1":"3829 Broadway Ave.","line2":"Suite 2","city":"New York","state":"NY","zip_code":"10012","phone":"212-239-1208","disabled":0}
{"address_id":11,"customer_id":8,"line1":"2381 Buena Vista St.","line2":"","city":"Los Angeles","state":"CA","zip_code":"90023","phone":"213-772-5033","disabled":0}
{"address_id":12,"customer_id":8,"line1":"291 W. Hollywood Blvd.","line2":"","city":"Los Angeles","state":"CA","zip_code":"90024","phone":"213-391-2938","disabled":0}
@@ -0,0 +1,46 @@
name: addresses
columns:
- name: address_id
type: int
default: null
autoIncrement: true
notNull: true
- name: customer_id
type: int
default: null
notNull: true
references: customers
- name: line1
type: varchar(60)
default: null
notNull: true
- name: line2
type: varchar(60)
default: null
- name: city
type: varchar(40)
default: null
notNull: true
- name: state
type: varchar(2)
default: null
notNull: true
- name: zip_code
type: varchar(10)
default: null
notNull: true
- name: phone
type: varchar(12)
default: null
notNull: true
- name: disabled
type: int
default: 0
notNull: true
primaryKey:
- address_id
indexes:
- name: addresses_fk_customers
unique: false
columns:
- customer_id
@@ -0,0 +1,4 @@
{"__isStreamHeader":true,"pureName":"administrators","tableRowCount":"3","tableEngine":"InnoDB","objectComment":"","modifyDate":"2025-02-03 02:56:33","objectId":"administrators","contentHash":"2025-02-03 02:56:33","columns":[{"notNull":true,"autoIncrement":true,"columnName":"admin_id","columnComment":"","dataType":"int","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"email_address","columnComment":"","dataType":"varchar(255)","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"password","columnComment":"","dataType":"varchar(255)","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"first_name","columnComment":"","dataType":"varchar(255)","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"last_name","columnComment":"","dataType":"varchar(255)","defaultValue":null,"isUnsigned":false,"isZerofill":false}],"primaryKey":{"constraintName":"PRIMARY","pureName":"administrators","constraintType":"primaryKey","columns":[{"columnName":"admin_id"}]},"foreignKeys":[],"indexes":[],"uniques":[],"engine":"mysql@dbgate-plugin-mysql"}
{"admin_id":1,"email_address":"admin@myguitarshop.com","password":"6a718fbd768c2378b511f8249b54897f940e9022","first_name":"Admin","last_name":"User"}
{"admin_id":2,"email_address":"joel@murach.com","password":"971e95957d3b74d70d79c20c94e9cd91b85f7aae","first_name":"Joel","last_name":"Murach"}
{"admin_id":3,"email_address":"mike@murach.com","password":"3f2975c819cefc686282456aeae3a137bf896ee8","first_name":"Mike","last_name":"Murach"}
@@ -0,0 +1,25 @@
name: administrators
columns:
- name: admin_id
type: int
default: null
autoIncrement: true
notNull: true
- name: email_address
type: varchar(255)
default: null
notNull: true
- name: password
type: varchar(255)
default: null
notNull: true
- name: first_name
type: varchar(255)
default: null
notNull: true
- name: last_name
type: varchar(255)
default: null
notNull: true
primaryKey:
- admin_id
@@ -0,0 +1,5 @@
{"__isStreamHeader":true,"pureName":"categories","tableRowCount":"4","tableEngine":"InnoDB","objectComment":"","modifyDate":"2025-02-03 02:56:32","objectId":"categories","contentHash":"2025-02-03 02:56:32","columns":[{"notNull":true,"autoIncrement":true,"columnName":"category_id","columnComment":"","dataType":"int","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"category_name","columnComment":"","dataType":"varchar(255)","defaultValue":null,"isUnsigned":false,"isZerofill":false}],"primaryKey":{"constraintName":"PRIMARY","pureName":"categories","constraintType":"primaryKey","columns":[{"columnName":"category_id"}]},"foreignKeys":[],"indexes":[],"uniques":[{"constraintName":"category_name","columns":[{"columnName":"category_name"}]}],"engine":"mysql@dbgate-plugin-mysql"}
{"category_id":2,"category_name":"Basses"}
{"category_id":3,"category_name":"Drums"}
{"category_id":1,"category_name":"Guitars"}
{"category_id":4,"category_name":"Keyboards"}
@@ -0,0 +1,12 @@
name: categories
columns:
- name: category_id
type: int
default: null
notNull: true
- name: category_name
type: varchar(255)
default: null
notNull: true
primaryKey:
- category_id
@@ -0,0 +1,9 @@
{"__isStreamHeader":true,"pureName":"customers","tableRowCount":"8","tableEngine":"InnoDB","objectComment":"","modifyDate":"2025-02-03 02:56:32","objectId":"customers","contentHash":"2025-02-03 02:56:32","columns":[{"notNull":true,"autoIncrement":true,"columnName":"customer_id","columnComment":"","dataType":"int","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"email_address","columnComment":"","dataType":"varchar(255)","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"password","columnComment":"","dataType":"varchar(60)","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"first_name","columnComment":"","dataType":"varchar(60)","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"last_name","columnComment":"","dataType":"varchar(60)","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":false,"autoIncrement":false,"columnName":"shipping_address_id","columnComment":"","dataType":"int","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":false,"autoIncrement":false,"columnName":"billing_address_id","columnComment":"","dataType":"int","defaultValue":null,"isUnsigned":false,"isZerofill":false}],"primaryKey":{"constraintName":"PRIMARY","pureName":"customers","constraintType":"primaryKey","columns":[{"columnName":"customer_id"}]},"foreignKeys":[],"indexes":[],"uniques":[{"constraintName":"email_address","columns":[{"columnName":"email_address"}]}],"engine":"mysql@dbgate-plugin-mysql"}
{"customer_id":1,"email_address":"allan.sherwood@yahoo.com","password":"650215acec746f0e32bdfff387439eefc1358737","first_name":"Allan","last_name":"Sherwood","shipping_address_id":1,"billing_address_id":2}
{"customer_id":2,"email_address":"barryz@gmail.com","password":"3f563468d42a448cb1e56924529f6e7bbe529cc7","first_name":"Barry","last_name":"Zimmer","shipping_address_id":3,"billing_address_id":3}
{"customer_id":3,"email_address":"christineb@solarone.com","password":"ed19f5c0833094026a2f1e9e6f08a35d26037066","first_name":"Christine","last_name":"Brown","shipping_address_id":4,"billing_address_id":4}
{"customer_id":4,"email_address":"david.goldstein@hotmail.com","password":"b444ac06613fc8d63795be9ad0beaf55011936ac","first_name":"David","last_name":"Goldstein","shipping_address_id":5,"billing_address_id":6}
{"customer_id":5,"email_address":"erinv@gmail.com","password":"109f4b3c50d7b0df729d299bc6f8e9ef9066971f","first_name":"Erin","last_name":"Valentino","shipping_address_id":7,"billing_address_id":7}
{"customer_id":6,"email_address":"frankwilson@sbcglobal.net","password":"3ebfa301dc59196f18593c45e519287a23297589","first_name":"Frank Lee","last_name":"Wilson","shipping_address_id":8,"billing_address_id":8}
{"customer_id":7,"email_address":"gary_hernandez@yahoo.com","password":"1ff2b3704aede04eecb51e50ca698efd50a1379b","first_name":"Gary","last_name":"Hernandez","shipping_address_id":9,"billing_address_id":10}
{"customer_id":8,"email_address":"heatheresway@mac.com","password":"911ddc3b8f9a13b5499b6bc4638a2b4f3f68bf23","first_name":"Heather","last_name":"Esway","shipping_address_id":11,"billing_address_id":12}
@@ -0,0 +1,31 @@
name: customers
columns:
- name: customer_id
type: int
default: null
autoIncrement: true
notNull: true
- name: email_address
type: varchar(255)
default: null
notNull: true
- name: password
type: varchar(60)
default: null
notNull: true
- name: first_name
type: varchar(60)
default: null
notNull: true
- name: last_name
type: varchar(60)
default: null
notNull: true
- name: shipping_address_id
type: int
default: null
- name: billing_address_id
type: int
default: null
primaryKey:
- customer_id
@@ -0,0 +1,13 @@
{"__isStreamHeader":true,"pureName":"order_items","tableRowCount":"12","tableEngine":"InnoDB","objectComment":"","modifyDate":"2025-02-03 02:56:33","objectId":"order_items","contentHash":"2025-02-03 02:56:33","columns":[{"notNull":true,"autoIncrement":true,"columnName":"item_id","columnComment":"","dataType":"int","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"order_id","columnComment":"","dataType":"int","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"product_id","columnComment":"","dataType":"int","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"item_price","columnComment":"","dataType":"decimal(10,2)","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"discount_amount","columnComment":"","dataType":"decimal(10,2)","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"quantity","columnComment":"","dataType":"int","defaultValue":null,"isUnsigned":false,"isZerofill":false}],"primaryKey":{"constraintName":"PRIMARY","pureName":"order_items","constraintType":"primaryKey","columns":[{"columnName":"item_id"}]},"foreignKeys":[{"constraintName":"items_fk_products","constraintType":"foreignKey","pureName":"order_items","refTableName":"products","updateAction":"NO ACTION","deleteAction":"NO ACTION","columns":[{"columnName":"product_id","refColumnName":"product_id"}]},{"constraintName":"items_fk_orders","constraintType":"foreignKey","pureName":"order_items","refTableName":"orders","updateAction":"NO ACTION","deleteAction":"NO ACTION","columns":[{"columnName":"order_id","refColumnName":"order_id"}]}],"indexes":[{"constraintName":"items_fk_orders","indexType":"BTREE","isUnique":false,"columns":[{"columnName":"order_id","isDescending":0}]},{"constraintName":"items_fk_products","indexType":"BTREE","isUnique":false,"columns":[{"columnName":"product_id","isDescending":0}]}],"uniques":[],"engine":"mysql@dbgate-plugin-mysql"}
{"item_id":1,"order_id":1,"product_id":2,"item_price":"1199.00","discount_amount":"359.70","quantity":1}
{"item_id":2,"order_id":2,"product_id":4,"item_price":"489.99","discount_amount":"186.20","quantity":1}
{"item_id":3,"order_id":3,"product_id":3,"item_price":"2517.00","discount_amount":"1308.84","quantity":1}
{"item_id":4,"order_id":3,"product_id":6,"item_price":"415.00","discount_amount":"161.85","quantity":1}
{"item_id":5,"order_id":4,"product_id":2,"item_price":"1199.00","discount_amount":"359.70","quantity":2}
{"item_id":6,"order_id":5,"product_id":5,"item_price":"299.00","discount_amount":"0.00","quantity":1}
{"item_id":7,"order_id":6,"product_id":5,"item_price":"299.00","discount_amount":"0.00","quantity":1}
{"item_id":8,"order_id":7,"product_id":1,"item_price":"699.00","discount_amount":"209.70","quantity":1}
{"item_id":9,"order_id":7,"product_id":7,"item_price":"799.99","discount_amount":"240.00","quantity":1}
{"item_id":10,"order_id":7,"product_id":9,"item_price":"699.99","discount_amount":"210.00","quantity":1}
{"item_id":11,"order_id":8,"product_id":10,"item_price":"799.99","discount_amount":"120.00","quantity":1}
{"item_id":12,"order_id":9,"product_id":1,"item_price":"699.00","discount_amount":"209.70","quantity":1}
@@ -0,0 +1,40 @@
name: order_items
columns:
- name: item_id
type: int
default: null
autoIncrement: true
notNull: true
- name: order_id
type: int
default: null
notNull: true
references: orders
- name: product_id
type: int
default: null
notNull: true
references: products
- name: item_price
type: decimal(10,2)
default: null
notNull: true
- name: discount_amount
type: decimal(10,2)
default: null
notNull: true
- name: quantity
type: int
default: null
notNull: true
primaryKey:
- item_id
indexes:
- name: items_fk_orders
unique: false
columns:
- order_id
- name: items_fk_products
unique: false
columns:
- product_id
@@ -0,0 +1,10 @@
{"__isStreamHeader":true,"pureName":"orders","tableRowCount":"9","tableEngine":"InnoDB","objectComment":"","modifyDate":"2025-02-03T02:56:32","objectId":"orders","contentHash":"2025-02-03 02:56:32","columns":[{"notNull":true,"autoIncrement":true,"columnName":"order_id","columnComment":"","dataType":"int","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"customer_id","columnComment":"","dataType":"int","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"order_date","columnComment":"","dataType":"datetime","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"ship_amount","columnComment":"","dataType":"decimal(10,2)","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"tax_amount","columnComment":"","dataType":"decimal(10,2)","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":false,"autoIncrement":false,"columnName":"ship_date","columnComment":"","dataType":"datetime","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"ship_address_id","columnComment":"","dataType":"int","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"card_type","columnComment":"","dataType":"varchar(50)","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"card_number","columnComment":"","dataType":"char(16)","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"card_expires","columnComment":"","dataType":"char(7)","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"billing_address_id","columnComment":"","dataType":"int","defaultValue":null,"isUnsigned":false,"isZerofill":false}],"primaryKey":{"constraintName":"PRIMARY","pureName":"orders","constraintType":"primaryKey","columns":[{"columnName":"order_id"}]},"foreignKeys":[{"constraintName":"orders_fk_customers","constraintType":"foreignKey","pureName":"orders","refTableName":"customers","updateAction":"NO ACTION","deleteAction":"NO ACTION","columns":[{"columnName":"customer_id","refColumnName":"customer_id"}]}],"indexes":[{"constraintName":"orders_fk_customers","indexType":"BTREE","isUnique":false,"columns":[{"columnName":"customer_id","isDescending":0}]}],"uniques":[],"engine":"mysql@dbgate-plugin-mysql"}
{"order_id":1,"customer_id":1,"order_date":"2018-03-28T09:40:28","ship_amount":"5.00","tax_amount":"32.32","ship_date":"2018-03-30T15:32:51","ship_address_id":1,"card_type":"Visa","card_number":"4111111111111111","card_expires":"04/2020","billing_address_id":2}
{"order_id":2,"customer_id":2,"order_date":"2018-03-28T11:23:20","ship_amount":"5.00","tax_amount":"0.00","ship_date":"2018-03-29T12:52:14","ship_address_id":3,"card_type":"Visa","card_number":"4012888888881881","card_expires":"08/2019","billing_address_id":3}
{"order_id":3,"customer_id":1,"order_date":"2018-03-29T09:44:58","ship_amount":"10.00","tax_amount":"89.92","ship_date":"2018-03-31T09:11:41","ship_address_id":1,"card_type":"Visa","card_number":"4111111111111111","card_expires":"04/2017","billing_address_id":2}
{"order_id":4,"customer_id":3,"order_date":"2018-03-30T15:22:31","ship_amount":"5.00","tax_amount":"0.00","ship_date":"2018-04-03T16:32:21","ship_address_id":4,"card_type":"American Express","card_number":"378282246310005","card_expires":"04/2016","billing_address_id":4}
{"order_id":5,"customer_id":4,"order_date":"2018-03-31T05:43:11","ship_amount":"5.00","tax_amount":"0.00","ship_date":"2018-04-02T14:21:12","ship_address_id":5,"card_type":"Visa","card_number":"4111111111111111","card_expires":"04/2019","billing_address_id":6}
{"order_id":6,"customer_id":5,"order_date":"2018-03-31T18:37:22","ship_amount":"5.00","tax_amount":"0.00","ship_date":null,"ship_address_id":7,"card_type":"Discover","card_number":"6011111111111117","card_expires":"04/2019","billing_address_id":7}
{"order_id":7,"customer_id":6,"order_date":"2018-04-01T23:11:12","ship_amount":"15.00","tax_amount":"0.00","ship_date":"2018-04-03T10:21:35","ship_address_id":8,"card_type":"MasterCard","card_number":"5555555555554444","card_expires":"04/2019","billing_address_id":8}
{"order_id":8,"customer_id":7,"order_date":"2018-04-02T11:26:38","ship_amount":"5.00","tax_amount":"0.00","ship_date":null,"ship_address_id":9,"card_type":"Visa","card_number":"4012888888881881","card_expires":"04/2019","billing_address_id":10}
{"order_id":9,"customer_id":4,"order_date":"2018-04-03T12:22:31","ship_amount":"5.00","tax_amount":"0.00","ship_date":null,"ship_address_id":5,"card_type":"Visa","card_number":"4111111111111111","card_expires":"04/2019","billing_address_id":6}
@@ -0,0 +1,54 @@
name: orders
columns:
- name: order_id
type: int
default: null
autoIncrement: true
notNull: true
- name: customer_id
type: int
default: null
notNull: true
references: customers
- name: order_date
type: datetime
default: null
notNull: true
- name: ship_amount
type: decimal(10,2)
default: null
notNull: true
- name: tax_amount
type: decimal(10,2)
default: null
notNull: true
- name: ship_date
type: datetime
default: null
- name: ship_address_id
type: int
default: null
notNull: true
- name: card_type
type: varchar(50)
default: null
notNull: true
- name: card_number
type: char(16)
default: null
notNull: true
- name: card_expires
type: char(7)
default: null
notNull: true
- name: billing_address_id
type: int
default: null
notNull: true
primaryKey:
- order_id
indexes:
- name: orders_fk_customers
unique: false
columns:
- customer_id
@@ -0,0 +1,11 @@
{"__isStreamHeader":true,"pureName":"products","tableRowCount":"10","tableEngine":"InnoDB","objectComment":"","modifyDate":"2025-02-03 02:56:32","objectId":"products","contentHash":"2025-02-03 02:56:32","columns":[{"notNull":true,"autoIncrement":true,"columnName":"product_id","columnComment":"","dataType":"int","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"category_id","columnComment":"","dataType":"int","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"product_code","columnComment":"","dataType":"varchar(10)","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"product_name","columnComment":"","dataType":"varchar(255)","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"description","columnComment":"","dataType":"text","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"list_price","columnComment":"","dataType":"decimal(10,2)","defaultValue":null,"isUnsigned":false,"isZerofill":false},{"notNull":true,"autoIncrement":false,"columnName":"discount_percent","columnComment":"","dataType":"decimal(10,2)","defaultValue":"0.00","isUnsigned":false,"isZerofill":false},{"notNull":false,"autoIncrement":false,"columnName":"date_added","columnComment":"","dataType":"datetime","defaultValue":null,"isUnsigned":false,"isZerofill":false}],"primaryKey":{"constraintName":"PRIMARY","pureName":"products","constraintType":"primaryKey","columns":[{"columnName":"product_id"}]},"foreignKeys":[{"constraintName":"products_fk_categories","constraintType":"foreignKey","pureName":"products","refTableName":"categories","updateAction":"NO ACTION","deleteAction":"NO ACTION","columns":[{"columnName":"category_id","refColumnName":"category_id"}]}],"indexes":[{"constraintName":"products_fk_categories","indexType":"BTREE","isUnique":false,"columns":[{"columnName":"category_id","isDescending":0}]}],"uniques":[{"constraintName":"product_code","columns":[{"columnName":"product_code"}]}],"engine":"mysql@dbgate-plugin-mysql"}
{"product_id":1,"category_id":1,"product_code":"strat","product_name":"Fender Stratocaster","description":"The Fender Stratocaster is the electric guitar design that changed the world. New features include a tinted neck, parchment pickguard and control knobs, and a '70s-style logo. Includes select alder body, 21-fret maple neck with your choice of a rosewood or maple fretboard, 3 single-coil pickups, vintage-style tremolo, and die-cast tuning keys. This guitar features a thicker bridge block for increased sustain and a more stable point of contact with the strings. At this low price, why play anything but the real thing?\r\n\r\nFeatures:\r\n\r\n* New features:\r\n* Thicker bridge block\r\n* 3-ply parchment pick guard\r\n* Tinted neck","list_price":"699.00","discount_percent":"30.00","date_added":"2017-10-30T09:32:40"}
{"product_id":2,"category_id":1,"product_code":"les_paul","product_name":"Gibson Les Paul","description":"This Les Paul guitar offers a carved top and humbucking pickups. It has a simple yet elegant design. Cutting-yet-rich tone?the hallmark of the Les Paul?pours out of the 490R and 498T Alnico II magnet humbucker pickups, which are mounted on a carved maple top with a mahogany back. The faded finish models are equipped with BurstBucker Pro pickups and a mahogany top. This guitar includes a Gibson hardshell case (Faded and satin finish models come with a gig bag) and a limited lifetime warranty.\r\n\r\nFeatures:\r\n\r\n* Carved maple top and mahogany back (Mahogany top on faded finish models)\r\n* Mahogany neck, '59 Rounded Les Paul\r\n* Rosewood fingerboard (Ebony on Alpine white)\r\n* Tune-O-Matic bridge with stopbar\r\n* Chrome or gold hardware\r\n* 490R and 498T Alnico 2 magnet humbucker pickups (BurstBucker Pro on faded finish models)\r\n* 2 volume and 2 tone knobs, 3-way switch","list_price":"1199.00","discount_percent":"30.00","date_added":"2017-12-05T16:33:13"}
{"product_id":3,"category_id":1,"product_code":"sg","product_name":"Gibson SG","description":"This Gibson SG electric guitar takes the best of the '62 original and adds the longer and sturdier neck joint of the late '60s models. All the classic features you'd expect from a historic guitar. Hot humbuckers go from rich, sweet lightning to warm, tingling waves of sustain. A silky-fast rosewood fretboard plays like a dream. The original-style beveled mahogany body looks like a million bucks. Plus, Tune-O-Matic bridge and chrome hardware. Limited lifetime warranty. Includes hardshell case.\r\n\r\nFeatures:\r\n\r\n* Double-cutaway beveled mahogany body\r\n* Set mahogany neck with rounded '50s profile\r\n* Bound rosewood fingerboard with trapezoid inlays\r\n* Tune-O-Matic bridge with stopbar tailpiece\r\n* Chrome hardware\r\n* 490R humbucker in the neck position\r\n* 498T humbucker in the bridge position\r\n* 2 volume knobs, 2 tone knobs, 3-way switch\r\n* 24-3/4\" scale","list_price":"2517.00","discount_percent":"52.00","date_added":"2018-02-04T11:04:31"}
{"product_id":4,"category_id":1,"product_code":"fg700s","product_name":"Yamaha FG700S","description":"The Yamaha FG700S solid top acoustic guitar has the ultimate combo for projection and pure tone. The expertly braced spruce top speaks clearly atop the rosewood body. It has a rosewood fingerboard, rosewood bridge, die-cast tuners, body and neck binding, and a tortoise pickguard.\r\n\r\nFeatures:\r\n\r\n* Solid Sitka spruce top\r\n* Rosewood back and sides\r\n* Rosewood fingerboard\r\n* Rosewood bridge\r\n* White/black body and neck binding\r\n* Die-cast tuners\r\n* Tortoise pickguard\r\n* Limited lifetime warranty","list_price":"489.99","discount_percent":"38.00","date_added":"2018-06-01T11:12:59"}
{"product_id":5,"category_id":1,"product_code":"washburn","product_name":"Washburn D10S","description":"The Washburn D10S acoustic guitar is superbly crafted with a solid spruce top and mahogany back and sides for exceptional tone. A mahogany neck and rosewood fingerboard make fretwork a breeze, while chrome Grover-style machines keep you perfectly tuned. The Washburn D10S comes with a limited lifetime warranty.\r\n\r\nFeatures:\r\n\r\n * Spruce top\r\n * Mahogany back, sides\r\n * Mahogany neck Rosewood fingerboard\r\n * Chrome Grover-style machines","list_price":"299.00","discount_percent":"0.00","date_added":"2018-07-30T13:58:35"}
{"product_id":6,"category_id":1,"product_code":"rodriguez","product_name":"Rodriguez Caballero 11","description":"Featuring a carefully chosen, solid Canadian cedar top and laminated bubinga back and sides, the Caballero 11 classical guitar is a beauty to behold and play. The headstock and fretboard are of Indian rosewood. Nickel-plated tuners and Silver-plated frets are installed to last a lifetime. The body binding and wood rosette are exquisite.\r\n\r\nThe Rodriguez Guitar is hand crafted and glued to create precise balances. From the invisible careful sanding, even inside the body, that ensures the finished instrument's purity of tone, to the beautifully unique rosette inlays around the soundhole and on the back of the neck, each guitar is a credit to its luthier and worthy of being handed down from one generation to another.\r\n\r\nThe tone, resonance and beauty of fine guitars are all dependent upon the wood from which they are made. The wood used in the construction of Rodriguez guitars is carefully chosen and aged to guarantee the highest quality. No wood is purchased before the tree has been cut down, and at least 2 years must elapse before the tree is turned into lumber. The wood has to be well cut from the log. The grain must be close and absolutely vertical. The shop is totally free from humidity.","list_price":"415.00","discount_percent":"39.00","date_added":"2018-07-30T14:12:41"}
{"product_id":7,"category_id":2,"product_code":"precision","product_name":"Fender Precision","description":"The Fender Precision bass guitar delivers the sound, look, and feel today's bass players demand. This bass features that classic P-Bass old-school design. Each Precision bass boasts contemporary features and refinements that make it an excellent value. Featuring an alder body and a split single-coil pickup, this classic electric bass guitar lives up to its Fender legacy.\r\n\r\nFeatures:\r\n\r\n* Body: Alder\r\n* Neck: Maple, modern C shape, tinted satin urethane finish\r\n* Fingerboard: Rosewood or maple (depending on color)\r\n* 9-1/2\" Radius (241 mm)\r\n* Frets: 20 Medium-jumbo frets\r\n* Pickups: 1 Standard Precision Bass split single-coil pickup (Mid)\r\n* Controls: Volume, Tone\r\n* Bridge: Standard vintage style with single groove saddles\r\n* Machine heads: Standard\r\n* Hardware: Chrome\r\n* Pickguard: 3-Ply Parchment\r\n* Scale Length: 34\" (864 mm)\r\n* Width at Nut: 1-5/8\" (41.3 mm)\r\n* Unique features: Knurled chrome P Bass knobs, Fender transition logo","list_price":"799.99","discount_percent":"30.00","date_added":"2018-06-01T11:29:35"}
{"product_id":8,"category_id":2,"product_code":"hofner","product_name":"Hofner Icon","description":"With authentic details inspired by the original, the Hofner Icon makes the legendary violin bass available to the rest of us. Don't get the idea that this a just a \"nowhere man\" look-alike. This quality instrument features a real spruce top and beautiful flamed maple back and sides. The semi-hollow body and set neck will give you the warm, round tone you expect from the violin bass.\r\n\r\nFeatures:\r\n\r\n* Authentic details inspired by the original\r\n* Spruce top\r\n* Flamed maple back and sides\r\n* Set neck\r\n* Rosewood fretboard\r\n* 30\" scale\r\n* 22 frets\r\n* Dot inlay","list_price":"499.99","discount_percent":"25.00","date_added":"2018-07-30T14:18:33"}
{"product_id":9,"category_id":3,"product_code":"ludwig","product_name":"Ludwig 5-piece Drum Set with Cymbals","description":"This product includes a Ludwig 5-piece drum set and a Zildjian starter cymbal pack.\r\n\r\nWith the Ludwig drum set, you get famous Ludwig quality. This set features a bass drum, two toms, a floor tom, and a snare?each with a wrapped finish. Drum hardware includes LA214FP bass pedal, snare stand, cymbal stand, hi-hat stand, and a throne.\r\n\r\nWith the Zildjian cymbal pack, you get a 14\" crash, 18\" crash/ride, and a pair of 13\" hi-hats. Sound grooves and round hammer strikes in a simple circular pattern on the top surface of these cymbals magnify the basic sound of the distinctive alloy.\r\n\r\nFeatures:\r\n\r\n* Famous Ludwig quality\r\n* Wrapped finishes\r\n* 22\" x 16\" kick drum\r\n* 12\" x 10\" and 13\" x 11\" toms\r\n* 16\" x 16\" floor tom\r\n* 14\" x 6-1/2\" snare drum kick pedal\r\n* Snare stand\r\n* Straight cymbal stand hi-hat stand\r\n* FREE throne","list_price":"699.99","discount_percent":"30.00","date_added":"2018-07-30T12:46:40"}
{"product_id":10,"category_id":3,"product_code":"tama","product_name":"Tama 5-Piece Drum Set with Cymbals","description":"The Tama 5-piece Drum Set is the most affordable Tama drum kit ever to incorporate so many high-end features.\r\n\r\nWith over 40 years of experience, Tama knows what drummers really want. Which is why, no matter how long you've been playing the drums, no matter what budget you have to work with, Tama has the set you need, want, and can afford. Every aspect of the modern drum kit was exhaustively examined and reexamined and then improved before it was accepted as part of the Tama design. Which is why, if you start playing Tama now as a beginner, you'll still enjoy playing it when you've achieved pro-status. That's how good these groundbreaking new drums are.\r\n\r\nOnly Tama comes with a complete set of genuine Meinl HCS cymbals. These high-quality brass cymbals are made in Germany and are sonically matched so they sound great together. They are even lathed for a more refined tonal character. The set includes 14\" hi-hats, 16\" crash cymbal, and a 20\" ride cymbal.\r\n\r\nFeatures:\r\n\r\n* 100% poplar 6-ply/7.5mm shells\r\n* Precise bearing edges\r\n* 100% glued finishes\r\n* Original small lugs\r\n* Drum heads\r\n* Accu-tune bass drum hoops\r\n* Spur brackets\r\n* Tom holder\r\n* Tom brackets","list_price":"799.99","discount_percent":"15.00","date_added":"2018-07-30T13:14:15"}
@@ -0,0 +1,42 @@
name: products
columns:
- name: product_id
type: int
default: null
autoIncrement: true
notNull: true
- name: category_id
type: int
default: null
notNull: true
references: categories
- name: product_code
type: varchar(10)
default: null
notNull: true
- name: product_name
type: varchar(255)
default: null
notNull: true
- name: description
type: text
default: null
notNull: true
- name: list_price
type: decimal(10,2)
default: null
notNull: true
- name: discount_percent
type: decimal(10,2)
default: '0.00'
notNull: true
- name: date_added
type: datetime
default: null
primaryKey:
- product_id
indexes:
- name: products_fk_categories
unique: false
columns:
- category_id
+18 -1
View File
@@ -22,7 +22,7 @@ services:
restart: always
ports:
- 16005:3306
- "16012:22"
- "16015:22"
mysql-ssh-keyfile:
build: containers/mysql-ssh-keyfile
@@ -49,3 +49,20 @@ services:
image: redis
ports:
- 16011:6379
mssql:
image: mcr.microsoft.com/mssql/server
restart: always
ports:
- 16014:1433
environment:
- ACCEPT_EULA=Y
- SA_PASSWORD=Pwd2020Db
- MSSQL_PID=Express
oracle:
image: gvenzl/oracle-xe:21-slim
environment:
ORACLE_PASSWORD: Pwd2020Db
ports:
- 16013:1521
-38
View File
@@ -1,38 +0,0 @@
const path = require('path');
const os = require('os');
const fs = require('fs');
const baseDir = path.join(os.homedir(), '.dbgate');
// function createTimeStamp() {
// const now = new Date();
// const year = now.getFullYear();
// const month = String(now.getMonth() + 1).padStart(2, '0'); // měsíc je 0-indexovaný
// const day = String(now.getDate()).padStart(2, '0');
// const hours = String(now.getHours()).padStart(2, '0');
// const minutes = String(now.getMinutes()).padStart(2, '0');
// const seconds = String(now.getSeconds()).padStart(2, '0');
// // Poskládáme datum a čas do názvu souboru
// const ts = `${year}-${month}-${day}_${hours}-${minutes}-${seconds}`;
// return ts;
// }
function clearTestingData() {
if (fs.existsSync(path.join(baseDir, 'connections-e2etests.jsonl'))) {
fs.unlinkSync(path.join(baseDir, 'connections-e2etests.jsonl'));
}
if (fs.existsSync(path.join(baseDir, 'settings-e2etests.jsonl'))) {
fs.unlinkSync(path.join(baseDir, 'settings-e2etests.jsonl'));
}
if (fs.existsSync(path.join(baseDir, 'files-e2etests'))) {
fs.rmdirSync(path.join(baseDir, 'files-e2etests'), { recursive: true });
}
if (fs.existsSync(path.join(baseDir, 'archive-e2etests'))) {
fs.rmdirSync(path.join(baseDir, 'archive-e2etests'), { recursive: true });
}
}
module.exports = {
clearTestingData,
};
+45
View File
@@ -0,0 +1,45 @@
CONNECTIONS=mysql,postgres,mssql,oracle,sqlite,mongo
LOG_CONNECTION_SENSITIVE_VALUES=true
LABEL_mysql=MySql-connection
SERVER_mysql=localhost
USER_mysql=root
PASSWORD_mysql=Pwd2020Db
PORT_mysql=16004
ENGINE_mysql=mysql@dbgate-plugin-mysql
DBCONFIG_mysql=[{"name":"MyChinook","connectionColor":"cyan"}]
LABEL_postgres=Postgres-connection
SERVER_postgres=localhost
USER_postgres=postgres
PASSWORD_postgres=Pwd2020Db
PORT_postgres=16000
ENGINE_postgres=postgres@dbgate-plugin-postgres
DBCONFIG_postgres=[{"name":"PgChinook","connectionColor":"red"}]
LABEL_oracle=Oracle-connection
SERVER_oracle=localhost
USER_oracle=system
PASSWORD_oracle=Pwd2020Db
PORT_oracle=16013
ENGINE_oracle=oracle@dbgate-plugin-oracle
SERVICE_NAME_oracle=xe
LABEL_mssql=Mssql-connection
SERVER_mssql=localhost
USER_mssql=sa
PASSWORD_mssql=Pwd2020Db
PORT_mssql=16014
ENGINE_mssql=mssql@dbgate-plugin-mssql
LABEL_sqlite=Sqlite-connection
FILE_sqlite=%%E2E_TEST_DATA_DIRECTORY%%/my_guitar_shop.db
ENGINE_sqlite=sqlite@dbgate-plugin-sqlite
LABEL_mongo=Mongo-connection
SERVER_mongo=localhost
USER_mongo=root
PASSWORD_mongo=Pwd2020Db
PORT_mongo=16010
ENGINE_mongo=mongo@dbgate-plugin-mongo
+5
View File
@@ -195,6 +195,11 @@ async function run() {
path.join(baseDir, 'archive-e2etests', 'default')
);
await copyFolder(
path.resolve(path.join(__dirname, '../data/chinook-jsonl')),
path.join(baseDir, 'archive-e2etests', 'chinook-archive')
);
await copyFolder(
path.resolve(path.join(__dirname, '../data/files/query')),
path.join(baseDir, 'files-e2etests', 'query')
+130
View File
@@ -0,0 +1,130 @@
const path = require('path');
const localconfig = require('../.localconfig');
const dbgateApi = require('dbgate-api');
dbgateApi.initializeApiEnvironment();
const dbgatePluginMysql = require('dbgate-plugin-mysql');
dbgateApi.registerPlugins(dbgatePluginMysql);
const dbgatePluginPostgres = require('dbgate-plugin-postgres');
dbgateApi.registerPlugins(dbgatePluginPostgres);
async function createDb(connection, dropDbSql, createDbSql, database = 'my_guitar_shop', { dropDatabaseName } = {}) {
if (dropDbSql) {
try {
await dbgateApi.executeQuery({
connection,
sql: dropDbSql,
database: dropDatabaseName,
});
} catch (err) {
console.error('Failed to drop database', err);
}
}
if (createDbSql) {
await dbgateApi.executeQuery({
connection,
sql: createDbSql,
});
}
await dbgateApi.importDbFromFolder({
connection: {
...connection,
database,
},
folder: path.resolve(path.join(__dirname, '../data/my-guitar-shop')),
});
}
async function run() {
if (localconfig.postgres) {
await createDb(
{
server: process.env.SERVER_postgres,
user: process.env.USER_postgres,
password: process.env.PASSWORD_postgres,
port: process.env.PORT_postgres,
engine: 'postgres@dbgate-plugin-postgres',
},
'drop database if exists my_guitar_shop',
'create database my_guitar_shop'
);
}
if (localconfig.mysql) {
await createDb(
{
server: process.env.SERVER_mysql,
user: process.env.USER_mysql,
password: process.env.PASSWORD_mysql,
port: process.env.PORT_mysql,
engine: 'mysql@dbgate-plugin-mysql',
},
'drop database if exists my_guitar_shop',
'create database my_guitar_shop'
);
}
if (localconfig.mssql) {
await createDb(
{
server: process.env.SERVER_mssql,
user: process.env.USER_mssql,
password: process.env.PASSWORD_mssql,
port: process.env.PORT_mssql,
engine: 'mssql@dbgate-plugin-mssql',
},
'drop database if exists my_guitar_shop',
'create database my_guitar_shop'
);
}
if (localconfig.oracle) {
await createDb(
{
server: process.env.SERVER_oracle,
user: process.env.USER_oracle,
password: process.env.PASSWORD_oracle,
port: process.env.PORT_oracle,
engine: 'oracle@dbgate-plugin-oracle',
},
'DROP USER c##my_guitar_shop CASCADE',
'CREATE USER c##my_guitar_shop IDENTIFIED BY my_guitar_shop DEFAULT TABLESPACE users TEMPORARY TABLESPACE temp QUOTA 10M ON users',
'C##my_guitar_shop'
);
}
if (localconfig.sqlite) {
await createDb(
{
databaseFile: process.env.FILE_sqlite.replace(
'%%E2E_TEST_DATA_DIRECTORY%%',
path.join(path.dirname(__dirname), 'tmpdata')
),
singleDatabase: true,
engine: 'sqlite@dbgate-plugin-sqlite',
},
null,
null
);
}
if (localconfig.mongo) {
await createDb(
{
server: process.env.SERVER_mongo,
user: process.env.USER_mongo,
password: process.env.PASSWORD_mongo,
port: process.env.PORT_mongo,
engine: 'mongo@dbgate-plugin-mongo',
},
'db.dropDatabase()',
null,
'my_guitar_shop',
{ dropDatabaseName: 'my_guitar_shop' }
);
}
}
dbgateApi.runScript(run);
+9 -6
View File
@@ -20,20 +20,23 @@
"cy:run:oauth": "cypress run --spec cypress/e2e/oauth.cy.js",
"cy:run:browse-data": "cypress run --spec cypress/e2e/browse-data.cy.js",
"cy:run:team": "cypress run --spec cypress/e2e/team.cy.js",
"cy:run:multi-sql": "cypress run --spec cypress/e2e/multi-sql.cy.js",
"start:add-connection": "cd .. && node packer/build/bundle.js --listen-api --run-e2e-tests",
"start:portal": "cd .. && env-cmd -f e2e-tests/env/portal/.env node e2e-tests/init/portal.js && env-cmd -f e2e-tests/env/portal/.env node packer/build/bundle.js --listen-api --run-e2e-tests",
"start:oauth": "cd .. && env-cmd -f e2e-tests/env/oauth/.env node packer/build/bundle.js --listen-api --run-e2e-tests",
"start:browse-data": "cd .. && env-cmd -f e2e-tests/env/browse-data/.env node e2e-tests/init/browse-data.js && env-cmd -f e2e-tests/env/browse-data/.env node packer/build/bundle.js --listen-api --run-e2e-tests",
"start:team": "cd .. && env-cmd -f e2e-tests/env/team/.env node e2e-tests/init/team.js && env-cmd -f e2e-tests/env/team/.env node packer/build/bundle.js --listen-api --run-e2e-tests",
"start:add-connection": "node clearTestingData && cd .. && node packer/build/bundle.js --listen-api --run-e2e-tests",
"start:portal": "node clearTestingData && cd .. && env-cmd -f e2e-tests/env/portal/.env node e2e-tests/init/portal.js && env-cmd -f e2e-tests/env/portal/.env node packer/build/bundle.js --listen-api --run-e2e-tests",
"start:oauth": "node clearTestingData && cd .. && env-cmd -f e2e-tests/env/oauth/.env node packer/build/bundle.js --listen-api --run-e2e-tests",
"start:browse-data": "node clearTestingData && cd .. && env-cmd -f e2e-tests/env/browse-data/.env node e2e-tests/init/browse-data.js && env-cmd -f e2e-tests/env/browse-data/.env node packer/build/bundle.js --listen-api --run-e2e-tests",
"start:team": "node clearTestingData && cd .. && env-cmd -f e2e-tests/env/team/.env node e2e-tests/init/team.js && env-cmd -f e2e-tests/env/team/.env node packer/build/bundle.js --listen-api --run-e2e-tests",
"start:multi-sql": "node clearTestingData && cd .. && env-cmd -f e2e-tests/env/multi-sql/.env node e2e-tests/init/multi-sql.js && env-cmd -f e2e-tests/env/multi-sql/.env node packer/build/bundle.js --listen-api --run-e2e-tests",
"test:add-connection": "start-server-and-test start:add-connection http://localhost:3000 cy:run:add-connection",
"test:portal": "start-server-and-test start:portal http://localhost:3000 cy:run:portal",
"test:oauth": "start-server-and-test start:oauth http://localhost:3000 cy:run:oauth",
"test:browse-data": "start-server-and-test start:browse-data http://localhost:3000 cy:run:browse-data",
"test:team": "start-server-and-test start:team http://localhost:3000 cy:run:team",
"test:multi-sql": "start-server-and-test start:multi-sql http://localhost:3000 cy:run:multi-sql",
"test": "yarn test:add-connection && yarn test:portal && yarn test:oauth && yarn test:browse-data && yarn test:team",
"test": "yarn test:add-connection && yarn test:portal && yarn test:oauth && yarn test:browse-data && yarn test:team && yarn test:multi-sql",
"test:ci": "yarn test"
},
"dependencies": {}
View File
-1
View File
@@ -1 +0,0 @@
Folder with screenshots
View File
@@ -1,11 +1,12 @@
const engines = require('../engines');
const stream = require('stream');
const path = require('path');
const { testWrapper } = require('../tools');
const tableWriter = require('dbgate-api/src/shell/tableWriter');
const tableReader = require('dbgate-api/src/shell/tableReader');
const copyStream = require('dbgate-api/src/shell/copyStream');
const importDatabase = require('dbgate-api/src/shell/importDatabase');
const fakeObjectReader = require('dbgate-api/src/shell/fakeObjectReader');
const importDbFromFolder = require('dbgate-api/src/shell/importDbFromFolder');
const { runQueryOnDriver, runCommandOnDriver } = require('dbgate-tools');
function createImportStream() {
@@ -108,7 +109,6 @@ describe('DB Import/export', () => {
expect(res2.rows[0].cnt.toString()).toEqual('6');
})
);
const enginesWithDumpFile = engines.filter(x => x.dumpFile);
const hasEnginesWithDumpFile = enginesWithDumpFile.length > 0;
@@ -181,4 +181,18 @@ describe('DB Import/export', () => {
expect(result).toEqual(data);
})
);
test.each(engines.filter(engine => !engine.skipImportModel).map(engine => [engine.label, engine]))(
'Import guitar shop - schema + data - %s',
testWrapper(async (conn, driver, engine) => {
await importDbFromFolder({
systemConnection: conn,
driver,
folder: path.join(__dirname, '../../e2e-tests/data/my-guitar-shop'),
});
const res1 = await runQueryOnDriver(conn, driver, dmp => dmp.put(`select count(*) as ~cnt from ~categories`));
expect(res1.rows[0].cnt.toString()).toEqual('4');
})
);
});
+36 -27
View File
@@ -27,11 +27,11 @@ services:
# - MYSQL_ROOT_PASSWORD=Pwd2020Db
#
cassandradb:
image: cassandra:5.0.2
ports:
- 15942:9042
# cassandradb:
# image: cassandra:5.0.2
# ports:
# - 15942:9042
#
# clickhouse:
# image: bitnami/clickhouse:24.8.4
# restart: always
@@ -55,28 +55,37 @@ services:
# ports:
# - 15003:26257
# command: start-single-node --insecure
# mongodb:
# image: mongo:4.0.12
# restart: always
# volumes:
# - mongo-data:/data/db
# - mongo-config:/data/configdb
# ports:
# - 27017:27017
# mongodb:
# image: mongo:4.0.12
# restart: always
# volumes:
# - mongo-data:/data/db
# - mongo-config:/data/configdb
# ports:
# - 27017:27017
# cockroachdb-init:
# image: cockroachdb/cockroach
# # build: cockroach
# # entrypoint: /cockroach/init.sh
# entrypoint: ./cockroach sql --insecure --host="cockroachdb" --execute="CREATE DATABASE IF NOT EXISTS test;"
# cockroachdb-init:
# image: cockroachdb/cockroach
# # build: cockroach
# # entrypoint: /cockroach/init.sh
# entrypoint: ./cockroach sql --insecure --host="cockroachdb" --execute="CREATE DATABASE IF NOT EXISTS test;"
# depends_on:
# - cockroachdb
# restart: on-failure
# depends_on:
# - cockroachdb
# restart: on-failure
# oracle:
# image: gvenzl/oracle-xe:21-slim
# environment:
# ORACLE_PASSWORD: Pwd2020Db
# ports:
# - 15006:1521
# oracle:
# image: gvenzl/oracle-xe:21-slim
# environment:
# ORACLE_PASSWORD: Pwd2020Db
# ports:
# - 15006:1521
libsql:
image: ghcr.io/tursodatabase/libsql-server:latest
platform: linux/amd64
ports:
- '8080:8080'
- '5002:5001'
volumes:
- ./data/libsql:/var/lib/sqld
+24 -1
View File
@@ -506,6 +506,23 @@ const sqliteEngine = {
],
};
const libsqlFileEngine = {
...sqliteEngine,
label: 'LibSQL FILE',
connection: {
engine: 'libsql@dbgate-plugin-sqlite',
},
};
const libsqlWsEngine = {
...sqliteEngine,
label: 'LibSQL WS',
connection: {
engine: 'libsql@dbgate-plugin-sqlite',
databaseUrl: 'ws://localhost:8080',
},
};
/** @type {import('dbgate-types').TestEngineInfo} */
const cockroachDbEngine = {
label: 'CockroachDB',
@@ -539,6 +556,7 @@ const clickhouseEngine = {
alterTableAddColumnSyntax: true,
dbSnapshotBySeconds: true,
skipChangeColumn: true,
skipImportModel: true,
};
/** @type {import('dbgate-types').TestEngineInfo} */
@@ -627,6 +645,7 @@ const cassandraEngine = {
skipDataModifications: true,
skipDataDuplicator: true,
skipDeploy: true,
skipImportModel: true,
forceSortResults: true,
forceSortStructureColumns: true,
@@ -642,6 +661,8 @@ const enginesOnCi = [
postgreSqlEngine,
sqlServerEngine,
sqliteEngine,
libsqlFileEngine,
libsqlWsEngine,
// cockroachDbEngine,
clickhouseEngine,
oracleEngine,
@@ -650,7 +671,7 @@ const enginesOnCi = [
const enginesOnLocal = [
// all engines, which would be run on local test
cassandraEngine,
// cassandraEngine,
// mysqlEngine,
// mariaDbEngine,
// postgreSqlEngine,
@@ -658,6 +679,8 @@ const enginesOnLocal = [
// sqliteEngine,
// cockroachDbEngine,
// clickhouseEngine,
// libsqlFileEngine,
libsqlWsEngine,
// oracleEngine,
];
+8 -2
View File
@@ -1,6 +1,6 @@
{
"private": true,
"version": "6.1.7-premium-beta.2",
"version": "6.3.2",
"name": "dbgate-all",
"workspaces": [
"packages/*",
@@ -58,6 +58,7 @@
"install:drivers:packer": "node common/defineVolatileDependencies.js packer/build",
"prepare:docker": "yarn plugins:copydist && yarn build:web && yarn build:api && yarn copy:docker:build && yarn install:drivers:docker",
"prepare:packer": "yarn plugins:copydist && yarn build:web && yarn build:api && yarn copy:packer:build",
"build:e2e": "yarn build:lib && yarn prepare:packer",
"start": "concurrently --kill-others-on-fail \"yarn start:api\" \"yarn start:web\"",
"lib": "concurrently --kill-others-on-fail \"yarn start:sqltree\" \"yarn start:filterparser\" \"yarn start:datalib\" \"yarn start:tools\" \"yarn build:plugins:frontend:watch\"",
"ts:api": "yarn workspace dbgate-api ts",
@@ -65,7 +66,12 @@
"ts": "yarn ts:api && yarn ts:web",
"postinstall": "yarn resetPackagedPlugins && yarn build:lib && patch-package && yarn build:plugins:frontend",
"dbgate-serve": "node packages/dbgate/bin/dbgate-serve.js",
"workflows": "node common/processWorkflows.js"
"workflows": "node common/processWorkflows.js",
"cy:open": "cd e2e-tests && yarn cy:open",
"translations:extract": "node common/translations-cli/index.js extract",
"translations:add-missing": "node common/translations-cli/index.js add-missing",
"translations:remove-unused": "node common/translations-cli/index.js remove-unused",
"translations:check": "node common/translations-cli/index.js check"
},
"dependencies": {
"concurrently": "^5.1.0",
+1
View File
@@ -43,6 +43,7 @@ function authMiddleware(req, res, next) {
'/connections/dblogin-app',
'/connections/dblogin-auth',
'/connections/dblogin-auth-token',
'/health',
];
// console.log('********************* getAuthProvider()', getAuthProvider());
+15 -2
View File
@@ -62,7 +62,10 @@ function getPortalCollections() {
port: process.env[`PORT_${id}`],
databaseUrl: process.env[`URL_${id}`],
useDatabaseUrl: !!process.env[`URL_${id}`],
databaseFile: process.env[`FILE_${id}`],
databaseFile: process.env[`FILE_${id}`]?.replace(
'%%E2E_TEST_DATA_DIRECTORY%%',
path.join(path.dirname(path.dirname(__dirname)), 'e2e-tests', 'tmpdata')
),
socketPath: process.env[`SOCKET_PATH_${id}`],
serviceName: process.env[`SERVICE_NAME_${id}`],
authType: process.env[`AUTH_TYPE_${id}`] || (process.env[`SOCKET_PATH_${id}`] ? 'socket' : undefined),
@@ -77,6 +80,7 @@ function getPortalCollections() {
allowedDatabasesRegex: process.env[`ALLOWED_DATABASES_REGEX_${id}`],
parent: process.env[`PARENT_${id}`] || undefined,
useSeparateSchemas: !!process.env[`USE_SEPARATE_SCHEMAS_${id}`],
localDataCenter: process.env[`LOCAL_DATA_CENTER_${id}`],
// SSH tunnel
useSshTunnel: process.env[`USE_SSH_${id}`],
@@ -98,12 +102,21 @@ function getPortalCollections() {
trustServerCertificate: process.env[`SSL_TRUST_CERTIFICATE_${id}`],
}));
for(const conn of connections) {
for(const prop in process.env) {
if (prop.startsWith(`CONNECTION_${conn._id}_`)) {
const name = prop.substring(`CONNECTION_${conn._id}_`.length);
conn[name] = process.env[prop];
}
}
}
logger.info({ connections: connections.map(pickSafeConnectionInfo) }, 'Using connections from ENV variables');
const noengine = connections.filter(x => !x.engine);
if (noengine.length > 0) {
logger.warn(
{ connections: noengine.map(x => x._id) },
'Invalid CONNECTIONS configutation, missing ENGINE for connection ID'
'Invalid CONNECTIONS configuration, missing ENGINE for connection ID'
);
}
return connections;
@@ -1,4 +1,5 @@
const connections = require('./connections');
const runners = require('./runners');
const archive = require('./archive');
const socket = require('../utility/socket');
const { fork } = require('child_process');
@@ -71,6 +72,11 @@ module.exports = {
handle_error(conid, database, props) {
const { error } = props;
logger.error(`Error in database connection ${conid}, database ${database}: ${error}`);
if (props?.msgid) {
const [resolve, reject] = this.requests[props?.msgid];
reject(error);
delete this.requests[props?.msgid];
}
},
handle_response(conid, database, { msgid, ...response }) {
const [resolve, reject] = this.requests[msgid];
@@ -228,6 +234,7 @@ module.exports = {
dispatchDatabaseChangedEvent_meta: true,
dispatchDatabaseChangedEvent({ event, conid, database }) {
socket.emitChanged(event, { conid, database });
return null;
},
loadKeys_meta: true,
@@ -607,4 +614,129 @@ module.exports = {
return res;
},
async getNativeOpCommandArgs(
command,
{ conid, database, outputFile, inputFile, options, selectedTables, skippedTables, argsFormat }
) {
const connection = await connections.getCore({ conid });
const driver = requireEngineDriver(connection);
const settingsValue = await config.getSettings();
const externalTools = {};
for (const pair of Object.entries(settingsValue || {})) {
const [name, value] = pair;
if (name.startsWith('externalTools.')) {
externalTools[name.substring('externalTools.'.length)] = value;
}
}
return {
...(command == 'backup'
? driver.backupDatabaseCommand(
connection,
{ outputFile, database, options, selectedTables, skippedTables, argsFormat },
// @ts-ignore
externalTools
)
: driver.restoreDatabaseCommand(
connection,
{ inputFile, database, options, argsFormat },
// @ts-ignore
externalTools
)),
transformMessage: driver.transformNativeCommandMessage
? message => driver.transformNativeCommandMessage(message, command)
: null,
};
},
commandArgsToCommandLine(commandArgs) {
const { command, args, stdinFilePath } = commandArgs;
let res = `${command} ${args.join(' ')}`;
if (stdinFilePath) {
res += ` < ${stdinFilePath}`;
}
return res;
},
nativeBackup_meta: true,
async nativeBackup({ conid, database, outputFile, runid, options, selectedTables, skippedTables }) {
const commandArgs = await this.getNativeOpCommandArgs('backup', {
conid,
database,
inputFile: undefined,
outputFile,
options,
selectedTables,
skippedTables,
argsFormat: 'spawn',
});
return runners.nativeRunCore(runid, {
...commandArgs,
onFinished: () => {
socket.emitChanged(`files-changed`, { folder: 'sql' });
socket.emitChanged(`all-files-changed`);
},
});
},
nativeBackupCommand_meta: true,
async nativeBackupCommand({ conid, database, outputFile, options, selectedTables, skippedTables }) {
const commandArgs = await this.getNativeOpCommandArgs('backup', {
conid,
database,
outputFile,
inputFile: undefined,
options,
selectedTables,
skippedTables,
argsFormat: 'shell',
});
return {
...commandArgs,
transformMessage: null,
commandLine: this.commandArgsToCommandLine(commandArgs),
};
},
nativeRestore_meta: true,
async nativeRestore({ conid, database, inputFile, runid }) {
const commandArgs = await this.getNativeOpCommandArgs('restore', {
conid,
database,
inputFile,
outputFile: undefined,
options: undefined,
argsFormat: 'spawn',
});
return runners.nativeRunCore(runid, {
...commandArgs,
onFinished: () => {
this.syncModel({ conid, database, isFullRefresh: true });
},
});
},
nativeRestoreCommand_meta: true,
async nativeRestoreCommand({ conid, database, inputFile }) {
const commandArgs = await this.getNativeOpCommandArgs('restore', {
conid,
database,
inputFile,
outputFile: undefined,
options: undefined,
argsFormat: 'shell',
});
return {
...commandArgs,
transformMessage: null,
commandLine: this.commandArgsToCommandLine(commandArgs),
};
},
};
+2 -2
View File
@@ -195,8 +195,8 @@ module.exports = {
},
exportDiagram_meta: true,
async exportDiagram({ filePath, html, css, themeType, themeClassName }) {
await fs.writeFile(filePath, getDiagramExport(html, css, themeType, themeClassName));
async exportDiagram({ filePath, html, css, themeType, themeClassName, watermark }) {
await fs.writeFile(filePath, getDiagramExport(html, css, themeType, themeClassName, watermark));
return true;
},
+97 -5
View File
@@ -4,7 +4,7 @@ const path = require('path');
const fs = require('fs-extra');
const byline = require('byline');
const socket = require('../utility/socket');
const { fork } = require('child_process');
const { fork, spawn } = require('child_process');
const { rundir, uploadsdir, pluginsdir, getPluginBackendPath, packagedPluginList } = require('../utility/directories');
const {
extractShellApiPlugins,
@@ -13,6 +13,8 @@ const {
getLogger,
safeJsonParse,
pinoLogRecordToMessageRecord,
extractErrorMessage,
extractErrorLogData,
} = require('dbgate-tools');
const { handleProcessCommunication } = require('../utility/processComm');
const processArgs = require('../utility/processArgs');
@@ -80,6 +82,7 @@ module.exports = {
}
: {
message,
severity: 'info',
time: new Date(),
};
@@ -94,14 +97,26 @@ module.exports = {
handle_ping() {},
handle_freeData(runid, { freeData }) {
const [resolve, reject] = this.requests[runid];
const { resolve } = this.requests[runid];
resolve(freeData);
delete this.requests[runid];
},
handle_copyStreamError(runid, { copyStreamError }) {
const { reject, exitOnStreamError } = this.requests[runid] || {};
if (exitOnStreamError) {
reject(copyStreamError);
delete this.requests[runid];
}
},
handle_progress(runid, progressData) {
socket.emit(`runner-progress-${runid}`, progressData);
},
rejectRequest(runid, error) {
if (this.requests[runid]) {
const [resolve, reject] = this.requests[runid];
const { reject } = this.requests[runid];
reject(error);
delete this.requests[runid];
}
@@ -113,6 +128,8 @@ module.exports = {
fs.writeFileSync(`${scriptFile}`, scriptText);
fs.mkdirSync(directory);
const pluginNames = extractPlugins(scriptText);
// console.log('********************** SCRIPT TEXT **********************');
// console.log(scriptText);
logger.info({ scriptFile }, 'Running script');
// const subprocess = fork(scriptFile, ['--checkParent', '--max-old-space-size=8192'], {
const subprocess = fork(
@@ -150,17 +167,21 @@ module.exports = {
byline(subprocess.stdout).on('data', pipeDispatcher('info'));
byline(subprocess.stderr).on('data', pipeDispatcher('error'));
subprocess.on('exit', code => {
// console.log('... EXITED', code);
this.rejectRequest(runid, { message: 'No data returned, maybe input data source is too big' });
logger.info({ code, pid: subprocess.pid }, 'Exited process');
socket.emit(`runner-done-${runid}`, code);
this.opened = this.opened.filter(x => x.runid != runid);
});
subprocess.on('error', error => {
// console.log('... ERROR subprocess', error);
this.rejectRequest(runid, { message: error && (error.message || error.toString()) });
console.error('... ERROR subprocess', error);
this.dispatchMessage({
this.dispatchMessage(runid, {
severity: 'error',
message: error.toString(),
});
this.opened = this.opened.filter(x => x.runid != runid);
});
const newOpened = {
runid,
@@ -176,6 +197,77 @@ module.exports = {
return _.pick(newOpened, ['runid']);
},
nativeRunCore(runid, commandArgs) {
const { command, args, env, transformMessage, stdinFilePath, onFinished } = commandArgs;
const pipeDispatcher = severity => data => {
let messageObject = {
message: data.toString().trim(),
severity,
};
if (transformMessage) {
messageObject = transformMessage(messageObject);
}
if (messageObject) {
return this.dispatchMessage(runid, messageObject);
}
};
const subprocess = spawn(command, args, { env: { ...process.env, ...env } });
byline(subprocess.stdout).on('data', pipeDispatcher('info'));
byline(subprocess.stderr).on('data', pipeDispatcher('error'));
subprocess.on('exit', code => {
console.log('... EXITED', code);
logger.info({ code, pid: subprocess.pid }, 'Exited process');
this.dispatchMessage(runid, `Finished external process with code ${code}`);
socket.emit(`runner-done-${runid}`, code);
if (onFinished) {
onFinished();
}
this.opened = this.opened.filter(x => x.runid != runid);
});
subprocess.on('spawn', () => {
this.dispatchMessage(runid, `Started external process ${command}`);
});
subprocess.on('error', error => {
console.log('... ERROR subprocess', error);
this.dispatchMessage(runid, {
severity: 'error',
message: error.toString(),
});
if (error['code'] == 'ENOENT') {
this.dispatchMessage(runid, {
severity: 'error',
message: `Command ${command} not found, please install it and configure its location in DbGate settings, Settings/External tools, if ${command} is not in system PATH`,
});
}
socket.emit(`runner-done-${runid}`);
this.opened = this.opened.filter(x => x.runid != runid);
});
if (stdinFilePath) {
const inputStream = fs.createReadStream(stdinFilePath);
inputStream.pipe(subprocess.stdin);
subprocess.stdin.on('error', err => {
this.dispatchMessage(runid, {
severity: 'error',
message: extractErrorMessage(err),
});
logger.error(extractErrorLogData(err), 'Caught error on stdin');
});
}
const newOpened = {
runid,
subprocess,
};
this.opened.push(newOpened);
return _.pick(newOpened, ['runid']);
},
start_meta: true,
async start({ script }) {
const runid = crypto.randomUUID();
@@ -231,7 +323,7 @@ module.exports = {
const promise = new Promise((resolve, reject) => {
const runid = crypto.randomUUID();
this.requests[runid] = [resolve, reject];
this.requests[runid] = { resolve, reject, exitOnStreamError: true };
this.startCore(runid, loaderScriptTemplate(prefix, functionName, props, runid));
});
return promise;
+27 -3
View File
@@ -56,12 +56,19 @@ module.exports = {
handle_done(sesid, props) {
socket.emit(`session-done-${sesid}`);
if (!props.skipFinishedMessage) {
this.dispatchMessage(sesid, 'Query execution finished');
if (props.controlCommand) {
this.dispatchMessage(sesid, `${_.startCase(props.controlCommand)} finished`);
} else {
this.dispatchMessage(sesid, 'Query execution finished');
}
}
const session = this.opened.find(x => x.sesid == sesid);
if (session.loadingReader_jslid) {
socket.emit(`session-jslid-done-${session.loadingReader_jslid}`);
}
if (props.autoCommit) {
this.executeControlCommand({ sesid, command: 'commitTransaction' });
}
if (session.killOnDone) {
this.kill({ sesid });
}
@@ -120,6 +127,9 @@ module.exports = {
this.dispatchMessage(sesid, 'Query session closed');
socket.emit(`session-closed-${sesid}`);
});
subprocess.on('error', () => {
this.opened = this.opened.filter(x => x.sesid != sesid);
});
subprocess.send({
msgtype: 'connect',
@@ -131,7 +141,7 @@ module.exports = {
},
executeQuery_meta: true,
async executeQuery({ sesid, sql }) {
async executeQuery({ sesid, sql, autoCommit }) {
const session = this.opened.find(x => x.sesid == sesid);
if (!session) {
throw new Error('Invalid session');
@@ -139,7 +149,21 @@ module.exports = {
logger.info({ sesid, sql }, 'Processing query');
this.dispatchMessage(sesid, 'Query execution started');
session.subprocess.send({ msgtype: 'executeQuery', sql });
session.subprocess.send({ msgtype: 'executeQuery', sql, autoCommit });
return { state: 'ok' };
},
executeControlCommand_meta: true,
async executeControlCommand({ sesid, command }) {
const session = this.opened.find(x => x.sesid == sesid);
if (!session) {
throw new Error('Invalid session');
}
logger.info({ sesid, command }, 'Processing control command');
this.dispatchMessage(sesid, `${_.startCase(command)} started`);
session.subprocess.send({ msgtype: 'executeControlCommand', command });
return { state: 'ok' };
},
+48 -1
View File
@@ -1,6 +1,6 @@
const crypto = require('crypto');
const path = require('path');
const { uploadsdir, getLogsFilePath } = require('../utility/directories');
const { uploadsdir, getLogsFilePath, filesdir } = require('../utility/directories');
const { getLogger, extractErrorLogData } = require('dbgate-tools');
const logger = getLogger('uploads');
const axios = require('axios');
@@ -13,6 +13,7 @@ const serverConnections = require('./serverConnections');
const config = require('./config');
const gistSecret = require('../gistSecret');
const currentVersion = require('../currentVersion');
const socket = require('../utility/socket');
module.exports = {
upload_meta: {
@@ -38,6 +39,52 @@ module.exports = {
});
},
uploadDataFile_meta: {
method: 'post',
raw: true,
},
uploadDataFile(req, res) {
const { data } = req.files || {};
if (!data) {
res.json(null);
return;
}
if (data.name.toLowerCase().endsWith('.sql')) {
logger.info(`Uploading SQL file ${data.name}, size=${data.size}`);
data.mv(path.join(filesdir(), 'sql', data.name), () => {
res.json({
name: data.name,
folder: 'sql',
});
socket.emitChanged(`files-changed`, { folder: 'sql' });
socket.emitChanged(`all-files-changed`);
});
return;
}
res.json(null);
},
saveDataFile_meta: true,
async saveDataFile({ filePath }) {
if (filePath.toLowerCase().endsWith('.sql')) {
logger.info(`Saving SQL file ${filePath}`);
await fs.copyFile(filePath, path.join(filesdir(), 'sql', path.basename(filePath)));
socket.emitChanged(`files-changed`, { folder: 'sql' });
socket.emitChanged(`all-files-changed`);
return {
name: path.basename(filePath),
folder: 'sql',
};
}
return null;
},
get_meta: {
method: 'get',
raw: true,
+15 -1
View File
@@ -30,7 +30,7 @@ const queryHistory = require('./controllers/queryHistory');
const onFinished = require('on-finished');
const processArgs = require('./utility/processArgs');
const { rundir } = require('./utility/directories');
const { rundir, filesdir } = require('./utility/directories');
const platformInfo = require('./utility/platformInfo');
const getExpressPath = require('./utility/getExpressPath');
const _ = require('lodash');
@@ -38,6 +38,7 @@ const { getLogger } = require('dbgate-tools');
const { getDefaultAuthProvider } = require('./auth/authProvider');
const startCloudUpgradeTimer = require('./utility/cloudUpgrade');
const { isProApp } = require('./utility/checkLicense');
const getHealthStatus = require('./utility/healthStatus');
const logger = getLogger('main');
@@ -78,6 +79,8 @@ function start() {
app.use(getExpressPath('/'), express.static('/home/dbgate-docker/public'));
} else if (platformInfo.isAwsUbuntuLayout) {
app.use(getExpressPath('/'), express.static('/home/ubuntu/build/public'));
} else if (platformInfo.isAzureUbuntuLayout) {
app.use(getExpressPath('/'), express.static('/home/azureuser/build/public'));
} else if (processArgs.runE2eTests) {
app.use(getExpressPath('/'), express.static(path.resolve('packer/build/public')));
} else if (platformInfo.isNpmDist) {
@@ -115,6 +118,12 @@ function start() {
});
});
app.get(getExpressPath('/health'), async function (req, res) {
res.setHeader('Content-Type', 'application/json');
const health = await getHealthStatus();
res.end(JSON.stringify(health, null, 2));
});
app.use(bodyParser.json({ limit: '50mb' }));
app.use(
@@ -131,6 +140,7 @@ function start() {
// }
app.use(getExpressPath('/runners/data'), express.static(rundir()));
app.use(getExpressPath('/files/data'), express.static(filesdir()));
if (platformInfo.isDocker) {
const port = process.env.PORT || 3000;
@@ -140,6 +150,10 @@ function start() {
const port = process.env.PORT || 3000;
logger.info(`DbGate API listening on port ${port} (AWS AMI build)`);
server.listen(port);
} else if (platformInfo.isAzureUbuntuLayout) {
const port = process.env.PORT || 3000;
logger.info(`DbGate API listening on port ${port} (Azure VM build)`);
server.listen(port);
} else if (platformInfo.isNpmDist) {
getPort({
port: parseInt(
-9
View File
@@ -1,9 +0,0 @@
// this file is generated automatically by script fillNativeModules.js, do not edit it manually
const content = {};
content['better-sqlite3'] = () => require('better-sqlite3');
content['oracledb'] = () => require('oracledb');
module.exports = content;
+2
View File
@@ -38,6 +38,8 @@ function start() {
detail: formatErrorDetail(e, connection),
});
}
process.exit(0);
});
}
@@ -427,7 +427,11 @@ function start() {
await handleMessage(message);
} catch (err) {
logger.error(extractErrorLogData(err), 'Error in DB connection');
process.send({ msgtype: 'error', error: extractErrorMessage(err, 'Error processing message') });
process.send({
msgtype: 'error',
error: extractErrorMessage(err, 'Error processing message'),
msgid: message?.msgid,
});
}
});
}
+43 -2
View File
@@ -245,7 +245,47 @@ async function handleStopProfiler({ jslid }) {
currentProfiler = null;
}
async function handleExecuteQuery({ sql }) {
async function handleExecuteControlCommand({ command }) {
lastActivity = new Date().getTime();
await waitConnected();
const driver = requireEngineDriver(storedConnection);
if (command == 'commitTransaction' && !allowExecuteCustomScript(driver)) {
process.send({
msgtype: 'info',
info: {
message: 'Connection without read-only sessions is read only',
severity: 'error',
},
});
process.send({ msgtype: 'done', skipFinishedMessage: true });
return;
//process.send({ msgtype: 'error', error: e.message });
}
executingScripts++;
try {
const dmp = driver.createDumper();
switch (command) {
case 'commitTransaction':
await dmp.commitTransaction();
break;
case 'rollbackTransaction':
await dmp.rollbackTransaction();
break;
case 'beginTransaction':
await dmp.beginTransaction();
break;
}
await driver.query(dbhan, dmp.s, { discardResult: true });
process.send({ msgtype: 'done', controlCommand: command });
} finally {
executingScripts--;
}
}
async function handleExecuteQuery({ sql, autoCommit }) {
lastActivity = new Date().getTime();
await waitConnected();
@@ -279,7 +319,7 @@ async function handleExecuteQuery({ sql }) {
// handler.stream = stream;
// resultIndex = handler.resultIndex;
}
process.send({ msgtype: 'done' });
process.send({ msgtype: 'done', autoCommit });
} finally {
executingScripts--;
}
@@ -323,6 +363,7 @@ function handlePing() {
const messageHandlers = {
connect: handleConnect,
executeQuery: handleExecuteQuery,
executeControlCommand: handleExecuteControlCommand,
executeReader: handleExecuteReader,
startProfiler: handleStartProfiler,
stopProfiler: handleStopProfiler,
+65 -30
View File
@@ -1,6 +1,27 @@
const EnsureStreamHeaderStream = require('../utility/EnsureStreamHeaderStream');
const Stream = require('stream');
const ColumnMapTransformStream = require('../utility/ColumnMapTransformStream');
const streamPipeline = require('../utility/streamPipeline');
const { getLogger, extractErrorLogData, RowProgressReporter, extractErrorMessage } = require('dbgate-tools');
const logger = getLogger('copyStream');
const stream = require('stream');
class ReportingTransform extends stream.Transform {
constructor(reporter, options = {}) {
super({ ...options, objectMode: true });
this.reporter = reporter;
}
_transform(chunk, encoding, callback) {
if (!chunk?.__isStreamHeader) {
this.reporter.add(1);
}
this.push(chunk);
callback();
}
_flush(callback) {
this.reporter.finish();
callback();
}
}
/**
* Copies reader to writer. Used for import, export tables and transfer data between tables
@@ -9,10 +30,23 @@ const ColumnMapTransformStream = require('../utility/ColumnMapTransformStream');
* @param {object} options - options
* @returns {Promise}
*/
function copyStream(input, output, options) {
const { columns } = options || {};
async function copyStream(input, output, options) {
const { columns, progressName } = options || {};
if (progressName) {
process.send({
msgtype: 'progress',
progressName,
status: 'running',
});
}
const transforms = [];
if (progressName) {
const reporter = new RowProgressReporter(progressName, 'readRowCount');
transforms.push(new ReportingTransform(reporter));
}
if (columns) {
transforms.push(new ColumnMapTransformStream(columns));
}
@@ -20,36 +54,37 @@ function copyStream(input, output, options) {
transforms.push(new EnsureStreamHeaderStream());
}
// return new Promise((resolve, reject) => {
// Stream.pipeline(input, ...transforms, output, err => {
// if (err) {
// reject(err);
// } else {
// resolve();
// }
// });
// });
try {
await streamPipeline(input, transforms, output);
return new Promise((resolve, reject) => {
const finisher = output['finisher'] || output;
finisher.on('finish', resolve);
finisher.on('error', reject);
let lastStream = input;
for (const tran of transforms) {
lastStream.pipe(tran);
lastStream = tran;
if (progressName) {
process.send({
msgtype: 'progress',
progressName,
status: 'done',
});
}
lastStream.pipe(output);
} catch (err) {
process.send({
msgtype: 'copyStreamError',
copyStreamError: {
message: extractErrorMessage(err),
...err,
},
});
// if (output.requireFixedStructure) {
// const ensureHeader = new EnsureStreamHeaderStream();
// input.pipe(ensureHeader);
// ensureHeader.pipe(output);
// } else {
// input.pipe(output);
// }
});
if (progressName) {
process.send({
msgtype: 'progress',
progressName,
status: 'error',
errorMessage: extractErrorMessage(err),
});
}
logger.error(extractErrorLogData(err, { progressName }), 'Import/export job failed');
// throw err;
}
}
module.exports = copyStream;
-2
View File
@@ -24,8 +24,6 @@ async function dataDuplicator({
const dbhan = systemConnection || (await connectUtility(driver, connection, 'write'));
try {
logger.info(`Connected.`);
if (!analysedStructure) {
analysedStructure = await driver.analyseFull(dbhan);
}
@@ -19,8 +19,6 @@ async function dropAllDbObjects({ connection, systemConnection, driver, analysed
const dbhan = systemConnection || (await connectUtility(driver, connection, 'write'));
logger.info(`Connected.`);
if (!analysedStructure) {
analysedStructure = await driver.analyseFull(dbhan);
}
-49
View File
@@ -1,49 +0,0 @@
const requireEngineDriver = require('../utility/requireEngineDriver');
const { connectUtility } = require('../utility/connectUtility');
const { getLogger } = require('dbgate-tools');
const logger = getLogger('dumpDb');
function doDump(dumper) {
return new Promise((resolve, reject) => {
dumper.once('end', () => {
resolve(true);
});
dumper.once('error', err => {
reject(err);
});
dumper.run();
});
}
async function dumpDatabase({
connection = undefined,
systemConnection = undefined,
driver = undefined,
outputFile,
databaseName,
schemaName,
}) {
logger.info(`Dumping database`);
if (!driver) driver = requireEngineDriver(connection);
const dbhan = systemConnection || (await connectUtility(driver, connection, 'read', { forceRowsAsObjects: true }));
try {
logger.info(`Connected.`);
const dumper = await driver.createBackupDumper(dbhan, {
outputFile,
databaseName,
schemaName,
});
await doDump(dumper);
} finally {
if (!systemConnection) {
await driver.close(dbhan);
}
}
}
module.exports = dumpDatabase;
+1 -1
View File
@@ -36,7 +36,7 @@ async function executeQuery({
}
try {
logger.info(`Connected.`);
logger.debug(`Running SQL query, length: ${sql.length}`);
await driver.script(dbhan, sql, { logScriptItems });
} finally {
+3 -16
View File
@@ -5,6 +5,7 @@ const { splitQueryStream } = require('dbgate-query-splitter/lib/splitQueryStream
const download = require('./download');
const stream = require('stream');
const { getLogger } = require('dbgate-tools');
const streamPipeline = require('../utility/streamPipeline');
const logger = getLogger('importDb');
@@ -43,25 +44,12 @@ class ImportStream extends stream.Transform {
}
}
function awaitStreamEnd(stream) {
return new Promise((resolve, reject) => {
stream.once('end', () => {
resolve(true);
});
stream.once('error', err => {
reject(err);
});
});
}
async function importDatabase({ connection = undefined, systemConnection = undefined, driver = undefined, inputFile }) {
logger.info(`Importing database`);
if (!driver) driver = requireEngineDriver(connection);
const dbhan = systemConnection || (await connectUtility(driver, connection, 'write'));
try {
logger.info(`Connected.`);
logger.info(`Input file: ${inputFile}`);
const downloadedFile = await download(inputFile);
logger.info(`Downloaded file: ${downloadedFile}`);
@@ -72,9 +60,8 @@ async function importDatabase({ connection = undefined, systemConnection = undef
returnRichInfo: true,
});
const importStream = new ImportStream(dbhan, driver);
// @ts-ignore
splittedStream.pipe(importStream);
await awaitStreamEnd(importStream);
await streamPipeline(splittedStream, importStream);
} finally {
if (!systemConnection) {
await driver.close(dbhan);
@@ -0,0 +1,125 @@
const path = require('path');
const fs = require('fs-extra');
const executeQuery = require('./executeQuery');
const { connectUtility } = require('../utility/connectUtility');
const requireEngineDriver = require('../utility/requireEngineDriver');
const { getAlterDatabaseScript, DatabaseAnalyser, runCommandOnDriver } = require('dbgate-tools');
const importDbModel = require('../utility/importDbModel');
const jsonLinesReader = require('./jsonLinesReader');
const tableWriter = require('./tableWriter');
const copyStream = require('./copyStream');
/**
* Deploys database model stored in modelFolder (table as yamls) to database
* @param {object} options
* @param {connectionType} options.connection - connection object
* @param {object} options.systemConnection - system connection (result of driver.connect). If not provided, new connection will be created
* @param {object} options.driver - driver object. If not provided, it will be loaded from connection
* @param {string} options.folder - folder with model files (YAML files for tables, SQL files for views, procedures, ...)
* @param {function[]} options.modelTransforms - array of functions for transforming model
*/
async function importDbFromFolder({ connection, systemConnection, driver, folder, modelTransforms }) {
if (!driver) driver = requireEngineDriver(connection);
const dbhan = systemConnection || (await connectUtility(driver, connection, 'read'));
try {
if (driver?.databaseEngineTypes?.includes('sql')) {
const model = await importDbModel(folder);
let modelAdapted = {
...model,
tables: model.tables.map(table => driver.adaptTableInfo(table)),
};
for (const transform of modelTransforms || []) {
modelAdapted = transform(modelAdapted);
}
const modelNoFk = {
...modelAdapted,
tables: modelAdapted.tables.map(table => ({
...table,
foreignKeys: [],
})),
};
// const plan = createAlterDatabasePlan(
// DatabaseAnalyser.createEmptyStructure(),
// driver.dialect.enableAllForeignKeys ? modelAdapted : modelNoFk,
// {},
// DatabaseAnalyser.createEmptyStructure(),
// driver.dialect.enableAllForeignKeys ? modelAdapted : modelNoFk,
// driver
// );
// const dmp1 = driver.createDumper({ useHardSeparator: true });
// if (driver.dialect.enableAllForeignKeys) {
// dmp1.enableAllForeignKeys(false);
// }
// plan.run(dmp1);
// if (driver.dialect.enableAllForeignKeys) {
// dmp1.enableAllForeignKeys(true);
// }
const { sql } = getAlterDatabaseScript(
DatabaseAnalyser.createEmptyStructure(),
driver.dialect.enableAllForeignKeys ? modelAdapted : modelNoFk,
{},
DatabaseAnalyser.createEmptyStructure(),
driver.dialect.enableAllForeignKeys ? modelAdapted : modelNoFk,
driver
);
// console.log('CREATING STRUCTURE:', sql);
await executeQuery({ connection, systemConnection: dbhan, driver, sql, logScriptItems: true });
if (driver.dialect.enableAllForeignKeys) {
await runCommandOnDriver(dbhan, driver, dmp => dmp.enableAllForeignKeys(false));
}
for (const table of modelAdapted.tables) {
const fileName = path.join(folder, `${table.pureName}.jsonl`);
if (await fs.exists(fileName)) {
const src = await jsonLinesReader({ fileName });
const dst = await tableWriter({
systemConnection: dbhan,
pureName: table.pureName,
driver,
targetTableStructure: table,
});
await copyStream(src, dst);
}
}
if (driver.dialect.enableAllForeignKeys) {
await runCommandOnDriver(dbhan, driver, dmp => dmp.enableAllForeignKeys(true));
} else if (driver.dialect.createForeignKey) {
const dmp = driver.createDumper();
for (const table of modelAdapted.tables) {
for (const fk of table.foreignKeys) {
dmp.createForeignKey(fk);
}
}
// create foreign keys
await executeQuery({ connection, systemConnection: dbhan, driver, sql: dmp.s, logScriptItems: true });
}
} else if (driver?.databaseEngineTypes?.includes('document')) {
for (const file of fs.readdirSync(folder)) {
if (!file.endsWith('.jsonl')) continue;
const pureName = path.parse(file).name;
const src = await jsonLinesReader({ fileName: path.join(folder, file) });
const dst = await tableWriter({
systemConnection: dbhan,
pureName,
driver,
createIfNotExists: true,
});
await copyStream(src, dst);
}
}
} finally {
if (!systemConnection) {
await driver.close(dbhan);
}
}
}
module.exports = importDbFromFolder;
+2 -2
View File
@@ -21,7 +21,6 @@ const executeQuery = require('./executeQuery');
const loadFile = require('./loadFile');
const deployDb = require('./deployDb');
const initializeApiEnvironment = require('./initializeApiEnvironment');
const dumpDatabase = require('./dumpDatabase');
const importDatabase = require('./importDatabase');
const loadDatabase = require('./loadDatabase');
const generateModelSql = require('./generateModelSql');
@@ -35,6 +34,7 @@ const sqlTextReplacementTransform = require('./sqlTextReplacementTransform');
const autoIndexForeignKeysTransform = require('./autoIndexForeignKeysTransform');
const generateDeploySql = require('./generateDeploySql');
const dropAllDbObjects = require('./dropAllDbObjects');
const importDbFromFolder = require('./importDbFromFolder');
const dbgateApi = {
queryReader,
@@ -60,7 +60,6 @@ const dbgateApi = {
loadFile,
deployDb,
initializeApiEnvironment,
dumpDatabase,
importDatabase,
loadDatabase,
generateModelSql,
@@ -73,6 +72,7 @@ const dbgateApi = {
autoIndexForeignKeysTransform,
generateDeploySql,
dropAllDbObjects,
importDbFromFolder,
};
requirePlugin.initializeDbgateApi(dbgateApi);
+1 -2
View File
@@ -53,8 +53,7 @@ async function jsonLinesReader({ fileName, encoding = 'utf-8', limitRows = undef
);
const liner = byline(fileStream);
const parser = new ParseStream({ limitRows });
liner.pipe(parser);
return parser;
return [liner, parser];
}
module.exports = jsonLinesReader;
+16 -8
View File
@@ -10,7 +10,6 @@ const download = require('./download');
const logger = getLogger('jsonReader');
class ParseStream extends stream.Transform {
constructor({ limitRows, jsonStyle, keyField }) {
super({ objectMode: true });
@@ -72,8 +71,12 @@ async function jsonReader({
// @ts-ignore
encoding
);
const parseJsonStream = parser();
fileStream.pipe(parseJsonStream);
const resultPipe = [fileStream, parseJsonStream];
// fileStream.pipe(parseJsonStream);
const parseStream = new ParseStream({ limitRows, jsonStyle, keyField });
@@ -81,15 +84,20 @@ async function jsonReader({
if (rootField) {
const filterStream = pick({ filter: rootField });
parseJsonStream.pipe(filterStream);
filterStream.pipe(tramsformer);
} else {
parseJsonStream.pipe(tramsformer);
resultPipe.push(filterStream);
// parseJsonStream.pipe(filterStream);
// filterStream.pipe(tramsformer);
}
// else {
// parseJsonStream.pipe(tramsformer);
// }
tramsformer.pipe(parseStream);
resultPipe.push(tramsformer);
resultPipe.push(parseStream);
return parseStream;
// tramsformer.pipe(parseStream);
return resultPipe;
}
module.exports = jsonReader;
+4 -3
View File
@@ -99,9 +99,10 @@ async function jsonWriter({ fileName, jsonStyle, keyField = '_key', rootField, e
logger.info(`Writing file ${fileName}`);
const stringify = new StringifyStream({ jsonStyle, keyField, rootField });
const fileStream = fs.createWriteStream(fileName, encoding);
stringify.pipe(fileStream);
stringify['finisher'] = fileStream;
return stringify;
return [stringify, fileStream];
// stringify.pipe(fileStream);
// stringify['finisher'] = fileStream;
// return stringify;
}
module.exports = jsonWriter;
+2 -4
View File
@@ -6,15 +6,13 @@ const exportDbModel = require('../utility/exportDbModel');
const logger = getLogger('analyseDb');
async function loadDatabase({ connection = undefined, systemConnection = undefined, driver = undefined, outputDir }) {
logger.info(`Analysing database`);
logger.debug(`Analysing database`);
if (!driver) driver = requireEngineDriver(connection);
const dbhan = systemConnection || (await connectUtility(driver, connection, 'read', { forceRowsAsObjects: true }));
try {
logger.info(`Connected.`);
const dbInfo = await driver.analyseFull(dbhan);
logger.info(`Analyse finished`);
logger.debug(`Analyse finished`);
await exportDbModel(dbInfo, outputDir);
} finally {
@@ -141,8 +141,9 @@ async function modifyJsonLinesReader({
);
const liner = byline(fileStream);
const parser = new ParseStream({ limitRows, changeSet, mergedRows, mergeKey, mergeMode });
liner.pipe(parser);
return parser;
return [liner, parser];
// liner.pipe(parser);
// return parser;
}
module.exports = modifyJsonLinesReader;
-1
View File
@@ -30,7 +30,6 @@ async function queryReader({
const driver = requireEngineDriver(connection);
const pool = await connectUtility(driver, connection, queryType == 'json' ? 'read' : 'script');
logger.info(`Connected.`);
const reader =
queryType == 'json' ? await driver.readJsonQuery(pool, query) : await driver.readQuery(pool, query || sql);
return reader;
+4 -3
View File
@@ -44,9 +44,10 @@ async function sqlDataWriter({ fileName, dataName, driver, encoding = 'utf-8' })
logger.info(`Writing file ${fileName}`);
const stringify = new SqlizeStream({ fileName, dataName });
const fileStream = fs.createWriteStream(fileName, encoding);
stringify.pipe(fileStream);
stringify['finisher'] = fileStream;
return stringify;
return [stringify, fileStream];
// stringify.pipe(fileStream);
// stringify['finisher'] = fileStream;
// return stringify;
}
module.exports = sqlDataWriter;
-1
View File
@@ -18,7 +18,6 @@ async function tableReader({ connection, systemConnection, pureName, schemaName,
driver = requireEngineDriver(connection);
}
const dbhan = systemConnection || (await connectUtility(driver, connection, 'read'));
logger.info(`Connected.`);
const fullName = { pureName, schemaName };
+16 -2
View File
@@ -15,6 +15,8 @@ const logger = getLogger('tableWriter');
* @param {boolean} options.truncate - truncate table before insert
* @param {boolean} options.createIfNotExists - create table if not exists
* @param {boolean} options.commitAfterInsert - commit transaction after insert
* @param {string} options.progressName - name for reporting progress
* @param {any} options.targetTableStructure - target table structure (don't analyse if given)
* @returns {Promise<writerType>} - writer object
*/
async function tableWriter({ connection, schemaName, pureName, driver, systemConnection, ...options }) {
@@ -25,8 +27,20 @@ async function tableWriter({ connection, schemaName, pureName, driver, systemCon
}
const dbhan = systemConnection || (await connectUtility(driver, connection, 'write'));
logger.info(`Connected.`);
return await driver.writeTable(dbhan, { schemaName, pureName }, options);
try {
return await driver.writeTable(dbhan, { schemaName, pureName }, options);
} catch (err) {
if (options.progressName) {
process.send({
msgtype: 'progress',
progressName: options.progressName,
status: 'error',
errorMessage: err.message,
});
}
throw err;
}
}
module.exports = tableWriter;
+3
View File
@@ -88,6 +88,9 @@ function decryptConnection(connection) {
}
function pickSafeConnectionInfo(connection) {
if (process.env.LOG_CONNECTION_SENSITIVE_VALUES) {
return connection;
}
return _.mapValues(connection, (v, k) => {
if (k == 'engine' || k == 'port' || k == 'authType' || k == 'sshMode' || k == 'passwordMode') return v;
if (v === null || v === true || v === false) return v;
+3
View File
@@ -82,6 +82,9 @@ function packagedPluginsDir() {
if (platformInfo.isAwsUbuntuLayout) {
return '/home/ubuntu/build/plugins';
}
if (platformInfo.isAzureUbuntuLayout) {
return '/home/azureuser/build/plugins';
}
if (platformInfo.isNpmDist) {
// node_modules
return global['PLUGINS_DIR'];
+43 -2
View File
@@ -1,4 +1,11 @@
const getDiagramExport = (html, css, themeType, themeClassName) => {
const getDiagramExport = (html, css, themeType, themeClassName, watermark) => {
const watermarkHtml = watermark
? `
<div style="position: fixed; bottom: 0; right: 0; padding: 5px; font-size: 12px; color: var(--theme-font-2); background-color: var(--theme-bg-2); border-top-left-radius: 5px; border: 1px solid var(--theme-border);">
${watermark}
</div>
`
: '';
return `<html>
<meta charset='utf-8'>
@@ -13,10 +20,44 @@ const getDiagramExport = (html, css, themeType, themeClassName) => {
</style>
<link rel="stylesheet" href='https://cdn.jsdelivr.net/npm/@mdi/font@6.5.95/css/materialdesignicons.css' />
<script>
let lastX = null;
let lastY = null;
const handleMoveDown = e => {
lastX = e.clientX;
lastY = e.clientY;
document.addEventListener('mousemove', handleMoveMove, true);
document.addEventListener('mouseup', handleMoveEnd, true);
};
const handleMoveMove = e => {
e.preventDefault();
document.body.scrollLeft -= e.clientX - lastX;
document.body.scrollTop -= e.clientY - lastY;
lastX = e.clientX;
lastY = e.clientY;
};
const handleMoveEnd = e => {
e.preventDefault();
e.stopPropagation();
lastX = null;
lastY = null;
document.removeEventListener('mousemove', handleMoveMove, true);
document.removeEventListener('mouseup', handleMoveEnd, true);
};
document.addEventListener('mousedown', handleMoveDown);
</script>
</head>
<body class='${themeType == 'dark' ? 'theme-type-dark' : 'theme-type-light'} ${themeClassName}'>
<body class='${themeType == 'dark' ? 'theme-type-dark' : 'theme-type-light'} ${themeClassName}' style='user-select:none; cursor:pointer'>
${html}
${watermarkHtml}
</body>
</html>`;
@@ -73,6 +73,7 @@ async function getPublicHardwareFingerprint() {
region: fingerprint.region,
isDocker: platformInfo.isDocker,
isAwsUbuntuLayout: platformInfo.isAwsUbuntuLayout,
isAzureUbuntuLayout: platformInfo.isAzureUbuntuLayout,
isElectron: platformInfo.isElectron,
},
};

Some files were not shown because too many files have changed in this diff Show More