@nocobase/cli 2.1.4-test.1 → 2.1.4-test.3
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/bin/early-locale.js +89 -0
- package/bin/run.js +3 -0
- package/bin/windows-admin.js +60 -0
- package/dist/commands/self/check.js +1 -1
- package/dist/commands/self/update.js +2 -2
- package/dist/lib/self-manager.js +3 -0
- package/dist/locale/en-US.json +6 -0
- package/dist/locale/zh-CN.json +6 -0
- package/package.json +1 -1
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
|
|
6
|
+
export function normalizeEarlyCliLocale(value) {
|
|
7
|
+
const normalized = String(value ?? '')
|
|
8
|
+
.trim()
|
|
9
|
+
.replace(/\..*$/, '')
|
|
10
|
+
.replace(/_/g, '-')
|
|
11
|
+
.toLowerCase();
|
|
12
|
+
|
|
13
|
+
if (normalized === 'zh' || normalized.startsWith('zh-')) {
|
|
14
|
+
return 'zh-CN';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (normalized === 'en' || normalized.startsWith('en-')) {
|
|
18
|
+
return 'en-US';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function readConfiguredEarlyCliLocale() {
|
|
25
|
+
try {
|
|
26
|
+
const cliHomeRoot = String(process.env.NB_CLI_ROOT ?? '').trim() || os.homedir();
|
|
27
|
+
const configPath = path.join(cliHomeRoot, '.nocobase', 'config.json');
|
|
28
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
29
|
+
const parsed = JSON.parse(content);
|
|
30
|
+
return normalizeEarlyCliLocale(parsed?.settings?.locale);
|
|
31
|
+
} catch {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function detectEarlyCliLocale() {
|
|
37
|
+
const candidates = [
|
|
38
|
+
process.env.NB_LOCALE,
|
|
39
|
+
readConfiguredEarlyCliLocale(),
|
|
40
|
+
process.env.LC_ALL,
|
|
41
|
+
process.env.LC_MESSAGES,
|
|
42
|
+
process.env.LANG,
|
|
43
|
+
Intl.DateTimeFormat().resolvedOptions().locale,
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
for (const candidate of candidates) {
|
|
47
|
+
const locale = normalizeEarlyCliLocale(candidate);
|
|
48
|
+
if (locale) {
|
|
49
|
+
return locale;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return 'en-US';
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function getEarlyLocalePathValue(input, key) {
|
|
57
|
+
let current = input;
|
|
58
|
+
for (const part of key.split('.')) {
|
|
59
|
+
if (!current || typeof current !== 'object' || !Object.prototype.hasOwnProperty.call(current, part)) {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
current = current[part];
|
|
63
|
+
}
|
|
64
|
+
return typeof current === 'string' ? current : undefined;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function readEarlyLocaleMessages(locale) {
|
|
68
|
+
const moduleDir = path.dirname(fileURLToPath(import.meta.url));
|
|
69
|
+
const packageRoot = path.resolve(moduleDir, '..');
|
|
70
|
+
const localePaths = [
|
|
71
|
+
path.join(packageRoot, 'src', 'locale', `${locale}.json`),
|
|
72
|
+
path.join(packageRoot, 'dist', 'locale', `${locale}.json`),
|
|
73
|
+
];
|
|
74
|
+
|
|
75
|
+
for (const localePath of localePaths) {
|
|
76
|
+
try {
|
|
77
|
+
return JSON.parse(fs.readFileSync(localePath, 'utf8'));
|
|
78
|
+
} catch {
|
|
79
|
+
// Try the next runtime layout.
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function translateEarlyCli(key, fallback, locale = detectEarlyCliLocale()) {
|
|
87
|
+
const messages = readEarlyLocaleMessages(locale);
|
|
88
|
+
return getEarlyLocalePathValue(messages, key) ?? fallback;
|
|
89
|
+
}
|
package/bin/run.js
CHANGED
|
@@ -8,6 +8,7 @@ import pc from 'picocolors';
|
|
|
8
8
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
9
9
|
import { formatUnsupportedNodeVersionMessage, isSupportedNodeVersion } from './node-version.js';
|
|
10
10
|
import { normalizeNodeOptions, normalizeSessionEnv } from './session-env.js';
|
|
11
|
+
import { ensureWindowsAdministrator } from './windows-admin.js';
|
|
11
12
|
|
|
12
13
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
13
14
|
const requireFromCli = createRequire(import.meta.url);
|
|
@@ -27,6 +28,8 @@ if (!isSupportedNodeVersion()) {
|
|
|
27
28
|
normalizeSessionEnv();
|
|
28
29
|
normalizeNodeOptions();
|
|
29
30
|
|
|
31
|
+
ensureWindowsAdministrator();
|
|
32
|
+
|
|
30
33
|
/**
|
|
31
34
|
* In the monorepo, plain `node` cannot load `.ts`. Re-exec once with `--import <tsx>`
|
|
32
35
|
* (same effect as a dedicated dev entry with `#!/usr/bin/env -S node --import tsx`).
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import pc from 'picocolors';
|
|
3
|
+
import { detectEarlyCliLocale, translateEarlyCli } from './early-locale.js';
|
|
4
|
+
|
|
5
|
+
const windowsAdministratorCheckScript = [
|
|
6
|
+
'$identity = [Security.Principal.WindowsIdentity]::GetCurrent();',
|
|
7
|
+
'$principal = New-Object Security.Principal.WindowsPrincipal($identity);',
|
|
8
|
+
'if ($principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { exit 0 }',
|
|
9
|
+
'exit 1',
|
|
10
|
+
].join(' ');
|
|
11
|
+
|
|
12
|
+
export function formatWindowsAdministratorRequiredMessage() {
|
|
13
|
+
const locale = detectEarlyCliLocale();
|
|
14
|
+
const message = translateEarlyCli(
|
|
15
|
+
'entry.windowsAdministratorRequired.message',
|
|
16
|
+
'NocoBase CLI must be run as Administrator on Windows.',
|
|
17
|
+
locale,
|
|
18
|
+
);
|
|
19
|
+
const hint = translateEarlyCli(
|
|
20
|
+
'entry.windowsAdministratorRequired.hint',
|
|
21
|
+
'Open your terminal as Administrator, then run the command again.',
|
|
22
|
+
locale,
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
return [message, hint].join('\n');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function isWindowsAdministrator() {
|
|
29
|
+
for (const command of ['pwsh.exe', 'powershell.exe']) {
|
|
30
|
+
const result = spawnSync(
|
|
31
|
+
command,
|
|
32
|
+
['-NoLogo', '-NoProfile', '-NonInteractive', '-Command', windowsAdministratorCheckScript],
|
|
33
|
+
{
|
|
34
|
+
stdio: 'ignore',
|
|
35
|
+
windowsHide: true,
|
|
36
|
+
},
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
if (result.error?.code === 'ENOENT') {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return result.status === 0;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function ensureWindowsAdministrator() {
|
|
50
|
+
if (process.platform !== 'win32' || process.env.NB_CLI_WINDOWS_ADMIN_CHECKED === '1') {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!isWindowsAdministrator()) {
|
|
55
|
+
console.error(pc.red(formatWindowsAdministratorRequiredMessage()));
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
process.env.NB_CLI_WINDOWS_ADMIN_CHECKED = '1';
|
|
60
|
+
}
|
|
@@ -20,7 +20,7 @@ export default class SelfCheck extends Command {
|
|
|
20
20
|
static flags = {
|
|
21
21
|
channel: Flags.string({
|
|
22
22
|
description: 'Release channel to compare against. Defaults to the current CLI channel.',
|
|
23
|
-
options: ['auto', 'latest', 'beta', 'alpha'],
|
|
23
|
+
options: ['auto', 'latest', 'test', 'beta', 'alpha'],
|
|
24
24
|
default: 'auto',
|
|
25
25
|
}),
|
|
26
26
|
json: Flags.boolean({
|
|
@@ -31,12 +31,12 @@ export default class SelfUpdate extends Command {
|
|
|
31
31
|
'<%= config.bin %> <%= command.id %>',
|
|
32
32
|
'<%= config.bin %> <%= command.id %> --yes',
|
|
33
33
|
'<%= config.bin %> <%= command.id %> --skills',
|
|
34
|
-
'<%= config.bin %> <%= command.id %> --channel
|
|
34
|
+
'<%= config.bin %> <%= command.id %> --channel test --json',
|
|
35
35
|
];
|
|
36
36
|
static flags = {
|
|
37
37
|
channel: Flags.string({
|
|
38
38
|
description: 'Release channel to update to. Defaults to the current CLI channel.',
|
|
39
|
-
options: ['auto', 'latest', 'beta', 'alpha'],
|
|
39
|
+
options: ['auto', 'latest', 'test', 'beta', 'alpha'],
|
|
40
40
|
default: 'auto',
|
|
41
41
|
}),
|
|
42
42
|
yes: Flags.boolean({
|
package/dist/lib/self-manager.js
CHANGED
|
@@ -97,6 +97,9 @@ function detectChannel(currentVersion) {
|
|
|
97
97
|
if (/-beta(?:[.-]|$)/i.test(currentVersion)) {
|
|
98
98
|
return 'beta';
|
|
99
99
|
}
|
|
100
|
+
if (/-test(?:[.-]|$)/i.test(currentVersion)) {
|
|
101
|
+
return 'test';
|
|
102
|
+
}
|
|
100
103
|
return 'latest';
|
|
101
104
|
}
|
|
102
105
|
function readCurrentVersion(packageRoot) {
|
package/dist/locale/en-US.json
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
+
"entry": {
|
|
3
|
+
"windowsAdministratorRequired": {
|
|
4
|
+
"message": "NocoBase CLI must be run as Administrator on Windows.",
|
|
5
|
+
"hint": "Open your terminal as Administrator, then run the command again."
|
|
6
|
+
}
|
|
7
|
+
},
|
|
2
8
|
"promptCatalog": {
|
|
3
9
|
"common": {
|
|
4
10
|
"cancelled": "Cancelled.",
|
package/dist/locale/zh-CN.json
CHANGED