@nocobase/cli 2.2.0-beta.7 → 2.2.0-beta.9
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.
- package/assets/env-proxy/nginx/app.conf.tpl +23 -0
- package/assets/env-proxy/nginx/nocobase.conf.tpl +5 -0
- package/assets/env-proxy/nginx/snippets/dist-location.conf +5 -0
- package/assets/env-proxy/nginx/snippets/gzip.conf +17 -0
- package/assets/env-proxy/nginx/snippets/log-format-http.conf +13 -0
- package/assets/env-proxy/nginx/snippets/maps-http.conf +14 -0
- package/assets/env-proxy/nginx/snippets/mime-types.conf +98 -0
- package/assets/env-proxy/nginx/snippets/proxy-location.conf +18 -0
- package/assets/env-proxy/nginx/snippets/spa-location.conf +6 -0
- package/assets/env-proxy/nginx/snippets/uploads-location.conf +21 -0
- package/dist/commands/app/start.js +4 -1
- package/dist/commands/install.js +53 -138
- package/dist/commands/proxy/caddy/generate.js +93 -7
- package/dist/commands/proxy/nginx/generate.js +98 -7
- package/dist/commands/revision/create.js +1 -1
- package/dist/commands/self/update.js +2 -2
- package/dist/commands/source/download.js +16 -12
- package/dist/lib/app-managed-resources.js +3 -4
- package/dist/lib/auth-store.js +82 -6
- package/dist/lib/cli-config.js +71 -1
- package/dist/lib/docker-image.js +94 -6
- package/dist/lib/env-auth.js +291 -45
- package/dist/lib/env-config.js +5 -0
- package/dist/lib/env-proxy-config.js +48 -0
- package/dist/lib/env-proxy.js +164 -58
- package/dist/lib/prompt-validators.js +1 -1
- package/dist/lib/proxy-caddy.js +77 -9
- package/dist/lib/proxy-nginx.js +71 -11
- package/dist/lib/run-npm.js +4 -0
- package/dist/lib/self-manager.js +251 -46
- package/dist/lib/startup-update.js +1 -1
- package/dist/locale/en-US.json +2 -2
- package/dist/locale/zh-CN.json +2 -2
- package/package.json +3 -2
package/dist/lib/self-manager.js
CHANGED
|
@@ -7,14 +7,12 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
import fs from 'node:fs';
|
|
10
|
-
import
|
|
10
|
+
import os from 'node:os';
|
|
11
11
|
import path from 'node:path';
|
|
12
12
|
import { fileURLToPath } from 'node:url';
|
|
13
|
-
import { resolveCliHomeDir } from './cli-home.js';
|
|
14
13
|
import { commandOutput, run } from './run-npm.js';
|
|
15
14
|
const DEFAULT_PACKAGE_NAME = '@nocobase/cli';
|
|
16
15
|
const PACKAGE_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
17
|
-
const INSTALL_METHOD_CACHE_FILE = 'self-install-methods.json';
|
|
18
16
|
function normalizePath(value) {
|
|
19
17
|
return path.resolve(value);
|
|
20
18
|
}
|
|
@@ -108,56 +106,216 @@ function readCurrentVersion(packageRoot) {
|
|
|
108
106
|
const pkg = JSON.parse(content);
|
|
109
107
|
return String(pkg.version ?? '').trim();
|
|
110
108
|
}
|
|
111
|
-
function detectInstallMethod(packageRoot,
|
|
109
|
+
function detectInstallMethod(packageRoot, options = {}) {
|
|
112
110
|
if (fs.existsSync(path.join(packageRoot, 'src'))
|
|
113
111
|
&& fs.existsSync(path.join(packageRoot, 'tsconfig.json'))) {
|
|
114
112
|
return 'source';
|
|
115
113
|
}
|
|
116
|
-
if (globalPrefix && isSubPath(globalPrefix, packageRoot)) {
|
|
114
|
+
if (options.globalPrefix && isSubPath(options.globalPrefix, packageRoot)) {
|
|
117
115
|
return 'npm-global';
|
|
118
116
|
}
|
|
117
|
+
if (options.yarnGlobalDir && isSubPath(options.yarnGlobalDir, packageRoot)) {
|
|
118
|
+
return 'yarn-global';
|
|
119
|
+
}
|
|
120
|
+
if (isPnpmGlobalInstallPath({
|
|
121
|
+
packageName: options.packageName ?? DEFAULT_PACKAGE_NAME,
|
|
122
|
+
packageRoot,
|
|
123
|
+
pnpmGlobalBin: options.pnpmGlobalBin,
|
|
124
|
+
pnpmGlobalRoot: options.pnpmGlobalRoot,
|
|
125
|
+
})) {
|
|
126
|
+
return 'pnpm-global';
|
|
127
|
+
}
|
|
128
|
+
// Best-effort fallback for environments where pnpm probes are unavailable.
|
|
129
|
+
if (isPnpmGlobalPath(packageRoot)) {
|
|
130
|
+
return 'pnpm-global';
|
|
131
|
+
}
|
|
119
132
|
if (packageRoot.includes(`${path.sep}node_modules${path.sep}`)) {
|
|
120
133
|
return 'package-local';
|
|
121
134
|
}
|
|
122
135
|
return 'unknown';
|
|
123
136
|
}
|
|
124
|
-
function
|
|
125
|
-
|
|
137
|
+
function isPnpmGlobalPath(packageRoot) {
|
|
138
|
+
const normalized = normalizePath(packageRoot);
|
|
139
|
+
const segments = normalized.split(path.sep).filter(Boolean);
|
|
140
|
+
const globalIndex = segments.findIndex((segment, index) => segment === 'global' && segments[index - 1] === 'pnpm');
|
|
141
|
+
if (globalIndex === -1) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
return segments.slice(globalIndex + 2).includes('node_modules');
|
|
126
145
|
}
|
|
127
|
-
function
|
|
128
|
-
|
|
146
|
+
function normalizePnpmGlobalNodeModulesRoot(pnpmGlobalRoot) {
|
|
147
|
+
const normalizedGlobalRoot = normalizePath(pnpmGlobalRoot);
|
|
148
|
+
return path.basename(normalizedGlobalRoot) === 'node_modules'
|
|
149
|
+
? normalizedGlobalRoot
|
|
150
|
+
: path.join(normalizedGlobalRoot, 'node_modules');
|
|
129
151
|
}
|
|
130
|
-
|
|
152
|
+
function readSiblingPnpmGlobalNodeModulesRoots(pnpmGlobalRoot) {
|
|
153
|
+
const globalNodeModulesDir = normalizePnpmGlobalNodeModulesRoot(pnpmGlobalRoot);
|
|
154
|
+
const globalProjectDir = path.dirname(globalNodeModulesDir);
|
|
155
|
+
let entries;
|
|
131
156
|
try {
|
|
132
|
-
|
|
133
|
-
return JSON.parse(raw);
|
|
157
|
+
entries = fs.readdirSync(globalProjectDir);
|
|
134
158
|
}
|
|
135
159
|
catch {
|
|
136
|
-
return
|
|
160
|
+
return [];
|
|
137
161
|
}
|
|
162
|
+
return entries
|
|
163
|
+
.filter((entry) => {
|
|
164
|
+
if (entry === path.basename(globalNodeModulesDir)) {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
try {
|
|
168
|
+
return fs.statSync(path.join(globalProjectDir, entry)).isDirectory();
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
})
|
|
174
|
+
.map((entry) => path.join(globalProjectDir, entry, 'node_modules'));
|
|
138
175
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
await fsp.mkdir(path.dirname(filePath), { recursive: true });
|
|
142
|
-
await fsp.writeFile(filePath, JSON.stringify(state, null, 2));
|
|
176
|
+
function readPnpmGlobalNodeModulesRoots(pnpmGlobalRoot) {
|
|
177
|
+
return [normalizePnpmGlobalNodeModulesRoot(pnpmGlobalRoot), ...readSiblingPnpmGlobalNodeModulesRoots(pnpmGlobalRoot)];
|
|
143
178
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
return state.entries?.[getInstallMethodCacheKey(packageRoot)];
|
|
179
|
+
function packageNameToPath(packageName) {
|
|
180
|
+
return packageName.split('/').filter(Boolean);
|
|
147
181
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
182
|
+
function isSameRealPath(left, right) {
|
|
183
|
+
try {
|
|
184
|
+
return normalizePath(fs.realpathSync(left)) === normalizePath(fs.realpathSync(right));
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
function isPnpmGlobalRootPath(pnpmGlobalRoot, packageRoot) {
|
|
191
|
+
if (isSubPath(pnpmGlobalRoot, packageRoot)) {
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
const globalNodeModulesDir = normalizePnpmGlobalNodeModulesRoot(pnpmGlobalRoot);
|
|
195
|
+
const globalProjectDir = path.dirname(globalNodeModulesDir);
|
|
196
|
+
if (!isSubPath(globalProjectDir, packageRoot)) {
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
const segments = normalizePath(packageRoot).split(path.sep).filter(Boolean);
|
|
200
|
+
const pnpmStoreIndex = segments.indexOf('.pnpm');
|
|
201
|
+
if (pnpmStoreIndex === -1) {
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
return segments.slice(pnpmStoreIndex + 1).includes('node_modules');
|
|
205
|
+
}
|
|
206
|
+
function isPnpmGlobalPackagePath(pnpmGlobalRoot, packageRoot, packageName) {
|
|
207
|
+
return readPnpmGlobalNodeModulesRoots(pnpmGlobalRoot).some((pnpmGlobalNodeModulesRoot) => isSameRealPath(path.join(pnpmGlobalNodeModulesRoot, ...packageNameToPath(packageName)), packageRoot));
|
|
208
|
+
}
|
|
209
|
+
function isPnpmGlobalBinProjectPath(pnpmGlobalBin, packageRoot, packageName) {
|
|
210
|
+
const pnpmHome = path.dirname(normalizePath(pnpmGlobalBin));
|
|
211
|
+
const globalDir = path.join(pnpmHome, 'global');
|
|
212
|
+
if (isSubPath(globalDir, packageRoot)) {
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
let entries;
|
|
216
|
+
try {
|
|
217
|
+
entries = fs.readdirSync(globalDir);
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
return entries.some((entry) => {
|
|
223
|
+
const pnpmGlobalRoot = path.join(globalDir, entry);
|
|
224
|
+
return (isPnpmGlobalRootPath(pnpmGlobalRoot, packageRoot)
|
|
225
|
+
|| isPnpmGlobalPackagePath(pnpmGlobalRoot, packageRoot, packageName));
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
function isPnpmGlobalInstallPath(options) {
|
|
229
|
+
if (options.pnpmGlobalRoot) {
|
|
230
|
+
const matchedRoot = isPnpmGlobalRootPath(options.pnpmGlobalRoot, options.packageRoot)
|
|
231
|
+
|| isPnpmGlobalPackagePath(options.pnpmGlobalRoot, options.packageRoot, options.packageName);
|
|
232
|
+
if (matchedRoot) {
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if (options.pnpmGlobalBin) {
|
|
237
|
+
return isPnpmGlobalBinProjectPath(options.pnpmGlobalBin, options.packageRoot, options.packageName);
|
|
238
|
+
}
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
function readCurrentBinPath(currentBinPath) {
|
|
242
|
+
const candidate = String(currentBinPath ?? process.argv[1] ?? '').trim();
|
|
243
|
+
if (!candidate) {
|
|
244
|
+
return undefined;
|
|
245
|
+
}
|
|
246
|
+
return normalizePath(candidate);
|
|
247
|
+
}
|
|
248
|
+
function cleanCommandPath(value) {
|
|
249
|
+
const trimmed = value.trim();
|
|
250
|
+
return trimmed ? trimmed : undefined;
|
|
251
|
+
}
|
|
252
|
+
function resolvePackageManagerProbeCwd() {
|
|
253
|
+
const candidates = [os.homedir(), os.tmpdir(), path.parse(process.cwd()).root];
|
|
254
|
+
for (const candidate of candidates) {
|
|
255
|
+
if (!candidate) {
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
try {
|
|
259
|
+
if (fs.statSync(candidate).isDirectory()) {
|
|
260
|
+
return candidate;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
// Ignore invalid probe cwd candidates and continue to the next one.
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return undefined;
|
|
155
268
|
}
|
|
156
269
|
async function readGlobalPrefix(commandOutputFn) {
|
|
157
270
|
try {
|
|
158
|
-
return (await commandOutputFn('npm', ['prefix', '-g'], {
|
|
271
|
+
return cleanCommandPath(await commandOutputFn('npm', ['prefix', '-g'], {
|
|
272
|
+
cwd: resolvePackageManagerProbeCwd(),
|
|
159
273
|
errorName: 'npm prefix',
|
|
160
|
-
}))
|
|
274
|
+
}));
|
|
275
|
+
}
|
|
276
|
+
catch {
|
|
277
|
+
return undefined;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
async function readPnpmGlobalBin(commandOutputFn) {
|
|
281
|
+
try {
|
|
282
|
+
return cleanCommandPath(await commandOutputFn('pnpm', ['bin', '-g'], {
|
|
283
|
+
cwd: resolvePackageManagerProbeCwd(),
|
|
284
|
+
errorName: 'pnpm bin',
|
|
285
|
+
}));
|
|
286
|
+
}
|
|
287
|
+
catch {
|
|
288
|
+
return undefined;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
async function readPnpmGlobalRoot(commandOutputFn) {
|
|
292
|
+
try {
|
|
293
|
+
return cleanCommandPath(await commandOutputFn('pnpm', ['root', '-g'], {
|
|
294
|
+
cwd: resolvePackageManagerProbeCwd(),
|
|
295
|
+
errorName: 'pnpm root',
|
|
296
|
+
}));
|
|
297
|
+
}
|
|
298
|
+
catch {
|
|
299
|
+
return undefined;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
async function readYarnGlobalDir(commandOutputFn) {
|
|
303
|
+
try {
|
|
304
|
+
return cleanCommandPath(await commandOutputFn('yarn', ['global', 'dir'], {
|
|
305
|
+
cwd: resolvePackageManagerProbeCwd(),
|
|
306
|
+
errorName: 'yarn global dir',
|
|
307
|
+
}));
|
|
308
|
+
}
|
|
309
|
+
catch {
|
|
310
|
+
return undefined;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
async function readYarnGlobalBin(commandOutputFn) {
|
|
314
|
+
try {
|
|
315
|
+
return cleanCommandPath(await commandOutputFn('yarn', ['global', 'bin'], {
|
|
316
|
+
cwd: resolvePackageManagerProbeCwd(),
|
|
317
|
+
errorName: 'yarn global bin',
|
|
318
|
+
}));
|
|
161
319
|
}
|
|
162
320
|
catch {
|
|
163
321
|
return undefined;
|
|
@@ -174,21 +332,21 @@ function getUnsupportedSelfUpdateReason(installMethod) {
|
|
|
174
332
|
if (installMethod === 'source') {
|
|
175
333
|
return [
|
|
176
334
|
'This CLI is running from source in a repository checkout.',
|
|
177
|
-
'Automatic self-update is only supported for standard global npm installs.',
|
|
335
|
+
'Automatic self-update is only supported for standard global npm, pnpm, or yarn installs.',
|
|
178
336
|
'Upgrade this checkout through your repo workflow instead.',
|
|
179
337
|
].join(' ');
|
|
180
338
|
}
|
|
181
339
|
if (installMethod === 'package-local') {
|
|
182
340
|
return [
|
|
183
341
|
'This CLI is installed from a local project dependency tree.',
|
|
184
|
-
'Automatic self-update is only supported for standard global npm installs.',
|
|
342
|
+
'Automatic self-update is only supported for standard global npm, pnpm, or yarn installs.',
|
|
185
343
|
'Upgrade the parent project dependency that provides this CLI instead.',
|
|
186
344
|
].join(' ');
|
|
187
345
|
}
|
|
188
346
|
if (installMethod === 'unknown') {
|
|
189
347
|
return [
|
|
190
|
-
'This CLI install could not be recognized as a standard global npm install.',
|
|
191
|
-
'Automatic self-update is only supported for standard global npm installs.',
|
|
348
|
+
'This CLI install could not be recognized as a standard global npm, pnpm, or yarn install.',
|
|
349
|
+
'Automatic self-update is only supported for standard global npm, pnpm, or yarn installs.',
|
|
192
350
|
].join(' ');
|
|
193
351
|
}
|
|
194
352
|
return undefined;
|
|
@@ -217,22 +375,45 @@ export function getSelfUpdatePackageSpec(status) {
|
|
|
217
375
|
}
|
|
218
376
|
export async function inspectSelfInstall(options = {}) {
|
|
219
377
|
const packageRoot = options.packageRoot ? normalizePath(options.packageRoot) : PACKAGE_ROOT;
|
|
378
|
+
const packageName = options.packageName ?? DEFAULT_PACKAGE_NAME;
|
|
220
379
|
const commandOutputFn = options.commandOutputFn ?? commandOutput;
|
|
221
|
-
const
|
|
222
|
-
const globalPrefix =
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
380
|
+
const currentBinPath = readCurrentBinPath(options.currentBinPath);
|
|
381
|
+
const globalPrefix = await readGlobalPrefix(commandOutputFn);
|
|
382
|
+
const pnpmGlobalBin = await readPnpmGlobalBin(commandOutputFn);
|
|
383
|
+
const pnpmGlobalRoot = await readPnpmGlobalRoot(commandOutputFn);
|
|
384
|
+
const yarnGlobalDir = await readYarnGlobalDir(commandOutputFn);
|
|
385
|
+
const yarnGlobalBin = await readYarnGlobalBin(commandOutputFn);
|
|
386
|
+
const installMethod = detectInstallMethodFromSignals({
|
|
387
|
+
packageRoot,
|
|
388
|
+
currentBinPath,
|
|
389
|
+
globalPrefix,
|
|
390
|
+
packageName,
|
|
391
|
+
pnpmGlobalBin,
|
|
392
|
+
pnpmGlobalRoot,
|
|
393
|
+
yarnGlobalBin,
|
|
394
|
+
yarnGlobalDir,
|
|
395
|
+
});
|
|
230
396
|
return {
|
|
231
397
|
packageRoot,
|
|
232
398
|
installMethod,
|
|
233
399
|
globalPrefix,
|
|
234
400
|
};
|
|
235
401
|
}
|
|
402
|
+
function detectInstallMethodFromSignals(options) {
|
|
403
|
+
if (options.currentBinPath && options.yarnGlobalBin && isSubPath(options.yarnGlobalBin, options.currentBinPath)) {
|
|
404
|
+
return 'yarn-global';
|
|
405
|
+
}
|
|
406
|
+
if (options.currentBinPath && options.pnpmGlobalBin && isSubPath(options.pnpmGlobalBin, options.currentBinPath)) {
|
|
407
|
+
return 'pnpm-global';
|
|
408
|
+
}
|
|
409
|
+
return detectInstallMethod(options.packageRoot, {
|
|
410
|
+
globalPrefix: options.globalPrefix,
|
|
411
|
+
packageName: options.packageName,
|
|
412
|
+
pnpmGlobalBin: options.pnpmGlobalBin,
|
|
413
|
+
pnpmGlobalRoot: options.pnpmGlobalRoot,
|
|
414
|
+
yarnGlobalDir: options.yarnGlobalDir,
|
|
415
|
+
});
|
|
416
|
+
}
|
|
236
417
|
export async function inspectSelfStatus(options = {}) {
|
|
237
418
|
const packageRoot = options.packageRoot ? normalizePath(options.packageRoot) : PACKAGE_ROOT;
|
|
238
419
|
const packageName = options.packageName ?? DEFAULT_PACKAGE_NAME;
|
|
@@ -240,6 +421,8 @@ export async function inspectSelfStatus(options = {}) {
|
|
|
240
421
|
const channel = options.channel && options.channel !== 'auto' ? options.channel : detectChannel(currentVersion);
|
|
241
422
|
const commandOutputFn = options.commandOutputFn ?? commandOutput;
|
|
242
423
|
const { installMethod, globalPrefix } = await inspectSelfInstall({
|
|
424
|
+
currentBinPath: options.currentBinPath,
|
|
425
|
+
packageName,
|
|
243
426
|
packageRoot,
|
|
244
427
|
commandOutputFn,
|
|
245
428
|
});
|
|
@@ -261,7 +444,7 @@ export async function inspectSelfStatus(options = {}) {
|
|
|
261
444
|
latestVersion,
|
|
262
445
|
updateAvailable,
|
|
263
446
|
installMethod,
|
|
264
|
-
updatable: installMethod === 'npm-global',
|
|
447
|
+
updatable: installMethod === 'npm-global' || installMethod === 'pnpm-global' || installMethod === 'yarn-global',
|
|
265
448
|
updateBlockedReason: getUnsupportedSelfUpdateReason(installMethod),
|
|
266
449
|
globalPrefix,
|
|
267
450
|
registryError,
|
|
@@ -270,9 +453,30 @@ export async function inspectSelfStatus(options = {}) {
|
|
|
270
453
|
export function formatUnsupportedSelfUpdateMessage(status) {
|
|
271
454
|
return status.updateBlockedReason
|
|
272
455
|
?? [
|
|
273
|
-
'Automatic self-update is only supported for standard global npm installs.',
|
|
456
|
+
'Automatic self-update is only supported for standard global npm, pnpm, or yarn installs.',
|
|
274
457
|
].join('\n');
|
|
275
458
|
}
|
|
459
|
+
function resolveSelfUpdateInstallCommand(installMethod, packageSpec) {
|
|
460
|
+
if (installMethod === 'pnpm-global') {
|
|
461
|
+
return {
|
|
462
|
+
command: 'pnpm',
|
|
463
|
+
args: ['add', '-g', packageSpec],
|
|
464
|
+
errorName: 'pnpm add',
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
if (installMethod === 'yarn-global') {
|
|
468
|
+
return {
|
|
469
|
+
command: 'yarn',
|
|
470
|
+
args: ['global', 'add', packageSpec],
|
|
471
|
+
errorName: 'yarn global add',
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
return {
|
|
475
|
+
command: 'npm',
|
|
476
|
+
args: ['install', '-g', packageSpec],
|
|
477
|
+
errorName: 'npm install',
|
|
478
|
+
};
|
|
479
|
+
}
|
|
276
480
|
export async function updateSelf(options = {}) {
|
|
277
481
|
const status = await inspectSelfStatus(options);
|
|
278
482
|
if (!status.updatable) {
|
|
@@ -291,9 +495,10 @@ export async function updateSelf(options = {}) {
|
|
|
291
495
|
};
|
|
292
496
|
}
|
|
293
497
|
const packageSpec = getSelfUpdatePackageSpec(status);
|
|
294
|
-
|
|
498
|
+
const installCommand = resolveSelfUpdateInstallCommand(status.installMethod, packageSpec);
|
|
499
|
+
await (options.runFn ?? run)(installCommand.command, installCommand.args, {
|
|
295
500
|
stdio: options.verbose ? 'inherit' : 'ignore',
|
|
296
|
-
errorName:
|
|
501
|
+
errorName: installCommand.errorName,
|
|
297
502
|
});
|
|
298
503
|
return {
|
|
299
504
|
action: 'updated',
|
|
@@ -151,7 +151,7 @@ export async function shouldRunStartupUpdateCheck(argv, now = new Date()) {
|
|
|
151
151
|
return readCurrentInstallLastCheckedDate(state) !== todayStamp(now);
|
|
152
152
|
}
|
|
153
153
|
export function shouldEnableStartupUpdateForInstallMethod(installMethod) {
|
|
154
|
-
return installMethod === 'npm-global';
|
|
154
|
+
return installMethod === 'npm-global' || installMethod === 'pnpm-global' || installMethod === 'yarn-global';
|
|
155
155
|
}
|
|
156
156
|
function hasPendingUpdates(selfStatus, skillsStatus) {
|
|
157
157
|
return Boolean(selfStatus.updateAvailable || skillsStatus.updateAvailable === true);
|
package/dist/locale/en-US.json
CHANGED
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"unreachable": "Unable to connect to the API base URL. Check the address and make sure the server is reachable. Details: {{details}}"
|
|
69
69
|
},
|
|
70
70
|
"envKey": {
|
|
71
|
-
"invalid": "Use letters and
|
|
71
|
+
"invalid": "Use letters, numbers, hyphens, and underscores only."
|
|
72
72
|
},
|
|
73
73
|
"appPublicPath": {
|
|
74
74
|
"invalid": "Use / or a slash-separated path like /nocobase/ or /foo-bar/baz_2/. Each path segment may contain letters, numbers, hyphens, and underscores only."
|
|
@@ -263,7 +263,7 @@
|
|
|
263
263
|
"version": {
|
|
264
264
|
"message": "Which version would you like to use?",
|
|
265
265
|
"latestLabel": "latest",
|
|
266
|
-
"latestHint": "Stable release. Best for production use and the most predictable experience.
|
|
266
|
+
"latestHint": "Stable release. Best for production use and the most predictable experience.",
|
|
267
267
|
"betaLabel": "beta",
|
|
268
268
|
"betaHint": "Preview release. Good for trying upcoming features before general release.",
|
|
269
269
|
"alphaLabel": "alpha",
|
package/dist/locale/zh-CN.json
CHANGED
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"unreachable": "无法连接到该 API 地址,请检查地址是否正确,并确认服务可访问。详情:{{details}}"
|
|
69
69
|
},
|
|
70
70
|
"envKey": {
|
|
71
|
-
"invalid": "
|
|
71
|
+
"invalid": "仅支持字母、数字、中划线和下划线。"
|
|
72
72
|
},
|
|
73
73
|
"appPublicPath": {
|
|
74
74
|
"invalid": "请输入 /,或类似 /nocobase/、/foo-bar/baz_2/ 这样的路径。每个路径段仅支持字母、数字、中划线和下划线。"
|
|
@@ -263,7 +263,7 @@
|
|
|
263
263
|
"version": {
|
|
264
264
|
"message": "你想使用哪个版本?",
|
|
265
265
|
"latestLabel": "latest",
|
|
266
|
-
"latestHint": "
|
|
266
|
+
"latestHint": "稳定版。适合生产环境和希望获得稳定体验的场景。",
|
|
267
267
|
"betaLabel": "beta",
|
|
268
268
|
"betaHint": "测试版。包含即将发布的新功能,适合提前体验和反馈。",
|
|
269
269
|
"alphaLabel": "alpha",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/cli",
|
|
3
|
-
"version": "2.2.0-beta.
|
|
3
|
+
"version": "2.2.0-beta.9",
|
|
4
4
|
"description": "NocoBase Command Line Tool",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/generated/command-registry.js",
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"author": "",
|
|
14
14
|
"license": "Apache-2.0",
|
|
15
15
|
"files": [
|
|
16
|
+
"assets",
|
|
16
17
|
"bin",
|
|
17
18
|
"dist",
|
|
18
19
|
"nocobase-ctl.config.json"
|
|
@@ -143,5 +144,5 @@
|
|
|
143
144
|
"type": "git",
|
|
144
145
|
"url": "git+https://github.com/nocobase/nocobase.git"
|
|
145
146
|
},
|
|
146
|
-
"gitHead": "
|
|
147
|
+
"gitHead": "60e3d7abbaa0c7cead76f71a4f3d5eedb6b8acdb"
|
|
147
148
|
}
|