@nocobase/cli 2.1.11-test.1 → 2.1.11-test.11
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/dist/commands/self/update.js +1 -1
- package/dist/lib/self-manager.js +195 -44
- package/package.json +1 -1
|
@@ -77,7 +77,7 @@ export default class SelfUpdate extends Command {
|
|
|
77
77
|
message: flags.skills
|
|
78
78
|
? `Update ${status.packageName} from ${status.currentVersion} to ${status.latestVersion} and refresh the globally installed NocoBase AI coding skills?`
|
|
79
79
|
: `Update ${status.packageName} from ${status.currentVersion} to ${status.latestVersion}?`,
|
|
80
|
-
default:
|
|
80
|
+
default: true,
|
|
81
81
|
});
|
|
82
82
|
}
|
|
83
83
|
catch {
|
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
|
}
|
|
@@ -119,6 +117,14 @@ function detectInstallMethod(packageRoot, options = {}) {
|
|
|
119
117
|
if (options.yarnGlobalDir && isSubPath(options.yarnGlobalDir, packageRoot)) {
|
|
120
118
|
return 'yarn-global';
|
|
121
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
|
+
}
|
|
122
128
|
if (isPnpmGlobalPath(packageRoot)) {
|
|
123
129
|
return 'pnpm-global';
|
|
124
130
|
}
|
|
@@ -136,43 +142,157 @@ function isPnpmGlobalPath(packageRoot) {
|
|
|
136
142
|
}
|
|
137
143
|
return segments.slice(globalIndex + 2).includes('node_modules');
|
|
138
144
|
}
|
|
139
|
-
function
|
|
140
|
-
|
|
145
|
+
function normalizePnpmGlobalNodeModulesRoot(pnpmGlobalRoot) {
|
|
146
|
+
const normalizedGlobalRoot = normalizePath(pnpmGlobalRoot);
|
|
147
|
+
return path.basename(normalizedGlobalRoot) === 'node_modules'
|
|
148
|
+
? normalizedGlobalRoot
|
|
149
|
+
: path.join(normalizedGlobalRoot, 'node_modules');
|
|
150
|
+
}
|
|
151
|
+
function readSiblingPnpmGlobalNodeModulesRoots(pnpmGlobalRoot) {
|
|
152
|
+
const globalNodeModulesDir = normalizePnpmGlobalNodeModulesRoot(pnpmGlobalRoot);
|
|
153
|
+
const globalProjectDir = path.dirname(globalNodeModulesDir);
|
|
154
|
+
let entries;
|
|
155
|
+
try {
|
|
156
|
+
entries = fs.readdirSync(globalProjectDir);
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
return [];
|
|
160
|
+
}
|
|
161
|
+
return entries
|
|
162
|
+
.filter((entry) => {
|
|
163
|
+
if (entry === path.basename(globalNodeModulesDir)) {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
try {
|
|
167
|
+
return fs.statSync(path.join(globalProjectDir, entry)).isDirectory();
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
})
|
|
173
|
+
.map((entry) => path.join(globalProjectDir, entry, 'node_modules'));
|
|
174
|
+
}
|
|
175
|
+
function readPnpmGlobalNodeModulesRoots(pnpmGlobalRoot) {
|
|
176
|
+
return [normalizePnpmGlobalNodeModulesRoot(pnpmGlobalRoot), ...readSiblingPnpmGlobalNodeModulesRoots(pnpmGlobalRoot)];
|
|
177
|
+
}
|
|
178
|
+
function packageNameToPath(packageName) {
|
|
179
|
+
return packageName.split('/').filter(Boolean);
|
|
180
|
+
}
|
|
181
|
+
function isSameRealPath(left, right) {
|
|
182
|
+
try {
|
|
183
|
+
return normalizePath(fs.realpathSync(left)) === normalizePath(fs.realpathSync(right));
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
function isPnpmGlobalRootPath(pnpmGlobalRoot, packageRoot) {
|
|
190
|
+
if (isSubPath(pnpmGlobalRoot, packageRoot)) {
|
|
191
|
+
return true;
|
|
192
|
+
}
|
|
193
|
+
const globalNodeModulesDir = normalizePnpmGlobalNodeModulesRoot(pnpmGlobalRoot);
|
|
194
|
+
const globalProjectDir = path.dirname(globalNodeModulesDir);
|
|
195
|
+
if (!isSubPath(globalProjectDir, packageRoot)) {
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
const segments = normalizePath(packageRoot).split(path.sep).filter(Boolean);
|
|
199
|
+
const pnpmStoreIndex = segments.indexOf('.pnpm');
|
|
200
|
+
if (pnpmStoreIndex === -1) {
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
return segments.slice(pnpmStoreIndex + 1).includes('node_modules');
|
|
141
204
|
}
|
|
142
|
-
function
|
|
143
|
-
return
|
|
205
|
+
function isPnpmGlobalPackagePath(pnpmGlobalRoot, packageRoot, packageName) {
|
|
206
|
+
return readPnpmGlobalNodeModulesRoots(pnpmGlobalRoot).some((pnpmGlobalNodeModulesRoot) => isSameRealPath(path.join(pnpmGlobalNodeModulesRoot, ...packageNameToPath(packageName)), packageRoot));
|
|
144
207
|
}
|
|
145
|
-
|
|
208
|
+
function isPnpmGlobalBinProjectPath(pnpmGlobalBin, packageRoot, packageName) {
|
|
209
|
+
const pnpmHome = path.dirname(normalizePath(pnpmGlobalBin));
|
|
210
|
+
const globalDir = path.join(pnpmHome, 'global');
|
|
211
|
+
if (isSubPath(globalDir, packageRoot)) {
|
|
212
|
+
return true;
|
|
213
|
+
}
|
|
214
|
+
let entries;
|
|
146
215
|
try {
|
|
147
|
-
|
|
148
|
-
return JSON.parse(raw);
|
|
216
|
+
entries = fs.readdirSync(globalDir);
|
|
149
217
|
}
|
|
150
218
|
catch {
|
|
151
|
-
return
|
|
219
|
+
return false;
|
|
152
220
|
}
|
|
221
|
+
return entries.some((entry) => {
|
|
222
|
+
const pnpmGlobalRoot = path.join(globalDir, entry);
|
|
223
|
+
return (isPnpmGlobalRootPath(pnpmGlobalRoot, packageRoot)
|
|
224
|
+
|| isPnpmGlobalPackagePath(pnpmGlobalRoot, packageRoot, packageName));
|
|
225
|
+
});
|
|
153
226
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
227
|
+
function isPnpmGlobalInstallPath(options) {
|
|
228
|
+
if (options.pnpmGlobalRoot) {
|
|
229
|
+
const matchedRoot = isPnpmGlobalRootPath(options.pnpmGlobalRoot, options.packageRoot)
|
|
230
|
+
|| isPnpmGlobalPackagePath(options.pnpmGlobalRoot, options.packageRoot, options.packageName);
|
|
231
|
+
if (matchedRoot) {
|
|
232
|
+
return true;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (options.pnpmGlobalBin) {
|
|
236
|
+
return isPnpmGlobalBinProjectPath(options.pnpmGlobalBin, options.packageRoot, options.packageName);
|
|
237
|
+
}
|
|
238
|
+
return false;
|
|
158
239
|
}
|
|
159
|
-
|
|
160
|
-
const
|
|
161
|
-
|
|
240
|
+
function readCurrentBinPath(currentBinPath) {
|
|
241
|
+
const candidate = String(currentBinPath ?? process.argv[1] ?? '').trim();
|
|
242
|
+
if (!candidate) {
|
|
243
|
+
return undefined;
|
|
244
|
+
}
|
|
245
|
+
return normalizePath(candidate);
|
|
162
246
|
}
|
|
163
|
-
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
247
|
+
function cleanCommandPath(value) {
|
|
248
|
+
const trimmed = value.trim();
|
|
249
|
+
return trimmed ? trimmed : undefined;
|
|
250
|
+
}
|
|
251
|
+
function resolvePackageManagerProbeCwd() {
|
|
252
|
+
const candidates = [os.homedir(), os.tmpdir(), path.parse(process.cwd()).root];
|
|
253
|
+
for (const candidate of candidates) {
|
|
254
|
+
if (!candidate) {
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
try {
|
|
258
|
+
if (fs.statSync(candidate).isDirectory()) {
|
|
259
|
+
return candidate;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
// Ignore invalid probe cwd candidates and continue to the next one.
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return undefined;
|
|
170
267
|
}
|
|
171
268
|
async function readGlobalPrefix(commandOutputFn) {
|
|
172
269
|
try {
|
|
173
|
-
return (await commandOutputFn('npm', ['prefix', '-g'], {
|
|
270
|
+
return cleanCommandPath(await commandOutputFn('npm', ['prefix', '-g'], {
|
|
271
|
+
cwd: resolvePackageManagerProbeCwd(),
|
|
174
272
|
errorName: 'npm prefix',
|
|
175
|
-
}))
|
|
273
|
+
}));
|
|
274
|
+
}
|
|
275
|
+
catch {
|
|
276
|
+
return undefined;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
async function readPnpmGlobalBin(commandOutputFn) {
|
|
280
|
+
try {
|
|
281
|
+
return cleanCommandPath(await commandOutputFn('pnpm', ['bin', '-g'], {
|
|
282
|
+
cwd: resolvePackageManagerProbeCwd(),
|
|
283
|
+
errorName: 'pnpm bin',
|
|
284
|
+
}));
|
|
285
|
+
}
|
|
286
|
+
catch {
|
|
287
|
+
return undefined;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
async function readPnpmGlobalRoot(commandOutputFn) {
|
|
291
|
+
try {
|
|
292
|
+
return cleanCommandPath(await commandOutputFn('pnpm', ['root', '-g'], {
|
|
293
|
+
cwd: resolvePackageManagerProbeCwd(),
|
|
294
|
+
errorName: 'pnpm root',
|
|
295
|
+
}));
|
|
176
296
|
}
|
|
177
297
|
catch {
|
|
178
298
|
return undefined;
|
|
@@ -180,9 +300,21 @@ async function readGlobalPrefix(commandOutputFn) {
|
|
|
180
300
|
}
|
|
181
301
|
async function readYarnGlobalDir(commandOutputFn) {
|
|
182
302
|
try {
|
|
183
|
-
return (await commandOutputFn('yarn', ['global', 'dir'], {
|
|
303
|
+
return cleanCommandPath(await commandOutputFn('yarn', ['global', 'dir'], {
|
|
304
|
+
cwd: resolvePackageManagerProbeCwd(),
|
|
184
305
|
errorName: 'yarn global dir',
|
|
185
|
-
}))
|
|
306
|
+
}));
|
|
307
|
+
}
|
|
308
|
+
catch {
|
|
309
|
+
return undefined;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
async function readYarnGlobalBin(commandOutputFn) {
|
|
313
|
+
try {
|
|
314
|
+
return cleanCommandPath(await commandOutputFn('yarn', ['global', 'bin'], {
|
|
315
|
+
cwd: resolvePackageManagerProbeCwd(),
|
|
316
|
+
errorName: 'yarn global bin',
|
|
317
|
+
}));
|
|
186
318
|
}
|
|
187
319
|
catch {
|
|
188
320
|
return undefined;
|
|
@@ -242,28 +374,45 @@ export function getSelfUpdatePackageSpec(status) {
|
|
|
242
374
|
}
|
|
243
375
|
export async function inspectSelfInstall(options = {}) {
|
|
244
376
|
const packageRoot = options.packageRoot ? normalizePath(options.packageRoot) : PACKAGE_ROOT;
|
|
377
|
+
const packageName = options.packageName ?? DEFAULT_PACKAGE_NAME;
|
|
245
378
|
const commandOutputFn = options.commandOutputFn ?? commandOutput;
|
|
246
|
-
const
|
|
247
|
-
const globalPrefix =
|
|
248
|
-
const
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
379
|
+
const currentBinPath = readCurrentBinPath(options.currentBinPath);
|
|
380
|
+
const globalPrefix = await readGlobalPrefix(commandOutputFn);
|
|
381
|
+
const pnpmGlobalBin = await readPnpmGlobalBin(commandOutputFn);
|
|
382
|
+
const pnpmGlobalRoot = await readPnpmGlobalRoot(commandOutputFn);
|
|
383
|
+
const yarnGlobalDir = await readYarnGlobalDir(commandOutputFn);
|
|
384
|
+
const yarnGlobalBin = await readYarnGlobalBin(commandOutputFn);
|
|
385
|
+
const installMethod = detectInstallMethodFromSignals({
|
|
386
|
+
packageRoot,
|
|
387
|
+
currentBinPath,
|
|
388
|
+
globalPrefix,
|
|
389
|
+
packageName,
|
|
390
|
+
pnpmGlobalBin,
|
|
391
|
+
pnpmGlobalRoot,
|
|
392
|
+
yarnGlobalBin,
|
|
393
|
+
yarnGlobalDir,
|
|
394
|
+
});
|
|
261
395
|
return {
|
|
262
396
|
packageRoot,
|
|
263
397
|
installMethod,
|
|
264
398
|
globalPrefix,
|
|
265
399
|
};
|
|
266
400
|
}
|
|
401
|
+
function detectInstallMethodFromSignals(options) {
|
|
402
|
+
if (options.currentBinPath && options.yarnGlobalBin && isSubPath(options.yarnGlobalBin, options.currentBinPath)) {
|
|
403
|
+
return 'yarn-global';
|
|
404
|
+
}
|
|
405
|
+
if (options.currentBinPath && options.pnpmGlobalBin && isSubPath(options.pnpmGlobalBin, options.currentBinPath)) {
|
|
406
|
+
return 'pnpm-global';
|
|
407
|
+
}
|
|
408
|
+
return detectInstallMethod(options.packageRoot, {
|
|
409
|
+
globalPrefix: options.globalPrefix,
|
|
410
|
+
packageName: options.packageName,
|
|
411
|
+
pnpmGlobalBin: options.pnpmGlobalBin,
|
|
412
|
+
pnpmGlobalRoot: options.pnpmGlobalRoot,
|
|
413
|
+
yarnGlobalDir: options.yarnGlobalDir,
|
|
414
|
+
});
|
|
415
|
+
}
|
|
267
416
|
export async function inspectSelfStatus(options = {}) {
|
|
268
417
|
const packageRoot = options.packageRoot ? normalizePath(options.packageRoot) : PACKAGE_ROOT;
|
|
269
418
|
const packageName = options.packageName ?? DEFAULT_PACKAGE_NAME;
|
|
@@ -271,6 +420,8 @@ export async function inspectSelfStatus(options = {}) {
|
|
|
271
420
|
const channel = options.channel && options.channel !== 'auto' ? options.channel : detectChannel(currentVersion);
|
|
272
421
|
const commandOutputFn = options.commandOutputFn ?? commandOutput;
|
|
273
422
|
const { installMethod, globalPrefix } = await inspectSelfInstall({
|
|
423
|
+
currentBinPath: options.currentBinPath,
|
|
424
|
+
packageName,
|
|
274
425
|
packageRoot,
|
|
275
426
|
commandOutputFn,
|
|
276
427
|
});
|