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

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 +477 -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,29 @@
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 { Command } from '@oclif/core';
10
+ import { listExplicitCliConfigValues, SUPPORTED_CLI_CONFIG_KEYS } from '../../lib/cli-config.js';
11
+ import { renderTable } from '../../lib/ui.js';
12
+ export default class ConfigList extends Command {
13
+ static summary = 'List explicitly configured CLI settings';
14
+ static examples = [
15
+ '<%= config.bin %> <%= command.id %>',
16
+ ];
17
+ async run() {
18
+ await this.parse(ConfigList);
19
+ const values = await listExplicitCliConfigValues();
20
+ const rows = SUPPORTED_CLI_CONFIG_KEYS
21
+ .filter((key) => Boolean(values[key]))
22
+ .map((key) => [key, values[key] ?? '']);
23
+ if (!rows.length) {
24
+ this.log('No CLI config values are set.');
25
+ return;
26
+ }
27
+ this.log(renderTable(['Key', 'Value'], rows));
28
+ }
29
+ }
@@ -0,0 +1,35 @@
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 { Args, Command } from '@oclif/core';
10
+ import { assertSupportedCliConfigKey, setCliConfigValue } from '../../lib/cli-config.js';
11
+ export default class ConfigSet extends Command {
12
+ static summary = 'Set a CLI configuration value';
13
+ static description = 'Set a supported CLI configuration key. Supported keys: license.pkg-url, docker.network, docker.container-prefix.';
14
+ static examples = [
15
+ '<%= config.bin %> <%= command.id %> license.pkg-url https://pkg.nocobase.com/',
16
+ '<%= config.bin %> <%= command.id %> docker.network nocobase',
17
+ '<%= config.bin %> <%= command.id %> docker.container-prefix nb',
18
+ ];
19
+ static args = {
20
+ key: Args.string({
21
+ description: 'Configuration key',
22
+ required: true,
23
+ }),
24
+ value: Args.string({
25
+ description: 'Configuration value',
26
+ required: true,
27
+ }),
28
+ };
29
+ async run() {
30
+ const { args } = await this.parse(ConfigSet);
31
+ const key = assertSupportedCliConfigKey(args.key);
32
+ const value = await setCliConfigValue(key, args.value);
33
+ this.log(`${key}=${value}`);
34
+ }
35
+ }
@@ -0,0 +1,238 @@
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 { Command, Flags } from '@oclif/core';
10
+ import { formatMissingManagedAppEnvMessage, resolveManagedAppRuntime } from '../../lib/app-runtime.js';
11
+ import { resolveBuiltinDbConnection } from '../../lib/builtin-db.js';
12
+ import { checkExternalDbConnection, formatDbCheckAddress, readExternalDbConnectionConfig, } from "../../lib/db-connection-check.js";
13
+ import { commandOutput } from '../../lib/run-npm.js';
14
+ import { validateTcpPort } from "../../lib/prompt-validators.js";
15
+ const DEFAULT_DOCKER_REGISTRY = 'nocobase/nocobase';
16
+ const DEFAULT_DOCKER_VERSION = 'alpha';
17
+ function trimValue(value) {
18
+ const text = String(value ?? '').trim();
19
+ return text || undefined;
20
+ }
21
+ function resolveRequiredDbField(flagValue, envValue) {
22
+ return trimValue(flagValue) ?? trimValue(envValue);
23
+ }
24
+ function normalizeDockerPlatform(value) {
25
+ const text = trimValue(value);
26
+ if (!text || text === 'auto') {
27
+ return undefined;
28
+ }
29
+ if (text === 'linux/amd64' || text === 'linux/arm64') {
30
+ return text;
31
+ }
32
+ return undefined;
33
+ }
34
+ function formatMissingFieldsMessage(missing, hasEnv) {
35
+ return [
36
+ 'Missing database settings for connectivity check.',
37
+ `Required: ${missing.join(', ')}.`,
38
+ hasEnv
39
+ ? 'Pass `--env <name>` to reuse a saved env, or provide the missing `--db-*` flags explicitly.'
40
+ : 'Provide all required `--db-*` flags explicitly, or pass `--env <name>` to reuse a saved env.',
41
+ ].join('\n');
42
+ }
43
+ function resolveDbConfigFromFlags(flags, envConfig) {
44
+ return {
45
+ builtinDb: false,
46
+ dbDialect: resolveRequiredDbField(flags['db-dialect'], envConfig?.dbDialect),
47
+ dbHost: resolveRequiredDbField(flags['db-host'], envConfig?.dbHost),
48
+ dbPort: resolveRequiredDbField(flags['db-port'], envConfig?.dbPort),
49
+ dbDatabase: resolveRequiredDbField(flags['db-database'], envConfig?.dbDatabase),
50
+ dbUser: resolveRequiredDbField(flags['db-user'], envConfig?.dbUser),
51
+ dbPassword: flags['db-password'] !== undefined
52
+ ? String(flags['db-password'] ?? '')
53
+ : envConfig?.dbPassword !== undefined
54
+ ? String(envConfig.dbPassword ?? '')
55
+ : undefined,
56
+ };
57
+ }
58
+ function validateDbConfigOrThrow(command, dbConfig, hasEnv) {
59
+ const missing = [];
60
+ if (!dbConfig.dbDialect) {
61
+ missing.push('--db-dialect');
62
+ }
63
+ if (!dbConfig.dbHost) {
64
+ missing.push('--db-host');
65
+ }
66
+ if (!dbConfig.dbPort) {
67
+ missing.push('--db-port');
68
+ }
69
+ if (!dbConfig.dbDatabase) {
70
+ missing.push('--db-database');
71
+ }
72
+ if (!dbConfig.dbUser) {
73
+ missing.push('--db-user');
74
+ }
75
+ if (!dbConfig.dbPassword) {
76
+ missing.push('--db-password');
77
+ }
78
+ if (missing.length > 0) {
79
+ command.error(formatMissingFieldsMessage(missing, hasEnv));
80
+ }
81
+ const portError = validateTcpPort(dbConfig.dbPort);
82
+ if (portError) {
83
+ command.error(portError);
84
+ }
85
+ }
86
+ async function resolveDbCheckInput(command, flags) {
87
+ const envName = flags.env?.trim() || undefined;
88
+ if (!envName) {
89
+ const dbConfig = resolveDbConfigFromFlags(flags);
90
+ validateDbConfigOrThrow(command, dbConfig, false);
91
+ return {
92
+ dbConfig,
93
+ };
94
+ }
95
+ const runtime = await resolveManagedAppRuntime(envName);
96
+ if (!runtime) {
97
+ command.error(formatMissingManagedAppEnvMessage(envName));
98
+ }
99
+ const envConfig = { ...runtime.env.config };
100
+ if ((runtime.kind === 'local' || runtime.kind === 'docker') && runtime.env.config.builtinDb) {
101
+ const builtinDbConnection = await resolveBuiltinDbConnection(runtime);
102
+ envConfig.dbHost = builtinDbConnection.dbHost;
103
+ envConfig.dbPort = builtinDbConnection.dbPort;
104
+ envConfig.dbDialect = builtinDbConnection.dbDialect;
105
+ }
106
+ const dbConfig = resolveDbConfigFromFlags(flags, envConfig);
107
+ validateDbConfigOrThrow(command, dbConfig, true);
108
+ return {
109
+ envName: runtime.envName,
110
+ kind: runtime.kind,
111
+ runtime: runtime,
112
+ dbConfig,
113
+ };
114
+ }
115
+ function buildConnectionConfigOrThrow(command, dbConfig) {
116
+ const connectionConfig = readExternalDbConnectionConfig(dbConfig);
117
+ if (!connectionConfig) {
118
+ command.error('Unsupported or incomplete database settings for connectivity check.');
119
+ }
120
+ return connectionConfig;
121
+ }
122
+ async function runExplicitDbCheck(command, dbConfig) {
123
+ const connectionConfig = buildConnectionConfigOrThrow(command, dbConfig);
124
+ const address = formatDbCheckAddress(connectionConfig);
125
+ const validationError = await checkExternalDbConnection(connectionConfig);
126
+ return {
127
+ ok: !validationError,
128
+ dialect: connectionConfig.dialect,
129
+ address,
130
+ error: validationError ?? null,
131
+ };
132
+ }
133
+ async function runDockerDbCheck(command, runtime, dbConfig) {
134
+ const connectionConfig = buildConnectionConfigOrThrow(command, dbConfig);
135
+ const config = runtime.env.config ?? {};
136
+ const imageRef = `${trimValue(config.dockerRegistry) || DEFAULT_DOCKER_REGISTRY}:${trimValue(config.downloadVersion) || DEFAULT_DOCKER_VERSION}`;
137
+ const args = [
138
+ 'run',
139
+ '--rm',
140
+ '--network',
141
+ runtime.dockerNetworkName || runtime.workspaceName,
142
+ ];
143
+ const dockerPlatform = normalizeDockerPlatform(config.dockerPlatform);
144
+ if (dockerPlatform) {
145
+ args.push('--platform', dockerPlatform);
146
+ }
147
+ args.push('--entrypoint', 'nb', imageRef, 'db', 'check', '--db-dialect', connectionConfig.dialect, '--db-host', connectionConfig.host, '--db-port', String(connectionConfig.port), '--db-database', connectionConfig.database, '--db-user', connectionConfig.user, '--db-password', connectionConfig.password, '--json');
148
+ const output = await commandOutput('docker', args, {
149
+ errorName: 'docker run',
150
+ });
151
+ let payload;
152
+ try {
153
+ payload = JSON.parse(output);
154
+ }
155
+ catch {
156
+ command.error(`Failed to parse database check response from Docker: ${output}`);
157
+ }
158
+ const ok = Boolean(payload.ok);
159
+ const dialect = trimValue(payload.dialect) || connectionConfig.dialect;
160
+ const address = trimValue(payload.address) || formatDbCheckAddress(connectionConfig);
161
+ const error = trimValue(payload.error) || null;
162
+ return {
163
+ ok,
164
+ dialect,
165
+ address,
166
+ error,
167
+ };
168
+ }
169
+ async function runDbCheckForRuntime(command, runtime, dbConfig) {
170
+ if (runtime.kind === 'docker') {
171
+ return await runDockerDbCheck(command, runtime, dbConfig);
172
+ }
173
+ if (runtime.kind === 'local') {
174
+ return await runExplicitDbCheck(command, dbConfig);
175
+ }
176
+ command.error(`Env "${runtime.envName}" does not support automatic database connectivity checks.`);
177
+ }
178
+ export default class DbCheck extends Command {
179
+ static description = 'Check whether a database is reachable using the selected env settings or explicit `--db-*` flags.';
180
+ static examples = [
181
+ '<%= config.bin %> <%= command.id %> --env app1',
182
+ '<%= config.bin %> <%= command.id %> --env app1 --db-password new-secret --json',
183
+ '<%= config.bin %> <%= command.id %> --db-dialect postgres --db-host 127.0.0.1 --db-port 5432 --db-database nocobase --db-user nocobase --db-password secret',
184
+ ];
185
+ static flags = {
186
+ env: Flags.string({
187
+ char: 'e',
188
+ description: 'CLI env name to read saved database settings from. Defaults to the current env when omitted.',
189
+ }),
190
+ 'db-dialect': Flags.string({
191
+ description: 'Database dialect: postgres, kingbase, mysql, or mariadb.',
192
+ options: ['postgres', 'kingbase', 'mysql', 'mariadb'],
193
+ }),
194
+ 'db-host': Flags.string({
195
+ description: 'Database host name or IP address.',
196
+ }),
197
+ 'db-port': Flags.string({
198
+ description: 'Database TCP port.',
199
+ }),
200
+ 'db-database': Flags.string({
201
+ description: 'Database name.',
202
+ }),
203
+ 'db-user': Flags.string({
204
+ description: 'Database username.',
205
+ }),
206
+ 'db-password': Flags.string({
207
+ description: 'Database password.',
208
+ }),
209
+ json: Flags.boolean({
210
+ description: 'Output the check result as JSON.',
211
+ default: false,
212
+ }),
213
+ };
214
+ async run() {
215
+ const { flags } = await this.parse(DbCheck);
216
+ const input = await resolveDbCheckInput(this, flags);
217
+ const result = input.runtime
218
+ ? await runDbCheckForRuntime(this, input.runtime, input.dbConfig)
219
+ : await runExplicitDbCheck(this, input.dbConfig);
220
+ if (flags.json) {
221
+ this.log(JSON.stringify({
222
+ ok: result.ok,
223
+ env: input.envName,
224
+ kind: input.kind,
225
+ dialect: result.dialect,
226
+ address: result.address,
227
+ error: result.error,
228
+ }, null, 2));
229
+ return;
230
+ }
231
+ if (!result.ok) {
232
+ this.error(result.error ?? 'Database check failed.');
233
+ }
234
+ this.log(input.envName
235
+ ? `Database check passed for env "${input.envName}" (${result.dialect} ${result.address}).`
236
+ : `Database check passed (${result.dialect} ${result.address}).`);
237
+ }
238
+ }
@@ -0,0 +1,85 @@
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 { Command, Flags } from '@oclif/core';
10
+ import { formatMissingManagedAppEnvMessage } from '../../lib/app-runtime.js';
11
+ import { run } from '../../lib/run-npm.js';
12
+ import { printInfo } from '../../lib/ui.js';
13
+ import { formatUnmanagedDbLogsMessage, resolveDbRuntime } from './shared.js';
14
+ function formatDbLogsFailure(envName, message) {
15
+ if (/does not exist/i.test(message)) {
16
+ return [
17
+ `Can't show database logs for "${envName}" yet.`,
18
+ 'The saved built-in database container for this env could not be found on this machine.',
19
+ 'Try reinstalling the env, or check whether the container was removed outside the CLI.',
20
+ `Details: ${message}`,
21
+ ].join('\n');
22
+ }
23
+ return [
24
+ `Couldn't show database logs for "${envName}".`,
25
+ 'Check that the built-in database runtime for this env is still available, then try again.',
26
+ `Details: ${message}`,
27
+ ].join('\n');
28
+ }
29
+ export default class DbLogs extends Command {
30
+ static description = 'Show logs for the built-in database container of the selected env.';
31
+ static examples = [
32
+ '<%= config.bin %> <%= command.id %>',
33
+ '<%= config.bin %> <%= command.id %> --env app1',
34
+ '<%= config.bin %> <%= command.id %> --env app1 --tail 200',
35
+ '<%= config.bin %> <%= command.id %> --env app1 --no-follow',
36
+ ];
37
+ static flags = {
38
+ env: Flags.string({
39
+ char: 'e',
40
+ description: 'CLI env name to inspect built-in database logs for. Defaults to the current env when omitted',
41
+ }),
42
+ tail: Flags.integer({
43
+ description: 'Number of recent log lines to show before following',
44
+ default: 100,
45
+ min: 0,
46
+ }),
47
+ follow: Flags.boolean({
48
+ char: 'f',
49
+ description: 'Keep streaming new log lines',
50
+ default: false,
51
+ allowNo: true,
52
+ }),
53
+ };
54
+ async run() {
55
+ const { flags } = await this.parse(DbLogs);
56
+ const requestedEnv = flags.env?.trim() || undefined;
57
+ const runtime = await resolveDbRuntime(requestedEnv);
58
+ if (!runtime) {
59
+ this.error(formatMissingManagedAppEnvMessage(requestedEnv));
60
+ }
61
+ if (runtime.kind !== 'builtin') {
62
+ this.error(formatUnmanagedDbLogsMessage(runtime));
63
+ }
64
+ const tail = String(flags.tail ?? 100);
65
+ const follow = flags.follow === true;
66
+ printInfo(follow
67
+ ? `Showing built-in database logs for "${runtime.envName}" (press Ctrl+C to stop).`
68
+ : `Showing recent built-in database logs for "${runtime.envName}".`);
69
+ const dockerArgs = ['logs', '--tail', tail];
70
+ if (follow) {
71
+ dockerArgs.push('--follow');
72
+ }
73
+ dockerArgs.push(runtime.containerName);
74
+ try {
75
+ await run('docker', dockerArgs, {
76
+ errorName: 'docker logs',
77
+ stdio: 'inherit',
78
+ });
79
+ }
80
+ catch (error) {
81
+ const message = error instanceof Error ? error.message : String(error);
82
+ this.error(formatDbLogsFailure(runtime.envName, message));
83
+ }
84
+ }
85
+ }
@@ -0,0 +1,60 @@
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 { Command, Flags } from '@oclif/core';
10
+ import { formatMissingManagedAppEnvMessage } from '../../lib/app-runtime.js';
11
+ import { listEnvs } from '../../lib/auth-store.js';
12
+ import { renderTable } from '../../lib/ui.js';
13
+ import { builtinDbStatus, resolveDbRuntime } from './shared.js';
14
+ export default class DbPs extends Command {
15
+ static description = 'Show built-in database runtime status for configured envs without starting or stopping anything.';
16
+ static examples = [
17
+ '<%= config.bin %> <%= command.id %>',
18
+ '<%= config.bin %> <%= command.id %> --env app1',
19
+ ];
20
+ static flags = {
21
+ env: Flags.string({
22
+ char: 'e',
23
+ description: 'CLI env name to inspect. Omit to show all configured envs',
24
+ }),
25
+ };
26
+ async run() {
27
+ const { flags } = await this.parse(DbPs);
28
+ const requestedEnv = flags.env?.trim() || undefined;
29
+ const envNames = requestedEnv
30
+ ? [requestedEnv]
31
+ : Object.keys((await listEnvs()).envs).sort();
32
+ if (!envNames.length) {
33
+ this.log('No NocoBase env is configured yet. Run `nb init` to create one first.');
34
+ return;
35
+ }
36
+ const rows = [];
37
+ for (const envName of envNames) {
38
+ const runtime = await resolveDbRuntime(envName);
39
+ if (!runtime) {
40
+ if (requestedEnv) {
41
+ this.error(formatMissingManagedAppEnvMessage(envName));
42
+ }
43
+ rows.push([envName, '-', '-', 'missing', '']);
44
+ continue;
45
+ }
46
+ const type = runtime.kind === 'builtin' ? 'builtin' : runtime.status;
47
+ const status = runtime.kind === 'builtin'
48
+ ? await builtinDbStatus(runtime.containerName)
49
+ : runtime.status;
50
+ rows.push([
51
+ runtime.envName,
52
+ type,
53
+ runtime.dbDialect,
54
+ status,
55
+ runtime.address,
56
+ ]);
57
+ }
58
+ this.log(renderTable(['Env', 'Type', 'Dialect', 'Status', 'Address'], rows));
59
+ }
60
+ }
@@ -0,0 +1,96 @@
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 { dockerContainerExists, dockerContainerIsRunning, resolveManagedAppRuntime, } from '../../lib/app-runtime.js';
10
+ import { resolveBuiltinDbConnection } from '../../lib/builtin-db.js';
11
+ function formatAddress(host, port, fallbackHost) {
12
+ const normalizedHost = String(host ?? '').trim() || String(fallbackHost ?? '').trim();
13
+ const normalizedPort = String(port ?? '').trim();
14
+ if (normalizedHost && normalizedPort) {
15
+ return `${normalizedHost}:${normalizedPort}`;
16
+ }
17
+ return normalizedHost || normalizedPort || '';
18
+ }
19
+ export async function resolveDbRuntime(envName) {
20
+ const runtime = await resolveManagedAppRuntime(envName);
21
+ if (!runtime) {
22
+ return undefined;
23
+ }
24
+ const source = runtime.kind === 'http' || runtime.kind === 'ssh' ? runtime.kind : runtime.source;
25
+ const dbDialect = String(runtime.env.config.dbDialect ?? 'postgres').trim() || 'postgres';
26
+ if ((runtime.kind === 'local' || runtime.kind === 'docker') && runtime.env.config.builtinDb) {
27
+ const connection = await resolveBuiltinDbConnection(runtime);
28
+ return {
29
+ kind: 'builtin',
30
+ envName: runtime.envName,
31
+ source,
32
+ dbDialect: connection.dbDialect,
33
+ containerName: connection.containerName,
34
+ address: formatAddress(connection.dbHost, connection.dbPort, connection.containerName),
35
+ appRuntime: runtime,
36
+ };
37
+ }
38
+ return {
39
+ kind: 'external',
40
+ envName: runtime.envName,
41
+ source,
42
+ dbDialect,
43
+ address: formatAddress(runtime.env.config.dbHost, runtime.env.config.dbPort),
44
+ status: runtime.kind === 'http' || runtime.kind === 'ssh' ? runtime.kind : 'external',
45
+ appRuntime: runtime,
46
+ };
47
+ }
48
+ export async function builtinDbStatus(containerName) {
49
+ if (!(await dockerContainerExists(containerName))) {
50
+ return 'missing';
51
+ }
52
+ return await dockerContainerIsRunning(containerName) ? 'running' : 'stopped';
53
+ }
54
+ export function formatUnmanagedDbMessage(action, runtime) {
55
+ const verb = action === 'start' ? 'start' : 'stop';
56
+ if (runtime.appRuntime.kind === 'http') {
57
+ return [
58
+ `Can't ${verb} the database for "${runtime.envName}" from this machine.`,
59
+ 'This env only has an API connection, so there is no CLI-managed database container here.',
60
+ 'If you need CLI-managed database start and stop, create a local env with the built-in database option enabled.',
61
+ ].join('\n');
62
+ }
63
+ if (runtime.appRuntime.kind === 'ssh') {
64
+ return [
65
+ `Can't ${verb} the database for "${runtime.envName}" yet.`,
66
+ 'SSH env support is reserved but not implemented yet.',
67
+ 'Use a local env with the built-in database option enabled if you need CLI-managed database operations right now.',
68
+ ].join('\n');
69
+ }
70
+ return [
71
+ `Can't ${verb} the database for "${runtime.envName}" from this machine.`,
72
+ 'This env does not use a CLI-managed built-in database, so there is no saved database container to manage here.',
73
+ 'If you need CLI-managed database start and stop, recreate the env with the built-in database option enabled.',
74
+ ].join('\n');
75
+ }
76
+ export function formatUnmanagedDbLogsMessage(runtime) {
77
+ if (runtime.appRuntime.kind === 'http') {
78
+ return [
79
+ `Can't show database logs for "${runtime.envName}" from this machine.`,
80
+ 'This env only has an API connection, so there is no CLI-managed database container here.',
81
+ 'If you need CLI-managed database logs, create a local env with the built-in database option enabled.',
82
+ ].join('\n');
83
+ }
84
+ if (runtime.appRuntime.kind === 'ssh') {
85
+ return [
86
+ `Can't show database logs for "${runtime.envName}" yet.`,
87
+ 'SSH env support is reserved but not implemented yet.',
88
+ 'Use a local env with the built-in database option enabled if you need CLI-managed database logs right now.',
89
+ ].join('\n');
90
+ }
91
+ return [
92
+ `Can't show database logs for "${runtime.envName}" from this machine.`,
93
+ 'This env does not use a CLI-managed built-in database, so there is no saved database container to read logs from here.',
94
+ 'If you need CLI-managed database logs, recreate the env with the built-in database option enabled.',
95
+ ].join('\n');
96
+ }
@@ -0,0 +1,71 @@
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 { Command, Flags } from '@oclif/core';
10
+ import { formatMissingManagedAppEnvMessage, startDockerContainer, } from '../../lib/app-runtime.js';
11
+ import { announceTargetEnv, failTask, startTask, succeedTask } from '../../lib/ui.js';
12
+ import { formatUnmanagedDbMessage, resolveDbRuntime } from './shared.js';
13
+ function formatDbStartFailure(envName, message) {
14
+ if (/does not exist/i.test(message)) {
15
+ return [
16
+ `Can't start the database for "${envName}" yet.`,
17
+ 'The saved built-in database container for this env could not be found on this machine.',
18
+ 'Try reinstalling the env, or check whether the container was removed outside the CLI.',
19
+ `Details: ${message}`,
20
+ ].join('\n');
21
+ }
22
+ return [
23
+ `Couldn't start the database for "${envName}".`,
24
+ 'Check that the built-in database runtime for this env is still available, then try again.',
25
+ `Details: ${message}`,
26
+ ].join('\n');
27
+ }
28
+ export default class DbStart extends Command {
29
+ static description = 'Start the built-in database container for the selected env.';
30
+ static examples = [
31
+ '<%= config.bin %> <%= command.id %>',
32
+ '<%= config.bin %> <%= command.id %> --env app1',
33
+ '<%= config.bin %> <%= command.id %> --env app1 --verbose',
34
+ ];
35
+ static flags = {
36
+ env: Flags.string({
37
+ char: 'e',
38
+ description: 'CLI env name to start the built-in database for. Defaults to the current env when omitted',
39
+ }),
40
+ verbose: Flags.boolean({
41
+ description: 'Show raw startup output from the underlying Docker command',
42
+ default: false,
43
+ }),
44
+ };
45
+ async run() {
46
+ const { flags } = await this.parse(DbStart);
47
+ const requestedEnv = flags.env?.trim() || undefined;
48
+ const runtime = await resolveDbRuntime(requestedEnv);
49
+ if (!runtime) {
50
+ this.error(formatMissingManagedAppEnvMessage(requestedEnv));
51
+ }
52
+ if (runtime.kind !== 'builtin') {
53
+ this.error(formatUnmanagedDbMessage('start', runtime));
54
+ }
55
+ announceTargetEnv(runtime.envName);
56
+ startTask(`Starting the built-in database for "${runtime.envName}"...`);
57
+ try {
58
+ const state = await startDockerContainer(runtime.containerName, {
59
+ stdio: flags.verbose ? 'inherit' : 'ignore',
60
+ });
61
+ succeedTask(state === 'already-running'
62
+ ? `The built-in database is already running for "${runtime.envName}"${runtime.address ? ` at ${runtime.address}` : ''}.`
63
+ : `The built-in database is running for "${runtime.envName}"${runtime.address ? ` at ${runtime.address}` : ''}.`);
64
+ }
65
+ catch (error) {
66
+ const message = error instanceof Error ? error.message : String(error);
67
+ failTask(`Failed to start the built-in database for "${runtime.envName}".`);
68
+ this.error(formatDbStartFailure(runtime.envName, message));
69
+ }
70
+ }
71
+ }