├── . cursorrules ├── .editorconfig ├── .eslintignore ├── .eslintrc.cjs ├── .github └── workflows │ └── release.yaml ├── .gitignore ├── .prettierignore ├── .prettierrc.yaml ├── .vscode ├── extensions.json ├── launch.json └── settings.json ├── LICENSE ├── README.md ├── build ├── entitlements.mac.plist ├── icon.icns ├── icon.ico └── icon.png ├── dev-app-update.yml ├── electron-builder.yml ├── electron.vite.config.ts ├── package.json ├── resources ├── icon.png ├── mysql │ └── mac │ │ └── 8 │ │ └── bin │ │ ├── mysql │ │ └── mysqldump └── postgres │ ├── mac │ └── 17 │ │ ├── bin │ │ ├── createdb │ │ ├── createuser │ │ ├── pg_dump │ │ └── pg_restore │ │ └── lib │ │ ├── libcom_err.3.0.dylib │ │ ├── libcom_err.3.dylib │ │ ├── libcom_err.dylib │ │ ├── libcrypto.3.dylib │ │ ├── libcrypto.dylib │ │ ├── libecpg.6.dylib │ │ ├── libecpg.a │ │ ├── libecpg.dylib │ │ ├── libecpg_compat.3.dylib │ │ ├── libecpg_compat.a │ │ ├── libecpg_compat.dylib │ │ ├── libedit.0.dylib │ │ ├── libedit.dylib │ │ ├── libgssapi_krb5.2.2.dylib │ │ ├── libgssapi_krb5.2.dylib │ │ ├── libgssapi_krb5.dylib │ │ ├── libgssrpc.4.2.dylib │ │ ├── libgssrpc.4.dylib │ │ ├── libgssrpc.dylib │ │ ├── libiconv.2.dylib │ │ ├── libiconv.dylib │ │ ├── libicui18n.68.2.dylib │ │ ├── libicui18n.68.dylib │ │ ├── libicui18n.dylib │ │ ├── libicuuc.68.2.dylib │ │ ├── libicuuc.68.dylib │ │ ├── libicuuc.dylib │ │ ├── libintl.8.dylib │ │ ├── libintl.dylib │ │ ├── libk5crypto.3.1.dylib │ │ ├── libk5crypto.3.dylib │ │ ├── libk5crypto.dylib │ │ ├── libkrb5.3.3.dylib │ │ ├── libkrb5.3.dylib │ │ ├── libkrb5.dylib │ │ ├── libkrb5support.1.1.dylib │ │ ├── libkrb5support.1.dylib │ │ ├── libkrb5support.dylib │ │ ├── liblz4.1.10.0.dylib │ │ ├── liblz4.1.dylib │ │ ├── liblz4.dylib │ │ ├── libpgcommon.a │ │ ├── libpgcommon_shlib.a │ │ ├── libpgfeutils.a │ │ ├── libpgport.a │ │ ├── libpgport_shlib.a │ │ ├── libpgtypes.3.dylib │ │ ├── libpgtypes.a │ │ ├── libpgtypes.dylib │ │ ├── libpq.5.dylib │ │ ├── libpq.a │ │ ├── libpq.dylib │ │ ├── libssl.3.dylib │ │ ├── libssl.dylib │ │ ├── libuuid.1.1.dylib │ │ ├── libxml2.2.dylib │ │ ├── libxml2.dylib │ │ ├── libxslt.1.dylib │ │ ├── libxslt.dylib │ │ ├── libz.1.3.1.dylib │ │ ├── libz.1.dylib │ │ ├── libz.dylib │ │ ├── libzstd.1.5.6.dylib │ │ ├── libzstd.1.dylib │ │ ├── libzstd.dylib │ │ └── pkgconfig │ │ ├── libecpg.pc │ │ ├── libecpg_compat.pc │ │ ├── libpgtypes.pc │ │ └── libpq.pc │ └── win │ └── 16 │ ├── createdb.exe │ ├── libcrypto-3-x64.dll │ ├── libcurl.dll │ ├── libcurl.lib │ ├── libecpg.dll │ ├── libecpg_compat.dll │ ├── libiconv-2.dll │ ├── libintl-9.dll │ ├── liblz4.dll │ ├── libpgtypes.dll │ ├── libpq.dll │ ├── libssl-3-x64.dll │ ├── libwinpthread-1.dll │ ├── libxml2.dll │ ├── libxslt.dll │ ├── libzstd.dll │ ├── pg_dump.exe │ ├── pg_restore.exe │ └── zlib1.dll ├── screenshot ├── 1.jpg ├── 2.jpg ├── 3.jpg ├── 4.jpg ├── 5.jpg ├── 6.jpg └── 7.jpg ├── src ├── main │ ├── index.ts │ ├── menuTemplate.ts │ └── updater.ts ├── preload │ ├── index.d.ts │ └── index.ts ├── renderer │ ├── index.html │ └── src │ │ ├── App.tsx │ │ ├── assets │ │ ├── base.css │ │ ├── icons │ │ │ └── icon.tsx │ │ └── main.css │ │ ├── components │ │ ├── AddColumnForm.tsx │ │ ├── AddIndexForm.tsx │ │ ├── AddRoleForm.tsx │ │ ├── AddRowForm.tsx │ │ ├── AddSchemaForm.tsx │ │ ├── ConnectionForm.tsx │ │ ├── ConnectionItem.tsx │ │ ├── CreateDbFrom.tsx │ │ ├── CreateMysqlDbForm.tsx │ │ ├── CreateTableForm.tsx │ │ ├── DdlSql.tsx │ │ ├── EditIndex.tsx │ │ ├── EditRolePermission.tsx │ │ ├── EditTable.tsx │ │ ├── Layout.tsx │ │ ├── List.tsx │ │ ├── TabelContent.tsx │ │ └── Versions.tsx │ │ ├── env.d.ts │ │ ├── interface │ │ └── index.ts │ │ ├── main.tsx │ │ └── utils │ │ ├── constant.ts │ │ ├── context.ts │ │ └── logHelper.ts └── server │ ├── common.ts │ ├── db.ts │ ├── index.ts │ ├── lib │ ├── connectionJson.ts │ ├── excel.ts │ └── storageHelper.ts │ ├── mysql.ts │ └── postgres.ts ├── tsconfig.json ├── tsconfig.node.json └── tsconfig.web.json /. cursorrules: -------------------------------------------------------------------------------- 1 | # 项目背景 2 | - 这个一个支持postgres,mysql 跨平台的桌面工具, 基于electron + nodejs + typescript + react + antd + vite 开发 3 | 4 | 5 | 6 | # 文件结构 7 | - src/server/db.ts 是数据库查询的逻辑, 然后根据数据库类型, 执行不同的数据库逻辑 8 | - src/server/mysql.ts 是mysql 的查询逻辑 9 | - src/server/postgres.ts 是postgres 的查询逻辑 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | out 4 | .gitignore 5 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | 'eslint:recommended', 4 | 'plugin:react/recommended', 5 | 'plugin:react/jsx-runtime', 6 | '@electron-toolkit/eslint-config-ts/recommended', 7 | '@electron-toolkit/eslint-config-prettier' 8 | ], 9 | rules: { 10 | '@typescript-eslint/explicit-function-return-type': 'off' 11 | }, 12 | settings: { 13 | 'import/resolver': { 14 | typescript: { 15 | project: ['./tsconfig.web.json', './tsconfig.node.json'] 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Build and Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | 8 | jobs: 9 | build: 10 | runs-on: ${{ matrix.os }} 11 | 12 | strategy: 13 | matrix: 14 | os: [macos-13, windows-2019, macos-14, macos-latest, windows-latest] 15 | 16 | steps: 17 | - name: Checkout repository 18 | uses: actions/checkout@v4 19 | 20 | - name: Set up Node.js 21 | uses: actions/setup-node@v2 22 | with: 23 | node-version: 20.x 24 | 25 | - name: Install dependencies 26 | run: npm install 27 | - name: macos 28 | if: startsWith(matrix.os, 'macos') 29 | run: npm run build:mac 30 | - name: win 31 | if: startsWith(matrix.os, 'win') 32 | run: npm run build:win 33 | - name: Cleanup Artifacts for Windows 34 | if: startsWith(matrix.os, 'win') 35 | run: | 36 | npx del-cli "dist/*" "!dist/*.exe" "!dist/*.zip" "!dist/*.yml" 37 | 38 | - name: Cleanup Artifacts for MacOS 39 | if: startsWith(matrix.os, 'macos') 40 | run: | 41 | npx del-cli "dist/*" "!dist/(*.dmg|*.zip|latest*.yml)" 42 | 43 | - name: Display structure of downloaded files 44 | run: | 45 | ls dist 46 | echo "github.ref is ${{ github.ref }}" 47 | echo "github.ref_name is ${{ github.ref_name }}" 48 | echo "Tag name from GITHUB_REF_NAME: $GITHUB_REF_NAME" 49 | 50 | - name: Archive production artifacts 51 | uses: actions/upload-artifact@v4 52 | with: 53 | name: ${{ matrix.os }} 54 | path: dist 55 | 56 | - name: Release 57 | uses: softprops/action-gh-release@v2 58 | if: startsWith(github.ref, 'refs/tags/') 59 | with: 60 | files: 'dist/**' 61 | env: 62 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 63 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | out 4 | .DS_Store 5 | *.log* 6 | test 7 | *.sql 8 | package-lock.json 9 | tsconfig.*.tsbuildinfo -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | out 2 | dist 3 | pnpm-lock.yaml 4 | LICENSE.md 5 | tsconfig.json 6 | tsconfig.*.json 7 | -------------------------------------------------------------------------------- /.prettierrc.yaml: -------------------------------------------------------------------------------- 1 | singleQuote: true 2 | semi: false 3 | printWidth: 100 4 | trailingComma: none 5 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["dbaeumer.vscode-eslint"] 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Debug Main Process", 6 | "type": "node", 7 | "request": "launch", 8 | "cwd": "${workspaceRoot}", 9 | "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-vite", 10 | "windows": { 11 | "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-vite.cmd" 12 | }, 13 | "runtimeArgs": ["--sourcemap"], 14 | "env": { 15 | "REMOTE_DEBUGGING_PORT": "9222" 16 | } 17 | }, 18 | { 19 | "name": "Debug Renderer Process", 20 | "port": 9222, 21 | "request": "attach", 22 | "type": "chrome", 23 | "webRoot": "${workspaceFolder}/src/renderer", 24 | "timeout": 60000, 25 | "presentation": { 26 | "hidden": true 27 | } 28 | } 29 | ], 30 | "compounds": [ 31 | { 32 | "name": "Debug All", 33 | "configurations": ["Debug Main Process", "Debug Renderer Process"], 34 | "presentation": { 35 | "order": 1 36 | } 37 | } 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "[typescript]": { 3 | "editor.defaultFormatter": "esbenp.prettier-vscode" 4 | }, 5 | "[javascript]": { 6 | "editor.defaultFormatter": "esbenp.prettier-vscode" 7 | }, 8 | "[json]": { 9 | "editor.defaultFormatter": "esbenp.prettier-vscode" 10 | }, 11 | "editor.formatOnSave": true 12 | } 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DBA 2 | 3 | Hello, welcome to my newly released open-source PostgreSQL/Mysql desktop tool! This tool is currently available for both macOS and Windows, offering developers and database administrators a simple yet efficient way to manage PostgreSQL databases. 4 | 5 | Our goal is to create a powerful and user-friendly tool that helps you handle data more easily and boosts your productivity. As the project is still in continuous development and optimization, your feedback and suggestions are incredibly valuable to us. If you encounter any issues or have ideas for feature improvements, performance enhancements, or any other aspect, feel free to raise an issue or contribute on GitHub. 6 | 7 | With everyone’s collective effort, we hope to make this tool an even more complete and robust solution. We truly look forward to your participation and support! 8 | 9 | 10 | ## Features 11 | - Cross platform 12 | - Database Editing 13 | - Database backup and recovery 14 | - Support dark color mode 15 | - Excel data export 16 | - Role permission management 17 | - Common SQL Management 18 | 19 | ## Download 20 | 21 | You can download prebuilt binaries from GitHub releases. 22 | 23 | 24 | ## Screenshot 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | ## Build from sources 34 | 35 | ### Install 36 | 37 | ```bash 38 | $ npm install 39 | ``` 40 | 41 | ### Development 42 | 43 | ```bash 44 | $ npm run dev 45 | ``` 46 | 47 | ### Build 48 | 49 | ```bash 50 | # For windows 51 | $ npm run build:win 52 | 53 | # For macOS 54 | $ npm run build:mac 55 | 56 | ``` 57 | -------------------------------------------------------------------------------- /build/entitlements.mac.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.cs.allow-jit 6 | 7 | com.apple.security.cs.allow-unsigned-executable-memory 8 | 9 | com.apple.security.cs.allow-dyld-environment-variables 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /build/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/build/icon.icns -------------------------------------------------------------------------------- /build/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/build/icon.ico -------------------------------------------------------------------------------- /build/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/build/icon.png -------------------------------------------------------------------------------- /dev-app-update.yml: -------------------------------------------------------------------------------- 1 | provider: generic 2 | url: https://example.com/auto-updates 3 | updaterCacheDirName: electron-app-updater 4 | -------------------------------------------------------------------------------- /electron-builder.yml: -------------------------------------------------------------------------------- 1 | appId: com.electron.app 2 | productName: DBA 3 | directories: 4 | buildResources: build 5 | files: 6 | - '**/*' 7 | - '!**/.vscode/*' 8 | - '!src/*' 9 | - '!electron.vite.config.{js,ts,mjs,cjs}' 10 | - '!{.eslintignore,.eslintrc.cjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}' 11 | - '!{.env,.env.*,.npmrc,pnpm-lock.yaml}' 12 | - '!{tsconfig.json,tsconfig.node.json,tsconfig.web.json}' 13 | - '!screenshot/*' 14 | asarUnpack: 15 | - resources/** 16 | win: 17 | executableName: DBA 18 | nsis: 19 | artifactName: ${name}-${version}-setup.${ext} 20 | shortcutName: ${productName} 21 | uninstallDisplayName: ${productName} 22 | createDesktopShortcut: always 23 | mac: 24 | entitlementsInherit: build/entitlements.mac.plist 25 | extendInfo: 26 | - NSCameraUsageDescription: Application requests access to the device's camera. 27 | - NSMicrophoneUsageDescription: Application requests access to the device's microphone. 28 | - NSDocumentsFolderUsageDescription: Application requests access to the user's Documents folder. 29 | - NSDownloadsFolderUsageDescription: Application requests access to the user's Downloads folder. 30 | notarize: false 31 | dmg: 32 | artifactName: ${name}-${version}-${arch}.${ext} 33 | linux: 34 | target: 35 | - AppImage 36 | - snap 37 | - deb 38 | maintainer: electronjs.org 39 | category: Utility 40 | appImage: 41 | artifactName: ${name}-${version}.${ext} 42 | npmRebuild: false 43 | publish: 44 | provider: github 45 | owner: underway2014 46 | repo: DBA 47 | -------------------------------------------------------------------------------- /electron.vite.config.ts: -------------------------------------------------------------------------------- 1 | import { resolve } from 'path' 2 | import { defineConfig, externalizeDepsPlugin } from 'electron-vite' 3 | import react from '@vitejs/plugin-react' 4 | 5 | export default defineConfig({ 6 | main: { 7 | plugins: [externalizeDepsPlugin()] //{ exclude: ['execa'] } 8 | }, 9 | preload: { 10 | plugins: [externalizeDepsPlugin()] 11 | }, 12 | renderer: { 13 | resolve: { 14 | alias: { 15 | '@renderer': resolve('src/renderer/src') 16 | } 17 | }, 18 | plugins: [react()] 19 | } 20 | }) 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "DBA", 3 | "version": "0.5.5", 4 | "description": "A PostgreSQL tool", 5 | "main": "./out/main/index.js", 6 | "author": "viki", 7 | "homepage": "https://github.com/underway2014/dba", 8 | "scripts": { 9 | "format": "prettier --write .", 10 | "lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix", 11 | "typecheck:node": "tsc --noEmit -p tsconfig.node.json --composite false", 12 | "typecheck:web": "tsc --noEmit -p tsconfig.web.json --composite false", 13 | "typecheck": "npm run typecheck:node && npm run typecheck:web", 14 | "start": "electron-vite preview", 15 | "dev": "electron-vite dev", 16 | "build": "electron-vite build", 17 | "build-origin": "npm run typecheck && electron-vite build", 18 | "postinstall": "electron-builder install-app-deps", 19 | "build:unpack": "npm run build && electron-builder --dir", 20 | "build:win": "npm run build && electron-builder --win --config --publish never", 21 | "build:mac": "electron-vite build && electron-builder --mac --config --publish never", 22 | "build:linux": "electron-vite build && electron-builder --linux" 23 | }, 24 | "dependencies": { 25 | "@electron-toolkit/preload": "^3.0.0", 26 | "@electron-toolkit/utils": "^3.0.0", 27 | "@electron/remote": "^2.1.2", 28 | "@koa/router": "^12.0.1", 29 | "@types/koa": "^2.15.0", 30 | "antd": "^5.21.0", 31 | "axios": "^1.7.2", 32 | "dayjs": "^1.11.13", 33 | "electron-store": "^10.0.0", 34 | "electron-updater": "^6.1.7", 35 | "exceljs": "^4.4.0", 36 | "execa": "^9.4.0", 37 | "koa": "^2.15.3", 38 | "koa-bodyparser": "^4.4.1", 39 | "lodash": "^4.17.21", 40 | "moment": "^2.30.1", 41 | "mysql2": "^3.11.3", 42 | "pg": "^8.12.0", 43 | "pg-hstore": "^2.3.4", 44 | "react-highlight-within-textarea": "^3.2.2", 45 | "sequelize": "^6.37.3", 46 | "sql-formatter": "^15.4.11", 47 | "zx": "^8.1.4" 48 | }, 49 | "devDependencies": { 50 | "@electron-toolkit/eslint-config-prettier": "^2.0.0", 51 | "@electron-toolkit/eslint-config-ts": "^1.0.1", 52 | "@electron-toolkit/tsconfig": "^1.0.1", 53 | "@types/koa__router": "^12.0.4", 54 | "@types/node": "^18.19.9", 55 | "@types/react": "^18.2.48", 56 | "@types/react-dom": "^18.2.18", 57 | "@vitejs/plugin-react": "^4.2.1", 58 | "del-cli": "^5.1.0", 59 | "electron": "^28.2.0", 60 | "electron-builder": "^24.9.1", 61 | "electron-vite": "^2.0.0", 62 | "eslint": "^8.56.0", 63 | "eslint-import-resolver-typescript": "^3.6.1", 64 | "eslint-plugin-react": "^7.33.2", 65 | "npx": "^10.2.2", 66 | "prettier": "^3.2.4", 67 | "react": "^18.2.0", 68 | "react-dom": "^18.2.0", 69 | "typescript": "^5.3.3", 70 | "vite": "^5.0.12" 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/icon.png -------------------------------------------------------------------------------- /resources/mysql/mac/8/bin/mysql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/mysql/mac/8/bin/mysql -------------------------------------------------------------------------------- /resources/mysql/mac/8/bin/mysqldump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/mysql/mac/8/bin/mysqldump -------------------------------------------------------------------------------- /resources/postgres/mac/17/bin/createdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/bin/createdb -------------------------------------------------------------------------------- /resources/postgres/mac/17/bin/createuser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/bin/createuser -------------------------------------------------------------------------------- /resources/postgres/mac/17/bin/pg_dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/bin/pg_dump -------------------------------------------------------------------------------- /resources/postgres/mac/17/bin/pg_restore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/bin/pg_restore -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libcom_err.3.0.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libcom_err.3.0.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libcom_err.3.dylib: -------------------------------------------------------------------------------- 1 | libcom_err.3.0.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libcom_err.dylib: -------------------------------------------------------------------------------- 1 | libcom_err.3.0.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libcrypto.3.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libcrypto.3.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libcrypto.dylib: -------------------------------------------------------------------------------- 1 | libcrypto.3.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libecpg.6.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libecpg.6.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libecpg.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libecpg.a -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libecpg.dylib: -------------------------------------------------------------------------------- 1 | libecpg.6.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libecpg_compat.3.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libecpg_compat.3.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libecpg_compat.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libecpg_compat.a -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libecpg_compat.dylib: -------------------------------------------------------------------------------- 1 | libecpg_compat.3.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libedit.0.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libedit.0.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libedit.dylib: -------------------------------------------------------------------------------- 1 | libedit.0.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libgssapi_krb5.2.2.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libgssapi_krb5.2.2.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libgssapi_krb5.2.dylib: -------------------------------------------------------------------------------- 1 | libgssapi_krb5.2.2.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libgssapi_krb5.dylib: -------------------------------------------------------------------------------- 1 | libgssapi_krb5.2.2.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libgssrpc.4.2.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libgssrpc.4.2.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libgssrpc.4.dylib: -------------------------------------------------------------------------------- 1 | libgssrpc.4.2.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libgssrpc.dylib: -------------------------------------------------------------------------------- 1 | libgssrpc.4.2.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libiconv.2.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libiconv.2.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libiconv.dylib: -------------------------------------------------------------------------------- 1 | libiconv.2.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libicui18n.68.2.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libicui18n.68.2.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libicui18n.68.dylib: -------------------------------------------------------------------------------- 1 | libicui18n.68.2.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libicui18n.dylib: -------------------------------------------------------------------------------- 1 | libicui18n.68.2.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libicuuc.68.2.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libicuuc.68.2.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libicuuc.68.dylib: -------------------------------------------------------------------------------- 1 | libicuuc.68.2.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libicuuc.dylib: -------------------------------------------------------------------------------- 1 | libicuuc.68.2.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libintl.8.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libintl.8.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libintl.dylib: -------------------------------------------------------------------------------- 1 | libintl.8.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libk5crypto.3.1.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libk5crypto.3.1.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libk5crypto.3.dylib: -------------------------------------------------------------------------------- 1 | libk5crypto.3.1.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libk5crypto.dylib: -------------------------------------------------------------------------------- 1 | libk5crypto.3.1.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libkrb5.3.3.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libkrb5.3.3.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libkrb5.3.dylib: -------------------------------------------------------------------------------- 1 | libkrb5.3.3.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libkrb5.dylib: -------------------------------------------------------------------------------- 1 | libkrb5.3.3.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libkrb5support.1.1.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libkrb5support.1.1.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libkrb5support.1.dylib: -------------------------------------------------------------------------------- 1 | libkrb5support.1.1.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libkrb5support.dylib: -------------------------------------------------------------------------------- 1 | libkrb5support.1.1.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/liblz4.1.10.0.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/liblz4.1.10.0.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/liblz4.1.dylib: -------------------------------------------------------------------------------- 1 | liblz4.1.10.0.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/liblz4.dylib: -------------------------------------------------------------------------------- 1 | liblz4.1.10.0.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libpgcommon.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libpgcommon.a -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libpgcommon_shlib.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libpgcommon_shlib.a -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libpgfeutils.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libpgfeutils.a -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libpgport.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libpgport.a -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libpgport_shlib.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libpgport_shlib.a -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libpgtypes.3.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libpgtypes.3.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libpgtypes.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libpgtypes.a -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libpgtypes.dylib: -------------------------------------------------------------------------------- 1 | libpgtypes.3.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libpq.5.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libpq.5.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libpq.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libpq.a -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libpq.dylib: -------------------------------------------------------------------------------- 1 | libpq.5.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libssl.3.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libssl.3.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libssl.dylib: -------------------------------------------------------------------------------- 1 | libssl.3.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libuuid.1.1.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libuuid.1.1.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libxml2.2.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libxml2.2.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libxml2.dylib: -------------------------------------------------------------------------------- 1 | libxml2.2.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libxslt.1.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libxslt.1.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libxslt.dylib: -------------------------------------------------------------------------------- 1 | libxslt.1.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libz.1.3.1.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libz.1.3.1.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libz.1.dylib: -------------------------------------------------------------------------------- 1 | libz.1.3.1.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libz.dylib: -------------------------------------------------------------------------------- 1 | libz.1.3.1.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libzstd.1.5.6.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/mac/17/lib/libzstd.1.5.6.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libzstd.1.dylib: -------------------------------------------------------------------------------- 1 | libzstd.1.5.6.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/libzstd.dylib: -------------------------------------------------------------------------------- 1 | libzstd.1.5.6.dylib -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/pkgconfig/libecpg.pc: -------------------------------------------------------------------------------- 1 | prefix=/opt/pginstaller_17.auto/server/staging_cache/osx.build 2 | exec_prefix=${prefix} 3 | libdir=${exec_prefix}/lib 4 | includedir=${prefix}/include 5 | 6 | Name: libecpg 7 | Description: PostgreSQL libecpg library 8 | URL: https://www.postgresql.org/ 9 | Version: 17.0 10 | Requires: 11 | Requires.private: libpq, libpgtypes 12 | Cflags: -I/Library/PostgreSQL/17/includedir} 13 | Libs: -L/Library/PostgreSQL/17/libdir} -lecpg 14 | Libs.private: -L/opt/local/20240903/lib -L/opt/local/Current_v15/lib -lpgcommon -lpgport -lpq -lm 15 | -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/pkgconfig/libecpg_compat.pc: -------------------------------------------------------------------------------- 1 | prefix=/opt/pginstaller_17.auto/server/staging_cache/osx.build 2 | exec_prefix=${prefix} 3 | libdir=${exec_prefix}/lib 4 | includedir=${prefix}/include 5 | 6 | Name: libecpg_compat 7 | Description: PostgreSQL libecpg_compat library 8 | URL: https://www.postgresql.org/ 9 | Version: 17.0 10 | Requires: 11 | Requires.private: libecpg, libpgtypes 12 | Cflags: -I/Library/PostgreSQL/17/includedir} 13 | Libs: -L/Library/PostgreSQL/17/libdir} -lecpg_compat 14 | Libs.private: -L/opt/local/20240903/lib -L/opt/local/Current_v15/lib -lecpg -lpgcommon -lpgport -lpq -lm 15 | -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/pkgconfig/libpgtypes.pc: -------------------------------------------------------------------------------- 1 | prefix=/opt/pginstaller_17.auto/server/staging_cache/osx.build 2 | exec_prefix=${prefix} 3 | libdir=${exec_prefix}/lib 4 | includedir=${prefix}/include 5 | 6 | Name: libpgtypes 7 | Description: PostgreSQL libpgtypes library 8 | URL: https://www.postgresql.org/ 9 | Version: 17.0 10 | Requires: 11 | Requires.private: 12 | Cflags: -I/Library/PostgreSQL/17/includedir} 13 | Libs: -L/Library/PostgreSQL/17/libdir} -lpgtypes 14 | Libs.private: -L/opt/local/20240903/lib -L/opt/local/Current_v15/lib -lpgcommon -lpgport -lm 15 | -------------------------------------------------------------------------------- /resources/postgres/mac/17/lib/pkgconfig/libpq.pc: -------------------------------------------------------------------------------- 1 | prefix=/opt/pginstaller_17.auto/server/staging_cache/osx.build 2 | exec_prefix=${prefix} 3 | libdir=${exec_prefix}/lib 4 | includedir=${prefix}/include 5 | 6 | Name: libpq 7 | Description: PostgreSQL libpq library 8 | URL: https://www.postgresql.org/ 9 | Version: 17.0 10 | Requires: 11 | Requires.private: libssl, libcrypto 12 | Cflags: -I/Library/PostgreSQL/17/includedir} 13 | Libs: -L/Library/PostgreSQL/17/libdir} -lpq 14 | Libs.private: -L/opt/local/20240903/lib -L/opt/local/Current_v15/lib -lpgcommon -lpgport -lssl -lgssapi_krb5 -lm -lldap_r 15 | -------------------------------------------------------------------------------- /resources/postgres/win/16/createdb.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/win/16/createdb.exe -------------------------------------------------------------------------------- /resources/postgres/win/16/libcrypto-3-x64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/win/16/libcrypto-3-x64.dll -------------------------------------------------------------------------------- /resources/postgres/win/16/libcurl.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/win/16/libcurl.dll -------------------------------------------------------------------------------- /resources/postgres/win/16/libcurl.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/win/16/libcurl.lib -------------------------------------------------------------------------------- /resources/postgres/win/16/libecpg.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/win/16/libecpg.dll -------------------------------------------------------------------------------- /resources/postgres/win/16/libecpg_compat.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/win/16/libecpg_compat.dll -------------------------------------------------------------------------------- /resources/postgres/win/16/libiconv-2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/win/16/libiconv-2.dll -------------------------------------------------------------------------------- /resources/postgres/win/16/libintl-9.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/win/16/libintl-9.dll -------------------------------------------------------------------------------- /resources/postgres/win/16/liblz4.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/win/16/liblz4.dll -------------------------------------------------------------------------------- /resources/postgres/win/16/libpgtypes.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/win/16/libpgtypes.dll -------------------------------------------------------------------------------- /resources/postgres/win/16/libpq.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/win/16/libpq.dll -------------------------------------------------------------------------------- /resources/postgres/win/16/libssl-3-x64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/win/16/libssl-3-x64.dll -------------------------------------------------------------------------------- /resources/postgres/win/16/libwinpthread-1.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/win/16/libwinpthread-1.dll -------------------------------------------------------------------------------- /resources/postgres/win/16/libxml2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/win/16/libxml2.dll -------------------------------------------------------------------------------- /resources/postgres/win/16/libxslt.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/win/16/libxslt.dll -------------------------------------------------------------------------------- /resources/postgres/win/16/libzstd.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/win/16/libzstd.dll -------------------------------------------------------------------------------- /resources/postgres/win/16/pg_dump.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/win/16/pg_dump.exe -------------------------------------------------------------------------------- /resources/postgres/win/16/pg_restore.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/win/16/pg_restore.exe -------------------------------------------------------------------------------- /resources/postgres/win/16/zlib1.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/resources/postgres/win/16/zlib1.dll -------------------------------------------------------------------------------- /screenshot/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/screenshot/1.jpg -------------------------------------------------------------------------------- /screenshot/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/screenshot/2.jpg -------------------------------------------------------------------------------- /screenshot/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/screenshot/3.jpg -------------------------------------------------------------------------------- /screenshot/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/screenshot/4.jpg -------------------------------------------------------------------------------- /screenshot/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/screenshot/5.jpg -------------------------------------------------------------------------------- /screenshot/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/screenshot/6.jpg -------------------------------------------------------------------------------- /screenshot/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/underway2014/DBA/82dc93552fa38541c8aaf272e6dced9eadc90d79/screenshot/7.jpg -------------------------------------------------------------------------------- /src/main/index.ts: -------------------------------------------------------------------------------- 1 | import { app, shell, BrowserWindow, ipcMain, screen, Menu, nativeTheme } from 'electron' 2 | import { join } from 'path' 3 | import { electronApp, optimizer, is } from '@electron-toolkit/utils' 4 | import icon from '../../resources/icon.png?asset' 5 | import { 6 | changeMode, 7 | editConnection, 8 | getConfig, 9 | storeAdd, 10 | storeDel, 11 | storeSearch 12 | } from '../server/lib/connectionJson' 13 | import updater from './updater' 14 | import { menuTemplate } from './menuTemplate' 15 | 16 | import { 17 | addRow, 18 | alterTable, 19 | backup, 20 | closeConnection, 21 | createDb, 22 | createRole, 23 | delRole, 24 | delRows, 25 | editIndex, 26 | editSchema, 27 | editTable, 28 | getColums, 29 | getDDL, 30 | getIndexs, 31 | getRolePermission, 32 | getRoles, 33 | getSchema, 34 | getTableData, 35 | getTables, 36 | grantRolePermission, 37 | query, 38 | restore, 39 | updateDate 40 | } from '../server/db' 41 | import { exportFile } from '../server/lib/excel' 42 | // import { menuTemplate } from './menuTemplate' 43 | // require('@electron/remote/main').initialize() 44 | // remoteMain.initialize() 45 | 46 | function createWindow(): void { 47 | const { width, height } = screen.getPrimaryDisplay().bounds 48 | // Create the browser window. 49 | const mainWindow = new BrowserWindow({ 50 | width, 51 | height, 52 | show: false, 53 | autoHideMenuBar: true, 54 | darkTheme: true, 55 | ...(process.platform === 'linux' ? { icon } : {}), 56 | webPreferences: { 57 | preload: join(__dirname, '../preload/index.js'), 58 | sandbox: false 59 | } 60 | // fullscreen: true, 61 | // maximizable 62 | }) 63 | 64 | mainWindow.on('ready-to-show', () => { 65 | mainWindow.show() 66 | }) 67 | 68 | mainWindow.on('close', async () => { 69 | await closeConnection() 70 | }) 71 | 72 | mainWindow.webContents.setWindowOpenHandler((details) => { 73 | shell.openExternal(details.url) 74 | return { action: 'deny' } 75 | }) 76 | 77 | // HMR for renderer base on electron-vite cli. 78 | // Load the remote URL for development or the local html file for production. 79 | if (is.dev && process.env['ELECTRON_RENDERER_URL']) { 80 | mainWindow.webContents.openDevTools() 81 | mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL']) 82 | } else { 83 | mainWindow.loadFile(join(__dirname, '../renderer/index.html')) 84 | } 85 | 86 | updater(mainWindow) 87 | initMenu() 88 | } 89 | 90 | function initMenu() { 91 | const menu = Menu.buildFromTemplate(menuTemplate) 92 | Menu.setApplicationMenu(menu) 93 | } 94 | 95 | // This method will be called when Electron has finished 96 | // initialization and is ready to create browser windows. 97 | // Some APIs can only be used after this event occurs. 98 | app.whenReady().then(() => { 99 | // server() 100 | // Set app user model id for windows 101 | electronApp.setAppUserModelId('electron.viki.com') 102 | 103 | // Default open or close DevTools by F12 in development 104 | // and ignore CommandOrControl + R in production. 105 | // see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils 106 | app.on('browser-window-created', (_, window) => { 107 | optimizer.watchWindowShortcuts(window) 108 | }) 109 | 110 | // IPC test 111 | ipcMain.on('ping', () => {}) 112 | 113 | ipcMain.handle('store:get', () => { 114 | const data = getConfig() 115 | 116 | return data 117 | }) 118 | ipcMain.handle('store:add', (_, val) => { 119 | storeAdd(val) 120 | }) 121 | ipcMain.handle('store:edit', (_, val) => { 122 | editConnection(val) 123 | }) 124 | ipcMain.handle('store:del', (_, val) => { 125 | return storeDel(val) 126 | }) 127 | ipcMain.handle('store:search', (_, val) => { 128 | return storeSearch(val) 129 | }) 130 | ipcMain.handle('db:backup', async (_, val) => { 131 | return backup(val) 132 | }) 133 | ipcMain.handle('db:restore', (_, val) => { 134 | return restore(val) 135 | }) 136 | ipcMain.handle('db:create', (_, val) => { 137 | return createDb(val) 138 | }) 139 | ipcMain.handle('getSchema', (_, val) => { 140 | return getSchema(val) 141 | }) 142 | ipcMain.handle('getTables', (_, val) => { 143 | return getTables(val) 144 | }) 145 | ipcMain.handle('querySql', (_, val) => { 146 | return query(val) 147 | }) 148 | ipcMain.handle('updateDate', (_, val) => { 149 | return updateDate(val) 150 | }) 151 | ipcMain.handle('getTableData', (_, val) => { 152 | return getTableData(val) 153 | }) 154 | ipcMain.handle('alterTable', (_, val) => { 155 | return alterTable(val) 156 | }) 157 | ipcMain.handle('addRow', (_, val) => { 158 | return addRow(val) 159 | }) 160 | ipcMain.handle('delRows', (_, val) => { 161 | return delRows(val) 162 | }) 163 | ipcMain.handle('connection:close', (_, val) => { 164 | return closeConnection(val) 165 | }) 166 | ipcMain.handle('db:indexs', (_, val) => { 167 | return getIndexs(val) 168 | }) 169 | ipcMain.handle('db:editindexs', (_, val) => { 170 | return editIndex(val) 171 | }) 172 | ipcMain.handle('db:getcolumns', (_, val) => { 173 | return getColums(val) 174 | }) 175 | ipcMain.handle('db:edittable', (_, val) => { 176 | return editTable(val) 177 | }) 178 | 179 | ipcMain.handle('dark-mode:toggle', (_, val) => { 180 | nativeTheme.themeSource = val 181 | changeMode(val) 182 | return nativeTheme.shouldUseDarkColors 183 | }) 184 | 185 | ipcMain.handle('excel:export', (_, val) => { 186 | return exportFile(val) 187 | }) 188 | ipcMain.handle('db:editschema', (_, val) => { 189 | console.log('db:editschema val: ', val) 190 | 191 | return editSchema(val) 192 | }) 193 | 194 | ipcMain.handle('db:getroles', (_, val) => { 195 | console.log('db:getroles val: ', val) 196 | 197 | return getRoles(val) 198 | }) 199 | ipcMain.handle('db:createrole', (_, val) => { 200 | console.log('db:createrole val: ', val) 201 | 202 | return createRole(val) 203 | }) 204 | ipcMain.handle('db:grantrole', (_, val) => { 205 | return grantRolePermission(val) 206 | }) 207 | ipcMain.handle('db:getrolepermission', (_, val) => { 208 | return getRolePermission(val) 209 | }) 210 | ipcMain.handle('db:delrole', (_, val) => { 211 | return delRole(val) 212 | }) 213 | ipcMain.handle('db:getddl', (_, val) => { 214 | return getDDL(val) 215 | }) 216 | 217 | createWindow() 218 | 219 | app.on('activate', function () { 220 | // On macOS it's common to re-create a window in the app when the 221 | // dock icon is clicked and there are no other windows open. 222 | if (BrowserWindow.getAllWindows().length === 0) createWindow() 223 | }) 224 | }) 225 | 226 | // Quit when all windows are closed, except on macOS. There, it's common 227 | // for applications and their menu bar to stay active until the user quits 228 | // explicitly with Cmd + Q. 229 | app.on('window-all-closed', async () => { 230 | // e.preventDefault() 231 | 232 | if (process.platform !== 'darwin') { 233 | app.quit() 234 | } 235 | }) 236 | 237 | // app.on('before-quit', e => { 238 | 239 | // }) 240 | 241 | // In this file you can include the rest of your app"s specific main process 242 | // code. You can also put them in separate files and require them here. 243 | -------------------------------------------------------------------------------- /src/main/menuTemplate.ts: -------------------------------------------------------------------------------- 1 | import { autoUpdater } from 'electron-updater' 2 | 3 | export const menuTemplate = [ 4 | { 5 | label: 'DBA', 6 | submenu: [ 7 | { 8 | label: 'About', 9 | role: 'about' 10 | }, 11 | { 12 | type: 'separator' 13 | }, 14 | { 15 | label: 'Hide', 16 | role: 'hide' 17 | }, 18 | { 19 | label: 'HideOthers', 20 | role: 'hideOthers' 21 | }, 22 | { 23 | type: 'separator' 24 | }, 25 | { 26 | label: 'Quit', 27 | role: 'quit' 28 | } 29 | ] 30 | }, 31 | { 32 | label: 'Edit', 33 | submenu: [ 34 | { 35 | label: 'Undo', 36 | role: 'undo' 37 | }, 38 | { 39 | label: 'Redo', 40 | role: 'redo' 41 | }, 42 | { 43 | type: 'separator' 44 | }, 45 | { 46 | label: 'Cut', 47 | role: 'cut' 48 | }, 49 | { 50 | label: 'Copy', 51 | role: 'copy' 52 | }, 53 | { 54 | label: 'Paste', 55 | role: 'paste' 56 | }, 57 | { 58 | label: 'Delete', 59 | role: 'delete' 60 | }, 61 | { 62 | label: 'SelectAll', 63 | role: 'selectAll' 64 | } 65 | ] 66 | }, 67 | { 68 | label: 'Window', 69 | submenu: [ 70 | { 71 | label: 'Minimize', 72 | role: 'minimize' 73 | }, 74 | { 75 | label: 'Close', 76 | role: 'close' 77 | }, 78 | { 79 | label: 'Togglefullscreen', 80 | role: 'togglefullscreen' 81 | } 82 | ] 83 | }, 84 | { 85 | role: 'Help', 86 | submenu: [ 87 | { 88 | label: 'DBA Community', 89 | click: async () => { 90 | const { shell } = require('electron') 91 | await shell.openExternal('https://github.com/underway2014/DBA') 92 | } 93 | }, 94 | { 95 | label: 'Check for Updates', 96 | click: () => { 97 | // dialog.showMessageBox({ 98 | // type: 'info', 99 | // title: 'Check Update', 100 | // message: 'checking...' 101 | // }) 102 | autoUpdater.checkForUpdates() // 点击时检查更新 103 | } 104 | } 105 | ] 106 | } 107 | ] 108 | -------------------------------------------------------------------------------- /src/main/updater.ts: -------------------------------------------------------------------------------- 1 | import { BrowserWindow, dialog, shell, ipcMain } from 'electron' 2 | import { autoUpdater } from 'electron-updater' 3 | 4 | // auto download 5 | autoUpdater.autoDownload = false 6 | // auto install after quit 7 | autoUpdater.autoInstallOnAppQuit = false 8 | 9 | export default (win: BrowserWindow) => { 10 | const checkForUpdates = (manual = false) => { 11 | autoUpdater.checkForUpdates().catch((error) => { 12 | console.error('Error checking for updates:', error) 13 | }) 14 | 15 | if (manual) { 16 | dialog.showMessageBox({ 17 | type: 'info', 18 | title: 'Check Update', 19 | message: 'checking...' 20 | }) 21 | } 22 | } 23 | // 监听来自渲染进程的手动检查更新请求 24 | ipcMain.on('startForCheckUpdate', () => { 25 | console.log('startForCheckUpdate>>>>') 26 | }) 27 | // checkForUpdates() 28 | 29 | // 监听来自渲染进程的手动检查更新请求 30 | ipcMain.on('CheckForUpdates', () => { 31 | console.log('CheckForUpdates>>>>') 32 | checkForUpdates(true) 33 | }) 34 | 35 | autoUpdater.on('update-available', (info) => { 36 | dialog 37 | .showMessageBox({ 38 | type: 'info', 39 | title: 'Update Tip', 40 | message: `new version ${info.version},update or not?`, 41 | detail: info.releaseNotes ? `Update Explanation: ${info.releaseNotes}` : '', 42 | buttons: ['update', 'cancel'], 43 | cancelId: 1 44 | }) 45 | .then((res) => { 46 | if (res.response === 0) { 47 | autoUpdater.downloadUpdate() 48 | } 49 | }) 50 | }) 51 | 52 | autoUpdater.on('update-not-available', (info) => { 53 | dialog.showMessageBox({ 54 | type: 'info', 55 | title: 'Update Tip', 56 | message: `now version ${info.version}, It's already the latest version` 57 | }) 58 | }) 59 | 60 | autoUpdater.on('download-progress', (prog) => { 61 | win.webContents.send('downloadProgress', { 62 | speed: Math.ceil(prog.bytesPerSecond / 1000), // 网速 63 | percent: Math.ceil(prog.percent) // 百分比 64 | }) 65 | }) 66 | 67 | autoUpdater.on('update-downloaded', () => { 68 | win.webContents.send('downloaded') 69 | dialog 70 | .showMessageBox({ 71 | type: 'info', 72 | title: 'Update Complete', 73 | message: 'The update has been downloaded and completed. Do you want to install it now?', 74 | buttons: ['Yes', 'Not'], 75 | cancelId: 1 76 | }) 77 | .then((res) => { 78 | if (res.response === 0) { 79 | autoUpdater.quitAndInstall() 80 | } 81 | }) 82 | }) 83 | 84 | autoUpdater.on('error', (error) => { 85 | dialog 86 | .showMessageBox({ 87 | type: 'error', 88 | title: 'Update Error', 89 | message: 'An error occurred during the software update process', 90 | detail: error ? error.toString() : '', 91 | buttons: ['Download', 'Cancel'], 92 | cancelId: 1 93 | }) 94 | .then((res) => { 95 | if (res.response === 0) { 96 | shell.openExternal('https://github.com/underway2014/dba/releases') 97 | } 98 | }) 99 | }) 100 | } 101 | -------------------------------------------------------------------------------- /src/preload/index.d.ts: -------------------------------------------------------------------------------- 1 | import { ElectronAPI } from '@electron-toolkit/preload' 2 | 3 | type DBReturn = Promise 4 | 5 | interface ApiFunction { 6 | addStore: (val) => DBReturn 7 | editStore: (val) => DBReturn 8 | delStore: (val) => DBReturn 9 | getStore: () => DBReturn 10 | getTables: (val) => DBReturn 11 | getSchema: (val) => DBReturn 12 | querySql: (val) => DBReturn 13 | getTableData: (val) => DBReturn 14 | updateDate: (val) => DBReturn 15 | dbCreate: (val) => DBReturn 16 | dbBackup: (val) => DBReturn 17 | dbRestore: (val) => DBReturn 18 | alterTable: (val) => DBReturn 19 | editConnection: (val) => DBReturn 20 | addRow: (val) => DBReturn 21 | delRows: (val) => DBReturn 22 | closeConnections: (val) => DBReturn 23 | getIndexs: (val) => DBReturn 24 | editIndex: (val) => DBReturn 25 | getColums: (val) => DBReturn 26 | editTable: (val) => DBReturn 27 | toggleTheme: (val) => DBReturn 28 | exportFile: (val) => DBReturn 29 | editSchema: (val) => DBReturn 30 | getRoles: (val) => DBReturn 31 | createRole: (val) => DBReturn 32 | grantRolePermission: (val) => DBReturn 33 | getRolePermission: (val) => DBReturn 34 | delRole: (val) => DBReturn 35 | getDDL: (val) => DBReturn 36 | } 37 | 38 | declare global { 39 | interface Window { 40 | electron: ElectronAPI 41 | api: ApiFunction 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/preload/index.ts: -------------------------------------------------------------------------------- 1 | import { contextBridge, ipcRenderer } from 'electron' 2 | import { electronAPI } from '@electron-toolkit/preload' 3 | import { clearDb } from '../server/db' 4 | 5 | // Custom APIs for renderer 6 | const api = { 7 | addStore: (val) => { 8 | return ipcRenderer.invoke('store:add', val) 9 | }, 10 | delStore: (val) => { 11 | return ipcRenderer.invoke('store:del', val) 12 | }, 13 | editStore: (val) => { 14 | clearDb({ id: val.id }) 15 | return ipcRenderer.invoke('store:edit', val) 16 | }, 17 | getStore: async (val) => { 18 | return ipcRenderer.invoke('store:get', val) 19 | }, 20 | changeTheme: async (val) => { 21 | return ipcRenderer.invoke('store:changetheme', val) 22 | }, 23 | getTables: async (val) => { 24 | return ipcRenderer.invoke('getTables', val) 25 | }, 26 | getSchema: async (val) => { 27 | return ipcRenderer.invoke('getSchema', val) 28 | }, 29 | querySql: async (sql) => { 30 | return ipcRenderer.invoke('querySql', { sql }) 31 | }, 32 | updateDate: async (val) => { 33 | return ipcRenderer.invoke('updateDate', val) 34 | }, 35 | getTableData: async (val) => { 36 | return ipcRenderer.invoke('getTableData', val) 37 | }, 38 | dbBackup: async (val) => { 39 | return ipcRenderer.invoke('db:backup', val) 40 | }, 41 | dbRestore: async (val) => { 42 | return ipcRenderer.invoke('db:restore', val) 43 | }, 44 | dbCreate: async (val) => { 45 | return ipcRenderer.invoke('db:create', val) 46 | }, 47 | alterTable: async (val) => { 48 | return ipcRenderer.invoke('alterTable', val) 49 | }, 50 | addRow: async (val) => { 51 | return ipcRenderer.invoke('addRow', val) 52 | }, 53 | delRows: async (val) => { 54 | return ipcRenderer.invoke('delRows', val) 55 | }, 56 | closeConnections: async (val) => { 57 | return ipcRenderer.invoke('connection:close', val) 58 | }, 59 | getIndexs: async (val) => { 60 | return ipcRenderer.invoke('db:indexs', val) 61 | }, 62 | editIndex: async (val) => { 63 | return ipcRenderer.invoke('db:editindexs', val) 64 | }, 65 | getColums: async (val) => { 66 | return ipcRenderer.invoke('db:getcolumns', val) 67 | }, 68 | editTable: async (val) => { 69 | return ipcRenderer.invoke('db:edittable', val) 70 | }, 71 | toggleTheme: (val) => { 72 | return ipcRenderer.invoke('dark-mode:toggle', val) 73 | }, 74 | exportFile: (val) => { 75 | return ipcRenderer.invoke('excel:export', val) 76 | }, 77 | editSchema: (val) => { 78 | return ipcRenderer.invoke('db:editschema', val) 79 | }, 80 | getRoles: (val) => { 81 | return ipcRenderer.invoke('db:getroles', val) 82 | }, 83 | createRole: (val) => { 84 | return ipcRenderer.invoke('db:createrole', val) 85 | }, 86 | grantRolePermission: (val) => { 87 | return ipcRenderer.invoke('db:grantrole', val) 88 | }, 89 | getRolePermission: (val) => { 90 | return ipcRenderer.invoke('db:getrolepermission', val) 91 | }, 92 | delRole: (val) => { 93 | return ipcRenderer.invoke('db:delrole', val) 94 | }, 95 | getDDL: (val) => { 96 | return ipcRenderer.invoke('db:getddl', val) 97 | } 98 | } 99 | 100 | // Use `contextBridge` APIs to expose Electron APIs to 101 | // renderer only if context isolation is enabled, otherwise 102 | // just add to the DOM global. 103 | if (process.contextIsolated) { 104 | try { 105 | contextBridge.exposeInMainWorld('electron', electronAPI) 106 | contextBridge.exposeInMainWorld('api', api) 107 | const globalPolyfill = { 108 | setImmediate: (callback, ...args) => { 109 | return setTimeout(callback, 0, ...args) 110 | } 111 | } 112 | 113 | // 使用 contextBridge 暴露 globalPolyfill 114 | contextBridge.exposeInMainWorld('global', globalPolyfill) 115 | 116 | // contextBridge.exposeInMainWorld('darkMode', { 117 | // toggle: () => ipcRenderer.invoke('dark-mode:toggle'), 118 | // system: () => ipcRenderer.invoke('dark-mode:system') 119 | // }) 120 | } catch (error) { 121 | console.error(error) 122 | } 123 | } else { 124 | // @ts-ignore (define in dts) 125 | window.electron = electronAPI 126 | // @ts-ignore (define in dts) 127 | window.api = api 128 | } 129 | -------------------------------------------------------------------------------- /src/renderer/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | DBA 6 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/renderer/src/App.tsx: -------------------------------------------------------------------------------- 1 | import CLayout from './components/Layout' 2 | 3 | function App(): JSX.Element { 4 | return ( 5 |
6 | 7 |
8 | ) 9 | } 10 | 11 | export default App 12 | -------------------------------------------------------------------------------- /src/renderer/src/assets/base.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --ev-c-white: #ffffff; 3 | --ev-c-white-soft: #f8f8f8; 4 | --ev-c-white-mute: #f2f2f2; 5 | 6 | --ev-c-black: #1b1b1f; 7 | /* --ev-c-black-soft: #222222; 8 | --ev-c-black-mute: #282828; */ 9 | 10 | --ev-c-gray-1: #515c67; 11 | --ev-c-gray-2: #414853; 12 | --ev-c-gray-3: #32363f; 13 | 14 | --ev-c-text-1: rgba(255, 255, 245, 0.86); 15 | --ev-c-text-2: rgba(235, 235, 245, 0.6); 16 | --ev-c-text-3: rgba(235, 235, 245, 0.38); 17 | 18 | --ev-button-alt-border: transparent; 19 | --ev-button-alt-text: var(--ev-c-text-1); 20 | --ev-button-alt-bg: var(--ev-c-gray-3); 21 | --ev-button-alt-hover-border: transparent; 22 | --ev-button-alt-hover-text: var(--ev-c-text-1); 23 | --ev-button-alt-hover-bg: var(--ev-c-gray-2); 24 | } 25 | 26 | :root { 27 | --color-background: var(--ev-c-black); 28 | --color-background-soft: var(--ev-c-black-soft); 29 | --color-background-mute: var(--ev-c-black-mute); 30 | 31 | --color-text: var(--ev-c-text-1); 32 | } 33 | 34 | *, 35 | *::before, 36 | *::after { 37 | box-sizing: border-box; 38 | margin: 0; 39 | font-weight: normal; 40 | } 41 | 42 | ul { 43 | list-style: none; 44 | } 45 | 46 | body { 47 | min-height: 100vh; 48 | color: var(--color-text); 49 | /* background: var(--color-background); */ 50 | line-height: 1.6; 51 | font-family: 52 | Inter, 53 | -apple-system, 54 | BlinkMacSystemFont, 55 | 'Segoe UI', 56 | Roboto, 57 | Oxygen, 58 | Ubuntu, 59 | Cantarell, 60 | 'Fira Sans', 61 | 'Droid Sans', 62 | 'Helvetica Neue', 63 | sans-serif; 64 | text-rendering: optimizeLegibility; 65 | -webkit-font-smoothing: antialiased; 66 | -moz-osx-font-smoothing: grayscale; 67 | } 68 | -------------------------------------------------------------------------------- /src/renderer/src/assets/icons/icon.tsx: -------------------------------------------------------------------------------- 1 | export const RunIcon = () => ( 2 | 11 | 16 | 17 | ) 18 | 19 | export const AddIcon = () => ( 20 | 29 | 34 | 35 | ) 36 | 37 | export const MinusIcon = () => ( 38 | 47 | 52 | 53 | ) 54 | -------------------------------------------------------------------------------- /src/renderer/src/assets/main.css: -------------------------------------------------------------------------------- 1 | @import './base.css'; 2 | 3 | body { 4 | overflow: hidden; 5 | /* background-color: white; */ 6 | } 7 | 8 | .chighlight { 9 | color: #f37bb7; 10 | background-color: transparent; 11 | } 12 | 13 | .treeTitle { 14 | display: flex; 15 | 16 | .treeBtn { 17 | display: none; 18 | } 19 | } 20 | 21 | .treeTitle:hover { 22 | .treeBtn { 23 | display: flex; 24 | } 25 | } 26 | 27 | .ant-tree-title { 28 | display: inline-block; 29 | } 30 | 31 | .cellHover { 32 | position: relative; 33 | white-space: nowrap; 34 | height: 20px; 35 | } 36 | 37 | .cellHover:hover .cellPlus { 38 | display: inline-block; 39 | position: absolute; 40 | /* size: 20; */ 41 | width: 10; 42 | height: 10; 43 | right: 0; 44 | cursor: pointer; 45 | /* background-color: rgba(rgb(224, 13, 13), green, blue, 0.5); */ 46 | } 47 | 48 | .cellPlus { 49 | display: none; 50 | } 51 | 52 | /* table { 53 | table-layout: fixed; 54 | } */ -------------------------------------------------------------------------------- /src/renderer/src/components/AddColumnForm.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react' 2 | import { AutoComplete, Button, Checkbox, Form, Input } from 'antd' 3 | 4 | type LayoutType = Parameters[0]['layout'] 5 | type CustomProps = { 6 | addColumn: (values, defaultvalues) => void 7 | defautValues?: object 8 | isMysql: boolean 9 | } 10 | 11 | const AddColumnForm: React.FC = (props) => { 12 | const [form] = Form.useForm() 13 | const [_, setFormLayout] = useState('horizontal') 14 | const { addColumn } = props 15 | const onFormLayoutChange = ({ layout }: { layout: LayoutType }) => { 16 | setFormLayout(layout) 17 | } 18 | 19 | const onFinish = () => { 20 | addColumn(form.getFieldsValue(), props.defautValues) 21 | 22 | form.resetFields() 23 | } 24 | 25 | const onFinishFailed = () => {} 26 | 27 | form.setFieldsValue(props.defautValues) 28 | 29 | const options = props.isMysql 30 | ? [ 31 | { value: 'tinyint' }, 32 | { value: 'smallint' }, 33 | { value: 'mediumint' }, 34 | { value: 'int' }, 35 | { value: 'integer' }, 36 | { value: 'bigint' }, 37 | { value: 'float' }, 38 | { value: 'double' }, 39 | { value: 'decimal' }, 40 | { value: 'bit' }, 41 | { value: 'date' }, 42 | { value: 'time' }, 43 | { value: 'year' }, 44 | { value: 'datetime' }, 45 | { value: 'timestamp' }, 46 | { value: 'char' }, 47 | { value: 'varchar' }, 48 | { value: 'tinytext' }, 49 | { value: 'text' }, 50 | { value: 'mediumtext' }, 51 | { value: 'longtext' }, 52 | { value: 'binary' }, 53 | { value: 'varbinary' }, 54 | { value: 'tinyblob' }, 55 | { value: 'blob' }, 56 | { value: 'mediumblob' }, 57 | { value: 'longblob' }, 58 | { value: 'enum' }, 59 | { value: 'set' }, 60 | { value: 'json' } 61 | ] 62 | : [ 63 | { value: 'int2' }, 64 | { value: 'int4' }, 65 | { value: 'int8' }, 66 | { value: 'bit(6)' }, 67 | { value: 'varbit(6)' }, 68 | { value: 'boolean' }, 69 | { value: 'box' }, 70 | { value: 'bytea' }, 71 | { value: 'char(6)' }, 72 | { value: 'varchar(255)' }, 73 | { value: 'cidr' }, 74 | { value: 'circle' }, 75 | { value: 'date' }, 76 | { value: 'float4' }, 77 | { value: 'float8' }, 78 | { value: 'inet' }, 79 | { value: 'interval' }, 80 | { value: 'json' }, 81 | { value: 'jsonb' }, 82 | { value: 'line' }, 83 | { value: 'lseg' }, 84 | { value: 'macaddr' }, 85 | { value: 'macaddr8' }, 86 | { value: 'money' }, 87 | { value: 'numeric(12,4)' }, 88 | { value: 'point' }, 89 | { value: 'smallserial' }, 90 | { value: 'serial' }, 91 | { value: 'bigserial' }, 92 | { value: 'text' }, 93 | { value: 'timestamptz' }, 94 | { value: 'tsquery' }, 95 | { value: 'tsvector' }, 96 | { value: 'txid_snapshot' }, 97 | { value: 'uuid' }, 98 | { value: 'xml' } 99 | ] 100 | 101 | return ( 102 |
113 | 114 | 115 | 116 | 117 | 122 | option!.value.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1 123 | } 124 | /> 125 | 126 | 132 | Not Null 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 |
144 | ) 145 | } 146 | 147 | export default AddColumnForm 148 | -------------------------------------------------------------------------------- /src/renderer/src/components/AddIndexForm.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Button, Form, Input, Select, Switch } from 'antd' 3 | 4 | interface IndexFormValues { 5 | name: string 6 | columns: string[] 7 | unique: boolean 8 | type: string 9 | } 10 | 11 | interface CustomProps { 12 | editIndex: (values: IndexFormValues) => void 13 | isMysql: boolean 14 | columns: Array<{ value: string; label: string }> 15 | defaultValues?: Partial 16 | } 17 | 18 | const AddIndexForm: React.FC = ({ editIndex, isMysql, columns, defaultValues }) => { 19 | const [form] = Form.useForm() 20 | 21 | const onFinish = () => { 22 | const values = form.getFieldsValue() 23 | editIndex(values) 24 | form.resetFields() 25 | } 26 | 27 | const onFinishFailed = () => { 28 | // 可以添加错误处理逻辑 29 | } 30 | 31 | if (defaultValues) { 32 | form.setFieldsValue(defaultValues) 33 | } 34 | 35 | const IndexTypeOptions = isMysql 36 | ? [{ value: 'btree' }, { value: 'hash' }, { value: 'rtree' }] 37 | : [ 38 | { value: 'btree' }, 39 | { value: 'hash' }, 40 | { value: 'gist' }, 41 | { value: 'spgist' }, 42 | { value: 'gin' }, 43 | { value: 'brin' } 44 | ] 45 | 46 | return ( 47 |
57 | 58 | 59 | 60 | 61 | 62 | 82 | 83 | 84 | 85 | 88 | 89 |
90 | ) 91 | } 92 | 93 | export default AddIndexForm 94 | -------------------------------------------------------------------------------- /src/renderer/src/components/AddRoleForm.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react' 2 | import { Button, Checkbox, Col, DatePicker, Form, Input, Row } from 'antd' 3 | import { RolePermissionMap, RolePermissionVal } from '@renderer/utils/constant' 4 | import dayjs from 'dayjs' 5 | 6 | type LayoutType = Parameters[0]['layout'] 7 | type RoleData = { 8 | connectionId: string 9 | roleName: string 10 | timeStamp: number 11 | } 12 | type CustomProps = { 13 | addRole: Function 14 | defautValues?: RoleData | null 15 | } 16 | 17 | const AddRoleForm: React.FC = (props) => { 18 | const [form] = Form.useForm() 19 | const [_, setFormLayout] = useState('horizontal') 20 | const { addRole } = props 21 | const onFormLayoutChange = ({ layout }: { layout: LayoutType }) => { 22 | setFormLayout(layout) 23 | } 24 | const [defaultValue, setDefaultValue] = useState(null) 25 | form.resetFields() 26 | const onFinish = (values) => { 27 | addRole(form.getFieldsValue()) 28 | } 29 | 30 | useEffect(() => { 31 | getRoleInfo() 32 | }, [ 33 | props.defautValues?.connectionId, 34 | props.defautValues?.roleName, 35 | props.defautValues?.timeStamp 36 | ]) 37 | 38 | function getRoleInfo() { 39 | console.log('getRole info execute', props.defautValues) 40 | if (props.defautValues?.roleName && props.defautValues.connectionId) { 41 | window.api 42 | .getRoles({ id: props.defautValues.connectionId, roleName: props.defautValues.roleName }) 43 | .then((res) => { 44 | const ps: string[] = [] 45 | Object.keys(RolePermissionMap).forEach((el) => { 46 | if (res[0][el]) { 47 | ps.push(RolePermissionMap[el]) 48 | } 49 | }) 50 | 51 | console.log( 52 | 'get role data: ', 53 | res[0].rolvaliduntil, 54 | typeof res[0].rolvaliduntil, 55 | ' check: ', 56 | isFinite(res[0].rolvaliduntil) 57 | ) 58 | 59 | setDefaultValue({ 60 | name: res[0].rolname, 61 | password: res[0].rolpassword, 62 | permissions: ps, 63 | // validuntil: res[0].rolvaliduntil ? moment(res[0].rolvaliduntil) : null 64 | validuntil: res[0].rolvaliduntil 65 | ? isFinite(res[0].rolvaliduntil) 66 | ? dayjs(res[0].rolvaliduntil) 67 | : null 68 | : null 69 | }) 70 | }) 71 | } else { 72 | form.resetFields() 73 | } 74 | } 75 | 76 | const onFinishFailed = (errorInfo) => {} 77 | 78 | form.setFieldsValue(defaultValue) 79 | 80 | function onChange(date, str) { 81 | console.log('onChange: ', date, str) 82 | } 83 | 84 | return ( 85 |
96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | {RolePermissionVal.map((el, index) => { 106 | return ( 107 | 108 | 109 | {el} 110 | 111 | 112 | ) 113 | })} 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 |
125 | ) 126 | } 127 | 128 | export default AddRoleForm 129 | -------------------------------------------------------------------------------- /src/renderer/src/components/AddRowForm.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Button, Form, Input } from 'antd' 3 | 4 | interface FieldData { 5 | name: string | number | (string | number)[] 6 | value?: any 7 | touched?: boolean 8 | validating?: boolean 9 | errors?: string[] 10 | } 11 | 12 | type CustomProps = { 13 | fields: FieldData[] 14 | addRowData: Function 15 | } 16 | 17 | const AddRowForm: React.FC = (props) => { 18 | const [form] = Form.useForm() 19 | form.resetFields() 20 | const items = props.fields.map((el) => { 21 | return ( 22 | 23 | 24 | 25 | ) 26 | }) 27 | 28 | const onFinish = (values) => { 29 | props.addRowData(form.getFieldsValue()) 30 | } 31 | 32 | const onFinishFailed = (errorInfo) => {} 33 | 34 | return ( 35 |
44 | {items} 45 | 46 | 47 | 48 | 49 |
50 | ) 51 | } 52 | 53 | export default AddRowForm 54 | -------------------------------------------------------------------------------- /src/renderer/src/components/AddSchemaForm.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react' 2 | import { Button, Form, Input } from 'antd' 3 | 4 | type LayoutType = Parameters[0]['layout'] 5 | type CustomProps = { 6 | editSchema: Function 7 | } 8 | 9 | const AddSchemaForm: React.FC = (props) => { 10 | const [form] = Form.useForm() 11 | const [_, setFormLayout] = useState('horizontal') 12 | const { editSchema } = props 13 | const onFormLayoutChange = ({ layout }: { layout: LayoutType }) => { 14 | setFormLayout(layout) 15 | } 16 | 17 | const onFinish = (values) => { 18 | editSchema(form.getFieldsValue()) 19 | 20 | form.resetFields() 21 | } 22 | 23 | const onFinishFailed = (errorInfo) => {} 24 | 25 | // form.setFieldsValue(props.defautValues) 26 | 27 | return ( 28 |
39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 |
47 | ) 48 | } 49 | 50 | export default AddSchemaForm 51 | -------------------------------------------------------------------------------- /src/renderer/src/components/ConnectionForm.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react' 2 | import { Button, Form, Input, Select, Switch } from 'antd' 3 | 4 | type LayoutType = Parameters[0]['layout'] 5 | type CustomProps = { 6 | addConnection: Function 7 | defautValues?: Object 8 | } 9 | 10 | const ConnectionForm: React.FC = (props) => { 11 | const [form] = Form.useForm() 12 | const [_, setFormLayout] = useState('horizontal') 13 | const [dbType, setDbType] = useState(props.defautValues?.dialect || 'postgres') 14 | const { addConnection } = props 15 | const onFormLayoutChange = ({ layout }: { layout: LayoutType }) => { 16 | setFormLayout(layout) 17 | } 18 | 19 | const onFinish = (values) => { 20 | console.log('form values: ', form.getFieldsValue()) 21 | addConnection({ ...form.getFieldsValue(), id: props.defautValues?.id }) 22 | } 23 | 24 | const onFinishFailed = (errorInfo) => { } 25 | 26 | const changeHandler = (value) => { 27 | console.log('db value: ', value) 28 | 29 | setDbType(value) 30 | } 31 | 32 | // host: '35.221.166.196', 33 | // port: '8002', 34 | // username: 'postgres', 35 | // password: 'ZLKLMqzHy2308jU6', 36 | // dialect: 'postgres', 37 | // database: 'postgres' 38 | return ( 39 |
56 | 57 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | {dbType === 'postgres' && ( 83 | 84 | 85 | 86 | )} 87 | 88 | 89 |
90 | 91 |
92 |
93 |
94 | ) 95 | } 96 | 97 | export default ConnectionForm 98 | -------------------------------------------------------------------------------- /src/renderer/src/components/CreateDbFrom.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react' 2 | import { Button, Form, Input } from 'antd' 3 | 4 | type LayoutType = Parameters[0]['layout'] 5 | type CustomProps = { 6 | createDatabase: Function 7 | } 8 | 9 | const CreateDbForm: React.FC = (props) => { 10 | const [form] = Form.useForm() 11 | const [_, setFormLayout] = useState('horizontal') 12 | const { createDatabase } = props 13 | const onFormLayoutChange = ({ layout }: { layout: LayoutType }) => { 14 | setFormLayout(layout) 15 | } 16 | 17 | const onFinish = (values) => { 18 | createDatabase(form.getFieldsValue()) 19 | } 20 | 21 | const onFinishFailed = (errorInfo) => {} 22 | return ( 23 |
34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 |
47 | ) 48 | } 49 | 50 | export default CreateDbForm 51 | -------------------------------------------------------------------------------- /src/renderer/src/components/CreateMysqlDbForm.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react' 2 | import { Button, Form, Input, Select } from 'antd' 3 | 4 | type LayoutType = Parameters[0]['layout'] 5 | type CustomProps = { 6 | createDatabase: Function 7 | } 8 | 9 | const CreateMysqlDbForm: React.FC = (props) => { 10 | const [form] = Form.useForm() 11 | const [_, setFormLayout] = useState('horizontal') 12 | const { createDatabase } = props 13 | const onFormLayoutChange = ({ layout }: { layout: LayoutType }) => { 14 | setFormLayout(layout) 15 | } 16 | 17 | const onFinish = (values) => { 18 | createDatabase(form.getFieldsValue()) 19 | } 20 | 21 | const handleChange = (value: string[]) => { 22 | console.log(`selected ${value}`) 23 | } 24 | 25 | const characters = [ 26 | { value: 'utf8' }, 27 | { value: 'utf8mb4' }, 28 | { value: 'latin1' }, 29 | { value: 'ascii' }, 30 | { value: 'gbk' }, 31 | { value: 'big5' }, 32 | { value: 'cp1251' }, 33 | { value: 'ucs2' }, 34 | { value: 'binary' } 35 | ] 36 | const collates = [ 37 | { value: 'utf8mb4_general_ci' }, 38 | { value: 'utf8mb4_unicode_ci' }, 39 | { value: 'utf8mb4_unicode_520_ci' }, 40 | { value: 'utf8mb4_bin' }, 41 | { value: 'utf8mb4_0900_ai_ci' }, 42 | { value: 'utf8_general_ci' }, 43 | { value: 'utf8_unicode_ci' }, 44 | { value: 'utf8_bin' }, 45 | { value: 'latin1_swedish_ci' }, 46 | { value: 'latin1_general_ci' }, 47 | { value: 'latin1_bin' }, 48 | { value: 'ascii_general_ci' }, 49 | { value: 'ascii_bin' }, 50 | { value: 'gbk_chinese_ci' }, 51 | { value: 'gbk_bin' }, 52 | { value: 'big5_chinese_ci' }, 53 | { value: 'big5_bin' }, 54 | { value: 'ucs2_general_ci' }, 55 | { value: 'ucs2_unicode_ci' }, 56 | { value: 'ucs2_bin' }, 57 | { value: 'binary' } 58 | ] 59 | 60 | const onFinishFailed = (errorInfo) => { } 61 | return ( 62 |
73 | 74 | 75 | 76 | 77 | 87 | 88 | 89 | 90 | 91 | 92 |
93 | ) 94 | } 95 | 96 | export default CreateMysqlDbForm 97 | -------------------------------------------------------------------------------- /src/renderer/src/components/CreateTableForm.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react' 2 | import { Button, Form, Input, Select } from 'antd' 3 | 4 | type LayoutType = Parameters[0]['layout'] 5 | type CustomProps = { 6 | createTable: Function 7 | isMysql: boolean 8 | } 9 | 10 | const CreateTableForm: React.FC = (props) => { 11 | const [form] = Form.useForm() 12 | const [_, setFormLayout] = useState('horizontal') 13 | const { createTable } = props 14 | const onFormLayoutChange = ({ layout }: { layout: LayoutType }) => { 15 | setFormLayout(layout) 16 | } 17 | 18 | const onFinish = (values) => { 19 | createTable(form.getFieldsValue()) 20 | 21 | form.resetFields() 22 | } 23 | 24 | const onFinishFailed = (errorInfo) => { } 25 | 26 | return ( 27 |
37 | 38 | 39 | 40 | 41 | {props.isMysql && ( 42 | 43 | setSelectedKeys(e.target.value ? [e.target.value] : [])} 274 | onPressEnter={() => handleSearch(selectedKeys, confirm, dataIndex)} 275 | style={{ marginBottom: 8, display: 'block' }} 276 | /> 277 | 278 | 287 | 294 | 295 | 296 | ), 297 | filterIcon: (filtered) => ( 298 | 299 | ), 300 | onFilter: (value, record) => 301 | record[dataIndex] 302 | ? record[dataIndex].toString().toLowerCase().includes(value.toLowerCase()) 303 | : false 304 | // render: (text) => 305 | // searchedColumn === dataIndex ? ( 306 | // {text} 307 | // ) : ( 308 | // text 309 | // ) 310 | }) 311 | 312 | return ( 313 | 314 |
315 | 316 |
317 | 318 | 319 | 320 |
321 | 322 |
341 |
342 |
343 | 344 | 345 | 346 | 347 | 348 |
355 | {}} 359 | width={400} 360 | // onCollapse={(collapsed, type) => {}} 361 | // style={{ width: '300px' }} 362 | > 363 | {noCons ? ( 364 |

372 | Right click to add connection 373 |

374 | ) : ( 375 | connections.map((el, index) => { 376 | return ( 377 | 385 | ) 386 | }) 387 | )} 388 |
389 |
390 |
391 |
392 | 393 | 394 | 395 | 396 | 397 |
398 |
399 | 400 | 401 | 405 |
406 | { 410 | return ( 411 |
412 | [{item.type}] 413 | 414 | [{item.date}] {item.text} 415 | 416 | 417 | {item.affectRows || item.affectRows === 0 418 | ? `AffectRows: ${item.affectRows}` 419 | : ''} 420 | 421 | {item.sql ?

SQL: {item.sql}

: ''}
422 |
423 | ) 424 | }} 425 | /> 426 |
427 |
428 |
429 | 430 | 437 | 438 | 439 | 440 | 447 | 448 | 449 | { 455 | console.log('on cancel') 456 | setSqlListData({ ...sqlListData, show: false }) 457 | }} 458 | > 459 | Note, 463 | key: 'note', 464 | dataIndex: 'note', 465 | width: 300, 466 | ...getColumnSearchProps('note') 467 | }, 468 | { 469 | title: 'Content', 470 | key: 'content', 471 | dataIndex: 'content', 472 | // ellipsis: true, 473 | render: (text) => { 474 | return ( 475 | 476 | {text?.substring(0, 70)} 477 | 478 | ) 479 | } 480 | }, 481 | { 482 | title: 'Operater', 483 | key: 'id', 484 | dataIndex: 'operate', 485 | width: 130, 486 | render: (_, record) => { 487 | return ( 488 | 489 | copySql(record)} 491 | style={{ marginInlineEnd: 8 }} 492 | > 493 | Copy 494 | 495 | delSql(record)}> 496 | Delete 497 | 498 | 499 | ) 500 | } 501 | } 502 | ]} 503 | // rowSelection={{}} 504 | dataSource={sqlListData.list} 505 | /> 506 | 507 | 508 | 509 | 510 | ) 511 | } 512 | 513 | export default CLayout 514 | -------------------------------------------------------------------------------- /src/renderer/src/components/List.tsx: -------------------------------------------------------------------------------- 1 | import React, { forwardRef, useContext, useEffect, useRef, useState } from 'react' 2 | import { Flex, Table, Tooltip, Modal, Button } from 'antd' 3 | import type { TableProps } from 'antd' 4 | import TextArea from 'antd/es/input/TextArea' 5 | import { 6 | EditOutlined, 7 | CaretRightOutlined, 8 | DeleteOutlined, 9 | PlusOutlined, 10 | ExclamationCircleFilled, 11 | DownloadOutlined, 12 | SaveOutlined, 13 | AlignCenterOutlined 14 | } from '@ant-design/icons' 15 | import { LogAction, LogType, PGKEYS } from '@renderer/utils/constant' 16 | import CustomContext from '@renderer/utils/context' 17 | import AddRowForm from './AddRowForm' 18 | import { addLog } from '@renderer/utils/logHelper' 19 | import HighlightWithinTextarea from 'react-highlight-within-textarea' 20 | import { IGetTabData } from '@renderer/interface' 21 | import { format } from 'sql-formatter' 22 | 23 | const { confirm } = Modal 24 | 25 | type TableRowSelection = TableProps['rowSelection'] 26 | 27 | interface DataType { 28 | key: React.Key 29 | name: string 30 | age: number 31 | address: string 32 | } 33 | 34 | type CustomProps = { 35 | tabData: IGetTabData 36 | } 37 | 38 | const DataList: React.FC = (props) => { 39 | const { logList, setLogList, isDark } = useContext(CustomContext) 40 | const inputRef = useRef(null) 41 | const defaultSql = props.tabData.sql?.trim() || '' 42 | const [sqlTxt, setSqlTxt] = useState(defaultSql) 43 | const [currentSchema, setSchema] = useState(props.tabData.schema) 44 | const [tableName, setTableName] = useState(props.tabData.tableName) 45 | const [isloading, setIsloading] = useState(false) 46 | const [listRows, setListRows] = useState({ 47 | rows: [], 48 | page: 1, 49 | pageSize: 10, 50 | // pageSizeList: 51 | total: 0 52 | }) 53 | 54 | const [editRow, setEditRow] = useState({ show: false, data: { content: '', id: 0, field: '' } }) 55 | 56 | const [addForm, setAddForm] = useState(false) 57 | const [addSqlForm, setAddSqlForm] = useState(false) 58 | const [sqlNote, setSqlNote] = useState('') 59 | 60 | const [selectedRowKeys, setSelectedRowKeys] = useState([]) 61 | useEffect(() => { 62 | getAndUpdateTable(listRows) 63 | }, []) 64 | 65 | function getAndUpdateTable({ page, pageSize } = {}) { 66 | setIsloading(true) 67 | console.log('props.tabData: ', props.tabData) 68 | window.api 69 | .getTableData({ ...props.tabData, sql: sqlTxt, page, pageSize }) 70 | .then((data) => { 71 | console.log('getTableData data: ', data) 72 | if ( 73 | /^\s*(SELECT[\s\S]*?FROM|show\s+max_connections|select\s+nextval|with\s+)/i.test(sqlTxt) 74 | ) { 75 | const tableName = getTableName(sqlTxt) 76 | updateList({ listData: data, tableName: tableName, page, pageSize }) 77 | } else { 78 | addLog({ 79 | type: LogType.SUCCESS, 80 | logList, 81 | setLogList, 82 | sql: sqlTxt, 83 | affectRows: data?.length > 1 ? data[1] : null, 84 | text: 'success', 85 | action: LogAction.EDITTABLE 86 | }) 87 | } 88 | setIsloading(false) 89 | }) 90 | .catch((err) => { 91 | addLog({ 92 | type: LogType.ERROR, 93 | logList, 94 | sql: sqlTxt, 95 | setLogList, 96 | text: err.message, 97 | action: LogAction.EDITTABLE 98 | }) 99 | setIsloading(false) 100 | }) 101 | } 102 | 103 | const [columns, setColumns] = useState([]) 104 | 105 | function showEditCell(e, data) { 106 | setEditRow({ data, show: true }) 107 | } 108 | 109 | function updateList({ listData, tableName, page, pageSize }) { 110 | if (tableName) { 111 | const a = tableName.split('.') 112 | let schema = 'public' 113 | if (a.length > 1) { 114 | schema = a[0] 115 | tableName = a[1] 116 | } 117 | setTableName(tableName) 118 | setSchema(schema) 119 | } 120 | 121 | listData.rows.forEach( 122 | (el) => 123 | (el.key = `${el.id ? el.id : ''}_${new Date().getTime()}_${(Math.random() + '').replace('.', '')}`) 124 | ) 125 | 126 | listData.rows.forEach((el) => { 127 | Object.keys(el).forEach((key) => { 128 | if (el[key] === null || el[key] === undefined) { 129 | el[key] = '' 130 | } else if (typeof el[key] === 'object') { 131 | el[key] = JSON.stringify(el[key]) 132 | } else if (typeof el[key] === 'boolean') { 133 | el[key] = el[key] ? 'true' : 'false' 134 | } else { 135 | el[key] = String(el[key]) 136 | } 137 | }) 138 | }) 139 | 140 | setListRows({ 141 | ...listRows, 142 | rows: listData.rows, 143 | total: listData.total, 144 | page: page || 1, 145 | pageSize: pageSize || listRows.pageSize 146 | }) 147 | 148 | console.log('update list listRows: ', listRows) 149 | if (listRows.page === 1) { 150 | setColumns( 151 | listData.columns.map((el) => { 152 | return { 153 | title: el.name, 154 | dataIndex: el.name, 155 | key: el.name, 156 | // ellipsis: true, 157 | width: 100, 158 | render: (address, a) => { 159 | if (el.name === 'id') return address 160 | if (!address) address = '' 161 | let s = address 162 | if (address.length > 50) { 163 | s = address.substring(0, 45) + '... ' 164 | } 165 | return ( 166 |
167 | {s} 168 | 169 | { 170 |
173 | showEditCell(e, { content: address, id: a.id, field: el.name }) 174 | } 175 | > 176 | 177 |
178 | } 179 |
180 | ) 181 | } 182 | } 183 | }) 184 | ) 185 | } 186 | } 187 | 188 | const onSelectChange = (newSelectedRowKeys: React.Key[]) => { 189 | setSelectedRowKeys(newSelectedRowKeys) 190 | } 191 | 192 | const rowSelection: TableRowSelection = { 193 | selectedRowKeys, 194 | onChange: onSelectChange, 195 | selections: [ 196 | Table.SELECTION_ALL, 197 | Table.SELECTION_INVERT, 198 | Table.SELECTION_NONE, 199 | { 200 | key: 'odd', 201 | text: 'Select Odd Row', 202 | onSelect: (changeableRowKeys) => { 203 | const newSelectedRowKeys = changeableRowKeys.filter((_, index) => { 204 | if (index % 2 !== 0) { 205 | return false 206 | } 207 | return true 208 | }) 209 | setSelectedRowKeys(newSelectedRowKeys) 210 | } 211 | }, 212 | { 213 | key: 'even', 214 | text: 'Select Even Row', 215 | onSelect: (changeableRowKeys) => { 216 | const newSelectedRowKeys = changeableRowKeys.filter((_, index) => { 217 | if (index % 2 !== 0) { 218 | return true 219 | } 220 | return false 221 | }) 222 | setSelectedRowKeys(newSelectedRowKeys) 223 | } 224 | } 225 | ] 226 | } 227 | 228 | function editRowOk() { 229 | const editData = listRows.rows.find((el) => el.id === editRow.data.id) 230 | if (!editData) { 231 | setEditRow({ show: false, data: { content: '', id: 0, field: '' } }) 232 | return 233 | } 234 | 235 | if (editData[editRow.data.field] === editRow.data.content) { 236 | setEditRow({ show: false, data: { content: '', id: 0, field: '' } }) 237 | return 238 | } 239 | 240 | console.log('edit row: ', props.tabData) 241 | window.api 242 | .updateDate({ 243 | tableName: tableName, 244 | dataId: editRow.data.id, 245 | data: { field: editRow.data.field, value: editRow.data.content }, 246 | type: 2, 247 | id: props.tabData.id 248 | }) 249 | .then(() => { 250 | // setListRows(newData); 251 | setEditRow({ show: false, data: { content: '', id: 0, field: '' } }) 252 | 253 | getAndUpdateTable(listRows) 254 | }) 255 | .catch((error) => { 256 | addDbError({ error }) 257 | }) 258 | } 259 | 260 | function addDbError({ error }) { 261 | addLog({ 262 | logList, 263 | setLogList, 264 | text: error?.message, 265 | action: LogAction.DBCONNECTION, 266 | type: LogType.ERROR 267 | }) 268 | } 269 | 270 | function editRowCancel() { 271 | setEditRow({ show: false, data: { content: '', id: 0, field: '' } }) 272 | } 273 | 274 | function runSql() { 275 | sqlHandler() 276 | } 277 | 278 | function addRow() { 279 | setAddForm(true) 280 | } 281 | function cancelAddRow() { 282 | setAddForm(false) 283 | } 284 | 285 | function getTableName(sql) { 286 | if (!sql) { 287 | throw new Error(`${sql} error`) 288 | } 289 | 290 | const a = sql.replaceAll('\n', '').split(/from/i) 291 | if (a.length < 2) { 292 | return '' 293 | } 294 | const b = a[1].split(' ') 295 | 296 | return b.find((el) => !!el) 297 | } 298 | 299 | function saveSqlShow() { 300 | setAddSqlForm(true) 301 | } 302 | 303 | function saveSql() { 304 | window.api 305 | .addStore({ 306 | data: { 307 | content: sqlTxt, 308 | note: sqlNote 309 | }, 310 | type: 2 311 | }) 312 | .then((res) => { 313 | console.log('save res', res) 314 | setAddSqlForm(false) 315 | setSqlNote('') 316 | addLog({ 317 | logList, 318 | setLogList, 319 | type: LogType.SUCCESS, 320 | text: `save success `, 321 | action: LogAction.SAVESQL 322 | }) 323 | }) 324 | .catch((error) => { 325 | addLog({ 326 | logList, 327 | setLogList, 328 | type: LogType.ERROR, 329 | text: `save data fail, ${error.message}`, 330 | action: LogAction.EXPORTDATA 331 | }) 332 | }) 333 | } 334 | 335 | function exportData() { 336 | window.api 337 | .exportFile({ ...props.tabData, sql: sqlTxt }) 338 | .then((res) => { 339 | console.log('exportData res', res) 340 | if (res.code === 0) { 341 | addLog({ 342 | logList, 343 | setLogList, 344 | type: LogType.SUCCESS, 345 | text: `export data success, path: ${res.path}`, 346 | action: LogAction.EXPORTDATA 347 | }) 348 | } 349 | }) 350 | .catch((error) => { 351 | addLog({ 352 | logList, 353 | setLogList, 354 | type: LogType.ERROR, 355 | text: `export data fail, ${error.message}`, 356 | action: LogAction.EXPORTDATA 357 | }) 358 | }) 359 | } 360 | 361 | function sqlHandler() { 362 | getAndUpdateTable() 363 | } 364 | 365 | function addRowData(data) { 366 | setAddForm(false) 367 | console.log('add row data: ', props.tabData) 368 | window.api 369 | .addRow({ 370 | tableName, 371 | id: props.tabData.id, 372 | fields: data, 373 | schema: props.tabData.schema 374 | }) 375 | .then(() => { 376 | if (/^\s*\bselect\b/i.test(sqlTxt)) { 377 | getAndUpdateTable({ page: 1, pageSize: listRows.pageSize }) 378 | } 379 | }) 380 | .catch((error) => { 381 | addDbError({ error }) 382 | }) 383 | } 384 | 385 | function formatSql() { 386 | const formatRes = format(sqlTxt, { 387 | language: 'postgresql', 388 | tabWidth: 2, 389 | keywordCase: 'upper', 390 | linesBetweenQueries: 2 391 | }) 392 | setSqlTxt(formatRes) 393 | } 394 | 395 | function delRow() { 396 | // if (!selectedRowKeys.length) { 397 | // 404 | // } 405 | confirm({ 406 | title: 'Do you want to delete these rows?', 407 | icon: , 408 | content: '', 409 | onOk() { 410 | const delIds = selectedRowKeys 411 | 412 | window.api 413 | .delRows({ ...props.tabData, ids: delIds, schema: currentSchema, tableName: tableName }) 414 | .then((data) => { 415 | if (/^\s*select/i.test(sqlTxt)) { 416 | getAndUpdateTable({ page: 1, pageSize: listRows.pageSize }) 417 | } 418 | 419 | addLog({ 420 | type: LogType.SUCCESS, 421 | logList, 422 | setLogList, 423 | affectRows: data?.length > 1 ? data[1] : null, 424 | text: 'success', 425 | action: LogAction.DELETEROWS 426 | }) 427 | }) 428 | .catch((error) => { 429 | addDbError({ error }) 430 | }) 431 | }, 432 | onCancel() {} 433 | }) 434 | } 435 | 436 | function pageChange(page, pageSize) { 437 | if (pageSize !== listRows.pageSize) { 438 | page = 1 439 | } 440 | 441 | if (!/\blimit\b/i.test(sqlTxt)) { 442 | getAndUpdateTable({ page, pageSize }) 443 | } else { 444 | setListRows((a) => { 445 | return { ...a, page } 446 | }) 447 | } 448 | } 449 | const onChange = (value) => setSqlTxt(value || '') 450 | const sqlRemarkChange = (e: React.ChangeEvent) => { 451 | console.log('Change:', e.target.value) 452 | setSqlNote(e.target.value) 453 | } 454 | return ( 455 |
456 |
466 | 477 |
478 | 479 | 480 | 481 |
535 | 536 | 537 |