@nocobase/cli 2.1.0-alpha.4 → 2.1.0-alpha.45

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 (214) hide show
  1. package/LICENSE.txt +107 -0
  2. package/README.md +405 -19
  3. package/README.zh-CN.md +355 -0
  4. package/bin/run.cmd +3 -0
  5. package/bin/run.js +136 -0
  6. package/bin/session-env.js +39 -0
  7. package/dist/commands/api/resource/create.js +15 -0
  8. package/dist/commands/api/resource/destroy.js +15 -0
  9. package/dist/commands/api/resource/get.js +15 -0
  10. package/dist/commands/api/resource/index.js +20 -0
  11. package/dist/commands/api/resource/list.js +16 -0
  12. package/dist/commands/api/resource/query.js +15 -0
  13. package/dist/commands/api/resource/update.js +15 -0
  14. package/dist/commands/app/destroy.js +225 -0
  15. package/dist/commands/app/down.js +71 -0
  16. package/dist/commands/app/logs.js +114 -0
  17. package/dist/commands/app/restart.js +158 -0
  18. package/dist/commands/app/shared.js +122 -0
  19. package/dist/commands/app/start.js +286 -0
  20. package/dist/commands/app/stop.js +161 -0
  21. package/dist/commands/app/upgrade.js +519 -0
  22. package/dist/commands/backup/create.js +147 -0
  23. package/dist/commands/backup/index.js +20 -0
  24. package/dist/commands/backup/restore.js +105 -0
  25. package/{src/cli.js → dist/commands/build.js} +4 -11
  26. package/dist/commands/config/delete.js +34 -0
  27. package/dist/commands/config/get.js +33 -0
  28. package/dist/commands/config/index.js +20 -0
  29. package/dist/commands/config/list.js +29 -0
  30. package/dist/commands/config/set.js +39 -0
  31. package/dist/commands/db/check.js +240 -0
  32. package/dist/commands/db/logs.js +85 -0
  33. package/dist/commands/db/ps.js +60 -0
  34. package/dist/commands/db/shared.js +96 -0
  35. package/dist/commands/db/start.js +86 -0
  36. package/dist/commands/db/stop.js +71 -0
  37. package/{templates/plugin/src/client/models/index.ts → dist/commands/dev.js} +4 -4
  38. package/{src/commands/locale/react-js-cron/index.js → dist/commands/down.js} +3 -8
  39. package/dist/commands/download.js +13 -0
  40. package/dist/commands/env/add.js +426 -0
  41. package/dist/commands/env/auth.js +189 -0
  42. package/dist/commands/env/current.js +21 -0
  43. package/dist/commands/env/info.js +201 -0
  44. package/dist/commands/env/list.js +44 -0
  45. package/dist/commands/env/remove.js +84 -0
  46. package/dist/commands/env/shared.js +196 -0
  47. package/dist/commands/env/status.js +90 -0
  48. package/dist/commands/env/update.js +74 -0
  49. package/dist/commands/env/use.js +38 -0
  50. package/dist/commands/examples/prompts-stages.js +150 -0
  51. package/dist/commands/examples/prompts-test.js +181 -0
  52. package/dist/commands/init.js +1152 -0
  53. package/dist/commands/install.js +2424 -0
  54. package/dist/commands/license/activate.js +360 -0
  55. package/dist/commands/license/env.js +94 -0
  56. package/dist/commands/license/generate-id.js +108 -0
  57. package/dist/commands/license/id.js +70 -0
  58. package/dist/commands/license/index.js +20 -0
  59. package/dist/commands/license/plugins/clean.js +115 -0
  60. package/dist/commands/license/plugins/index.js +20 -0
  61. package/dist/commands/license/plugins/list.js +64 -0
  62. package/dist/commands/license/plugins/shared.js +331 -0
  63. package/dist/commands/license/plugins/sync.js +314 -0
  64. package/dist/commands/license/shared.js +423 -0
  65. package/dist/commands/license/status.js +64 -0
  66. package/dist/commands/logs.js +12 -0
  67. package/dist/commands/plugin/disable.js +86 -0
  68. package/dist/commands/plugin/enable.js +86 -0
  69. package/dist/commands/plugin/list.js +82 -0
  70. package/dist/commands/pm/disable.js +12 -0
  71. package/dist/commands/pm/enable.js +12 -0
  72. package/dist/commands/pm/list.js +12 -0
  73. package/dist/commands/restart.js +12 -0
  74. package/dist/commands/scaffold/migration.js +38 -0
  75. package/dist/commands/scaffold/plugin.js +37 -0
  76. package/dist/commands/self/check.js +71 -0
  77. package/dist/commands/self/index.js +20 -0
  78. package/dist/commands/self/update.js +95 -0
  79. package/dist/commands/session/id.js +24 -0
  80. package/dist/commands/session/remove.js +57 -0
  81. package/dist/commands/session/setup.js +62 -0
  82. package/dist/commands/skills/check.js +69 -0
  83. package/dist/commands/skills/index.js +20 -0
  84. package/dist/commands/skills/install.js +80 -0
  85. package/dist/commands/skills/remove.js +80 -0
  86. package/dist/commands/skills/update.js +87 -0
  87. package/dist/commands/source/build.js +58 -0
  88. package/dist/commands/source/dev.js +182 -0
  89. package/dist/commands/source/download.js +884 -0
  90. package/dist/commands/source/publish.js +109 -0
  91. package/dist/commands/source/registry/logs.js +70 -0
  92. package/dist/commands/source/registry/start.js +57 -0
  93. package/dist/commands/source/registry/status.js +33 -0
  94. package/dist/commands/source/registry/stop.js +48 -0
  95. package/dist/commands/source/test.js +477 -0
  96. package/dist/commands/start.js +12 -0
  97. package/dist/commands/stop.js +12 -0
  98. package/dist/commands/test.js +12 -0
  99. package/dist/commands/upgrade.js +12 -0
  100. package/dist/commands/v1.js +210 -0
  101. package/dist/generated/command-registry.js +134 -0
  102. package/dist/help/runtime-help.js +23 -0
  103. package/dist/lib/api-client.js +335 -0
  104. package/dist/lib/api-command-compat.js +641 -0
  105. package/dist/lib/app-health.js +132 -0
  106. package/dist/lib/app-managed-resources.js +316 -0
  107. package/dist/lib/app-runtime.js +180 -0
  108. package/dist/lib/auth-store.js +396 -0
  109. package/dist/lib/backup.js +171 -0
  110. package/dist/lib/bootstrap.js +403 -0
  111. package/dist/lib/build-config.js +18 -0
  112. package/dist/lib/builtin-db.js +86 -0
  113. package/dist/lib/cli-config.js +271 -0
  114. package/dist/lib/cli-home.js +47 -0
  115. package/dist/lib/cli-locale.js +141 -0
  116. package/dist/lib/command-discovery.js +39 -0
  117. package/dist/lib/db-connection-check.js +219 -0
  118. package/dist/lib/docker-env-file.js +52 -0
  119. package/dist/lib/docker-image.js +37 -0
  120. package/dist/lib/env-auth.js +952 -0
  121. package/dist/lib/env-config.js +95 -0
  122. package/dist/lib/env-guard.js +62 -0
  123. package/dist/lib/generated-command.js +203 -0
  124. package/dist/lib/http-request.js +49 -0
  125. package/dist/lib/inquirer-theme.js +17 -0
  126. package/dist/lib/inquirer.js +244 -0
  127. package/dist/lib/naming.js +70 -0
  128. package/dist/lib/object-utils.js +76 -0
  129. package/dist/lib/openapi.js +62 -0
  130. package/dist/lib/plugin-storage.js +64 -0
  131. package/dist/lib/post-processors.js +23 -0
  132. package/dist/lib/prompt-catalog-core.js +185 -0
  133. package/dist/lib/prompt-catalog-terminal.js +375 -0
  134. package/{src/index.js → dist/lib/prompt-catalog.js} +2 -6
  135. package/dist/lib/prompt-validators.js +258 -0
  136. package/dist/lib/prompt-web-ui.js +2227 -0
  137. package/dist/lib/resource-command.js +357 -0
  138. package/dist/lib/resource-request.js +104 -0
  139. package/dist/lib/run-npm.js +385 -0
  140. package/dist/lib/runtime-env-vars.js +32 -0
  141. package/dist/lib/runtime-generator.js +498 -0
  142. package/dist/lib/runtime-store.js +56 -0
  143. package/dist/lib/self-manager.js +301 -0
  144. package/dist/lib/session-id.js +17 -0
  145. package/dist/lib/session-integration.js +703 -0
  146. package/dist/lib/session-store.js +118 -0
  147. package/dist/lib/skills-manager.js +436 -0
  148. package/dist/lib/source-publish.js +306 -0
  149. package/dist/lib/source-registry.js +188 -0
  150. package/dist/lib/startup-update.js +285 -0
  151. package/dist/lib/ui.js +158 -0
  152. package/dist/locale/en-US.json +425 -0
  153. package/dist/locale/zh-CN.json +425 -0
  154. package/dist/post-processors/data-modeling.js +84 -0
  155. package/dist/post-processors/data-source-manager.js +138 -0
  156. package/dist/post-processors/index.js +19 -0
  157. package/nocobase-ctl.config.json +388 -0
  158. package/package.json +132 -26
  159. package/LICENSE +0 -661
  160. package/bin/index.js +0 -39
  161. package/nocobase.conf.tpl +0 -95
  162. package/src/commands/benchmark.js +0 -73
  163. package/src/commands/build.js +0 -49
  164. package/src/commands/clean.js +0 -30
  165. package/src/commands/client.js +0 -166
  166. package/src/commands/create-nginx-conf.js +0 -37
  167. package/src/commands/create-plugin.js +0 -33
  168. package/src/commands/dev.js +0 -200
  169. package/src/commands/doc.js +0 -76
  170. package/src/commands/e2e.js +0 -265
  171. package/src/commands/global.js +0 -43
  172. package/src/commands/index.js +0 -45
  173. package/src/commands/instance-id.js +0 -47
  174. package/src/commands/locale/cronstrue.js +0 -122
  175. package/src/commands/locale/react-js-cron/en-US.json +0 -75
  176. package/src/commands/locale/react-js-cron/zh-CN.json +0 -33
  177. package/src/commands/locale/react-js-cron/zh-TW.json +0 -33
  178. package/src/commands/locale.js +0 -81
  179. package/src/commands/p-test.js +0 -88
  180. package/src/commands/perf.js +0 -63
  181. package/src/commands/pkg.js +0 -321
  182. package/src/commands/pm2.js +0 -37
  183. package/src/commands/postinstall.js +0 -88
  184. package/src/commands/start.js +0 -148
  185. package/src/commands/tar.js +0 -36
  186. package/src/commands/test-coverage.js +0 -55
  187. package/src/commands/test.js +0 -107
  188. package/src/commands/umi.js +0 -33
  189. package/src/commands/update-deps.js +0 -72
  190. package/src/commands/upgrade.js +0 -47
  191. package/src/commands/view-license-key.js +0 -44
  192. package/src/license.js +0 -76
  193. package/src/logger.js +0 -75
  194. package/src/plugin-generator.js +0 -80
  195. package/src/util.js +0 -517
  196. package/templates/bundle-status.html +0 -338
  197. package/templates/create-app-package.json +0 -39
  198. package/templates/plugin/.npmignore.tpl +0 -2
  199. package/templates/plugin/README.md.tpl +0 -1
  200. package/templates/plugin/client.d.ts +0 -2
  201. package/templates/plugin/client.js +0 -1
  202. package/templates/plugin/package.json.tpl +0 -11
  203. package/templates/plugin/server.d.ts +0 -2
  204. package/templates/plugin/server.js +0 -1
  205. package/templates/plugin/src/client/client.d.ts +0 -249
  206. package/templates/plugin/src/client/index.tsx.tpl +0 -1
  207. package/templates/plugin/src/client/locale.ts +0 -21
  208. package/templates/plugin/src/client/plugin.tsx.tpl +0 -10
  209. package/templates/plugin/src/index.ts +0 -2
  210. package/templates/plugin/src/locale/en-US.json +0 -1
  211. package/templates/plugin/src/locale/zh-CN.json +0 -1
  212. package/templates/plugin/src/server/collections/.gitkeep +0 -0
  213. package/templates/plugin/src/server/index.ts.tpl +0 -1
  214. package/templates/plugin/src/server/plugin.ts.tpl +0 -19
@@ -0,0 +1,314 @@
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 pc from 'picocolors';
11
+ import { readFile } from 'node:fs/promises';
12
+ import path from 'node:path';
13
+ import { DEFAULT_DOCKER_REGISTRY, DEFAULT_DOCKER_VERSION, resolveDockerImageRef } from "../../../lib/docker-image.js";
14
+ import { ensureCrossEnvConfirmed, hasExplicitEnvSelection } from '../../../lib/env-guard.js';
15
+ import { createLicenseEnvFlag, licenseJsonFlag, licensePkgUrlFlag, licenseYesFlag, readSavedLicenseKey, requireLicenseRuntime, } from '../shared.js';
16
+ import { MissingSavedLicenseKeyError, syncLicensedPlugins } from './shared.js';
17
+ import { resolvePluginStoragePath } from '../../../lib/plugin-storage.js';
18
+ import { commandOutput } from '../../../lib/run-npm.js';
19
+ import { announceTargetEnv, startTask, stopTask, succeedTask, updateTask } from '../../../lib/ui.js';
20
+ const SYNC_LOADING_DELAY_MS = 1200;
21
+ const SYNC_LOADING_UPDATE_MS = 5000;
22
+ const LOCAL_APP_PACKAGE_JSON_PATH = 'node_modules/@nocobase/app/package.json';
23
+ function formatActionLabel(action) {
24
+ switch (action) {
25
+ case 'installed':
26
+ return pc.green('installed');
27
+ case 'updated':
28
+ return pc.cyan('updated');
29
+ case 'removed':
30
+ return pc.yellow('removed');
31
+ case 'skipped':
32
+ return pc.dim('skipped');
33
+ }
34
+ }
35
+ function trimValue(value) {
36
+ const text = String(value ?? '').trim();
37
+ return text || undefined;
38
+ }
39
+ function normalizeDockerPlatform(value) {
40
+ const text = trimValue(value);
41
+ if (!text || text === 'auto') {
42
+ return undefined;
43
+ }
44
+ if (text === 'linux/amd64' || text === 'linux/arm64') {
45
+ return text;
46
+ }
47
+ return undefined;
48
+ }
49
+ function normalizePluginRegistryVersion(version) {
50
+ const normalized = version.trim();
51
+ const rcMatch = normalized.match(/^(.+)-rc\.\d{8,}$/);
52
+ if (rcMatch) {
53
+ return rcMatch[1];
54
+ }
55
+ const betaMatch = normalized.match(/^(.+-beta\.\d+)\.\d{8,}$/);
56
+ if (betaMatch) {
57
+ return betaMatch[1];
58
+ }
59
+ const alphaMatch = normalized.match(/^(.+-alpha\.\d+)\.\d{8,}$/);
60
+ if (alphaMatch) {
61
+ return alphaMatch[1];
62
+ }
63
+ return normalized;
64
+ }
65
+ async function parseVersionFromPackageJson(content, sourceLabel) {
66
+ let parsed;
67
+ try {
68
+ parsed = JSON.parse(content);
69
+ }
70
+ catch {
71
+ throw new Error(`Failed to parse ${sourceLabel}.`);
72
+ }
73
+ const version = trimValue(parsed.version);
74
+ if (!version) {
75
+ throw new Error(`Missing version in ${sourceLabel}.`);
76
+ }
77
+ return version;
78
+ }
79
+ async function resolveLocalAppVersion(runtime) {
80
+ const packageJsonPath = path.join(runtime.projectRoot, LOCAL_APP_PACKAGE_JSON_PATH);
81
+ let content;
82
+ try {
83
+ content = await readFile(packageJsonPath, 'utf8');
84
+ }
85
+ catch {
86
+ throw new Error(`Missing ${LOCAL_APP_PACKAGE_JSON_PATH} for env "${runtime.envName}" at ${packageJsonPath}.`);
87
+ }
88
+ return await parseVersionFromPackageJson(content, packageJsonPath);
89
+ }
90
+ async function resolveDockerAppVersion(runtime) {
91
+ const config = runtime.env.config ?? {};
92
+ const imageRef = resolveDockerImageRef(config.dockerRegistry, config.downloadVersion, {
93
+ defaultRegistry: DEFAULT_DOCKER_REGISTRY,
94
+ defaultVersion: DEFAULT_DOCKER_VERSION,
95
+ });
96
+ const args = ['run', '--rm', '--network', runtime.workspaceName];
97
+ const dockerPlatform = normalizeDockerPlatform(config.dockerPlatform);
98
+ if (dockerPlatform) {
99
+ args.push('--platform', dockerPlatform);
100
+ }
101
+ args.push('--entrypoint', 'nb', imageRef, '--version');
102
+ let output;
103
+ try {
104
+ output = await commandOutput('docker', args, {
105
+ errorName: 'docker run',
106
+ });
107
+ }
108
+ catch (error) {
109
+ const message = error instanceof Error ? error.message : String(error);
110
+ throw new Error(`Failed to read app version for env "${runtime.envName}" from Docker image ${imageRef}. ${message}`);
111
+ }
112
+ const versionMatch = output.match(/@nocobase\/cli\/([^\s]+)/);
113
+ const version = trimValue(versionMatch?.[1] ?? output.replace(/^"+|"+$/g, ''));
114
+ if (!version) {
115
+ throw new Error(`Missing app version for env "${runtime.envName}" inside Docker image ${imageRef}.`);
116
+ }
117
+ return version;
118
+ }
119
+ async function resolveManagedAppVersion(runtime) {
120
+ if (runtime.kind === 'local') {
121
+ return await resolveLocalAppVersion(runtime);
122
+ }
123
+ if (runtime.kind === 'docker') {
124
+ return await resolveDockerAppVersion(runtime);
125
+ }
126
+ throw new Error(`Env "${runtime.envName}" does not support automatic app version detection.`);
127
+ }
128
+ function buildNoLicenseSkipPayload(runtime, dryRun) {
129
+ return {
130
+ ok: true,
131
+ env: runtime.envName,
132
+ kind: runtime.kind,
133
+ dryRun,
134
+ status: 'skipped',
135
+ skipReason: 'no-license-key',
136
+ };
137
+ }
138
+ export default class LicensePluginsSync extends Command {
139
+ static summary = 'Synchronize commercial plugins for the selected env';
140
+ static description = 'Synchronize the commercial plugins allowed by the current saved license key.';
141
+ static examples = [
142
+ '<%= config.bin %> <%= command.id %>',
143
+ '<%= config.bin %> <%= command.id %> --env app1',
144
+ '<%= config.bin %> <%= command.id %> --env app1 --dry-run',
145
+ '<%= config.bin %> <%= command.id %> --env app1 --json',
146
+ ];
147
+ static flags = {
148
+ env: createLicenseEnvFlag('CLI env name to sync licensed plugins for. Defaults to the current env when omitted'),
149
+ json: licenseJsonFlag,
150
+ 'pkg-url': licensePkgUrlFlag,
151
+ 'dry-run': Flags.boolean({
152
+ description: 'Preview plugin changes without installing, upgrading, or removing anything',
153
+ default: false,
154
+ }),
155
+ version: Flags.string({
156
+ description: 'Registry version or dist-tag to synchronize. Defaults to the current workspace version.',
157
+ }),
158
+ 'skip-if-no-license': Flags.boolean({
159
+ description: 'Skip without error when this env does not have a saved license key',
160
+ default: false,
161
+ }),
162
+ verbose: Flags.boolean({
163
+ description: 'Show detailed per-plugin sync logs',
164
+ default: false,
165
+ }),
166
+ yes: licenseYesFlag,
167
+ };
168
+ async run() {
169
+ const { flags } = await this.parse(LicensePluginsSync);
170
+ const requestedEnv = flags.env?.trim() || undefined;
171
+ const explicitEnvSelection = Boolean(requestedEnv && hasExplicitEnvSelection(this.argv ?? []));
172
+ if (explicitEnvSelection) {
173
+ const confirmed = await ensureCrossEnvConfirmed({
174
+ command: this,
175
+ requestedEnv,
176
+ yes: flags.yes,
177
+ });
178
+ if (!confirmed) {
179
+ return;
180
+ }
181
+ }
182
+ const runtime = await requireLicenseRuntime(flags.env);
183
+ if (!flags.json) {
184
+ announceTargetEnv(runtime.envName);
185
+ }
186
+ if (flags['skip-if-no-license']) {
187
+ const savedLicenseKey = await readSavedLicenseKey(runtime);
188
+ if (!savedLicenseKey) {
189
+ const payload = buildNoLicenseSkipPayload(runtime, Boolean(flags['dry-run']));
190
+ if (flags.json) {
191
+ this.log(JSON.stringify(payload, null, 2));
192
+ }
193
+ return;
194
+ }
195
+ }
196
+ const version = trimValue(flags.version) || (await resolveManagedAppVersion(runtime));
197
+ const registryVersion = normalizePluginRegistryVersion(version);
198
+ const shouldStreamLogs = !flags.json && Boolean(flags.verbose);
199
+ const pluginStoragePath = resolvePluginStoragePath(runtime.env.storagePath);
200
+ const shouldShowLoading = !flags.json && !flags.verbose;
201
+ if (!flags.json) {
202
+ this.log(pc.bold(flags['dry-run']
203
+ ? `Commercial plugin sync preview for env "${runtime.envName}"`
204
+ : `Commercial plugin sync for env "${runtime.envName}"`));
205
+ this.log(pc.dim(`App version: ${version}`));
206
+ if (registryVersion !== version) {
207
+ this.log(pc.dim(`Download version: ${registryVersion}`));
208
+ }
209
+ this.log(pc.dim(`Plugin storage path: ${pluginStoragePath}`));
210
+ }
211
+ let loadingStarted = false;
212
+ let loadingTimer;
213
+ let updateTimer;
214
+ let elapsedSeconds = 0;
215
+ if (shouldShowLoading) {
216
+ loadingTimer = setTimeout(() => {
217
+ loadingStarted = true;
218
+ elapsedSeconds = Math.floor(SYNC_LOADING_DELAY_MS / 1000);
219
+ startTask(flags['dry-run']
220
+ ? 'Preparing commercial plugin sync preview. Please wait...'
221
+ : 'Synchronizing commercial plugins. Please wait...');
222
+ updateTimer = setInterval(() => {
223
+ elapsedSeconds += Math.floor(SYNC_LOADING_UPDATE_MS / 1000);
224
+ updateTask(flags['dry-run']
225
+ ? `Preparing commercial plugin sync preview. Still working... (${elapsedSeconds}s elapsed)`
226
+ : `Synchronizing commercial plugins. Still working... (${elapsedSeconds}s elapsed)`);
227
+ }, SYNC_LOADING_UPDATE_MS);
228
+ }, SYNC_LOADING_DELAY_MS);
229
+ }
230
+ let result;
231
+ try {
232
+ try {
233
+ result = await syncLicensedPlugins(runtime, {
234
+ pkgUrl: flags['pkg-url'],
235
+ version: registryVersion,
236
+ dryRun: Boolean(flags['dry-run']),
237
+ onProgress: shouldStreamLogs
238
+ ? async (detail) => {
239
+ this.log(`${formatActionLabel(detail.action)} ${pc.bold(detail.packageName)}`);
240
+ this.log(pc.dim(` output: ${detail.outputDir}`));
241
+ if (detail.warning) {
242
+ this.log(pc.yellow(` warning: ${detail.warning}`));
243
+ }
244
+ }
245
+ : undefined,
246
+ });
247
+ }
248
+ catch (error) {
249
+ if (flags['skip-if-no-license'] && error instanceof MissingSavedLicenseKeyError) {
250
+ const payload = buildNoLicenseSkipPayload(runtime, Boolean(flags['dry-run']));
251
+ if (flags.json) {
252
+ this.log(JSON.stringify(payload, null, 2));
253
+ }
254
+ return;
255
+ }
256
+ throw error;
257
+ }
258
+ }
259
+ finally {
260
+ if (loadingTimer) {
261
+ clearTimeout(loadingTimer);
262
+ }
263
+ if (updateTimer) {
264
+ clearInterval(updateTimer);
265
+ }
266
+ if (loadingStarted) {
267
+ stopTask();
268
+ }
269
+ }
270
+ const payload = {
271
+ ok: true,
272
+ env: runtime.envName,
273
+ kind: runtime.kind,
274
+ dryRun: Boolean(flags['dry-run']),
275
+ version,
276
+ registryVersion,
277
+ ...result,
278
+ };
279
+ if (flags.json) {
280
+ this.log(JSON.stringify(payload, null, 2));
281
+ return;
282
+ }
283
+ if (loadingStarted) {
284
+ succeedTask(flags['dry-run'] ? 'Commercial plugin sync preview is ready.' : 'Commercial plugin sync completed.');
285
+ }
286
+ if (!flags.verbose) {
287
+ const changes = [];
288
+ if (result.installed.length > 0) {
289
+ changes.push(pc.green(`${result.installed.length} installed`));
290
+ }
291
+ if (result.updated.length > 0) {
292
+ changes.push(pc.cyan(`${result.updated.length} updated`));
293
+ }
294
+ if (result.removed.length > 0) {
295
+ changes.push(pc.yellow(`${result.removed.length} removed`));
296
+ }
297
+ if (result.skipped.length > 0) {
298
+ changes.push(pc.dim(`${result.skipped.length} skipped`));
299
+ }
300
+ if (changes.length === 0) {
301
+ changes.push(pc.dim('no plugin changes'));
302
+ }
303
+ this.log(`Result: ${changes.join(', ')}`);
304
+ }
305
+ else {
306
+ this.log(`Summary: ${result.installed.length} installed, ${result.updated.length} updated, ${result.removed.length} removed, ${result.skipped.length} skipped, ${result.warnings.length} warnings`);
307
+ }
308
+ if (result.warnings.length > 0 && !flags.verbose) {
309
+ for (const warning of result.warnings) {
310
+ this.log(pc.yellow(`Warning: ${warning}`));
311
+ }
312
+ }
313
+ }
314
+ }