fdb2 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/.dockerignore +21 -0
  2. package/.editorconfig +11 -0
  3. package/.eslintrc.cjs +14 -0
  4. package/.eslintrc.json +7 -0
  5. package/.prettierrc.js +3 -0
  6. package/.tpl.env +22 -0
  7. package/README.md +260 -0
  8. package/bin/build.sh +28 -0
  9. package/bin/deploy.sh +8 -0
  10. package/bin/dev.sh +10 -0
  11. package/bin/docker/.env +4 -0
  12. package/bin/docker/dev-docker-compose.yml +43 -0
  13. package/bin/docker/dev.Dockerfile +24 -0
  14. package/bin/docker/prod-docker-compose.yml +17 -0
  15. package/bin/docker/prod.Dockerfile +29 -0
  16. package/bin/fdb2.js +142 -0
  17. package/data/connections.demo.json +32 -0
  18. package/env.d.ts +1 -0
  19. package/nw-build.js +120 -0
  20. package/nw-dev.js +65 -0
  21. package/package.json +114 -0
  22. package/public/favicon.ico +0 -0
  23. package/public/index.html +9 -0
  24. package/public/modules/header.tpl +14 -0
  25. package/public/modules/initial_state.tpl +55 -0
  26. package/server/index.ts +677 -0
  27. package/server/model/connection.entity.ts +66 -0
  28. package/server/model/database.entity.ts +246 -0
  29. package/server/service/connection.service.ts +334 -0
  30. package/server/service/database/base.service.ts +363 -0
  31. package/server/service/database/database.service.ts +510 -0
  32. package/server/service/database/index.ts +7 -0
  33. package/server/service/database/mssql.service.ts +723 -0
  34. package/server/service/database/mysql.service.ts +761 -0
  35. package/server/service/database/oracle.service.ts +839 -0
  36. package/server/service/database/postgres.service.ts +744 -0
  37. package/server/service/database/sqlite.service.ts +559 -0
  38. package/server/service/session.service.ts +158 -0
  39. package/server.js +128 -0
  40. package/src/adapter/ajax.ts +135 -0
  41. package/src/assets/base.css +1 -0
  42. package/src/assets/database.css +950 -0
  43. package/src/assets/images/collapse.png +0 -0
  44. package/src/assets/images/no-login.png +0 -0
  45. package/src/assets/images/svg/illustrations/illustration-1.svg +1 -0
  46. package/src/assets/images/svg/illustrations/illustration-2.svg +2 -0
  47. package/src/assets/images/svg/illustrations/illustration-3.svg +50 -0
  48. package/src/assets/images/svg/illustrations/illustration-4.svg +1 -0
  49. package/src/assets/images/svg/illustrations/illustration-5.svg +73 -0
  50. package/src/assets/images/svg/illustrations/illustration-6.svg +89 -0
  51. package/src/assets/images/svg/illustrations/illustration-7.svg +39 -0
  52. package/src/assets/images/svg/illustrations/illustration-8.svg +1 -0
  53. package/src/assets/images/svg/separators/curve-2.svg +3 -0
  54. package/src/assets/images/svg/separators/curve.svg +3 -0
  55. package/src/assets/images/svg/separators/line.svg +3 -0
  56. package/src/assets/images/theme/light/screen-1-1000x800.jpg +0 -0
  57. package/src/assets/images/theme/light/screen-2-1000x800.jpg +0 -0
  58. package/src/assets/login/bg.jpg +0 -0
  59. package/src/assets/login/bg.png +0 -0
  60. package/src/assets/login/left.jpg +0 -0
  61. package/src/assets/logo.svg +73 -0
  62. package/src/assets/logo.webp +0 -0
  63. package/src/assets/main.css +1 -0
  64. package/src/base/config.ts +20 -0
  65. package/src/base/detect.ts +134 -0
  66. package/src/base/entity.ts +92 -0
  67. package/src/base/eventBus.ts +37 -0
  68. package/src/base//345/237/272/347/241/200/345/261/202.md +7 -0
  69. package/src/components/connection-editor/index.vue +590 -0
  70. package/src/components/dataGrid/index.vue +105 -0
  71. package/src/components/dataGrid/pagination.vue +106 -0
  72. package/src/components/loading/index.vue +43 -0
  73. package/src/components/modal/index.ts +181 -0
  74. package/src/components/modal/index.vue +560 -0
  75. package/src/components/toast/index.ts +44 -0
  76. package/src/components/toast/toast.vue +58 -0
  77. package/src/components/user/name.vue +104 -0
  78. package/src/components/user/selector.vue +416 -0
  79. package/src/domain/SysConfig.ts +74 -0
  80. package/src/platform/App.vue +8 -0
  81. package/src/platform/database/components/connection-detail.vue +1154 -0
  82. package/src/platform/database/components/data-editor.vue +478 -0
  83. package/src/platform/database/components/data-import-export.vue +1602 -0
  84. package/src/platform/database/components/database-detail.vue +1173 -0
  85. package/src/platform/database/components/database-monitor.vue +1086 -0
  86. package/src/platform/database/components/db-tools.vue +577 -0
  87. package/src/platform/database/components/query-history.vue +1349 -0
  88. package/src/platform/database/components/sql-executor.vue +738 -0
  89. package/src/platform/database/components/sql-query-editor.vue +1046 -0
  90. package/src/platform/database/components/table-detail.vue +1376 -0
  91. package/src/platform/database/components/table-editor.vue +690 -0
  92. package/src/platform/database/explorer.vue +1840 -0
  93. package/src/platform/database/index.vue +1193 -0
  94. package/src/platform/database/layout.vue +367 -0
  95. package/src/platform/database/router.ts +37 -0
  96. package/src/platform/database/styles/common.scss +602 -0
  97. package/src/platform/database/types/common.ts +445 -0
  98. package/src/platform/database/utils/export.ts +232 -0
  99. package/src/platform/database/utils/helpers.ts +437 -0
  100. package/src/platform/index.ts +33 -0
  101. package/src/platform/router.ts +41 -0
  102. package/src/service/base.ts +128 -0
  103. package/src/service/database.ts +500 -0
  104. package/src/service/login.ts +121 -0
  105. package/src/shims-vue.d.ts +7 -0
  106. package/src/stores/connection.ts +266 -0
  107. package/src/stores/session.ts +87 -0
  108. package/src/typings/database-types.ts +413 -0
  109. package/src/typings/database.ts +364 -0
  110. package/src/typings/global.d.ts +58 -0
  111. package/src/typings/pinia.d.ts +8 -0
  112. package/src/utils/clipboard.ts +30 -0
  113. package/src/utils/database-types.ts +243 -0
  114. package/src/utils/modal.ts +124 -0
  115. package/src/utils/request.ts +55 -0
  116. package/src/utils/sleep.ts +4 -0
  117. package/src/utils/toast.ts +73 -0
  118. package/src/utils/util.ts +171 -0
  119. package/src/utils/xlsx.ts +228 -0
  120. package/tsconfig.json +33 -0
  121. package/tsconfig.server.json +19 -0
  122. package/view/index.html +9 -0
  123. package/view/modules/header.tpl +14 -0
  124. package/view/modules/initial_state.tpl +20 -0
  125. package/vite.config.ts +384 -0
package/nw-build.js ADDED
@@ -0,0 +1,120 @@
1
+ const nwbuilder = require('nw-builder');
2
+ const { resolve, join } = require('path');
3
+ const { copyFileSync, existsSync, rmSync, readdirSync } = require('fs');
4
+
5
+ // 解析命令行参数
6
+ const args = process.argv.slice(2);
7
+ const targetPlatform = args.find(arg => arg.startsWith('--platform='))?.split('=')[1];
8
+
9
+ async function build() {
10
+ try {
11
+ console.log('开始构建 NW.js 应用...');
12
+
13
+ // 首先构建 Vue 应用
14
+ console.log('1. 构建 Vue 应用...');
15
+ const { execSync } = require('child_process');
16
+ execSync('npm run build', { stdio: 'inherit' });
17
+
18
+ console.log('2. 复制 package.json 到 dist 目录...');
19
+ const srcPackageJson = join(__dirname, 'package.json');
20
+ const destPackageJson = join(__dirname, 'dist', 'package.json');
21
+ if (existsSync(srcPackageJson)) {
22
+ copyFileSync(srcPackageJson, destPackageJson);
23
+ console.log('package.json 复制成功');
24
+ } else {
25
+ throw new Error('未找到 package.json 文件');
26
+ }
27
+
28
+ console.log('3. 安装 npm 依赖到 dist 目录...');
29
+ // 使用绝对路径执行 npm install 命令
30
+ const distPath = resolve(__dirname, 'dist');
31
+ console.log('Dist 路径:', distPath);
32
+
33
+ // 执行 npm install 命令
34
+ execSync('pnpm install --only=production', {
35
+ stdio: 'inherit',
36
+ cwd: distPath
37
+ });
38
+
39
+ // 检查 node_modules 目录是否创建成功
40
+ const nodeModulesPath = join(distPath, 'node_modules');
41
+ if (existsSync(nodeModulesPath)) {
42
+ console.log('npm 依赖安装成功');
43
+ console.log('node_modules 目录大小:', readdirSync(nodeModulesPath).length, '个包');
44
+ } else {
45
+ throw new Error('npm install 失败,node_modules 目录未创建');
46
+ }
47
+
48
+ console.log('4. 配置 NW.js 构建参数...');
49
+
50
+ // 根据命令行参数或当前操作系统确定要构建的平台
51
+ let platform;
52
+ if (targetPlatform) {
53
+ platform = targetPlatform;
54
+ console.log(`使用命令行指定的平台: ${platform}`);
55
+ } else {
56
+ platform = process.platform === 'darwin' ? 'osx' :
57
+ process.platform === 'linux' ? 'linux' : 'win';
58
+ console.log(`使用当前操作系统平台: ${platform}`);
59
+ }
60
+
61
+ // 为每个平台使用不同的输出目录
62
+ const outDir = resolve(__dirname, `nw-build-${platform}`);
63
+ console.log(`输出目录: ${outDir}`);
64
+
65
+ console.log(`\n正在构建 ${platform} 平台...`);
66
+
67
+ const buildOptions = {
68
+ mode: 'build',
69
+ srcDir: distPath,
70
+ version: '0.78.1',
71
+ flavor: 'normal',
72
+ platform: platform,
73
+ arch: 'x64',
74
+ outDir: outDir,
75
+ cacheDir: resolve(__dirname, 'nw-cache'),
76
+ zip: false,
77
+ downloadUrl: 'https://dl.nwjs.io',
78
+ logLevel: 'info',
79
+ glob: false,
80
+ app: {
81
+ icon: resolve(__dirname, 'public', 'favicon.ico')
82
+ }
83
+ };
84
+
85
+ // macOS 平台需要额外的配置
86
+ if (platform === 'osx') {
87
+ buildOptions.app.LSApplicationCategoryType = 'public.app-category.productivity';
88
+ buildOptions.app.NSHumanReadableCopyright = 'Copyright © 2025';
89
+ buildOptions.app.NSLocalNetworkUsageDescription = '需要网络访问以连接数据库';
90
+ buildOptions.app.CFBundleIdentifier = 'com.fdb.database';
91
+ buildOptions.app.CFBundleName = '数据库管理工具';
92
+ buildOptions.app.CFBundleDisplayName = '数据库管理工具';
93
+ buildOptions.app.CFBundleShortVersionString = '1.0.0';
94
+ buildOptions.app.CFBundleVersion = '1.0.0';
95
+ }
96
+
97
+ await nwbuilder.default(buildOptions);
98
+
99
+ console.log(`✅ ${platform} 平台构建完成`);
100
+
101
+ console.log('\n5. 打包完成!');
102
+ console.log(`应用已生成在: ${outDir}`);
103
+
104
+ // 验证打包后的应用程序
105
+ const packagedNodeModulesPath = join(outDir, platform, 'x64', 'package.nw', 'node_modules');
106
+ if (existsSync(packagedNodeModulesPath)) {
107
+ console.log(`✅ ${platform} 应用程序已包含 node_modules 目录`);
108
+ console.log(`✅ ${platform} 依赖包数量:`, readdirSync(packagedNodeModulesPath).length, '个');
109
+ } else {
110
+ console.warn(`⚠️ ${platform} 应用程序不包含 node_modules 目录`);
111
+ }
112
+
113
+ } catch (error) {
114
+ console.error('构建过程中出错:', error);
115
+ process.exit(1);
116
+ }
117
+ }
118
+
119
+ // 开始构建
120
+ build();
package/nw-dev.js ADDED
@@ -0,0 +1,65 @@
1
+ const { exec } = require('child_process');
2
+ const { createServer } = require('http');
3
+ const { join, resolve } = require('path');
4
+
5
+ // 启动 Vite 开发服务器
6
+ const viteProcess = exec('npm run dev', (error, stdout, stderr) => {
7
+ if (error) {
8
+ console.error(`执行 npm run dev 时出错: ${error}`);
9
+ return;
10
+ }
11
+ console.log(`stdout: ${stdout}`);
12
+ console.error(`stderr: ${stderr}`);
13
+ });
14
+
15
+ viteProcess.stdout.on('data', (data) => {
16
+ console.log(data);
17
+ // 当 Vite 服务器启动成功后,启动 NW.js
18
+ if (data.includes('ready')) {
19
+ setTimeout(() => {
20
+ console.log('starting NW.js...', 'npx nw . --url=http://localhost:9300');
21
+ const nwProcess = exec('npx nw . --url=http://localhost:9300', (error, stdout, stderr) => {
22
+ if (error) {
23
+ console.error(`启动 NW.js 时出错: ${error}`);
24
+ return;
25
+ }
26
+ console.log(`stdout: ${stdout}`);
27
+ console.error(`stderr: ${stderr}`);
28
+ });
29
+
30
+ nwProcess.stdout.on('data', (data) => {
31
+ console.log(data);
32
+ });
33
+
34
+ nwProcess.stderr.on('data', (data) => {
35
+ console.error(data);
36
+ });
37
+
38
+ nwProcess.on('close', (code) => {
39
+ console.log(`NW.js 进程退出,代码: ${code}`);
40
+ viteProcess.kill();
41
+ });
42
+
43
+ // 处理退出信号
44
+ process.on('SIGINT', () => {
45
+ nwProcess.kill();
46
+ viteProcess.kill();
47
+ process.exit();
48
+ });
49
+
50
+ process.on('SIGTERM', () => {
51
+ nwProcess.kill();
52
+ viteProcess.kill();
53
+ process.exit();
54
+ });
55
+ }, 2000);
56
+ }
57
+ });
58
+
59
+ viteProcess.stderr.on('data', (data) => {
60
+ console.error(data);
61
+ });
62
+
63
+ viteProcess.on('close', (code) => {
64
+ console.log(`Vite 进程退出,代码: ${code}`);
65
+ });
package/package.json ADDED
@@ -0,0 +1,114 @@
1
+ {
2
+ "name": "fdb2",
3
+ "version": "1.0.0",
4
+ "private": false,
5
+ "type": "commonjs",
6
+ "main": "view/index.html",
7
+ "window": {
8
+ "title": "数据库管理工具",
9
+ "width": 1200,
10
+ "height": 800,
11
+ "min_width": 800,
12
+ "min_height": 600,
13
+ "resizable": true,
14
+ "show_in_taskbar": true,
15
+ "frame": true,
16
+ "icon": "public/favicon.ico"
17
+ },
18
+ "scripts": {
19
+ "start": "pm2 start server.js --name fdb2-server --disable-logs --",
20
+ "restart": "pm2 restart fdb2-server --disable-logs --",
21
+ "stop": "pm2 stop fdb2-server --",
22
+ "dev": "vite",
23
+ "build": "npm run build-only",
24
+ "preview": "vite preview",
25
+ "test:unit": "vitest",
26
+ "build-only": "vite build && npm run build-server",
27
+ "build-server": "tsc -p tsconfig.server.json",
28
+ "move-assets": "node move-assets.cjs",
29
+ "type-check": "vue-tsc --noEmit --composite false",
30
+ "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
31
+ "nw:dev": "node nw-dev.js",
32
+ "nw:build": "node nw-build.js",
33
+ "nw:build:win": "node nw-build.js --platform=win",
34
+ "nw:build:osx": "node nw-build.js --platform=osx",
35
+ "nw:build:linux": "node nw-build.js --platform=linux",
36
+ "pkg:server": "cd d:/code/ycnull/db_tool && pkg dist/server/index.js -t node18-win-x64 -o dist/server/server.exe",
37
+ "build:server:pkg": "ncc build server/index.ts -o dist/server/pkg"
38
+ },
39
+ "dependencies": {
40
+ "@fefeding/common": "^1.0.58",
41
+ "axios": "^1.13.4",
42
+ "dayjs": "^1.11.19",
43
+ "express": "^5.2.1",
44
+ "mysql2": "^3.16.2",
45
+ "pg": "^8.17.2",
46
+ "pm2": "^6.0.14",
47
+ "reflect-metadata": "^0.2.2",
48
+ "sqlite3": "^5.1.7",
49
+ "typeorm": "^0.3.28"
50
+ },
51
+ "devDependencies": {
52
+ "@codemirror/commands": "^6.10.1",
53
+ "@codemirror/fold": "^0.19.4",
54
+ "@codemirror/lang-json": "^6.0.2",
55
+ "@codemirror/lang-sql": "^6.10.0",
56
+ "@codemirror/language": "^6.12.1",
57
+ "@codemirror/state": "^6.5.4",
58
+ "@codemirror/theme-one-dark": "^6.1.3",
59
+ "@codemirror/view": "^6.39.11",
60
+ "@fefeding/eventemitter": "^1.0.5",
61
+ "@fefeding/vite-nunjucks-plugin": "^1.0.2",
62
+ "@popperjs/core": "^2.11.8",
63
+ "@rollup/pluginutils": "^5.3.0",
64
+ "@types/bootstrap": "^5.2.10",
65
+ "@types/jsdom": "^21.1.7",
66
+ "@types/node": "^24.10.9",
67
+ "@types/vue": "^2.0.0",
68
+ "@vitejs/plugin-vue": "^6.0.3",
69
+ "@vitejs/plugin-vue-jsx": "^5.1.3",
70
+ "@vue/tsconfig": "^0.8.1",
71
+ "@vueuse/core": "^13.9.0",
72
+ "@zumer/snapdom": "^1.9.14",
73
+ "autoprefixer": "^10.4.23",
74
+ "bootstrap": "^5.3.8",
75
+ "bootstrap-icons": "^1.13.1",
76
+ "codemirror": "^6.0.2",
77
+ "dotenv": "^17.2.3",
78
+ "echarts": "^6.0.0",
79
+ "exceljs": "^4.4.0",
80
+ "js-cookie": "^3.0.5",
81
+ "jsdom": "^26.1.0",
82
+ "jszip": "^3.10.1",
83
+ "nw": "^0.107.0",
84
+ "nw-builder": "^4.17.2",
85
+ "pinia": "^3.0.4",
86
+ "pinia-plugin-persistedstate": "^4.7.1",
87
+ "postcss": "^8.5.6",
88
+ "sass": "^1.97.3",
89
+ "tailwindcss": "^3.4.19",
90
+ "typescript": "^5.9.3",
91
+ "vconsole": "^3.15.1",
92
+ "vite": "latest",
93
+ "vite-plugin-files-copy": "^3.8.0",
94
+ "vitest": "^3.2.4",
95
+ "vue": "^3.5.27",
96
+ "vue-json-pretty": "^2.6.0",
97
+ "vue-router": "^4.6.4",
98
+ "vue-tsc": "^3.2.4",
99
+ "vuex": "^4.1.0",
100
+ "xlsx": "^0.18.5"
101
+ },
102
+ "bin": {
103
+ "fdb2": "bin/fdb2.js"
104
+ },
105
+ "pkg": {
106
+ "scripts": [
107
+ "dist/server/**/*.js"
108
+ ],
109
+ "assets": [
110
+ "dist/node_modules/**/*",
111
+ "dist/client/**/*"
112
+ ]
113
+ }
114
+ }
Binary file
@@ -0,0 +1,9 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ {% include "./modules/header.tpl" %}
4
+ <body>
5
+ <div id="app" class="min-vh-100"></div>
6
+ <script type="module" lang="ts" src="{{prefix}}/src/platform/index.ts">
7
+ </script>
8
+ </body>
9
+ </html>
@@ -0,0 +1,14 @@
1
+ <head>
2
+ <meta charset="UTF-8" />
3
+ <base href="{{viteTarget}}" />
4
+ {% include "./initial_state.tpl" %}
5
+ <link rel="icon" href="{{prefix}}/public/favicon.png" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>数据库管理</title>
8
+ <meta name="description" content="{{description}}">
9
+ <script>
10
+ window.addEventListener('vite:preloadError', function (event) {
11
+ console.error(event);
12
+ });
13
+ </script>
14
+ </head>
@@ -0,0 +1,55 @@
1
+ <script type="text/template" id="__INITIAL_STATE__">
2
+ {{ data | dump | safe }}
3
+ </script>
4
+ <script type="text/template" id="__DEFAULTINITIAL_STATE__">
5
+ {{ __DEFAULTINITIAL_STATE__ }}
6
+ </script>
7
+ <script>
8
+ function __get_templateJson(id) {
9
+ try {
10
+ var tag = document.getElementById(id);
11
+ var obj = JSON.parse(tag.innerHTML);
12
+ return obj;
13
+ }
14
+ catch (e) {
15
+ return null;
16
+ }
17
+ }
18
+ var __INITIAL_STATE__ = __get_templateJson('__INITIAL_STATE__');
19
+ if(!__INITIAL_STATE__) __INITIAL_STATE__ = __get_templateJson('__DEFAULTINITIAL_STATE__');
20
+ // 动态加载入口
21
+ function __vitejs_load_entry(url, type) {
22
+ if(!url) return;
23
+ if(url.indexOf('/') !== 0) url = '/' + url;
24
+ var prefix = (window.__INITIAL_STATE__ && window.__INITIAL_STATE__.config && window.__INITIAL_STATE__.config.prefix) || '';
25
+ if(prefix && url.indexOf(prefix) !== 0) {
26
+ url = prefix + url;
27
+ }
28
+ var nodeObj;
29
+ switch(type) {
30
+ case 'script': {
31
+ // 检查是否已加载过
32
+ var existing = document.querySelector(`script[src="${url}"]`);
33
+ if(existing) return;
34
+ nodeObj = document.createElement('script');
35
+ nodeObj.src = url;
36
+ nodeObj.type = 'module';
37
+ break;
38
+ }
39
+ case 'stylesheet':
40
+ case 'modulepreload':
41
+ case 'icon': {
42
+ // 检查是否已加载过
43
+ var existing = document.querySelector(`link[href="${url}"]`);
44
+ if(existing) return;
45
+ nodeObj = document.createElement('link');
46
+ nodeObj.href = url;
47
+ nodeObj.rel = type;
48
+ break;
49
+ }
50
+ }
51
+ if(!nodeObj) return;
52
+ nodeObj.crossOrigin = 'crossorigin';
53
+ document.head.appendChild(nodeObj);
54
+ }
55
+ </script>