@nocobase/cli 2.1.0-alpha.3 → 2.1.0-alpha.30

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 (182) hide show
  1. package/LICENSE.txt +107 -0
  2. package/README.md +379 -19
  3. package/README.zh-CN.md +329 -0
  4. package/bin/run.cmd +3 -0
  5. package/bin/run.js +131 -0
  6. package/dist/commands/api/resource/create.js +15 -0
  7. package/dist/commands/api/resource/destroy.js +15 -0
  8. package/dist/commands/api/resource/get.js +15 -0
  9. package/dist/commands/api/resource/index.js +20 -0
  10. package/dist/commands/api/resource/list.js +16 -0
  11. package/dist/commands/api/resource/query.js +15 -0
  12. package/dist/commands/api/resource/update.js +15 -0
  13. package/dist/commands/app/down.js +266 -0
  14. package/dist/commands/app/logs.js +98 -0
  15. package/dist/commands/app/restart.js +75 -0
  16. package/dist/commands/app/start.js +253 -0
  17. package/dist/commands/app/stop.js +99 -0
  18. package/dist/commands/app/upgrade.js +582 -0
  19. package/{src/cli.js → dist/commands/build.js} +4 -11
  20. package/dist/commands/config/delete.js +30 -0
  21. package/dist/commands/config/get.js +29 -0
  22. package/dist/commands/config/index.js +20 -0
  23. package/dist/commands/config/list.js +29 -0
  24. package/dist/commands/config/set.js +35 -0
  25. package/dist/commands/db/check.js +238 -0
  26. package/dist/commands/db/logs.js +85 -0
  27. package/dist/commands/db/ps.js +60 -0
  28. package/dist/commands/db/shared.js +96 -0
  29. package/dist/commands/db/start.js +71 -0
  30. package/dist/commands/db/stop.js +71 -0
  31. package/{templates/plugin/src/client/models/index.ts → dist/commands/dev.js} +4 -4
  32. package/{src/index.js → dist/commands/down.js} +4 -6
  33. package/{src/commands/locale/react-js-cron/index.js → dist/commands/download.js} +4 -8
  34. package/dist/commands/env/add.js +312 -0
  35. package/dist/commands/env/auth.js +55 -0
  36. package/dist/commands/env/info.js +156 -0
  37. package/dist/commands/env/list.js +50 -0
  38. package/dist/commands/env/remove.js +59 -0
  39. package/dist/commands/env/shared.js +158 -0
  40. package/dist/commands/env/update.js +67 -0
  41. package/dist/commands/env/use.js +28 -0
  42. package/dist/commands/examples/prompts-stages.js +150 -0
  43. package/dist/commands/examples/prompts-test.js +181 -0
  44. package/dist/commands/init.js +1027 -0
  45. package/dist/commands/install.js +2206 -0
  46. package/dist/commands/license/activate.js +360 -0
  47. package/dist/commands/license/env.js +94 -0
  48. package/dist/commands/license/generate-id.js +108 -0
  49. package/dist/commands/license/id.js +56 -0
  50. package/dist/commands/license/index.js +20 -0
  51. package/dist/commands/license/plugins/clean.js +101 -0
  52. package/dist/commands/license/plugins/index.js +20 -0
  53. package/dist/commands/license/plugins/list.js +50 -0
  54. package/dist/commands/license/plugins/shared.js +325 -0
  55. package/dist/commands/license/plugins/sync.js +269 -0
  56. package/dist/commands/license/shared.js +414 -0
  57. package/dist/commands/license/status.js +50 -0
  58. package/dist/commands/logs.js +12 -0
  59. package/dist/commands/plugin/disable.js +66 -0
  60. package/dist/commands/plugin/enable.js +66 -0
  61. package/dist/commands/plugin/list.js +62 -0
  62. package/dist/commands/pm/disable.js +12 -0
  63. package/dist/commands/pm/enable.js +12 -0
  64. package/dist/commands/pm/list.js +12 -0
  65. package/dist/commands/restart.js +12 -0
  66. package/dist/commands/scaffold/migration.js +38 -0
  67. package/dist/commands/scaffold/plugin.js +37 -0
  68. package/dist/commands/self/check.js +71 -0
  69. package/dist/commands/self/index.js +20 -0
  70. package/dist/commands/self/update.js +86 -0
  71. package/dist/commands/skills/check.js +69 -0
  72. package/dist/commands/skills/index.js +20 -0
  73. package/dist/commands/skills/install.js +71 -0
  74. package/dist/commands/skills/remove.js +71 -0
  75. package/dist/commands/skills/update.js +78 -0
  76. package/dist/commands/source/build.js +58 -0
  77. package/dist/commands/source/dev.js +158 -0
  78. package/dist/commands/source/download.js +866 -0
  79. package/dist/commands/source/test.js +467 -0
  80. package/dist/commands/start.js +12 -0
  81. package/dist/commands/stop.js +12 -0
  82. package/dist/commands/test.js +12 -0
  83. package/dist/commands/upgrade.js +12 -0
  84. package/dist/generated/command-registry.js +133 -0
  85. package/dist/help/runtime-help.js +23 -0
  86. package/dist/lib/api-client.js +329 -0
  87. package/dist/lib/app-health.js +126 -0
  88. package/dist/lib/app-managed-resources.js +268 -0
  89. package/dist/lib/app-runtime.js +171 -0
  90. package/dist/lib/auth-store.js +328 -0
  91. package/dist/lib/bootstrap.js +384 -0
  92. package/dist/lib/build-config.js +18 -0
  93. package/dist/lib/builtin-db.js +86 -0
  94. package/dist/lib/cli-config.js +176 -0
  95. package/dist/lib/cli-home.js +47 -0
  96. package/dist/lib/cli-locale.js +129 -0
  97. package/dist/lib/command-discovery.js +39 -0
  98. package/dist/lib/db-connection-check.js +178 -0
  99. package/dist/lib/env-auth.js +872 -0
  100. package/dist/lib/env-config.js +87 -0
  101. package/dist/lib/generated-command.js +171 -0
  102. package/dist/lib/http-request.js +49 -0
  103. package/dist/lib/naming.js +70 -0
  104. package/dist/lib/openapi.js +62 -0
  105. package/dist/lib/plugin-storage.js +127 -0
  106. package/dist/lib/post-processors.js +23 -0
  107. package/dist/lib/prompt-catalog.js +581 -0
  108. package/dist/lib/prompt-validators.js +185 -0
  109. package/dist/lib/prompt-web-ui.js +2103 -0
  110. package/dist/lib/resource-command.js +343 -0
  111. package/dist/lib/resource-request.js +104 -0
  112. package/dist/lib/run-npm.js +250 -0
  113. package/dist/lib/runtime-env-vars.js +32 -0
  114. package/dist/lib/runtime-generator.js +498 -0
  115. package/dist/lib/runtime-store.js +56 -0
  116. package/dist/lib/self-manager.js +301 -0
  117. package/dist/lib/skills-manager.js +296 -0
  118. package/dist/lib/startup-update.js +281 -0
  119. package/dist/lib/ui.js +178 -0
  120. package/dist/locale/en-US.json +339 -0
  121. package/dist/locale/zh-CN.json +339 -0
  122. package/dist/post-processors/data-modeling.js +66 -0
  123. package/dist/post-processors/data-source-manager.js +114 -0
  124. package/dist/post-processors/index.js +19 -0
  125. package/nocobase-ctl.config.json +369 -0
  126. package/package.json +95 -26
  127. package/LICENSE +0 -661
  128. package/bin/index.js +0 -39
  129. package/nocobase.conf.tpl +0 -95
  130. package/src/commands/benchmark.js +0 -73
  131. package/src/commands/build.js +0 -49
  132. package/src/commands/clean.js +0 -30
  133. package/src/commands/client.js +0 -166
  134. package/src/commands/create-nginx-conf.js +0 -37
  135. package/src/commands/create-plugin.js +0 -33
  136. package/src/commands/dev.js +0 -200
  137. package/src/commands/doc.js +0 -76
  138. package/src/commands/e2e.js +0 -265
  139. package/src/commands/global.js +0 -43
  140. package/src/commands/index.js +0 -45
  141. package/src/commands/instance-id.js +0 -47
  142. package/src/commands/locale/cronstrue.js +0 -122
  143. package/src/commands/locale/react-js-cron/en-US.json +0 -75
  144. package/src/commands/locale/react-js-cron/zh-CN.json +0 -33
  145. package/src/commands/locale/react-js-cron/zh-TW.json +0 -33
  146. package/src/commands/locale.js +0 -81
  147. package/src/commands/p-test.js +0 -88
  148. package/src/commands/perf.js +0 -63
  149. package/src/commands/pkg.js +0 -321
  150. package/src/commands/pm2.js +0 -37
  151. package/src/commands/postinstall.js +0 -88
  152. package/src/commands/start.js +0 -148
  153. package/src/commands/tar.js +0 -36
  154. package/src/commands/test-coverage.js +0 -55
  155. package/src/commands/test.js +0 -107
  156. package/src/commands/umi.js +0 -33
  157. package/src/commands/update-deps.js +0 -72
  158. package/src/commands/upgrade.js +0 -47
  159. package/src/commands/view-license-key.js +0 -44
  160. package/src/license.js +0 -76
  161. package/src/logger.js +0 -75
  162. package/src/plugin-generator.js +0 -80
  163. package/src/util.js +0 -517
  164. package/templates/bundle-status.html +0 -338
  165. package/templates/create-app-package.json +0 -39
  166. package/templates/plugin/.npmignore.tpl +0 -2
  167. package/templates/plugin/README.md.tpl +0 -1
  168. package/templates/plugin/client.d.ts +0 -2
  169. package/templates/plugin/client.js +0 -1
  170. package/templates/plugin/package.json.tpl +0 -11
  171. package/templates/plugin/server.d.ts +0 -2
  172. package/templates/plugin/server.js +0 -1
  173. package/templates/plugin/src/client/client.d.ts +0 -249
  174. package/templates/plugin/src/client/index.tsx.tpl +0 -1
  175. package/templates/plugin/src/client/locale.ts +0 -21
  176. package/templates/plugin/src/client/plugin.tsx.tpl +0 -10
  177. package/templates/plugin/src/index.ts +0 -2
  178. package/templates/plugin/src/locale/en-US.json +0 -1
  179. package/templates/plugin/src/locale/zh-CN.json +0 -1
  180. package/templates/plugin/src/server/collections/.gitkeep +0 -0
  181. package/templates/plugin/src/server/index.ts.tpl +0 -1
  182. package/templates/plugin/src/server/plugin.ts.tpl +0 -19
@@ -0,0 +1,47 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+ import os from 'node:os';
10
+ import path from 'node:path';
11
+ export const CLI_HOME_DIRNAME = '.nocobase';
12
+ export const NB_CLI_ROOT_ENV = 'NB_CLI_ROOT';
13
+ export function resolveDefaultConfigScope() {
14
+ return 'global';
15
+ }
16
+ function readConfiguredPath(name) {
17
+ const value = String(process.env[name] ?? '').trim();
18
+ return value || undefined;
19
+ }
20
+ function resolveGlobalCliHomeRoot() {
21
+ return readConfiguredPath(NB_CLI_ROOT_ENV) ?? os.homedir();
22
+ }
23
+ export function resolveCliHomeRoot(scope = resolveDefaultConfigScope()) {
24
+ void scope;
25
+ return resolveGlobalCliHomeRoot();
26
+ }
27
+ export function resolveCliHomeDir(scope = resolveDefaultConfigScope()) {
28
+ return path.join(resolveCliHomeRoot(scope), CLI_HOME_DIRNAME);
29
+ }
30
+ export function resolveEnvRoot(scope = resolveDefaultConfigScope()) {
31
+ void scope;
32
+ return resolveCliHomeRoot();
33
+ }
34
+ export function resolveEnvRelativePath(relativePath, scope = resolveDefaultConfigScope()) {
35
+ return path.resolve(resolveEnvRoot(scope), relativePath);
36
+ }
37
+ export function resolveConfiguredEnvPath(value, scope = resolveDefaultConfigScope()) {
38
+ const text = String(value ?? '').trim();
39
+ if (!text) {
40
+ return undefined;
41
+ }
42
+ return path.isAbsolute(text) ? text : resolveEnvRelativePath(text, scope);
43
+ }
44
+ export function formatCliHomeScope(scope) {
45
+ void scope;
46
+ return 'global';
47
+ }
@@ -0,0 +1,129 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+ import { readFileSync } from 'node:fs';
10
+ import path from 'node:path';
11
+ import { fileURLToPath } from 'node:url';
12
+ export const SUPPORTED_CLI_LOCALES = ['en-US', 'zh-CN'];
13
+ export const CLI_LOCALE_FLAG_OPTIONS = [...SUPPORTED_CLI_LOCALES];
14
+ export const CLI_LOCALE_FLAG_DESCRIPTION = 'Language for CLI prompts and the local setup UI.';
15
+ const DEFAULT_CLI_LOCALE = 'en-US';
16
+ const localeCache = {};
17
+ function normalizeCliLocale(value) {
18
+ const raw = String(value ?? '').trim();
19
+ if (!raw) {
20
+ return undefined;
21
+ }
22
+ const normalized = raw.replace(/\..*$/, '').replace(/_/g, '-').toLowerCase();
23
+ if (normalized === 'zh' || normalized.startsWith('zh-')) {
24
+ return 'zh-CN';
25
+ }
26
+ if (normalized === 'en' || normalized.startsWith('en-')) {
27
+ return 'en-US';
28
+ }
29
+ return undefined;
30
+ }
31
+ function loadLocaleMessages(locale) {
32
+ if (localeCache[locale]) {
33
+ return localeCache[locale];
34
+ }
35
+ const moduleDir = path.dirname(fileURLToPath(import.meta.url));
36
+ const fallbackPath = path.resolve(moduleDir, '..', 'locale', `${locale}.json`);
37
+ const fileUrl = new URL(`../locale/${locale}.json`, import.meta.url);
38
+ let parsed;
39
+ try {
40
+ parsed = JSON.parse(readFileSync(fileUrl, 'utf8'));
41
+ }
42
+ catch (error) {
43
+ const code = error && typeof error === 'object' && 'code' in error ? String(error.code) : '';
44
+ if (code !== 'ENOENT') {
45
+ throw error;
46
+ }
47
+ parsed = JSON.parse(readFileSync(fallbackPath, 'utf8'));
48
+ }
49
+ localeCache[locale] = parsed;
50
+ return parsed;
51
+ }
52
+ function getPathValue(input, path) {
53
+ let current = input;
54
+ for (const part of path.split('.')) {
55
+ if (!current || typeof current !== 'object' || !Object.prototype.hasOwnProperty.call(current, part)) {
56
+ return undefined;
57
+ }
58
+ current = current[part];
59
+ }
60
+ return current;
61
+ }
62
+ function interpolateTemplate(template, values) {
63
+ return template.replace(/{{\s*([\w.]+)\s*}}/g, (_match, key) => {
64
+ const value = getPathValue(values, key);
65
+ return value === undefined || value === null ? '' : String(value);
66
+ });
67
+ }
68
+ export function detectCliLocale() {
69
+ const candidates = [
70
+ process.env.NB_LOCALE,
71
+ process.env.LC_ALL,
72
+ process.env.LC_MESSAGES,
73
+ process.env.LANG,
74
+ Intl.DateTimeFormat().resolvedOptions().locale,
75
+ ];
76
+ for (const candidate of candidates) {
77
+ const locale = normalizeCliLocale(candidate);
78
+ if (locale) {
79
+ return locale;
80
+ }
81
+ }
82
+ return DEFAULT_CLI_LOCALE;
83
+ }
84
+ export function resolveCliLocale(preferred) {
85
+ return normalizeCliLocale(preferred) ?? detectCliLocale();
86
+ }
87
+ export function applyCliLocale(preferred) {
88
+ const locale = resolveCliLocale(preferred);
89
+ process.env.NB_LOCALE = locale;
90
+ return locale;
91
+ }
92
+ export function createCliTranslate(preferred) {
93
+ const locale = resolveCliLocale(preferred);
94
+ return (key, values, fallback) => {
95
+ const messages = loadLocaleMessages(locale);
96
+ const template = getPathValue(messages, key);
97
+ if (typeof template !== 'string') {
98
+ return interpolateTemplate(fallback ?? key, values);
99
+ }
100
+ return interpolateTemplate(template, values);
101
+ };
102
+ }
103
+ export function translateCli(key, values, options) {
104
+ return createCliTranslate(options?.locale)(key, values, options?.fallback);
105
+ }
106
+ export function localeText(key, values, fallback) {
107
+ return {
108
+ key,
109
+ ...(values ? { values } : {}),
110
+ ...(fallback ? { fallback } : {}),
111
+ };
112
+ }
113
+ export function isLocalizedTextDef(value) {
114
+ return Boolean(value
115
+ && typeof value === 'object'
116
+ && typeof value.key === 'string');
117
+ }
118
+ export function resolveLocalizedText(text, options) {
119
+ if (text === undefined) {
120
+ return options?.fallback ?? '';
121
+ }
122
+ if (typeof text === 'string') {
123
+ return text;
124
+ }
125
+ return translateCli(text.key, text.values, {
126
+ locale: options?.locale,
127
+ fallback: text.fallback ?? options?.fallback,
128
+ });
129
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+ import { readdir } from 'node:fs/promises';
10
+ import { join } from 'node:path';
11
+ /**
12
+ * Recursively collect command module paths under `commandsRoot` (e.g. `dist/commands` → `.js`, `src/commands` → `.ts`).
13
+ */
14
+ export async function collectCommandModulePaths(commandsRoot, extension) {
15
+ const entries = await readdir(commandsRoot, { withFileTypes: true });
16
+ const files = [];
17
+ for (const ent of entries) {
18
+ const full = join(commandsRoot, ent.name);
19
+ if (ent.isDirectory()) {
20
+ files.push(...(await collectCommandModulePaths(full, extension)));
21
+ }
22
+ else if (ent.isFile() && ent.name.endsWith(extension)) {
23
+ files.push(full);
24
+ }
25
+ }
26
+ return files.sort();
27
+ }
28
+ /**
29
+ * Map a path relative to `commands/` with `.js` / `.ts` to an oclif explicit-registry key.
30
+ * `api/resource/foo.js` → `api:resource:foo`; trailing `index` maps to the parent command.
31
+ */
32
+ export function commandRelativePathToRegistryKey(relativePath) {
33
+ const normalized = relativePath.replace(/\\/g, '/').replace(/\.(js|ts)$/i, '');
34
+ const segments = normalized.split('/').filter(Boolean);
35
+ if (segments.at(-1) === 'index') {
36
+ segments.pop();
37
+ }
38
+ return segments.join(':');
39
+ }
@@ -0,0 +1,178 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+ import { translateCli } from "./cli-locale.js";
10
+ import { validateTcpPort } from "./prompt-validators.js";
11
+ const DB_CONNECTION_TIMEOUT_MS = 5_000;
12
+ const externalDbValidationCache = new Map();
13
+ function trimPromptValue(value) {
14
+ return String(value ?? '').trim();
15
+ }
16
+ export function readExternalDbConnectionConfig(values) {
17
+ const builtinDb = values.builtinDb === undefined ? true : Boolean(values.builtinDb);
18
+ if (builtinDb) {
19
+ return undefined;
20
+ }
21
+ const dialect = trimPromptValue(values.dbDialect || 'postgres');
22
+ if (dialect !== 'postgres' && dialect !== 'kingbase' && dialect !== 'mysql' && dialect !== 'mariadb') {
23
+ return undefined;
24
+ }
25
+ const host = trimPromptValue(values.dbHost);
26
+ const portText = trimPromptValue(values.dbPort);
27
+ const database = trimPromptValue(values.dbDatabase);
28
+ const user = trimPromptValue(values.dbUser);
29
+ const password = String(values.dbPassword ?? '');
30
+ if (!host || !portText || !database || !user || !password) {
31
+ return undefined;
32
+ }
33
+ if (validateTcpPort(portText)) {
34
+ return undefined;
35
+ }
36
+ return {
37
+ dialect,
38
+ host,
39
+ port: Number.parseInt(portText, 10),
40
+ database,
41
+ user,
42
+ password,
43
+ };
44
+ }
45
+ export function formatDbCheckAddress(config) {
46
+ return `${config.host}:${config.port}/${config.database}`;
47
+ }
48
+ function buildValidationCacheKey(config) {
49
+ return JSON.stringify(config);
50
+ }
51
+ function formatDbConnectionError(config, error) {
52
+ const maybeError = error;
53
+ const code = String(maybeError?.code ?? '').trim().toUpperCase();
54
+ const errno = typeof maybeError?.errno === 'number' ? maybeError.errno : undefined;
55
+ const rawMessage = String(maybeError?.message || maybeError?.sqlMessage || error || '').trim();
56
+ if (code === 'ECONNREFUSED' || code === 'ENOTFOUND' || code === 'EHOSTUNREACH' || code === 'ECONNRESET') {
57
+ return translateCli('validators.dbConnection.unreachable', {
58
+ host: config.host,
59
+ port: config.port,
60
+ details: rawMessage,
61
+ });
62
+ }
63
+ if (code === 'ETIMEDOUT') {
64
+ return translateCli('validators.dbConnection.timeout', {
65
+ host: config.host,
66
+ port: config.port,
67
+ seconds: Math.ceil(DB_CONNECTION_TIMEOUT_MS / 1000),
68
+ });
69
+ }
70
+ if (code === '28P01' || code === '28000' || code === 'ER_ACCESS_DENIED_ERROR' || errno === 1045) {
71
+ return translateCli('validators.dbConnection.authenticationFailed', {
72
+ user: config.user,
73
+ database: config.database,
74
+ });
75
+ }
76
+ if (code === '3D000' || code === 'ER_BAD_DB_ERROR' || errno === 1049) {
77
+ return translateCli('validators.dbConnection.databaseNotFound', {
78
+ database: config.database,
79
+ });
80
+ }
81
+ return translateCli('validators.dbConnection.connectionFailed', {
82
+ details: rawMessage || code || String(error),
83
+ });
84
+ }
85
+ async function checkPostgresFamilyConnection(config) {
86
+ const { default: pg } = await import('pg');
87
+ const client = new pg.Client({
88
+ host: config.host,
89
+ port: config.port,
90
+ user: config.user,
91
+ password: config.password,
92
+ database: config.database,
93
+ connectionTimeoutMillis: DB_CONNECTION_TIMEOUT_MS,
94
+ });
95
+ try {
96
+ await client.connect();
97
+ await client.query('SELECT 1');
98
+ }
99
+ finally {
100
+ await Promise.resolve(client.end()).catch(() => undefined);
101
+ }
102
+ }
103
+ async function checkMysqlConnection(config) {
104
+ const { default: mysql } = await import('mysql2/promise');
105
+ const connection = await mysql.createConnection({
106
+ host: config.host,
107
+ port: config.port,
108
+ user: config.user,
109
+ password: config.password,
110
+ database: config.database,
111
+ connectTimeout: DB_CONNECTION_TIMEOUT_MS,
112
+ });
113
+ try {
114
+ await connection.query('SELECT 1');
115
+ }
116
+ finally {
117
+ await Promise.resolve(connection.end()).catch(() => undefined);
118
+ }
119
+ }
120
+ async function checkMariaDbConnection(config) {
121
+ const { default: mariadb } = await import('mariadb');
122
+ const connection = await mariadb.createConnection({
123
+ host: config.host,
124
+ port: config.port,
125
+ user: config.user,
126
+ password: config.password,
127
+ database: config.database,
128
+ connectTimeout: DB_CONNECTION_TIMEOUT_MS,
129
+ });
130
+ try {
131
+ await connection.query('SELECT 1');
132
+ }
133
+ finally {
134
+ await Promise.resolve(connection.end()).catch(() => undefined);
135
+ }
136
+ }
137
+ async function performExternalDbConnectionCheck(config) {
138
+ try {
139
+ switch (config.dialect) {
140
+ case 'postgres':
141
+ case 'kingbase': {
142
+ await checkPostgresFamilyConnection(config);
143
+ return undefined;
144
+ }
145
+ case 'mysql': {
146
+ await checkMysqlConnection(config);
147
+ return undefined;
148
+ }
149
+ case 'mariadb': {
150
+ await checkMariaDbConnection(config);
151
+ return undefined;
152
+ }
153
+ }
154
+ }
155
+ catch (error) {
156
+ return formatDbConnectionError(config, error);
157
+ }
158
+ }
159
+ export async function checkExternalDbConnection(config) {
160
+ const cacheKey = buildValidationCacheKey(config);
161
+ const cached = externalDbValidationCache.get(cacheKey);
162
+ if (cached) {
163
+ return await cached;
164
+ }
165
+ const pending = performExternalDbConnectionCheck(config);
166
+ externalDbValidationCache.set(cacheKey, pending);
167
+ return await pending;
168
+ }
169
+ export async function validateExternalDbConfig(values) {
170
+ const config = readExternalDbConnectionConfig(values);
171
+ if (!config) {
172
+ return undefined;
173
+ }
174
+ return await checkExternalDbConnection(config);
175
+ }
176
+ export function clearExternalDbValidationCache() {
177
+ externalDbValidationCache.clear();
178
+ }