@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,50 @@
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 { resolveManagedAppRuntime } from '../../lib/app-runtime.js';
11
+ import { listEnvs } from '../../lib/auth-store.js';
12
+ import { resolveDefaultConfigScope } from '../../lib/cli-home.js';
13
+ import { renderTable } from '../../lib/ui.js';
14
+ import { apiStatus, appUrl, resolveApiBaseUrl } from './shared.js';
15
+ export default class EnvList extends Command {
16
+ static summary = 'List configured environments and API auth status';
17
+ static examples = [
18
+ '<%= config.bin %> <%= command.id %>',
19
+ ];
20
+ async run() {
21
+ await this.parse(EnvList);
22
+ const scope = resolveDefaultConfigScope();
23
+ const { currentEnv, envs } = await listEnvs({ scope });
24
+ const names = Object.keys(envs).sort();
25
+ if (!names.length) {
26
+ this.log('No envs configured.');
27
+ this.log('Run `nb env add <name> --api-base-url <url>` to add one.');
28
+ return;
29
+ }
30
+ const rows = [];
31
+ for (const name of names) {
32
+ const env = envs[name];
33
+ const runtime = await resolveManagedAppRuntime(name);
34
+ const statusConfig = {
35
+ ...env,
36
+ ...(runtime?.env.config ?? {}),
37
+ };
38
+ rows.push([
39
+ name === currentEnv ? '*' : '',
40
+ name,
41
+ runtime?.kind ?? env.kind ?? '-',
42
+ await apiStatus(name, statusConfig, { scope }),
43
+ runtime ? appUrl(runtime) : resolveApiBaseUrl(env),
44
+ env.auth?.type ?? '',
45
+ env.runtime?.version ?? '',
46
+ ]);
47
+ }
48
+ this.log(renderTable(['Current', 'Name', 'Kind', 'App Status', 'URL', 'Auth', 'Runtime'], rows));
49
+ }
50
+ }
@@ -0,0 +1,59 @@
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, Flags } from '@oclif/core';
10
+ import { getCurrentEnvName, removeEnv } from '../../lib/auth-store.js';
11
+ import { resolveDefaultConfigScope } from '../../lib/cli-home.js';
12
+ import { confirmAction, isInteractiveTerminal, printVerbose, setVerboseMode } from '../../lib/ui.js';
13
+ export default class EnvRemove extends Command {
14
+ static summary = 'Remove a configured environment';
15
+ static examples = [
16
+ '<%= config.bin %> <%= command.id %> staging',
17
+ '<%= config.bin %> <%= command.id %> staging -f',
18
+ ];
19
+ static flags = {
20
+ force: Flags.boolean({
21
+ char: 'f',
22
+ description: 'Remove without confirmation',
23
+ default: false,
24
+ }),
25
+ verbose: Flags.boolean({
26
+ description: 'Show detailed progress output',
27
+ default: false,
28
+ }),
29
+ };
30
+ static args = {
31
+ name: Args.string({
32
+ description: 'Configured environment name',
33
+ required: true,
34
+ }),
35
+ };
36
+ async run() {
37
+ const { args, flags } = await this.parse(EnvRemove);
38
+ setVerboseMode(flags.verbose);
39
+ const currentEnv = await getCurrentEnvName({ scope: resolveDefaultConfigScope() });
40
+ if (args.name === currentEnv && !flags.force) {
41
+ if (!isInteractiveTerminal()) {
42
+ this.error('Refusing to remove the current env without confirmation. Re-run with `--force`.');
43
+ }
44
+ const confirmed = await confirmAction(`Remove current env "${args.name}"?`, { defaultValue: false });
45
+ if (!confirmed) {
46
+ this.log('Canceled.');
47
+ return;
48
+ }
49
+ }
50
+ printVerbose(`Removing env "${args.name}"`);
51
+ const result = await removeEnv(args.name, { scope: resolveDefaultConfigScope() });
52
+ this.log(`Removed env "${result.removed}".`);
53
+ if (result.hasEnvs) {
54
+ this.log(`Current env: ${result.currentEnv}`);
55
+ return;
56
+ }
57
+ this.log('No envs configured.');
58
+ }
59
+ }
@@ -0,0 +1,158 @@
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 { buildDockerDbContainerName, dockerContainerExists, dockerContainerIsRunning, } from '../../lib/app-runtime.js';
10
+ import { executeRawApiRequest } from '../../lib/api-client.js';
11
+ export function resolveApiBaseUrl(config) {
12
+ return String(config.apiBaseUrl ?? config.baseUrl ?? config.apibaseUrl ?? '').trim();
13
+ }
14
+ export function appUrl(runtime) {
15
+ const port = String(runtime.env.config.appPort ?? '').trim();
16
+ if (port) {
17
+ return `http://127.0.0.1:${port}`;
18
+ }
19
+ const baseUrl = resolveApiBaseUrl(runtime.env.config);
20
+ return baseUrl.replace(/\/api\/?$/, '');
21
+ }
22
+ export function appRootPath(runtime) {
23
+ if (runtime.kind === 'http' || runtime.kind === 'docker') {
24
+ return '-';
25
+ }
26
+ if (runtime.kind === 'local') {
27
+ return String(runtime.projectRoot ?? runtime.env.appRootPath ?? '').trim() || '-';
28
+ }
29
+ return String(runtime.env.config.appRootPath ?? '').trim() || '-';
30
+ }
31
+ export function storagePath(runtime) {
32
+ if (runtime.kind === 'http') {
33
+ return '-';
34
+ }
35
+ const value = String(runtime.env.storagePath ?? runtime.env.config.storagePath ?? '').trim();
36
+ return value || '-';
37
+ }
38
+ function collectErrorCodes(value) {
39
+ if (!value || typeof value !== 'object') {
40
+ return [];
41
+ }
42
+ if (Array.isArray(value)) {
43
+ return value.flatMap((item) => collectErrorCodes(item));
44
+ }
45
+ const out = [];
46
+ const record = value;
47
+ if (typeof record.code === 'string') {
48
+ out.push(record.code);
49
+ }
50
+ for (const key of ['data', 'error', 'errors']) {
51
+ out.push(...collectErrorCodes(record[key]));
52
+ }
53
+ return out;
54
+ }
55
+ function isAuthFailureData(value) {
56
+ const codes = collectErrorCodes(value);
57
+ return codes.some((code) => ['EMPTY_TOKEN', 'INVALID_TOKEN', 'EXPIRED_TOKEN', 'BLOCKED_TOKEN', 'EXPIRED_SESSION', 'NOT_EXIST_USER'].includes(code));
58
+ }
59
+ function isNetworkFailure(error) {
60
+ if (!(error instanceof Error)) {
61
+ return false;
62
+ }
63
+ return (error.name === 'AbortError'
64
+ || /fetch failed|network|timeout|timed out|abort|ECONNREFUSED|ECONNRESET|ENOTFOUND|ETIMEDOUT|EAI_AGAIN|ENETUNREACH/i.test(error.message));
65
+ }
66
+ function isUnconfiguredFailure(error) {
67
+ return error instanceof Error && /missing (a )?base url|missing base URL/i.test(error.message);
68
+ }
69
+ function isAuthFailure(error) {
70
+ return (error instanceof Error
71
+ && /EMPTY_TOKEN|INVALID_TOKEN|EXPIRED_TOKEN|BLOCKED_TOKEN|EXPIRED_SESSION|NOT_EXIST_USER|invalid_grant|sign in|signin|authentication failed/i.test(error.message));
72
+ }
73
+ export async function apiStatus(envName, config, options = {}) {
74
+ if (!resolveApiBaseUrl(config)) {
75
+ return 'unconfigured';
76
+ }
77
+ try {
78
+ const response = await executeRawApiRequest({
79
+ envName,
80
+ scope: options.scope,
81
+ method: 'GET',
82
+ path: '/auth:check',
83
+ timeoutMs: options.timeoutMs ?? 2000,
84
+ });
85
+ if (response.ok) {
86
+ return 'ok';
87
+ }
88
+ if (response.status === 401 || response.status === 403 || isAuthFailureData(response.data)) {
89
+ return 'auth failed';
90
+ }
91
+ return 'error';
92
+ }
93
+ catch (error) {
94
+ if (isUnconfiguredFailure(error)) {
95
+ return 'unconfigured';
96
+ }
97
+ if (isAuthFailure(error)) {
98
+ return 'auth failed';
99
+ }
100
+ if (isNetworkFailure(error)) {
101
+ return 'unreachable';
102
+ }
103
+ return 'error';
104
+ }
105
+ }
106
+ async function isLocalAppHealthy(runtime) {
107
+ const port = String(runtime.env.config.appPort ?? '').trim();
108
+ if (!port) {
109
+ return false;
110
+ }
111
+ const controller = new AbortController();
112
+ const timeout = setTimeout(() => controller.abort(), 1500);
113
+ try {
114
+ const response = await fetch(`http://127.0.0.1:${port}/api/__health_check`, {
115
+ signal: controller.signal,
116
+ });
117
+ const text = await response.text();
118
+ return response.ok && text.trim().toLowerCase() === 'ok';
119
+ }
120
+ catch (_error) {
121
+ return false;
122
+ }
123
+ finally {
124
+ clearTimeout(timeout);
125
+ }
126
+ }
127
+ async function dockerStatus(containerName) {
128
+ if (!(await dockerContainerExists(containerName))) {
129
+ return 'missing';
130
+ }
131
+ return await dockerContainerIsRunning(containerName) ? 'running' : 'stopped';
132
+ }
133
+ export async function dbStatus(runtime) {
134
+ if (!runtime.env.config.builtinDb) {
135
+ return runtime.kind === 'http' ? 'external' : '-';
136
+ }
137
+ if (runtime.kind === 'http') {
138
+ return 'external';
139
+ }
140
+ if (runtime.kind === 'ssh') {
141
+ return '-';
142
+ }
143
+ const dbDialect = String(runtime.env.config.dbDialect ?? 'postgres').trim() || 'postgres';
144
+ const containerName = buildDockerDbContainerName(runtime.envName, dbDialect, runtime.dockerContainerPrefix || runtime.workspaceName);
145
+ return await dockerStatus(containerName);
146
+ }
147
+ export async function runtimeStatus(runtime) {
148
+ if (runtime.kind === 'http') {
149
+ return 'http';
150
+ }
151
+ if (runtime.kind === 'ssh') {
152
+ return 'ssh';
153
+ }
154
+ if (runtime.kind === 'docker') {
155
+ return await dockerStatus(runtime.containerName);
156
+ }
157
+ return await isLocalAppHealthy(runtime) ? 'running' : 'stopped';
158
+ }
@@ -0,0 +1,67 @@
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 path from 'node:path';
10
+ import { fileURLToPath } from 'node:url';
11
+ import { Args, Command, Flags } from '@oclif/core';
12
+ import { getCurrentEnvName } from '../../lib/auth-store.js';
13
+ import { updateEnvRuntime } from '../../lib/bootstrap.js';
14
+ import { resolveDefaultConfigScope } from '../../lib/cli-home.js';
15
+ import { failTask, startTask, succeedTask } from '../../lib/ui.js';
16
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
17
+ export default class EnvUpdate extends Command {
18
+ static summary = 'Refresh an environment runtime from swagger:get and persist connection overrides';
19
+ static examples = [
20
+ '<%= config.bin %> <%= command.id %>',
21
+ '<%= config.bin %> <%= command.id %> prod',
22
+ ];
23
+ static args = {
24
+ name: Args.string({
25
+ description: 'Environment name (omit to use the current env)',
26
+ required: false,
27
+ }),
28
+ };
29
+ static flags = {
30
+ verbose: Flags.boolean({
31
+ description: 'Show detailed progress output',
32
+ default: false,
33
+ }),
34
+ 'api-base-url': Flags.string({
35
+ description: 'NocoBase API base URL override. When provided, persist it to the target env before saving the refreshed runtime.',
36
+ }),
37
+ role: Flags.string({
38
+ description: 'Role override, sent as X-Role',
39
+ }),
40
+ token: Flags.string({
41
+ char: 't',
42
+ description: 'API key override. When provided, persist it to the target env before saving the refreshed runtime.',
43
+ }),
44
+ };
45
+ async run() {
46
+ const { args, flags } = await this.parse(EnvUpdate);
47
+ const envName = args.name;
48
+ const envLabel = envName ?? (await getCurrentEnvName({ scope: resolveDefaultConfigScope() }));
49
+ startTask(`Updating env runtime: ${envLabel}`);
50
+ try {
51
+ const runtime = await updateEnvRuntime({
52
+ envName,
53
+ scope: resolveDefaultConfigScope(),
54
+ baseUrl: flags['api-base-url'],
55
+ role: flags.role,
56
+ token: flags.token,
57
+ configFile: path.join(path.dirname(path.dirname(path.dirname(__dirname))), 'nocobase-ctl.config.json'),
58
+ verbose: flags.verbose,
59
+ });
60
+ succeedTask(`Updated env "${envLabel}" to runtime "${runtime.version}".`);
61
+ }
62
+ catch (error) {
63
+ failTask(`Failed to update env "${envLabel}".`);
64
+ throw error;
65
+ }
66
+ }
67
+ }
@@ -0,0 +1,28 @@
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 { setCurrentEnv } from '../../lib/auth-store.js';
11
+ import { resolveDefaultConfigScope } from '../../lib/cli-home.js';
12
+ export default class EnvUse extends Command {
13
+ static summary = 'Switch the current environment';
14
+ static examples = [
15
+ '<%= config.bin %> <%= command.id %> local',
16
+ ];
17
+ static args = {
18
+ name: Args.string({
19
+ description: 'Configured environment name',
20
+ required: true,
21
+ }),
22
+ };
23
+ async run() {
24
+ const { args } = await this.parse(EnvUse);
25
+ await setCurrentEnv(args.name, { scope: resolveDefaultConfigScope() });
26
+ this.log(`Current env: ${args.name}`);
27
+ }
28
+ }
@@ -0,0 +1,150 @@
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, Flags } from '@oclif/core';
10
+ import { runPromptCatalog, } from "../../lib/prompt-catalog.js";
11
+ import { applyCliLocale, CLI_LOCALE_FLAG_DESCRIPTION, CLI_LOCALE_FLAG_OPTIONS, } from "../../lib/cli-locale.js";
12
+ import { runPromptCatalogWebUI } from "../../lib/prompt-web-ui.js";
13
+ import PromptsTest from "./prompts-test.js";
14
+ function buildWebUiStagesFromTestPrompts(c) {
15
+ return [
16
+ {
17
+ sectionTitle: 'Step 1',
18
+ sectionDescription: 'intro, file, name, and boolean',
19
+ catalog: {
20
+ intro1: c.intro1,
21
+ file: c.file,
22
+ text: c.text,
23
+ boolean: c.boolean,
24
+ },
25
+ },
26
+ {
27
+ sectionTitle: 'Step 2',
28
+ sectionDescription: 'select, then the option1 run hook',
29
+ catalog: {
30
+ select: c.select,
31
+ onOption1: c.onOption1,
32
+ },
33
+ },
34
+ {
35
+ sectionTitle: 'Step 3',
36
+ sectionDescription: 'password, integer, and outro',
37
+ catalog: {
38
+ password: c.password,
39
+ integer: c.integer,
40
+ outro1: c.outro1,
41
+ },
42
+ },
43
+ ];
44
+ }
45
+ /**
46
+ * With `--ui`: `runPromptCatalogWebUI` using `stages` + `sectionTitle`, then
47
+ * `runPromptCatalog` on the same catalog as `prompts-test`. Without `--ui`, same terminal behavior
48
+ * as `prompts-test` (handy for comparing).
49
+ */
50
+ export default class PromptsStages extends Command {
51
+ static hidden = true;
52
+ static args = {
53
+ file: Args.string({ description: 'file to read', required: false }),
54
+ };
55
+ static description = 'Demo: with --ui, `runPromptCatalogWebUI` with `stages` (section headings in the form); without --ui, same as `prompts-test`. The submitted preset runs through the same `PromptsTest.prompts` catalog as `prompts-test`.';
56
+ static examples = [
57
+ '<%= config.bin %> <%= command.id %> # same terminal flow as `prompts-test`',
58
+ '<%= config.bin %> <%= command.id %> --ui # `runPromptCatalogWebUI` with `stages` + `sectionTitle`',
59
+ '<%= config.bin %> <%= command.id %> -y ./README.md -p secret --ui',
60
+ ];
61
+ static flags = {
62
+ ui: Flags.boolean({
63
+ description: 'Open the localhost form: `runPromptCatalogWebUI` with `stages` and `sectionTitle` (vs `prompts-test --ui`, which uses one `catalog`). Without --ui, behavior matches `prompts-test` (Clack in TTY / presets).',
64
+ default: false,
65
+ }),
66
+ yes: Flags.boolean({
67
+ char: 'y',
68
+ description: 'Accept defaults only in the terminal (no Clack after submit); same semantics as `prompts-test` when used with the submitted or default preset.',
69
+ default: false,
70
+ }),
71
+ locale: Flags.string({
72
+ description: CLI_LOCALE_FLAG_DESCRIPTION,
73
+ options: CLI_LOCALE_FLAG_OPTIONS,
74
+ }),
75
+ file: Flags.string({
76
+ char: 'f',
77
+ description: 'Merged into initialValues.file (default for the text prompt when set)',
78
+ }),
79
+ text: Flags.string({
80
+ char: 't',
81
+ description: 'Merged into initialValues.text (default for the text prompt when set)',
82
+ }),
83
+ boolean: Flags.boolean({
84
+ char: 'b',
85
+ description: 'Merged into initialValues.boolean (default for confirm when set)',
86
+ allowNo: true,
87
+ }),
88
+ select: Flags.string({
89
+ char: 's',
90
+ description: 'Merged into initialValues.select (default for select when set)',
91
+ options: ['option1', 'option2', 'option3'],
92
+ }),
93
+ password: Flags.string({
94
+ char: 'p',
95
+ description: 'Merged into initialValues.password (required when -y / non-TTY if password is required)',
96
+ }),
97
+ integer: Flags.integer({
98
+ char: 'i',
99
+ description: 'Merged into initialValues.integer (default for integer prompt when set)',
100
+ }),
101
+ };
102
+ async run() {
103
+ const { args, flags } = await this.parse(PromptsStages);
104
+ applyCliLocale(flags.locale);
105
+ let presetValues = this.buildPresetValuesFromParsed(args, flags);
106
+ if (flags.ui) {
107
+ presetValues = await runPromptCatalogWebUI({
108
+ stages: buildWebUiStagesFromTestPrompts(PromptsTest.prompts),
109
+ values: presetValues,
110
+ pageTitle: 'nb prompts-stages — Web UI',
111
+ documentHeading: 'nb prompts-stages — `stages` demo',
112
+ onServerStart: ({ host, port, url }) => {
113
+ this.log(`Local Web UI (multi-stage) ready — ${url} (listening on ${host}:${port}). Submit the form in the browser to continue.`);
114
+ },
115
+ onOpenBrowserError: (url, err) => {
116
+ this.log(`Open this URL in a browser: ${url} (${err instanceof Error ? err.message : String(err)})`);
117
+ },
118
+ });
119
+ }
120
+ const results = await runPromptCatalog(PromptsTest.prompts, {
121
+ initialValues: {},
122
+ values: presetValues,
123
+ yes: flags.yes || flags.ui,
124
+ });
125
+ this.log(JSON.stringify(results, null, 2));
126
+ }
127
+ buildPresetValuesFromParsed(args, flags) {
128
+ const preset = {};
129
+ const file = args.file ?? flags.file;
130
+ if (file !== undefined) {
131
+ preset.file = file;
132
+ }
133
+ if (flags.text !== undefined) {
134
+ preset.text = flags.text;
135
+ }
136
+ if (flags.boolean !== undefined) {
137
+ preset.boolean = flags.boolean;
138
+ }
139
+ if (flags.select !== undefined) {
140
+ preset.select = flags.select;
141
+ }
142
+ if (flags.password !== undefined) {
143
+ preset.password = flags.password;
144
+ }
145
+ if (flags.integer !== undefined) {
146
+ preset.integer = flags.integer;
147
+ }
148
+ return preset;
149
+ }
150
+ }