@nocobase/cli 2.1.0-beta.2 → 2.1.0-beta.21

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 (145) hide show
  1. package/LICENSE.txt +107 -0
  2. package/README.md +367 -19
  3. package/README.zh-CN.md +336 -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/build.js +57 -0
  14. package/dist/commands/db/logs.js +85 -0
  15. package/dist/commands/db/ps.js +60 -0
  16. package/dist/commands/db/shared.js +95 -0
  17. package/dist/commands/db/start.js +70 -0
  18. package/dist/commands/db/stop.js +70 -0
  19. package/dist/commands/dev.js +156 -0
  20. package/dist/commands/down.js +197 -0
  21. package/dist/commands/download.js +865 -0
  22. package/dist/commands/env/add.js +307 -0
  23. package/dist/commands/env/auth.js +55 -0
  24. package/dist/commands/env/list.js +36 -0
  25. package/dist/commands/env/remove.js +59 -0
  26. package/dist/commands/env/update.js +67 -0
  27. package/dist/commands/env/use.js +28 -0
  28. package/dist/commands/init.js +950 -0
  29. package/dist/commands/install.js +1927 -0
  30. package/dist/commands/logs.js +97 -0
  31. package/dist/commands/pm/disable.js +63 -0
  32. package/dist/commands/pm/enable.js +63 -0
  33. package/dist/commands/pm/list.js +61 -0
  34. package/dist/commands/prompts-stages.js +150 -0
  35. package/dist/commands/prompts-test.js +181 -0
  36. package/dist/commands/ps.js +119 -0
  37. package/dist/commands/restart.js +74 -0
  38. package/dist/commands/scaffold/migration.js +38 -0
  39. package/dist/commands/scaffold/plugin.js +37 -0
  40. package/dist/commands/self/check.js +71 -0
  41. package/dist/commands/self/index.js +20 -0
  42. package/dist/commands/self/update.js +86 -0
  43. package/dist/commands/skills/check.js +69 -0
  44. package/dist/commands/skills/index.js +20 -0
  45. package/dist/commands/skills/install.js +71 -0
  46. package/dist/commands/skills/update.js +71 -0
  47. package/dist/commands/start.js +218 -0
  48. package/dist/commands/stop.js +97 -0
  49. package/dist/commands/test.js +466 -0
  50. package/dist/commands/upgrade.js +594 -0
  51. package/dist/generated/command-registry.js +133 -0
  52. package/dist/help/runtime-help.js +20 -0
  53. package/dist/lib/api-client.js +244 -0
  54. package/dist/lib/app-runtime.js +153 -0
  55. package/dist/lib/auth-store.js +357 -0
  56. package/dist/lib/bootstrap.js +388 -0
  57. package/dist/lib/build-config.js +10 -0
  58. package/dist/lib/cli-home.js +61 -0
  59. package/dist/lib/cli-locale.js +115 -0
  60. package/dist/lib/command-discovery.js +39 -0
  61. package/dist/lib/env-auth.js +872 -0
  62. package/dist/lib/generated-command.js +150 -0
  63. package/dist/lib/http-request.js +49 -0
  64. package/dist/lib/naming.js +70 -0
  65. package/dist/lib/openapi.js +62 -0
  66. package/dist/lib/post-processors.js +23 -0
  67. package/dist/lib/prompt-catalog.js +581 -0
  68. package/dist/lib/prompt-validators.js +185 -0
  69. package/dist/lib/prompt-web-ui.js +2096 -0
  70. package/dist/lib/resource-command.js +343 -0
  71. package/dist/lib/resource-request.js +104 -0
  72. package/dist/lib/run-npm.js +197 -0
  73. package/dist/lib/runtime-generator.js +419 -0
  74. package/dist/lib/runtime-store.js +56 -0
  75. package/dist/lib/self-manager.js +246 -0
  76. package/dist/lib/skills-manager.js +269 -0
  77. package/dist/lib/startup-update.js +203 -0
  78. package/dist/lib/ui.js +175 -0
  79. package/dist/locale/en-US.json +336 -0
  80. package/dist/locale/zh-CN.json +336 -0
  81. package/dist/post-processors/data-modeling.js +66 -0
  82. package/dist/post-processors/data-source-manager.js +114 -0
  83. package/dist/post-processors/index.js +19 -0
  84. package/nocobase-ctl.config.json +287 -0
  85. package/package.json +60 -26
  86. package/LICENSE +0 -661
  87. package/bin/index.js +0 -39
  88. package/nocobase.conf.tpl +0 -95
  89. package/src/cli.js +0 -19
  90. package/src/commands/benchmark.js +0 -73
  91. package/src/commands/build.js +0 -49
  92. package/src/commands/clean.js +0 -30
  93. package/src/commands/client.js +0 -166
  94. package/src/commands/create-nginx-conf.js +0 -37
  95. package/src/commands/create-plugin.js +0 -33
  96. package/src/commands/dev.js +0 -200
  97. package/src/commands/doc.js +0 -76
  98. package/src/commands/e2e.js +0 -265
  99. package/src/commands/global.js +0 -43
  100. package/src/commands/index.js +0 -45
  101. package/src/commands/instance-id.js +0 -47
  102. package/src/commands/locale/cronstrue.js +0 -122
  103. package/src/commands/locale/react-js-cron/en-US.json +0 -75
  104. package/src/commands/locale/react-js-cron/index.js +0 -17
  105. package/src/commands/locale/react-js-cron/zh-CN.json +0 -33
  106. package/src/commands/locale/react-js-cron/zh-TW.json +0 -33
  107. package/src/commands/locale.js +0 -81
  108. package/src/commands/p-test.js +0 -88
  109. package/src/commands/perf.js +0 -63
  110. package/src/commands/pkg.js +0 -321
  111. package/src/commands/pm2.js +0 -37
  112. package/src/commands/postinstall.js +0 -88
  113. package/src/commands/start.js +0 -148
  114. package/src/commands/tar.js +0 -36
  115. package/src/commands/test-coverage.js +0 -55
  116. package/src/commands/test.js +0 -107
  117. package/src/commands/umi.js +0 -33
  118. package/src/commands/update-deps.js +0 -72
  119. package/src/commands/upgrade.js +0 -47
  120. package/src/commands/view-license-key.js +0 -44
  121. package/src/index.js +0 -14
  122. package/src/license.js +0 -76
  123. package/src/logger.js +0 -75
  124. package/src/plugin-generator.js +0 -80
  125. package/src/util.js +0 -517
  126. package/templates/bundle-status.html +0 -338
  127. package/templates/create-app-package.json +0 -39
  128. package/templates/plugin/.npmignore.tpl +0 -2
  129. package/templates/plugin/README.md.tpl +0 -1
  130. package/templates/plugin/client.d.ts +0 -2
  131. package/templates/plugin/client.js +0 -1
  132. package/templates/plugin/package.json.tpl +0 -11
  133. package/templates/plugin/server.d.ts +0 -2
  134. package/templates/plugin/server.js +0 -1
  135. package/templates/plugin/src/client/client.d.ts +0 -249
  136. package/templates/plugin/src/client/index.tsx.tpl +0 -1
  137. package/templates/plugin/src/client/locale.ts +0 -21
  138. package/templates/plugin/src/client/models/index.ts +0 -12
  139. package/templates/plugin/src/client/plugin.tsx.tpl +0 -10
  140. package/templates/plugin/src/index.ts +0 -2
  141. package/templates/plugin/src/locale/en-US.json +0 -1
  142. package/templates/plugin/src/locale/zh-CN.json +0 -1
  143. package/templates/plugin/src/server/collections/.gitkeep +0 -0
  144. package/templates/plugin/src/server/index.ts.tpl +0 -1
  145. package/templates/plugin/src/server/plugin.ts.tpl +0 -19
@@ -0,0 +1,357 @@
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 { promises as fs } from 'node:fs';
10
+ import path from 'node:path';
11
+ import { resolveCliHomeDir, resolveConfiguredEnvPath, resolveDefaultConfigScope, resolveEnvRelativePath, } from './cli-home.js';
12
+ function normalizeStoredEnvKind(value) {
13
+ const kind = String(value ?? '').trim();
14
+ if (kind === 'remote') {
15
+ return 'http';
16
+ }
17
+ if (kind === 'local' || kind === 'http' || kind === 'docker' || kind === 'ssh') {
18
+ return kind;
19
+ }
20
+ return undefined;
21
+ }
22
+ function normalizeOptionalString(value) {
23
+ const normalized = String(value ?? '').trim();
24
+ return normalized || undefined;
25
+ }
26
+ export function readEnvApiBaseUrl(config) {
27
+ if (!config) {
28
+ return undefined;
29
+ }
30
+ return (normalizeOptionalString(config.apiBaseUrl)
31
+ ?? normalizeOptionalString(config.baseUrl)
32
+ ?? normalizeOptionalString(config.apibaseUrl));
33
+ }
34
+ export function resolveEnvKind(config) {
35
+ if (!config) {
36
+ return undefined;
37
+ }
38
+ const explicitKind = normalizeStoredEnvKind(config.kind);
39
+ if (explicitKind) {
40
+ return explicitKind;
41
+ }
42
+ const source = String(config.source ?? '').trim();
43
+ if (source === 'docker') {
44
+ return 'docker';
45
+ }
46
+ if (source === 'npm' || source === 'git' || source === 'local') {
47
+ return 'local';
48
+ }
49
+ if (String(config.appRootPath ?? '').trim()) {
50
+ return 'local';
51
+ }
52
+ if (readEnvApiBaseUrl(config) || config.auth) {
53
+ return 'http';
54
+ }
55
+ return undefined;
56
+ }
57
+ function normalizeEnvConfigEntry(entry) {
58
+ if (!entry) {
59
+ return entry;
60
+ }
61
+ const { kind: _kind, apiBaseUrl: _apiBaseUrl, baseUrl: _baseUrl, apibaseUrl: _legacyApiBaseUrl, ...rest } = entry;
62
+ const normalizedKind = resolveEnvKind(entry);
63
+ const apiBaseUrl = readEnvApiBaseUrl(entry);
64
+ return {
65
+ ...rest,
66
+ ...(normalizedKind ? { kind: normalizedKind } : {}),
67
+ ...(apiBaseUrl !== undefined ? { apiBaseUrl } : {}),
68
+ };
69
+ }
70
+ function normalizeAuthConfig(config) {
71
+ return {
72
+ name: config.name || config.dockerResourcePrefix,
73
+ currentEnv: config.currentEnv || 'default',
74
+ envs: Object.fromEntries(Object.entries(config.envs || {}).map(([envName, entry]) => [envName, normalizeEnvConfigEntry(entry) ?? {}])),
75
+ };
76
+ }
77
+ function getConfigFile(options = {}) {
78
+ return path.join(resolveCliHomeDir(options.scope), 'config.json');
79
+ }
80
+ function createDefaultConfig() {
81
+ return {
82
+ currentEnv: 'default',
83
+ envs: {},
84
+ };
85
+ }
86
+ function hasConfiguredEnvs(config) {
87
+ return Object.keys(config.envs).length > 0;
88
+ }
89
+ function shouldFallbackToLegacyProjectScope(options = {}) {
90
+ const requestedScope = options.scope ?? resolveDefaultConfigScope();
91
+ return requestedScope === 'global';
92
+ }
93
+ async function loadExactAuthConfig(options = {}) {
94
+ try {
95
+ const content = await fs.readFile(getConfigFile(options), 'utf8');
96
+ const parsed = JSON.parse(content);
97
+ return normalizeAuthConfig(parsed);
98
+ }
99
+ catch (_error) {
100
+ return createDefaultConfig();
101
+ }
102
+ }
103
+ async function resolveEnvStorageScope(envName, options = {}) {
104
+ const requestedScope = options.scope ?? resolveDefaultConfigScope();
105
+ if (requestedScope !== 'global') {
106
+ return { ...options, scope: requestedScope };
107
+ }
108
+ const globalConfig = await loadExactAuthConfig({ scope: 'global' });
109
+ if (globalConfig.envs[envName]) {
110
+ return { ...options, scope: 'global' };
111
+ }
112
+ const projectConfig = await loadExactAuthConfig({ scope: 'project' });
113
+ if (projectConfig.envs[envName]) {
114
+ return { ...options, scope: 'project' };
115
+ }
116
+ return { ...options, scope: 'global' };
117
+ }
118
+ export async function loadAuthConfig(options = {}) {
119
+ const config = await loadExactAuthConfig(options);
120
+ if (!shouldFallbackToLegacyProjectScope(options) || hasConfiguredEnvs(config)) {
121
+ return config;
122
+ }
123
+ const legacyProjectConfig = await loadExactAuthConfig({ scope: 'project' });
124
+ return hasConfiguredEnvs(legacyProjectConfig) ? legacyProjectConfig : config;
125
+ }
126
+ export async function saveAuthConfig(config, options = {}) {
127
+ const filePath = getConfigFile(options);
128
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
129
+ await fs.writeFile(filePath, JSON.stringify(normalizeAuthConfig(config), null, 2));
130
+ }
131
+ export async function listEnvs(options = {}) {
132
+ const config = await loadAuthConfig(options);
133
+ return {
134
+ currentEnv: config.currentEnv || 'default',
135
+ envs: config.envs,
136
+ };
137
+ }
138
+ export async function getCurrentEnvName(options = {}) {
139
+ const config = await loadAuthConfig(options);
140
+ return config.currentEnv || 'default';
141
+ }
142
+ export async function setCurrentEnv(envName, options = {}) {
143
+ const writeOptions = await resolveEnvStorageScope(envName, options);
144
+ const config = await loadExactAuthConfig(writeOptions);
145
+ if (!config.envs[envName]) {
146
+ throw new Error(`Env "${envName}" is not configured`);
147
+ }
148
+ config.currentEnv = envName;
149
+ await saveAuthConfig(config, writeOptions);
150
+ }
151
+ export async function ensureWorkspaceName(defaultName, options = {}) {
152
+ const config = await loadExactAuthConfig(options);
153
+ const existing = config.name?.trim();
154
+ if (existing) {
155
+ return existing;
156
+ }
157
+ const next = defaultName.trim();
158
+ config.name = next;
159
+ await saveAuthConfig(config, options);
160
+ return next;
161
+ }
162
+ export class Env {
163
+ config;
164
+ constructor(config = {}) {
165
+ this.config = config;
166
+ }
167
+ get name() {
168
+ return this.config.name;
169
+ }
170
+ get baseUrl() {
171
+ return readEnvApiBaseUrl(this.config);
172
+ }
173
+ get apiBaseUrl() {
174
+ return readEnvApiBaseUrl(this.config);
175
+ }
176
+ get auth() {
177
+ return this.config.auth;
178
+ }
179
+ get runtime() {
180
+ return this.config.runtime;
181
+ }
182
+ get kind() {
183
+ return resolveEnvKind(this.config);
184
+ }
185
+ get appRootPath() {
186
+ if (this.kind === 'ssh') {
187
+ const configuredPath = String(this.config.appRootPath ?? '').trim();
188
+ if (configuredPath) {
189
+ return configuredPath;
190
+ }
191
+ }
192
+ return resolveConfiguredEnvPath(this.config.appRootPath) ?? resolveEnvRelativePath('.');
193
+ }
194
+ get storagePath() {
195
+ if (this.kind === 'ssh') {
196
+ const configuredPath = String(this.config.storagePath ?? '').trim();
197
+ if (configuredPath) {
198
+ return configuredPath;
199
+ }
200
+ }
201
+ return resolveConfiguredEnvPath(this.config.storagePath) ?? resolveEnvRelativePath('.');
202
+ }
203
+ get appPort() {
204
+ return this.config.appPort;
205
+ }
206
+ get envVars() {
207
+ const out = {
208
+ STORAGE_PATH: this.storagePath,
209
+ };
210
+ const put = (key, value) => {
211
+ if (value === undefined || value === null) {
212
+ return;
213
+ }
214
+ out[key] = String(value);
215
+ };
216
+ put('APP_PORT', this.appPort);
217
+ put('APP_KEY', this.config.appKey);
218
+ put('TZ', this.config.timezone);
219
+ put('DB_DIALECT', this.config.dbDialect);
220
+ put('DB_HOST', this.config.dbHost);
221
+ put('DB_PORT', this.config.dbPort);
222
+ put('DB_DATABASE', this.config.dbDatabase);
223
+ put('DB_USER', this.config.dbUser);
224
+ put('DB_PASSWORD', this.config.dbPassword);
225
+ return out;
226
+ }
227
+ }
228
+ export async function getEnv(envName, options = {}) {
229
+ const { config: snapshot, ...loadOptions } = options;
230
+ const config = snapshot ?? (await loadAuthConfig(loadOptions));
231
+ const resolved = envName?.trim() || config.currentEnv || 'default';
232
+ const envConfig = config.envs[resolved];
233
+ if (!envConfig) {
234
+ if (!shouldFallbackToLegacyProjectScope(loadOptions)) {
235
+ return undefined;
236
+ }
237
+ const legacyProjectConfig = await loadExactAuthConfig({ scope: 'project' });
238
+ const legacyResolved = envName?.trim() || legacyProjectConfig.currentEnv || 'default';
239
+ const legacyEnvConfig = legacyProjectConfig.envs[legacyResolved];
240
+ if (!legacyEnvConfig) {
241
+ return undefined;
242
+ }
243
+ return new Env({ ...(normalizeEnvConfigEntry(legacyEnvConfig) ?? {}), name: legacyResolved });
244
+ }
245
+ return new Env({ ...(normalizeEnvConfigEntry(envConfig) ?? {}), name: resolved });
246
+ }
247
+ function areAuthConfigsEquivalent(left, right) {
248
+ if (!left && !right) {
249
+ return true;
250
+ }
251
+ if (!left || !right || left.type !== right.type) {
252
+ return false;
253
+ }
254
+ if (left.type === 'token' && right.type === 'token') {
255
+ return left.accessToken === right.accessToken;
256
+ }
257
+ if (left.type === 'oauth' && right.type === 'oauth') {
258
+ return (left.accessToken === right.accessToken &&
259
+ left.refreshToken === right.refreshToken &&
260
+ left.expiresAt === right.expiresAt &&
261
+ left.scope === right.scope &&
262
+ left.issuer === right.issuer &&
263
+ left.clientId === right.clientId &&
264
+ left.resource === right.resource);
265
+ }
266
+ return false;
267
+ }
268
+ async function writeEnv(envName, updater, options = {}) {
269
+ const writeOptions = await resolveEnvStorageScope(envName, options);
270
+ const config = await loadExactAuthConfig(writeOptions);
271
+ const previous = config.envs[envName];
272
+ config.envs[envName] = updater(previous);
273
+ config.currentEnv = envName;
274
+ await saveAuthConfig(config, writeOptions);
275
+ }
276
+ export async function upsertEnv(envName, config, options = {}) {
277
+ await writeEnv(envName, (previous) => {
278
+ const { apiBaseUrl: _apiBaseUrl, baseUrl: _baseUrl, apibaseUrl: _legacyApiBaseUrl, accessToken, ...rest } = config;
279
+ const nextApiBaseUrl = readEnvApiBaseUrl(config);
280
+ const previousApiBaseUrl = readEnvApiBaseUrl(previous);
281
+ const baseUrlChanged = previousApiBaseUrl !== nextApiBaseUrl;
282
+ const nextAuth = accessToken
283
+ ? {
284
+ type: 'token',
285
+ accessToken,
286
+ }
287
+ : baseUrlChanged || previous?.auth?.type === 'token'
288
+ ? undefined
289
+ : previous?.auth;
290
+ const authChanged = !areAuthConfigsEquivalent(previous?.auth, nextAuth);
291
+ return {
292
+ ...previous,
293
+ apiBaseUrl: nextApiBaseUrl,
294
+ auth: nextAuth,
295
+ ...rest,
296
+ runtime: baseUrlChanged || authChanged ? undefined : previous?.runtime,
297
+ };
298
+ }, options);
299
+ }
300
+ export async function updateEnvConnection(envName, updates, options = {}) {
301
+ await writeEnv(envName, (previous) => {
302
+ const nextApiBaseUrl = readEnvApiBaseUrl(updates) ?? readEnvApiBaseUrl(previous);
303
+ const previousApiBaseUrl = readEnvApiBaseUrl(previous);
304
+ const baseUrlChanged = previousApiBaseUrl !== nextApiBaseUrl;
305
+ const nextAuth = updates.accessToken
306
+ ? {
307
+ type: 'token',
308
+ accessToken: updates.accessToken,
309
+ }
310
+ : baseUrlChanged || previous?.auth?.type === 'token'
311
+ ? undefined
312
+ : previous?.auth;
313
+ const authChanged = !areAuthConfigsEquivalent(previous?.auth, nextAuth);
314
+ return {
315
+ ...previous,
316
+ ...(nextApiBaseUrl !== undefined ? { apiBaseUrl: nextApiBaseUrl } : {}),
317
+ auth: nextAuth,
318
+ runtime: baseUrlChanged || authChanged ? undefined : previous?.runtime,
319
+ };
320
+ }, options);
321
+ }
322
+ export async function setEnvOauthSession(envName, auth, options = {}) {
323
+ await writeEnv(envName, (previous) => ({
324
+ ...previous,
325
+ auth,
326
+ runtime: options.preserveRuntime ? previous?.runtime : undefined,
327
+ }), options);
328
+ }
329
+ export async function setEnvRuntime(envName, runtime, options = {}) {
330
+ const writeOptions = await resolveEnvStorageScope(envName, options);
331
+ const config = await loadExactAuthConfig(writeOptions);
332
+ const current = config.envs[envName] ?? {};
333
+ config.envs[envName] = {
334
+ ...current,
335
+ runtime,
336
+ };
337
+ config.currentEnv = envName;
338
+ await saveAuthConfig(config, writeOptions);
339
+ }
340
+ export async function removeEnv(envName, options = {}) {
341
+ const writeOptions = await resolveEnvStorageScope(envName, options);
342
+ const config = await loadExactAuthConfig(writeOptions);
343
+ if (!config.envs[envName]) {
344
+ throw new Error(`Env "${envName}" is not configured`);
345
+ }
346
+ delete config.envs[envName];
347
+ if (config.currentEnv === envName) {
348
+ const nextEnv = Object.keys(config.envs).sort()[0];
349
+ config.currentEnv = nextEnv ?? 'default';
350
+ }
351
+ await saveAuthConfig(config, writeOptions);
352
+ return {
353
+ removed: envName,
354
+ currentEnv: config.currentEnv || 'default',
355
+ hasEnvs: Object.keys(config.envs).length > 0,
356
+ };
357
+ }