@nocobase/cli 2.1.0-beta.8 → 2.2.0-alpha.1

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 (263) hide show
  1. package/assets/env-proxy/nginx/app.conf.tpl +23 -0
  2. package/assets/env-proxy/nginx/nocobase.conf.tpl +5 -0
  3. package/assets/env-proxy/nginx/snippets/dist-location.conf +5 -0
  4. package/assets/env-proxy/nginx/snippets/gzip.conf +17 -0
  5. package/assets/env-proxy/nginx/snippets/log-format-http.conf +13 -0
  6. package/assets/env-proxy/nginx/snippets/maps-http.conf +14 -0
  7. package/assets/env-proxy/nginx/snippets/mime-types.conf +98 -0
  8. package/assets/env-proxy/nginx/snippets/proxy-location.conf +17 -0
  9. package/assets/env-proxy/nginx/snippets/spa-location.conf +6 -0
  10. package/assets/env-proxy/nginx/snippets/uploads-location.conf +21 -0
  11. package/bin/run.cmd +3 -0
  12. package/bin/run.js +145 -0
  13. package/bin/session-env.js +39 -0
  14. package/dist/commands/api/resource/create.js +15 -0
  15. package/dist/commands/api/resource/destroy.js +15 -0
  16. package/dist/commands/api/resource/get.js +15 -0
  17. package/dist/commands/api/resource/index.js +20 -0
  18. package/dist/commands/api/resource/list.js +16 -0
  19. package/dist/commands/api/resource/query.js +15 -0
  20. package/dist/commands/api/resource/update.js +15 -0
  21. package/dist/commands/app/autostart/disable.js +55 -0
  22. package/dist/commands/app/autostart/enable.js +55 -0
  23. package/dist/commands/app/autostart/list.js +37 -0
  24. package/dist/commands/app/autostart/run.js +84 -0
  25. package/dist/commands/app/autostart/shared.js +49 -0
  26. package/dist/commands/app/destroy.js +234 -0
  27. package/dist/commands/app/down.js +71 -0
  28. package/dist/commands/app/logs.js +115 -0
  29. package/dist/commands/app/restart.js +229 -0
  30. package/dist/commands/app/shared.js +123 -0
  31. package/dist/commands/app/start.js +416 -0
  32. package/dist/commands/app/stop.js +183 -0
  33. package/dist/commands/app/upgrade.js +523 -0
  34. package/dist/commands/backup/create.js +147 -0
  35. package/dist/commands/backup/index.js +20 -0
  36. package/dist/commands/backup/restore.js +105 -0
  37. package/{src/cli.js → dist/commands/build.js} +4 -11
  38. package/dist/commands/config/delete.js +42 -0
  39. package/dist/commands/config/get.js +39 -0
  40. package/dist/commands/config/index.js +20 -0
  41. package/dist/commands/config/list.js +29 -0
  42. package/dist/commands/config/set.js +49 -0
  43. package/dist/commands/db/check.js +240 -0
  44. package/dist/commands/db/logs.js +85 -0
  45. package/dist/commands/db/ps.js +47 -0
  46. package/dist/commands/db/shared.js +96 -0
  47. package/dist/commands/db/start.js +86 -0
  48. package/dist/commands/db/stop.js +71 -0
  49. package/{templates/plugin/src/client/models/index.ts → dist/commands/dev.js} +4 -4
  50. package/{src/commands/locale/react-js-cron/index.js → dist/commands/down.js} +3 -8
  51. package/dist/commands/download.js +13 -0
  52. package/dist/commands/env/add.js +406 -0
  53. package/dist/commands/env/auth.js +189 -0
  54. package/dist/commands/env/current.js +21 -0
  55. package/dist/commands/env/info.js +202 -0
  56. package/dist/commands/env/list.js +43 -0
  57. package/dist/commands/env/remove.js +174 -0
  58. package/dist/commands/env/shared.js +204 -0
  59. package/dist/commands/env/status.js +93 -0
  60. package/dist/commands/env/update.js +448 -0
  61. package/dist/commands/env/use.js +38 -0
  62. package/dist/commands/examples/prompts-stages.js +150 -0
  63. package/dist/commands/examples/prompts-test.js +181 -0
  64. package/dist/commands/init.js +1390 -0
  65. package/dist/commands/install.js +2609 -0
  66. package/dist/commands/license/activate.js +179 -0
  67. package/dist/commands/license/env.js +94 -0
  68. package/dist/commands/license/generate-id.js +108 -0
  69. package/dist/commands/license/id.js +70 -0
  70. package/dist/commands/license/index.js +20 -0
  71. package/dist/commands/license/plugins/clean.js +115 -0
  72. package/dist/commands/license/plugins/index.js +20 -0
  73. package/dist/commands/license/plugins/list.js +64 -0
  74. package/dist/commands/license/plugins/shared.js +382 -0
  75. package/dist/commands/license/plugins/sync.js +314 -0
  76. package/dist/commands/license/shared.js +423 -0
  77. package/dist/commands/license/status.js +64 -0
  78. package/dist/commands/logs.js +12 -0
  79. package/dist/commands/plugin/disable.js +86 -0
  80. package/dist/commands/plugin/enable.js +86 -0
  81. package/dist/commands/plugin/import.js +108 -0
  82. package/dist/commands/plugin/list.js +82 -0
  83. package/dist/commands/pm/disable.js +12 -0
  84. package/dist/commands/pm/enable.js +12 -0
  85. package/dist/commands/pm/list.js +12 -0
  86. package/dist/commands/proxy/caddy/current.js +17 -0
  87. package/dist/commands/proxy/caddy/generate.js +69 -0
  88. package/dist/commands/proxy/caddy/index.js +28 -0
  89. package/dist/commands/proxy/caddy/info.js +31 -0
  90. package/dist/commands/proxy/caddy/reload.js +30 -0
  91. package/dist/commands/proxy/caddy/restart.js +28 -0
  92. package/dist/commands/proxy/caddy/start.js +30 -0
  93. package/dist/commands/proxy/caddy/status.js +19 -0
  94. package/dist/commands/proxy/caddy/stop.js +30 -0
  95. package/dist/commands/proxy/caddy/use.js +26 -0
  96. package/dist/commands/proxy/index.js +28 -0
  97. package/dist/commands/proxy/nginx/current.js +18 -0
  98. package/dist/commands/proxy/nginx/generate.js +68 -0
  99. package/dist/commands/proxy/nginx/index.js +28 -0
  100. package/dist/commands/proxy/nginx/info.js +34 -0
  101. package/dist/commands/proxy/nginx/reload.js +30 -0
  102. package/dist/commands/proxy/nginx/restart.js +28 -0
  103. package/dist/commands/proxy/nginx/start.js +30 -0
  104. package/dist/commands/proxy/nginx/status.js +19 -0
  105. package/dist/commands/proxy/nginx/stop.js +30 -0
  106. package/dist/commands/proxy/nginx/use.js +31 -0
  107. package/dist/commands/restart.js +12 -0
  108. package/dist/commands/revision/create.js +118 -0
  109. package/dist/commands/scaffold/migration.js +38 -0
  110. package/dist/commands/scaffold/plugin.js +37 -0
  111. package/dist/commands/self/check.js +71 -0
  112. package/dist/commands/self/index.js +20 -0
  113. package/dist/commands/self/update.js +152 -0
  114. package/dist/commands/session/id.js +24 -0
  115. package/dist/commands/session/remove.js +57 -0
  116. package/dist/commands/session/setup.js +62 -0
  117. package/dist/commands/skills/check.js +69 -0
  118. package/dist/commands/skills/index.js +20 -0
  119. package/dist/commands/skills/install.js +80 -0
  120. package/dist/commands/skills/remove.js +80 -0
  121. package/dist/commands/skills/update.js +87 -0
  122. package/dist/commands/source/build.js +58 -0
  123. package/dist/commands/source/dev.js +182 -0
  124. package/dist/commands/source/download.js +884 -0
  125. package/dist/commands/source/publish.js +109 -0
  126. package/dist/commands/source/registry/logs.js +70 -0
  127. package/dist/commands/source/registry/start.js +57 -0
  128. package/dist/commands/source/registry/status.js +33 -0
  129. package/dist/commands/source/registry/stop.js +48 -0
  130. package/dist/commands/source/test.js +476 -0
  131. package/dist/commands/start.js +12 -0
  132. package/dist/commands/stop.js +12 -0
  133. package/dist/commands/test.js +12 -0
  134. package/dist/commands/upgrade.js +12 -0
  135. package/dist/commands/v1.js +210 -0
  136. package/dist/generated/command-registry.js +134 -0
  137. package/dist/help/runtime-help.js +23 -0
  138. package/dist/lib/api-client.js +335 -0
  139. package/dist/lib/api-command-compat.js +641 -0
  140. package/dist/lib/app-health.js +139 -0
  141. package/dist/lib/app-managed-resources.js +337 -0
  142. package/dist/lib/app-public-path.js +80 -0
  143. package/dist/lib/app-runtime.js +189 -0
  144. package/dist/lib/auth-store.js +528 -0
  145. package/dist/lib/backup.js +171 -0
  146. package/dist/lib/bootstrap.js +409 -0
  147. package/dist/lib/build-config.js +18 -0
  148. package/dist/lib/builtin-db.js +86 -0
  149. package/dist/lib/cli-config.js +569 -0
  150. package/dist/lib/cli-entry-error.js +52 -0
  151. package/dist/lib/cli-home.js +47 -0
  152. package/dist/lib/cli-locale.js +141 -0
  153. package/dist/lib/command-discovery.js +39 -0
  154. package/dist/lib/command-log.js +284 -0
  155. package/dist/lib/db-connection-check.js +219 -0
  156. package/dist/lib/docker-env-file.js +60 -0
  157. package/dist/lib/docker-image.js +37 -0
  158. package/dist/lib/docker-log-stream.js +45 -0
  159. package/dist/lib/env-auth.js +963 -0
  160. package/dist/lib/env-command-config.js +45 -0
  161. package/dist/lib/env-config.js +108 -0
  162. package/dist/lib/env-guard.js +61 -0
  163. package/dist/lib/env-paths.js +101 -0
  164. package/dist/lib/env-proxy.js +1325 -0
  165. package/dist/lib/generated-command.js +203 -0
  166. package/dist/lib/http-request.js +49 -0
  167. package/dist/lib/inquirer-theme.js +17 -0
  168. package/dist/lib/inquirer.js +243 -0
  169. package/dist/lib/managed-env-file.js +101 -0
  170. package/dist/lib/managed-init-env.js +32 -0
  171. package/dist/lib/naming.js +70 -0
  172. package/dist/lib/object-utils.js +76 -0
  173. package/dist/lib/openapi.js +62 -0
  174. package/dist/lib/plugin-import.js +279 -0
  175. package/dist/lib/plugin-storage.js +64 -0
  176. package/dist/lib/post-processors.js +23 -0
  177. package/dist/lib/prompt-catalog-core.js +186 -0
  178. package/dist/lib/prompt-catalog-terminal.js +374 -0
  179. package/{src/index.js → dist/lib/prompt-catalog.js} +2 -6
  180. package/dist/lib/prompt-validators.js +278 -0
  181. package/dist/lib/prompt-web-ui.js +2234 -0
  182. package/dist/lib/proxy-caddy.js +274 -0
  183. package/dist/lib/proxy-nginx.js +330 -0
  184. package/dist/lib/resource-command.js +357 -0
  185. package/dist/lib/resource-request.js +104 -0
  186. package/dist/lib/run-npm.js +429 -0
  187. package/dist/lib/runtime-env-vars.js +32 -0
  188. package/dist/lib/runtime-generator.js +498 -0
  189. package/dist/lib/runtime-store.js +56 -0
  190. package/dist/lib/self-manager.js +301 -0
  191. package/dist/lib/session-id.js +17 -0
  192. package/dist/lib/session-integration.js +703 -0
  193. package/dist/lib/session-store.js +118 -0
  194. package/dist/lib/skills-manager.js +438 -0
  195. package/dist/lib/source-publish.js +326 -0
  196. package/dist/lib/source-registry.js +188 -0
  197. package/dist/lib/startup-update.js +309 -0
  198. package/dist/lib/ui.js +159 -0
  199. package/dist/locale/en-US.json +526 -0
  200. package/dist/locale/zh-CN.json +526 -0
  201. package/dist/post-processors/data-modeling.js +84 -0
  202. package/dist/post-processors/data-source-manager.js +138 -0
  203. package/dist/post-processors/index.js +19 -0
  204. package/nocobase-ctl.config.json +388 -0
  205. package/package.json +128 -24
  206. package/scripts/build.mjs +34 -0
  207. package/scripts/clean.mjs +9 -0
  208. package/tsconfig.json +19 -0
  209. package/bin/index.js +0 -39
  210. package/nocobase.conf.tpl +0 -95
  211. package/src/commands/benchmark.js +0 -73
  212. package/src/commands/build.js +0 -49
  213. package/src/commands/clean.js +0 -30
  214. package/src/commands/client.js +0 -166
  215. package/src/commands/create-nginx-conf.js +0 -37
  216. package/src/commands/create-plugin.js +0 -33
  217. package/src/commands/dev.js +0 -200
  218. package/src/commands/doc.js +0 -76
  219. package/src/commands/e2e.js +0 -265
  220. package/src/commands/global.js +0 -43
  221. package/src/commands/index.js +0 -45
  222. package/src/commands/instance-id.js +0 -47
  223. package/src/commands/locale/cronstrue.js +0 -122
  224. package/src/commands/locale/react-js-cron/en-US.json +0 -75
  225. package/src/commands/locale/react-js-cron/zh-CN.json +0 -33
  226. package/src/commands/locale/react-js-cron/zh-TW.json +0 -33
  227. package/src/commands/locale.js +0 -81
  228. package/src/commands/p-test.js +0 -88
  229. package/src/commands/perf.js +0 -63
  230. package/src/commands/pkg.js +0 -321
  231. package/src/commands/pm2.js +0 -37
  232. package/src/commands/postinstall.js +0 -88
  233. package/src/commands/start.js +0 -148
  234. package/src/commands/tar.js +0 -36
  235. package/src/commands/test-coverage.js +0 -55
  236. package/src/commands/test.js +0 -107
  237. package/src/commands/umi.js +0 -33
  238. package/src/commands/update-deps.js +0 -72
  239. package/src/commands/upgrade.js +0 -47
  240. package/src/commands/view-license-key.js +0 -44
  241. package/src/license.js +0 -76
  242. package/src/logger.js +0 -75
  243. package/src/plugin-generator.js +0 -80
  244. package/src/util.js +0 -517
  245. package/templates/bundle-status.html +0 -338
  246. package/templates/create-app-package.json +0 -39
  247. package/templates/plugin/.npmignore.tpl +0 -2
  248. package/templates/plugin/README.md.tpl +0 -1
  249. package/templates/plugin/client.d.ts +0 -2
  250. package/templates/plugin/client.js +0 -1
  251. package/templates/plugin/package.json.tpl +0 -11
  252. package/templates/plugin/server.d.ts +0 -2
  253. package/templates/plugin/server.js +0 -1
  254. package/templates/plugin/src/client/client.d.ts +0 -249
  255. package/templates/plugin/src/client/index.tsx.tpl +0 -1
  256. package/templates/plugin/src/client/locale.ts +0 -21
  257. package/templates/plugin/src/client/plugin.tsx.tpl +0 -10
  258. package/templates/plugin/src/index.ts +0 -2
  259. package/templates/plugin/src/locale/en-US.json +0 -1
  260. package/templates/plugin/src/locale/zh-CN.json +0 -1
  261. package/templates/plugin/src/server/collections/.gitkeep +0 -0
  262. package/templates/plugin/src/server/index.ts.tpl +0 -1
  263. package/templates/plugin/src/server/plugin.ts.tpl +0 -19
@@ -0,0 +1,229 @@
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 { ensureCrossEnvConfirmed, hasExplicitEnvSelection } from '../../lib/env-guard.js';
11
+ import { formatMissingManagedAppEnvMessage, resolveManagedAppRuntime, stopDockerContainer, } from '../../lib/app-runtime.js';
12
+ import { formatAppUrl, resolveManagedAppApiBaseUrl, waitForAppReady } from '../../lib/app-health.js';
13
+ import { recreateSavedDockerApp } from '../../lib/app-managed-resources.js';
14
+ import { resolveAppUrlFromApiBaseUrl } from '../env/shared.js';
15
+ import { run } from '../../lib/run-npm.js';
16
+ import { announceTargetEnv, failTask, startTask, succeedTask } from '../../lib/ui.js';
17
+ function argvHasToken(argv, tokens) {
18
+ return tokens.some((token) => argv.includes(token));
19
+ }
20
+ function pushFlag(argv, flag, value) {
21
+ if (value !== undefined) {
22
+ argv.push(flag, String(value));
23
+ }
24
+ }
25
+ function buildLicenseSyncArgv(envName, options) {
26
+ const argv = ['--env', envName, '--skip-if-no-license'];
27
+ if (options.yes || options.explicitEnvSelection) {
28
+ argv.push('--yes');
29
+ }
30
+ if (options.verbose) {
31
+ argv.push('--verbose');
32
+ }
33
+ return argv;
34
+ }
35
+ async function runWithSuppressedTargetEnvLog(task) {
36
+ const previousTargetEnv = process.env.NB_SKIP_TARGET_ENV_LOG;
37
+ process.env.NB_SKIP_TARGET_ENV_LOG = '1';
38
+ try {
39
+ return await task();
40
+ }
41
+ finally {
42
+ if (previousTargetEnv === undefined) {
43
+ delete process.env.NB_SKIP_TARGET_ENV_LOG;
44
+ }
45
+ else {
46
+ process.env.NB_SKIP_TARGET_ENV_LOG = previousTargetEnv;
47
+ }
48
+ }
49
+ }
50
+ function formatDockerRestartFailure(envName, message) {
51
+ return [
52
+ `Couldn't restart NocoBase for "${envName}".`,
53
+ 'The CLI was not able to recreate the saved Docker app container successfully.',
54
+ 'Check the saved Docker image, envFile, container settings, and database connection, then try again.',
55
+ `Details: ${message}`,
56
+ ].join('\n');
57
+ }
58
+ function resolveDisplayAppUrl(apiBaseUrl, port, appPublicPath) {
59
+ const resolvedFromApiBaseUrl = resolveAppUrlFromApiBaseUrl(apiBaseUrl);
60
+ if (resolvedFromApiBaseUrl) {
61
+ return resolvedFromApiBaseUrl;
62
+ }
63
+ return formatAppUrl(port, appPublicPath);
64
+ }
65
+ export default class AppRestart extends Command {
66
+ static hidden = false;
67
+ static description = 'Restart NocoBase for the selected env. When applicable, the CLI synchronizes licensed commercial plugins first, then restarts the local app or recreates the saved Docker container.';
68
+ static examples = [
69
+ '<%= config.bin %> <%= command.id %>',
70
+ '<%= config.bin %> <%= command.id %> --env local',
71
+ '<%= config.bin %> <%= command.id %> --env local --verbose',
72
+ '<%= config.bin %> <%= command.id %> --env local-docker',
73
+ ];
74
+ static flags = {
75
+ env: Flags.string({
76
+ char: 'e',
77
+ description: 'CLI env name to restart. Defaults to the current env when omitted',
78
+ }),
79
+ yes: Flags.boolean({
80
+ char: 'y',
81
+ description: 'Confirm using --env when it targets a different env than the current env',
82
+ default: false,
83
+ }),
84
+ quickstart: Flags.boolean({
85
+ hidden: true,
86
+ description: 'Quickstart the application after stopping it',
87
+ required: false,
88
+ default: true,
89
+ allowNo: true,
90
+ }),
91
+ 'sync-licensed-plugins': Flags.boolean({
92
+ hidden: true,
93
+ description: 'Synchronize licensed commercial plugins before restarting the application',
94
+ required: false,
95
+ default: true,
96
+ allowNo: true,
97
+ }),
98
+ daemon: Flags.boolean({
99
+ hidden: true,
100
+ description: 'Run the application as a daemon after stopping it (default: true; use --no-daemon to stay in the foreground)',
101
+ char: 'd',
102
+ required: false,
103
+ default: true,
104
+ allowNo: true,
105
+ }),
106
+ verbose: Flags.boolean({
107
+ description: 'Show raw shutdown/startup output from the underlying local or Docker command',
108
+ default: false,
109
+ }),
110
+ };
111
+ async run() {
112
+ const { flags } = await this.parse(AppRestart);
113
+ const quickstart = flags.quickstart ?? true;
114
+ const requestedEnv = flags.env?.trim() || undefined;
115
+ const explicitEnvSelection = Boolean(requestedEnv && hasExplicitEnvSelection(this.argv));
116
+ const shouldSyncLicensedPlugins = flags['sync-licensed-plugins'] ?? true;
117
+ if (explicitEnvSelection) {
118
+ const confirmed = await ensureCrossEnvConfirmed({
119
+ command: this,
120
+ requestedEnv,
121
+ yes: flags.yes,
122
+ });
123
+ if (!confirmed) {
124
+ return;
125
+ }
126
+ }
127
+ const runtime = await resolveManagedAppRuntime(requestedEnv);
128
+ const runCommand = this.config.runCommand.bind(this.config);
129
+ const commandStdio = flags.verbose ? 'inherit' : 'ignore';
130
+ if (!runtime) {
131
+ this.error(formatMissingManagedAppEnvMessage(requestedEnv));
132
+ }
133
+ if (runtime.kind === 'http') {
134
+ this.error([
135
+ `Can't restart "${runtime.envName}" from this machine.`,
136
+ 'This env only has an API connection, so there is no saved local app or Docker runtime to restart here.',
137
+ 'Connect it to a local checkout or reinstall it with npm, git, or Docker if you want CLI-managed restart.',
138
+ ].join('\n'));
139
+ }
140
+ if (runtime.kind === 'ssh') {
141
+ this.error([
142
+ `Can't restart "${runtime.envName}" yet.`,
143
+ 'SSH env support is reserved but not implemented yet.',
144
+ 'Use a local or Docker env if you need CLI-managed restart right now.',
145
+ ].join('\n'));
146
+ }
147
+ announceTargetEnv(runtime.envName);
148
+ if (shouldSyncLicensedPlugins) {
149
+ try {
150
+ await runWithSuppressedTargetEnvLog(async () => {
151
+ await runCommand('license:plugins:sync', buildLicenseSyncArgv(runtime.envName, {
152
+ explicitEnvSelection,
153
+ yes: flags.yes,
154
+ verbose: flags.verbose,
155
+ }));
156
+ });
157
+ }
158
+ catch (error) {
159
+ this.error(error instanceof Error ? error.message : String(error));
160
+ }
161
+ }
162
+ if (runtime.kind === 'docker') {
163
+ startTask(`Stopping NocoBase for "${runtime.envName}" before restart...`);
164
+ try {
165
+ const state = await stopDockerContainer(runtime.containerName, {
166
+ stdio: commandStdio,
167
+ });
168
+ succeedTask(state === 'already-stopped'
169
+ ? `NocoBase was already stopped for "${runtime.envName}".`
170
+ : `Stopped NocoBase for "${runtime.envName}".`);
171
+ }
172
+ catch (error) {
173
+ const message = error instanceof Error ? error.message : String(error);
174
+ failTask(`Failed to stop NocoBase for "${runtime.envName}".`);
175
+ this.error(formatDockerRestartFailure(runtime.envName, message));
176
+ }
177
+ startTask(`Recreating the Docker app container for "${runtime.envName}"...`);
178
+ try {
179
+ await run('docker', ['rm', '-f', runtime.containerName], {
180
+ errorName: 'docker rm',
181
+ stdio: commandStdio,
182
+ }).catch(() => undefined);
183
+ await recreateSavedDockerApp(runtime, {
184
+ verbose: flags.verbose,
185
+ });
186
+ succeedTask(`Docker app container is ready for "${runtime.envName}".`);
187
+ }
188
+ catch (error) {
189
+ const message = error instanceof Error ? error.message : String(error);
190
+ failTask(`Failed to recreate NocoBase for "${runtime.envName}".`);
191
+ this.error(formatDockerRestartFailure(runtime.envName, message));
192
+ }
193
+ const apiBaseUrl = resolveManagedAppApiBaseUrl(runtime);
194
+ const appUrl = resolveDisplayAppUrl(apiBaseUrl, runtime.env.appPort === undefined || runtime.env.appPort === null ? undefined : String(runtime.env.appPort), runtime.env.config?.appPublicPath);
195
+ await waitForAppReady({
196
+ envName: runtime.envName,
197
+ apiBaseUrl,
198
+ containerName: runtime.containerName,
199
+ logHint: `You can inspect startup logs with \`nb app logs --env ${runtime.envName}\`.`,
200
+ ...(flags.verbose ? { verbose: true } : {}),
201
+ });
202
+ succeedTask(`NocoBase is running for "${runtime.envName}"${appUrl ? ` at ${appUrl}` : ''}.`);
203
+ return;
204
+ }
205
+ const stopArgv = [];
206
+ const daemonFlagWasProvided = argvHasToken(this.argv, ['--daemon', '--no-daemon']);
207
+ pushFlag(stopArgv, '--env', requestedEnv);
208
+ if (flags.yes || explicitEnvSelection) {
209
+ stopArgv.push('--yes');
210
+ }
211
+ if (flags.verbose) {
212
+ stopArgv.push('--verbose');
213
+ }
214
+ await runWithSuppressedTargetEnvLog(async () => {
215
+ await runCommand('app:stop', stopArgv);
216
+ });
217
+ const startArgv = [...stopArgv];
218
+ if (quickstart) {
219
+ startArgv.push('--quickstart');
220
+ }
221
+ startArgv.push('--no-sync-licensed-plugins');
222
+ if (daemonFlagWasProvided) {
223
+ startArgv.push(flags.daemon === false ? '--no-daemon' : '--daemon');
224
+ }
225
+ await runWithSuppressedTargetEnvLog(async () => {
226
+ await runCommand('app:start', startArgv);
227
+ });
228
+ }
229
+ }
@@ -0,0 +1,123 @@
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 fsp from 'node:fs/promises';
10
+ import os from 'node:os';
11
+ import path from 'node:path';
12
+ import { buildDockerDbContainerName } from '../../lib/app-runtime.js';
13
+ import { resolveConfiguredEnvPath } from '../../lib/cli-home.js';
14
+ import { resolveConfiguredAppPath } from '../../lib/env-paths.js';
15
+ import { commandOutput, run } from '../../lib/run-npm.js';
16
+ export function resolveConfiguredPath(value) {
17
+ return resolveConfiguredEnvPath(value);
18
+ }
19
+ function assertSafeRemovalPath(target, label) {
20
+ const resolved = path.resolve(target);
21
+ const cwd = path.resolve(process.cwd());
22
+ const home = path.resolve(os.homedir());
23
+ const root = path.parse(resolved).root;
24
+ if (resolved === root || resolved === cwd || resolved === home) {
25
+ throw new Error(`Refusing to remove ${label} at "${resolved}" because it is too broad.`);
26
+ }
27
+ }
28
+ export async function removePathIfExists(target, label) {
29
+ const resolved = path.resolve(target);
30
+ assertSafeRemovalPath(resolved, label);
31
+ await fsp.rm(resolved, { recursive: true, force: true });
32
+ }
33
+ function isMissingDockerContainerError(error) {
34
+ const message = error instanceof Error ? error.message : String(error);
35
+ return /No such (container|object)/i.test(message);
36
+ }
37
+ function isMissingDockerNetworkError(error) {
38
+ const message = error instanceof Error ? error.message : String(error);
39
+ return /No such network|network .* not found/i.test(message);
40
+ }
41
+ export async function removeDockerContainerIfExists(containerName, options) {
42
+ try {
43
+ await commandOutput('docker', ['container', 'inspect', containerName], {
44
+ errorName: 'docker container inspect',
45
+ });
46
+ }
47
+ catch (error) {
48
+ if (isMissingDockerContainerError(error)) {
49
+ return 'missing';
50
+ }
51
+ throw error;
52
+ }
53
+ await run('docker', ['rm', '-f', containerName], {
54
+ errorName: 'docker rm',
55
+ stdio: options?.stdio ?? 'ignore',
56
+ });
57
+ return 'removed';
58
+ }
59
+ async function dockerNetworkExists(networkName) {
60
+ try {
61
+ await commandOutput('docker', ['network', 'inspect', networkName], {
62
+ errorName: 'docker network inspect',
63
+ });
64
+ return true;
65
+ }
66
+ catch (error) {
67
+ if (isMissingDockerNetworkError(error)) {
68
+ return false;
69
+ }
70
+ throw error;
71
+ }
72
+ }
73
+ async function dockerNetworkHasActiveEndpoints(networkName) {
74
+ try {
75
+ const output = await commandOutput('docker', ['network', 'inspect', networkName, '--format', '{{json .Containers}}'], {
76
+ errorName: 'docker network inspect',
77
+ });
78
+ const containers = JSON.parse(output || '{}');
79
+ return Boolean(containers && typeof containers === 'object' && Object.keys(containers).length > 0);
80
+ }
81
+ catch {
82
+ return false;
83
+ }
84
+ }
85
+ export async function removeDockerNetworkIfUnused(networkName) {
86
+ if (!(await dockerNetworkExists(networkName))) {
87
+ return 'missing';
88
+ }
89
+ try {
90
+ await run('docker', ['network', 'rm', networkName], {
91
+ errorName: 'docker network rm',
92
+ stdio: 'ignore',
93
+ });
94
+ return 'removed';
95
+ }
96
+ catch (error) {
97
+ const message = error instanceof Error ? error.message : String(error);
98
+ if (/has active endpoints|is in use|active endpoints/i.test(message) ||
99
+ ((await dockerNetworkExists(networkName)) && (await dockerNetworkHasActiveEndpoints(networkName)))) {
100
+ return 'in-use';
101
+ }
102
+ if (isMissingDockerNetworkError(error)) {
103
+ return 'missing';
104
+ }
105
+ throw error;
106
+ }
107
+ }
108
+ export function builtinDbContainerName(runtime) {
109
+ if (!runtime.env.config.builtinDb) {
110
+ return undefined;
111
+ }
112
+ const dbDialect = String(runtime.env.config.dbDialect ?? 'postgres').trim() || 'postgres';
113
+ return buildDockerDbContainerName(runtime.envName, dbDialect, runtime.dockerContainerPrefix || runtime.workspaceName);
114
+ }
115
+ export function managedDockerNetworkName(runtime) {
116
+ return runtime.dockerNetworkName?.trim() || runtime.workspaceName?.trim() || undefined;
117
+ }
118
+ export function resolveManagedLocalAppPath(runtime) {
119
+ return resolveConfiguredAppPath(runtime.env.config) || runtime.projectRoot || resolveConfiguredPath(runtime.env.config.appRootPath);
120
+ }
121
+ export function shouldRemoveManagedLocalAppFiles(runtime) {
122
+ return runtime.source === 'npm' || runtime.source === 'git' || runtime.source === 'local';
123
+ }