@nocobase/cli 2.1.11-test.1 → 2.1.11-test.10
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 +168 -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,130 @@ 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');
|
|
141
150
|
}
|
|
142
|
-
function
|
|
143
|
-
return
|
|
151
|
+
function packageNameToPath(packageName) {
|
|
152
|
+
return packageName.split('/').filter(Boolean);
|
|
144
153
|
}
|
|
145
|
-
|
|
154
|
+
function isSameRealPath(left, right) {
|
|
146
155
|
try {
|
|
147
|
-
|
|
148
|
-
return JSON.parse(raw);
|
|
156
|
+
return normalizePath(fs.realpathSync(left)) === normalizePath(fs.realpathSync(right));
|
|
149
157
|
}
|
|
150
158
|
catch {
|
|
151
|
-
return
|
|
159
|
+
return false;
|
|
152
160
|
}
|
|
153
161
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
162
|
+
function isPnpmGlobalRootPath(pnpmGlobalRoot, packageRoot) {
|
|
163
|
+
if (isSubPath(pnpmGlobalRoot, packageRoot)) {
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
const globalNodeModulesDir = normalizePnpmGlobalNodeModulesRoot(pnpmGlobalRoot);
|
|
167
|
+
const globalProjectDir = path.dirname(globalNodeModulesDir);
|
|
168
|
+
if (!isSubPath(globalProjectDir, packageRoot)) {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
const segments = normalizePath(packageRoot).split(path.sep).filter(Boolean);
|
|
172
|
+
const pnpmStoreIndex = segments.indexOf('.pnpm');
|
|
173
|
+
if (pnpmStoreIndex === -1) {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
return segments.slice(pnpmStoreIndex + 1).includes('node_modules');
|
|
158
177
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
return state.entries?.[getInstallMethodCacheKey(packageRoot)];
|
|
178
|
+
function isPnpmGlobalPackagePath(pnpmGlobalRoot, packageRoot, packageName) {
|
|
179
|
+
return isSameRealPath(path.join(normalizePnpmGlobalNodeModulesRoot(pnpmGlobalRoot), ...packageNameToPath(packageName)), packageRoot);
|
|
162
180
|
}
|
|
163
|
-
|
|
164
|
-
const
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}
|
|
169
|
-
|
|
181
|
+
function isPnpmGlobalBinProjectPath(pnpmGlobalBin, packageRoot, packageName) {
|
|
182
|
+
const pnpmHome = path.dirname(normalizePath(pnpmGlobalBin));
|
|
183
|
+
const globalDir = path.join(pnpmHome, 'global');
|
|
184
|
+
if (isSubPath(globalDir, packageRoot)) {
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
let entries;
|
|
188
|
+
try {
|
|
189
|
+
entries = fs.readdirSync(globalDir);
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
return entries.some((entry) => {
|
|
195
|
+
const pnpmGlobalRoot = path.join(globalDir, entry, 'node_modules');
|
|
196
|
+
return (isPnpmGlobalRootPath(pnpmGlobalRoot, packageRoot)
|
|
197
|
+
|| isPnpmGlobalPackagePath(pnpmGlobalRoot, packageRoot, packageName));
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
function isPnpmGlobalInstallPath(options) {
|
|
201
|
+
if (options.pnpmGlobalRoot) {
|
|
202
|
+
const matchedRoot = isPnpmGlobalRootPath(options.pnpmGlobalRoot, options.packageRoot)
|
|
203
|
+
|| isPnpmGlobalPackagePath(options.pnpmGlobalRoot, options.packageRoot, options.packageName);
|
|
204
|
+
if (matchedRoot) {
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (options.pnpmGlobalBin) {
|
|
209
|
+
return isPnpmGlobalBinProjectPath(options.pnpmGlobalBin, options.packageRoot, options.packageName);
|
|
210
|
+
}
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
function readCurrentBinPath(currentBinPath) {
|
|
214
|
+
const candidate = String(currentBinPath ?? process.argv[1] ?? '').trim();
|
|
215
|
+
if (!candidate) {
|
|
216
|
+
return undefined;
|
|
217
|
+
}
|
|
218
|
+
return normalizePath(candidate);
|
|
219
|
+
}
|
|
220
|
+
function cleanCommandPath(value) {
|
|
221
|
+
const trimmed = value.trim();
|
|
222
|
+
return trimmed ? trimmed : undefined;
|
|
223
|
+
}
|
|
224
|
+
function resolvePackageManagerProbeCwd() {
|
|
225
|
+
const candidates = [os.homedir(), os.tmpdir(), path.parse(process.cwd()).root];
|
|
226
|
+
for (const candidate of candidates) {
|
|
227
|
+
if (!candidate) {
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
try {
|
|
231
|
+
if (fs.statSync(candidate).isDirectory()) {
|
|
232
|
+
return candidate;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
// Ignore invalid probe cwd candidates and continue to the next one.
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return undefined;
|
|
170
240
|
}
|
|
171
241
|
async function readGlobalPrefix(commandOutputFn) {
|
|
172
242
|
try {
|
|
173
|
-
return (await commandOutputFn('npm', ['prefix', '-g'], {
|
|
243
|
+
return cleanCommandPath(await commandOutputFn('npm', ['prefix', '-g'], {
|
|
244
|
+
cwd: resolvePackageManagerProbeCwd(),
|
|
174
245
|
errorName: 'npm prefix',
|
|
175
|
-
}))
|
|
246
|
+
}));
|
|
247
|
+
}
|
|
248
|
+
catch {
|
|
249
|
+
return undefined;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
async function readPnpmGlobalBin(commandOutputFn) {
|
|
253
|
+
try {
|
|
254
|
+
return cleanCommandPath(await commandOutputFn('pnpm', ['bin', '-g'], {
|
|
255
|
+
cwd: resolvePackageManagerProbeCwd(),
|
|
256
|
+
errorName: 'pnpm bin',
|
|
257
|
+
}));
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
return undefined;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
async function readPnpmGlobalRoot(commandOutputFn) {
|
|
264
|
+
try {
|
|
265
|
+
return cleanCommandPath(await commandOutputFn('pnpm', ['root', '-g'], {
|
|
266
|
+
cwd: resolvePackageManagerProbeCwd(),
|
|
267
|
+
errorName: 'pnpm root',
|
|
268
|
+
}));
|
|
176
269
|
}
|
|
177
270
|
catch {
|
|
178
271
|
return undefined;
|
|
@@ -180,9 +273,21 @@ async function readGlobalPrefix(commandOutputFn) {
|
|
|
180
273
|
}
|
|
181
274
|
async function readYarnGlobalDir(commandOutputFn) {
|
|
182
275
|
try {
|
|
183
|
-
return (await commandOutputFn('yarn', ['global', 'dir'], {
|
|
276
|
+
return cleanCommandPath(await commandOutputFn('yarn', ['global', 'dir'], {
|
|
277
|
+
cwd: resolvePackageManagerProbeCwd(),
|
|
184
278
|
errorName: 'yarn global dir',
|
|
185
|
-
}))
|
|
279
|
+
}));
|
|
280
|
+
}
|
|
281
|
+
catch {
|
|
282
|
+
return undefined;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
async function readYarnGlobalBin(commandOutputFn) {
|
|
286
|
+
try {
|
|
287
|
+
return cleanCommandPath(await commandOutputFn('yarn', ['global', 'bin'], {
|
|
288
|
+
cwd: resolvePackageManagerProbeCwd(),
|
|
289
|
+
errorName: 'yarn global bin',
|
|
290
|
+
}));
|
|
186
291
|
}
|
|
187
292
|
catch {
|
|
188
293
|
return undefined;
|
|
@@ -242,28 +347,45 @@ export function getSelfUpdatePackageSpec(status) {
|
|
|
242
347
|
}
|
|
243
348
|
export async function inspectSelfInstall(options = {}) {
|
|
244
349
|
const packageRoot = options.packageRoot ? normalizePath(options.packageRoot) : PACKAGE_ROOT;
|
|
350
|
+
const packageName = options.packageName ?? DEFAULT_PACKAGE_NAME;
|
|
245
351
|
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
|
-
|
|
352
|
+
const currentBinPath = readCurrentBinPath(options.currentBinPath);
|
|
353
|
+
const globalPrefix = await readGlobalPrefix(commandOutputFn);
|
|
354
|
+
const pnpmGlobalBin = await readPnpmGlobalBin(commandOutputFn);
|
|
355
|
+
const pnpmGlobalRoot = await readPnpmGlobalRoot(commandOutputFn);
|
|
356
|
+
const yarnGlobalDir = await readYarnGlobalDir(commandOutputFn);
|
|
357
|
+
const yarnGlobalBin = await readYarnGlobalBin(commandOutputFn);
|
|
358
|
+
const installMethod = detectInstallMethodFromSignals({
|
|
359
|
+
packageRoot,
|
|
360
|
+
currentBinPath,
|
|
361
|
+
globalPrefix,
|
|
362
|
+
packageName,
|
|
363
|
+
pnpmGlobalBin,
|
|
364
|
+
pnpmGlobalRoot,
|
|
365
|
+
yarnGlobalBin,
|
|
366
|
+
yarnGlobalDir,
|
|
367
|
+
});
|
|
261
368
|
return {
|
|
262
369
|
packageRoot,
|
|
263
370
|
installMethod,
|
|
264
371
|
globalPrefix,
|
|
265
372
|
};
|
|
266
373
|
}
|
|
374
|
+
function detectInstallMethodFromSignals(options) {
|
|
375
|
+
if (options.currentBinPath && options.yarnGlobalBin && isSubPath(options.yarnGlobalBin, options.currentBinPath)) {
|
|
376
|
+
return 'yarn-global';
|
|
377
|
+
}
|
|
378
|
+
if (options.currentBinPath && options.pnpmGlobalBin && isSubPath(options.pnpmGlobalBin, options.currentBinPath)) {
|
|
379
|
+
return 'pnpm-global';
|
|
380
|
+
}
|
|
381
|
+
return detectInstallMethod(options.packageRoot, {
|
|
382
|
+
globalPrefix: options.globalPrefix,
|
|
383
|
+
packageName: options.packageName,
|
|
384
|
+
pnpmGlobalBin: options.pnpmGlobalBin,
|
|
385
|
+
pnpmGlobalRoot: options.pnpmGlobalRoot,
|
|
386
|
+
yarnGlobalDir: options.yarnGlobalDir,
|
|
387
|
+
});
|
|
388
|
+
}
|
|
267
389
|
export async function inspectSelfStatus(options = {}) {
|
|
268
390
|
const packageRoot = options.packageRoot ? normalizePath(options.packageRoot) : PACKAGE_ROOT;
|
|
269
391
|
const packageName = options.packageName ?? DEFAULT_PACKAGE_NAME;
|
|
@@ -271,6 +393,8 @@ export async function inspectSelfStatus(options = {}) {
|
|
|
271
393
|
const channel = options.channel && options.channel !== 'auto' ? options.channel : detectChannel(currentVersion);
|
|
272
394
|
const commandOutputFn = options.commandOutputFn ?? commandOutput;
|
|
273
395
|
const { installMethod, globalPrefix } = await inspectSelfInstall({
|
|
396
|
+
currentBinPath: options.currentBinPath,
|
|
397
|
+
packageName,
|
|
274
398
|
packageRoot,
|
|
275
399
|
commandOutputFn,
|
|
276
400
|
});
|