@nocobase/cli 2.1.0-alpha.45 → 2.1.0-alpha.47
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/LICENSE +201 -0
- package/README.md +63 -380
- 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 +17 -0
- package/assets/env-proxy/nginx/snippets/spa-location.conf +6 -0
- package/assets/env-proxy/nginx/snippets/uploads-location.conf +21 -0
- package/bin/run.js +40 -32
- package/dist/commands/app/autostart/disable.js +55 -0
- package/dist/commands/app/autostart/enable.js +55 -0
- package/dist/commands/app/autostart/list.js +37 -0
- package/dist/commands/app/autostart/run.js +84 -0
- package/dist/commands/app/autostart/shared.js +49 -0
- package/dist/commands/app/destroy.js +21 -12
- package/dist/commands/app/down.js +2 -2
- package/dist/commands/app/logs.js +2 -1
- package/dist/commands/app/restart.js +92 -20
- package/dist/commands/app/shared.js +3 -2
- package/dist/commands/app/start.js +143 -38
- package/dist/commands/app/stop.js +31 -2
- package/dist/commands/app/upgrade.js +11 -7
- package/dist/commands/config/delete.js +10 -2
- package/dist/commands/config/get.js +7 -1
- package/dist/commands/config/set.js +12 -2
- package/dist/commands/db/ps.js +5 -18
- package/dist/commands/env/add.js +24 -44
- package/dist/commands/env/auth.js +1 -1
- package/dist/commands/env/info.js +3 -2
- package/dist/commands/env/list.js +4 -5
- package/dist/commands/env/proxy/caddy.js +28 -0
- package/dist/commands/env/proxy/index.js +353 -0
- package/dist/commands/env/proxy/nginx.js +28 -0
- package/dist/commands/env/remove.js +112 -22
- package/dist/commands/env/shared.js +17 -9
- package/dist/commands/env/status.js +10 -7
- package/dist/commands/env/update.js +385 -21
- package/dist/commands/init.js +368 -98
- package/dist/commands/install.js +271 -104
- package/dist/commands/license/activate.js +63 -244
- package/dist/commands/license/plugins/shared.js +64 -13
- package/dist/commands/plugin/import.js +108 -0
- package/dist/commands/revision/create.js +89 -0
- package/dist/commands/self/update.js +58 -1
- package/dist/commands/source/dev.js +5 -5
- package/dist/commands/source/test.js +13 -14
- package/dist/lib/app-health.js +39 -32
- package/dist/lib/app-managed-resources.js +25 -9
- package/dist/lib/app-public-path.js +80 -0
- package/dist/lib/app-runtime.js +12 -3
- package/dist/lib/auth-store.js +128 -4
- package/dist/lib/backup.js +3 -3
- package/dist/lib/bootstrap.js +14 -8
- package/dist/lib/cli-config.js +229 -3
- package/dist/lib/cli-entry-error.js +52 -0
- package/dist/lib/command-log.js +284 -0
- package/dist/lib/docker-env-file.js +10 -2
- package/dist/lib/docker-log-stream.js +45 -0
- package/dist/lib/env-auth.js +25 -14
- package/dist/lib/env-command-config.js +45 -0
- package/dist/lib/env-config.js +7 -2
- package/dist/lib/env-guard.js +9 -10
- package/dist/lib/env-paths.js +101 -0
- package/dist/lib/env-proxy.js +1295 -0
- package/dist/lib/inquirer.js +4 -5
- package/dist/lib/managed-env-file.js +98 -0
- package/dist/lib/plugin-import.js +279 -0
- package/dist/lib/prompt-catalog-core.js +3 -2
- package/dist/lib/prompt-validators.js +14 -0
- package/dist/lib/prompt-web-ui.js +8 -1
- package/dist/lib/run-npm.js +56 -12
- package/dist/lib/skills-manager.js +3 -1
- package/dist/lib/source-publish.js +22 -2
- package/dist/lib/startup-update.js +74 -50
- package/dist/lib/ui.js +2 -1
- package/dist/locale/en-US.json +122 -22
- package/dist/locale/zh-CN.json +119 -19
- package/package.json +5 -7
- package/scripts/build.mjs +34 -0
- package/scripts/clean.mjs +9 -0
- package/tsconfig.json +19 -0
- package/LICENSE.txt +0 -107
- package/README.zh-CN.md +0 -355
|
@@ -10,6 +10,7 @@ import fs from 'node:fs/promises';
|
|
|
10
10
|
import path from 'node:path';
|
|
11
11
|
import { fileURLToPath } from 'node:url';
|
|
12
12
|
import { confirm } from "./inquirer.js";
|
|
13
|
+
import { DEFAULT_UPDATE_POLICY, getExplicitCliConfigValue, loadCliConfig, } from './cli-config.js';
|
|
13
14
|
import { inspectSelfInstall, inspectSelfStatus, } from './self-manager.js';
|
|
14
15
|
import { inspectSkillsStatus } from './skills-manager.js';
|
|
15
16
|
import { resolveCliHomeDir } from './cli-home.js';
|
|
@@ -83,39 +84,53 @@ async function writeCurrentInstallEntry(updater) {
|
|
|
83
84
|
const state = await readState();
|
|
84
85
|
const installBinPath = getCurrentInstallBinPath();
|
|
85
86
|
const nextEntry = updater(getCurrentInstallEntry(state), state);
|
|
87
|
+
const entries = {
|
|
88
|
+
...(state.entries ?? {}),
|
|
89
|
+
};
|
|
90
|
+
if (nextEntry?.policy || nextEntry?.lastCheckedDate) {
|
|
91
|
+
entries[installBinPath] = nextEntry;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
delete entries[installBinPath];
|
|
95
|
+
}
|
|
86
96
|
await writeState({
|
|
87
97
|
...state,
|
|
88
|
-
entries:
|
|
89
|
-
...(state.entries ?? {}),
|
|
90
|
-
[installBinPath]: nextEntry,
|
|
91
|
-
},
|
|
98
|
+
entries: Object.keys(entries).length ? entries : undefined,
|
|
92
99
|
});
|
|
93
100
|
}
|
|
94
101
|
async function markChecked(now = new Date()) {
|
|
95
|
-
await writeCurrentInstallEntry((current
|
|
102
|
+
await writeCurrentInstallEntry((current) => {
|
|
96
103
|
return {
|
|
97
|
-
|
|
104
|
+
...current,
|
|
98
105
|
lastCheckedDate: todayStamp(now),
|
|
99
106
|
};
|
|
100
107
|
});
|
|
101
108
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
109
|
+
function resolveLegacyStartupUpdatePolicy(state) {
|
|
110
|
+
const policy = getCurrentInstallEntry(state)?.policy;
|
|
111
|
+
if (policy === 'disabled') {
|
|
112
|
+
return 'off';
|
|
113
|
+
}
|
|
114
|
+
if (policy === 'daily') {
|
|
115
|
+
return 'prompt';
|
|
116
|
+
}
|
|
117
|
+
return undefined;
|
|
110
118
|
}
|
|
111
|
-
async function
|
|
112
|
-
await
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
+
async function resolveStartupUpdatePolicy(state) {
|
|
120
|
+
const config = await loadCliConfig({ scope: 'global' });
|
|
121
|
+
const explicit = getExplicitCliConfigValue(config, 'update.policy');
|
|
122
|
+
return explicit ?? resolveLegacyStartupUpdatePolicy(state) ?? DEFAULT_UPDATE_POLICY;
|
|
123
|
+
}
|
|
124
|
+
export async function clearLegacyStartupUpdatePolicyForCurrentInstall() {
|
|
125
|
+
const state = await readState();
|
|
126
|
+
const current = getCurrentInstallEntry(state);
|
|
127
|
+
if (!current?.policy) {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
await writeCurrentInstallEntry(() => ({
|
|
131
|
+
lastCheckedDate: current.lastCheckedDate,
|
|
132
|
+
}));
|
|
133
|
+
return true;
|
|
119
134
|
}
|
|
120
135
|
export async function shouldRunStartupUpdateCheck(argv, now = new Date()) {
|
|
121
136
|
if (process.env[NB_SKIP_STARTUP_UPDATE_ENV] === '1') {
|
|
@@ -125,19 +140,14 @@ export async function shouldRunStartupUpdateCheck(argv, now = new Date()) {
|
|
|
125
140
|
return false;
|
|
126
141
|
}
|
|
127
142
|
const state = await readState();
|
|
128
|
-
const
|
|
129
|
-
if (
|
|
143
|
+
const policy = await resolveStartupUpdatePolicy(state);
|
|
144
|
+
if (policy === 'off') {
|
|
130
145
|
return false;
|
|
131
146
|
}
|
|
132
|
-
if (currentEntry?.policy === 'daily') {
|
|
133
|
-
return readCurrentInstallLastCheckedDate(state) !== todayStamp(now);
|
|
134
|
-
}
|
|
135
147
|
const selfInstall = await inspectSelfInstall();
|
|
136
148
|
if (!shouldEnableStartupUpdateForInstallMethod(selfInstall.installMethod)) {
|
|
137
|
-
await disableStartupUpdateForCurrentInstall();
|
|
138
149
|
return false;
|
|
139
150
|
}
|
|
140
|
-
await enableDailyStartupUpdateForCurrentInstall();
|
|
141
151
|
return readCurrentInstallLastCheckedDate(state) !== todayStamp(now);
|
|
142
152
|
}
|
|
143
153
|
export function shouldEnableStartupUpdateForInstallMethod(installMethod) {
|
|
@@ -189,14 +199,13 @@ function buildPromptMessage(selfStatus, skillsStatus) {
|
|
|
189
199
|
return lines.join('\n');
|
|
190
200
|
}
|
|
191
201
|
function buildUpdateCommands(selfStatus, skillsStatus) {
|
|
192
|
-
const commands = [];
|
|
193
202
|
if (selfStatus.updateAvailable && selfStatus.updatable) {
|
|
194
|
-
|
|
203
|
+
return [skillsStatus.updateAvailable === true ? 'nb self update --yes --skills' : 'nb self update --yes'];
|
|
195
204
|
}
|
|
196
205
|
if (skillsStatus.updateAvailable === true) {
|
|
197
|
-
|
|
206
|
+
return ['nb skills update --yes'];
|
|
198
207
|
}
|
|
199
|
-
return
|
|
208
|
+
return [];
|
|
200
209
|
}
|
|
201
210
|
function buildNonInteractiveWarning(selfStatus, skillsStatus) {
|
|
202
211
|
const commands = buildUpdateCommands(selfStatus, skillsStatus);
|
|
@@ -233,26 +242,36 @@ function buildDeclinedWarning(selfStatus, skillsStatus) {
|
|
|
233
242
|
'You may run into compatibility issues until you update.',
|
|
234
243
|
].join(' ');
|
|
235
244
|
}
|
|
236
|
-
async function runStartupUpdates() {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
}
|
|
245
|
+
async function runStartupUpdates(selfStatus, skillsStatus) {
|
|
246
|
+
if (selfStatus.updateAvailable && selfStatus.updatable) {
|
|
247
|
+
const args = ['self', 'update', '--yes'];
|
|
248
|
+
if (skillsStatus.updateAvailable === true) {
|
|
249
|
+
args.push('--skills');
|
|
250
|
+
}
|
|
251
|
+
await run('nb', args, {
|
|
252
|
+
stdio: 'inherit',
|
|
253
|
+
env: {
|
|
254
|
+
[NB_SKIP_STARTUP_UPDATE_ENV]: '1',
|
|
255
|
+
},
|
|
256
|
+
errorName: 'nb self update',
|
|
257
|
+
});
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
if (skillsStatus.updateAvailable === true) {
|
|
261
|
+
await run('nb', ['skills', 'update', '--yes'], {
|
|
262
|
+
stdio: 'inherit',
|
|
263
|
+
env: {
|
|
264
|
+
[NB_SKIP_STARTUP_UPDATE_ENV]: '1',
|
|
265
|
+
},
|
|
266
|
+
errorName: 'nb skills update',
|
|
267
|
+
});
|
|
268
|
+
}
|
|
251
269
|
}
|
|
252
|
-
export async function
|
|
270
|
+
export async function maybeRunStartupUpdate(argv) {
|
|
253
271
|
if (!(await shouldRunStartupUpdateCheck(argv))) {
|
|
254
272
|
return { kind: 'skipped' };
|
|
255
273
|
}
|
|
274
|
+
const policy = await resolveStartupUpdatePolicy(await readState());
|
|
256
275
|
const selfStatus = await inspectSelfStatus();
|
|
257
276
|
const skillsStatus = await inspectSkillsStatus();
|
|
258
277
|
if (!hasPendingUpdates(selfStatus, skillsStatus)) {
|
|
@@ -264,6 +283,11 @@ export async function maybeRunStartupUpdatePrompt(argv) {
|
|
|
264
283
|
await markChecked();
|
|
265
284
|
return { kind: 'warned' };
|
|
266
285
|
}
|
|
286
|
+
if (policy === 'auto') {
|
|
287
|
+
await runStartupUpdates(selfStatus, skillsStatus);
|
|
288
|
+
await markChecked();
|
|
289
|
+
return { kind: 'updated' };
|
|
290
|
+
}
|
|
267
291
|
let answer = false;
|
|
268
292
|
try {
|
|
269
293
|
answer = await confirm({
|
|
@@ -279,7 +303,7 @@ export async function maybeRunStartupUpdatePrompt(argv) {
|
|
|
279
303
|
await markChecked();
|
|
280
304
|
return { kind: 'declined' };
|
|
281
305
|
}
|
|
282
|
-
await runStartupUpdates();
|
|
306
|
+
await runStartupUpdates(selfStatus, skillsStatus);
|
|
283
307
|
await markChecked();
|
|
284
308
|
return { kind: 'updated' };
|
|
285
309
|
}
|
package/dist/lib/ui.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import { stdin as input, stdout as output } from 'node:process';
|
|
10
10
|
import ora from 'ora';
|
|
11
11
|
import pc from 'picocolors';
|
|
12
|
+
import { translateCli } from './cli-locale.js';
|
|
12
13
|
let activeSpinner;
|
|
13
14
|
let verboseMode = false;
|
|
14
15
|
let lastStaticTaskMessage;
|
|
@@ -57,7 +58,7 @@ export function announceTargetEnv(envName) {
|
|
|
57
58
|
if (process.env.NB_SKIP_TARGET_ENV_LOG === '1') {
|
|
58
59
|
return;
|
|
59
60
|
}
|
|
60
|
-
printInfo(
|
|
61
|
+
printInfo(translateCli('commands.shared.targetEnv', { envName }));
|
|
61
62
|
}
|
|
62
63
|
export function printVerbose(message) {
|
|
63
64
|
if (!verboseMode) {
|
package/dist/locale/en-US.json
CHANGED
|
@@ -63,6 +63,9 @@
|
|
|
63
63
|
"envKey": {
|
|
64
64
|
"invalid": "Use letters and numbers only."
|
|
65
65
|
},
|
|
66
|
+
"appPublicPath": {
|
|
67
|
+
"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."
|
|
68
|
+
},
|
|
66
69
|
"tcpPort": {
|
|
67
70
|
"invalid": "Enter a valid TCP port between 1 and 65535, for example {{example}}.",
|
|
68
71
|
"allocateFailed": "Failed to allocate an available TCP port.",
|
|
@@ -96,10 +99,10 @@
|
|
|
96
99
|
"placeholder": "https://demo.example.com/api or https://demo.example.com/api/__app/<subapp>"
|
|
97
100
|
},
|
|
98
101
|
"authType": {
|
|
99
|
-
"message": "
|
|
100
|
-
"basicLabel": "Basic
|
|
102
|
+
"message": "Which authentication method would you like to use?",
|
|
103
|
+
"basicLabel": "Basic authentication (username + password)",
|
|
101
104
|
"basicHint": "uses your credentials to fetch a token after save",
|
|
102
|
-
"oauthLabel": "OAuth (browser
|
|
105
|
+
"oauthLabel": "OAuth (browser authentication)",
|
|
103
106
|
"oauthHint": "runs nb env auth after save",
|
|
104
107
|
"tokenLabel": "API token / API key"
|
|
105
108
|
},
|
|
@@ -116,8 +119,91 @@
|
|
|
116
119
|
}
|
|
117
120
|
}
|
|
118
121
|
},
|
|
122
|
+
"envProxy": {
|
|
123
|
+
"messages": {
|
|
124
|
+
"generating": "Generating proxy config for env \"{{envName}}\"...",
|
|
125
|
+
"printed": "Printed proxy config for env \"{{envName}}\".",
|
|
126
|
+
"saved": "Saved generated proxy config for env \"{{envName}}\" at {{outputPath}}.",
|
|
127
|
+
"savedWithAppEntryCreated": "Saved generated proxy config for env \"{{envName}}\" at {{outputPath}}, and created editable app entry config at {{appConfigPath}}.",
|
|
128
|
+
"savedWithAppEntryMigrated": "Saved generated proxy config for env \"{{envName}}\" at {{outputPath}}, and migrated the app entry config at {{appConfigPath}}.",
|
|
129
|
+
"savedNginxBundleCreated": "Saved nginx proxy files for env \"{{envName}}\" under {{entryDir}}, and created editable app entry config at {{appConfigPath}}.",
|
|
130
|
+
"savedNginxBundleUpdated": "Saved nginx proxy files for env \"{{envName}}\" under {{entryDir}}, and refreshed editable app entry config at {{appConfigPath}}.",
|
|
131
|
+
"savedCaddyBundleCreated": "Saved caddy proxy files for env \"{{envName}}\" under {{entryDir}}, and created editable app entry config at {{appConfigPath}}.",
|
|
132
|
+
"savedCaddyBundleMigrated": "Saved caddy proxy files for env \"{{envName}}\" under {{entryDir}}, and migrated the app entry config at {{appConfigPath}}.",
|
|
133
|
+
"savedCaddyBundleUpdated": "Saved caddy proxy files for env \"{{envName}}\" under {{entryDir}}, and refreshed editable app entry config at {{appConfigPath}}.",
|
|
134
|
+
"failed": "Failed to generate proxy config for env \"{{envName}}\".",
|
|
135
|
+
"installingProvider": "Installing the shared proxy config into {{provider}}...",
|
|
136
|
+
"providerInstalled": "Installed the shared proxy config into the {{provider}} main config at {{configPath}}.",
|
|
137
|
+
"providerAlreadyInstalled": "The shared proxy config is already installed in the {{provider}} main config at {{configPath}}.",
|
|
138
|
+
"installProviderFailed": "Failed to install the shared proxy config into {{provider}}.",
|
|
139
|
+
"reloadingProvider": "Validating and reloading {{provider}}...",
|
|
140
|
+
"providerReloaded": "Validated and reloaded {{provider}}.",
|
|
141
|
+
"reloadProviderFailed": "Failed to validate and reload {{provider}}."
|
|
142
|
+
},
|
|
143
|
+
"errors": {
|
|
144
|
+
"httpEnvUnsupported": "Can't generate a proxy config for \"{{envName}}\" from this machine because the env only has an API connection.",
|
|
145
|
+
"sshEnvUnsupported": "Can't generate a proxy config for \"{{envName}}\" yet because SSH envs are not implemented.",
|
|
146
|
+
"invalidProxyPort": "Invalid proxy entry port \"{{port}}\". Use an integer between 1 and 65535.",
|
|
147
|
+
"missingAppPort": "Missing appPort for env \"{{envName}}\". Save or update the app port before generating proxy config.",
|
|
148
|
+
"missingVersion": "Couldn't determine the app version for env \"{{envName}}\". Run `nb env update {{envName}}` and try again.",
|
|
149
|
+
"appEntryMissingInclude": "The editable app entry config at {{appConfigPath}} does not reference {{generatedConfigPath}}. Add the managed generated-config reference back into the editable app entry and rerun the command.",
|
|
150
|
+
"nginxOutputUnsupported": "The nginx provider does not support `--output`. It writes `app.conf`, `public/index-v1.html`, `public/index-v2.html`, and `nocobase.conf` into `~/.nocobase/proxy/nginx/<env>/`.",
|
|
151
|
+
"caddyOutputUnsupported": "The caddy provider does not support `--output`. It writes `app.caddy`, `generated.caddy`, `public/index-v1.html`, `public/index-v2.html`, and `nocobase.caddy` into `~/.nocobase/proxy/caddy/<env>/`.",
|
|
152
|
+
"nginxAppEntryMissingManagedBlock": "The editable nginx app entry config at {{appConfigPath}} does not contain the NocoBase managed block. Restore the managed block or delete the file and rerun `nb env proxy`."
|
|
153
|
+
}
|
|
154
|
+
},
|
|
119
155
|
"shared": {
|
|
120
|
-
"missingCommand": "Couldn't run `{{action}}` because the {{displayName}} executable could not be found. Install {{displayName}} or update `nb config set {{configKey}} <path>` and try again."
|
|
156
|
+
"missingCommand": "Couldn't run `{{action}}` because the {{displayName}} executable could not be found. Install {{displayName}} or update `nb config set {{configKey}} <path>` and try again.",
|
|
157
|
+
"dockerDaemonUnavailable": "Couldn't run `{{action}}` because Docker is installed but the Docker daemon is not running. Start Docker Desktop or the Docker daemon service, then try again. Details: {{details}}",
|
|
158
|
+
"targetEnv": "Using env \"{{envName}}\".",
|
|
159
|
+
"crossEnv": {
|
|
160
|
+
"prompt": "Current env is \"{{currentEnv}}\", but this command targets \"{{requestedEnv}}\" via --env. Continue without switching the current env?",
|
|
161
|
+
"refusal": "Refusing to run against env \"{{requestedEnv}}\" because the current env is \"{{currentEnv}}\" and interactive confirmation is unavailable in the current agent session.\n\nFor safety, the agent will not switch envs automatically and will not add --yes on your behalf.\n\nTo continue:\n- run `nb env use {{requestedEnv}}` yourself and then re-run the command, or\n- re-run the same command with `--env {{requestedEnv}} --yes` to confirm this one-off cross-env operation."
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
"license": {
|
|
165
|
+
"activate": {
|
|
166
|
+
"interactive": {
|
|
167
|
+
"notice": {
|
|
168
|
+
"hostnameLabel": "❯ Hostname",
|
|
169
|
+
"instanceIdLabel": "❯ Instance ID",
|
|
170
|
+
"copyHintWithHostname": "Copy this hostname and instance ID when checking or activating the license key.",
|
|
171
|
+
"copyHintWithoutHostname": "Copy this instance ID when checking or activating the license key."
|
|
172
|
+
},
|
|
173
|
+
"prompts": {
|
|
174
|
+
"provideMethod": {
|
|
175
|
+
"message": "How do you want to provide the license key?",
|
|
176
|
+
"keyOption": "Paste the license key",
|
|
177
|
+
"fileOption": "Read the key from a file"
|
|
178
|
+
},
|
|
179
|
+
"key": {
|
|
180
|
+
"message": "License key",
|
|
181
|
+
"transformer": "Entered {{count}} chars",
|
|
182
|
+
"required": "License key is required."
|
|
183
|
+
},
|
|
184
|
+
"keyFile": {
|
|
185
|
+
"message": "Path to the license key file",
|
|
186
|
+
"required": "License key file path is required."
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
"errors": {
|
|
191
|
+
"provideKeyOrKeyFile": "Provide --key or --key-file to continue.",
|
|
192
|
+
"emptyInput": "License key input was empty.",
|
|
193
|
+
"activationFailed": "Failed to activate the license for env \"{{envName}}\": {{reason}}.",
|
|
194
|
+
"reasons": {
|
|
195
|
+
"keyStatus": "license key is {{status}}",
|
|
196
|
+
"envMismatch": "license key does not match the current instance environment",
|
|
197
|
+
"domainMismatch": "license key does not match the current app domain",
|
|
198
|
+
"licenseStatus": "license status is {{status}}",
|
|
199
|
+
"validationFailed": "license validation failed"
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
"messages": {
|
|
203
|
+
"activated": "Activated the license for env \"{{envName}}\".",
|
|
204
|
+
"savedLicenseKey": "Saved license key at {{licenseKeyPath}}"
|
|
205
|
+
}
|
|
206
|
+
}
|
|
121
207
|
},
|
|
122
208
|
"download": {
|
|
123
209
|
"failures": {
|
|
@@ -236,14 +322,18 @@
|
|
|
236
322
|
"lang": {
|
|
237
323
|
"message": "Which language would you like to use?"
|
|
238
324
|
},
|
|
239
|
-
"
|
|
240
|
-
"message": "Where should this app be stored?",
|
|
241
|
-
"placeholder": "./<env>/
|
|
325
|
+
"appPath": {
|
|
326
|
+
"message": "Where should this app be stored? (relative to {{root}})",
|
|
327
|
+
"placeholder": "./<env>/"
|
|
242
328
|
},
|
|
243
329
|
"appPort": {
|
|
244
330
|
"message": "Which port should this app use?",
|
|
245
331
|
"placeholder": "13000"
|
|
246
332
|
},
|
|
333
|
+
"appPublicPath": {
|
|
334
|
+
"message": "What is the app subpath? (for example, /nocobase/)",
|
|
335
|
+
"placeholder": "/ or /nocobase/"
|
|
336
|
+
},
|
|
247
337
|
"storagePath": {
|
|
248
338
|
"message": "Where should uploads and local files be stored?",
|
|
249
339
|
"placeholder": "./<env>/storage/"
|
|
@@ -308,7 +398,7 @@
|
|
|
308
398
|
"envExists": "Env \"{{envName}}\" already exists. Choose another env name."
|
|
309
399
|
},
|
|
310
400
|
"messages": {
|
|
311
|
-
"title": "Set
|
|
401
|
+
"title": "Set up NocoBase for coding agents",
|
|
312
402
|
"appNameRequiredWhenSkipped": "Env name is required when prompts are skipped.",
|
|
313
403
|
"appNameEnvHelp": "Use `nb init --yes --env <envName>` to continue.",
|
|
314
404
|
"resumeEnvRequired": "Env name is required when resuming setup.",
|
|
@@ -325,10 +415,14 @@
|
|
|
325
415
|
"message": "What should this environment use for `--env`?",
|
|
326
416
|
"placeholder": "local"
|
|
327
417
|
},
|
|
328
|
-
"
|
|
329
|
-
"message": "
|
|
330
|
-
"
|
|
331
|
-
"
|
|
418
|
+
"setupMode": {
|
|
419
|
+
"message": "How would you like to set up this environment?",
|
|
420
|
+
"installNewLabel": "Install a new app",
|
|
421
|
+
"installNewHint": "Install a brand-new app from scratch. Best for first-time setup, evaluation, or a fresh local environment.",
|
|
422
|
+
"manageLocalLabel": "Manage an app already on this machine",
|
|
423
|
+
"manageLocalHint": "Bring an app on this machine under nb management so install, upgrade, and startup can be handled in one place. During takeover, nb will re-download the app source or image and upgrade the app; storage will be created automatically when needed.",
|
|
424
|
+
"connectRemoteLabel": "Connect a remote app",
|
|
425
|
+
"connectRemoteHint": "Save only the remote app connection. Nothing will be installed or taken over on this machine."
|
|
332
426
|
},
|
|
333
427
|
"installSkills": {
|
|
334
428
|
"message": "Install NocoBase AI coding skills (nocobase/skills)?"
|
|
@@ -342,24 +436,24 @@
|
|
|
342
436
|
}
|
|
343
437
|
},
|
|
344
438
|
"webUi": {
|
|
345
|
-
"pageTitle": "Set
|
|
346
|
-
"documentHeading": "Set
|
|
347
|
-
"documentHint": "
|
|
439
|
+
"pageTitle": "Set up NocoBase for coding agents",
|
|
440
|
+
"documentHeading": "Set up NocoBase for coding agents",
|
|
441
|
+
"documentHint": "Install a new app, manage one that already exists on this machine, or connect a remote app so coding agents can access and work with NocoBase.",
|
|
348
442
|
"gettingStarted": {
|
|
349
443
|
"title": "Getting started",
|
|
350
|
-
"description": "Choose whether to
|
|
444
|
+
"description": "Choose whether to install a new app, manage a local app, or connect a remote app."
|
|
351
445
|
},
|
|
352
446
|
"connectExistingApp": {
|
|
353
|
-
"title": "
|
|
354
|
-
"description": "
|
|
447
|
+
"title": "Connection & authentication",
|
|
448
|
+
"description": "Enter the app access URL and choose an authentication method."
|
|
355
449
|
},
|
|
356
450
|
"createNewApp": {
|
|
357
|
-
"title": "
|
|
358
|
-
"description": "Set app basics and
|
|
451
|
+
"title": "App environment",
|
|
452
|
+
"description": "Set the app basics, storage location, and runtime port."
|
|
359
453
|
},
|
|
360
454
|
"downloadAppFiles": {
|
|
361
|
-
"title": "
|
|
362
|
-
"description": "Choose how to get the app
|
|
455
|
+
"title": "App source and version",
|
|
456
|
+
"description": "Choose how to get the app and which source and version to use."
|
|
363
457
|
},
|
|
364
458
|
"configureDatabase": {
|
|
365
459
|
"title": "Configure the database",
|
|
@@ -370,6 +464,12 @@
|
|
|
370
464
|
"description": "Set up the first admin."
|
|
371
465
|
}
|
|
372
466
|
}
|
|
467
|
+
},
|
|
468
|
+
"env": {
|
|
469
|
+
"messages": {
|
|
470
|
+
"noEnvsConfigured": "No envs configured.",
|
|
471
|
+
"noEnvsConfiguredHelp": "Run `nb init --ui` to create one first."
|
|
472
|
+
}
|
|
373
473
|
}
|
|
374
474
|
},
|
|
375
475
|
"apiCommandCompat": {
|
package/dist/locale/zh-CN.json
CHANGED
|
@@ -63,6 +63,9 @@
|
|
|
63
63
|
"envKey": {
|
|
64
64
|
"invalid": "仅支持字母和数字。"
|
|
65
65
|
},
|
|
66
|
+
"appPublicPath": {
|
|
67
|
+
"invalid": "请输入 /,或类似 /nocobase/、/foo-bar/baz_2/ 这样的路径。每个路径段仅支持字母、数字、中划线和下划线。"
|
|
68
|
+
},
|
|
66
69
|
"tcpPort": {
|
|
67
70
|
"invalid": "请输入 1 到 65535 之间的有效 TCP 端口,例如 {{example}}。",
|
|
68
71
|
"allocateFailed": "分配可用 TCP 端口失败。",
|
|
@@ -96,10 +99,10 @@
|
|
|
96
99
|
"placeholder": "https://demo.example.com/api 或 https://demo.example.com/api/__app/<subapp>"
|
|
97
100
|
},
|
|
98
101
|
"authType": {
|
|
99
|
-
"message": "
|
|
100
|
-
"basicLabel": "Basic
|
|
102
|
+
"message": "你想使用哪种认证方式?",
|
|
103
|
+
"basicLabel": "Basic 认证(用户名 + 密码)",
|
|
101
104
|
"basicHint": "保存后会用用户名和密码换取 Token",
|
|
102
|
-
"oauthLabel": "OAuth
|
|
105
|
+
"oauthLabel": "OAuth(浏览器认证)",
|
|
103
106
|
"oauthHint": "保存后会自动执行 nb env auth",
|
|
104
107
|
"tokenLabel": "API Token / API Key"
|
|
105
108
|
},
|
|
@@ -116,8 +119,91 @@
|
|
|
116
119
|
}
|
|
117
120
|
}
|
|
118
121
|
},
|
|
122
|
+
"envProxy": {
|
|
123
|
+
"messages": {
|
|
124
|
+
"generating": "正在为 env \"{{envName}}\" 生成代理配置...",
|
|
125
|
+
"printed": "已输出 env \"{{envName}}\" 的代理配置。",
|
|
126
|
+
"saved": "已将 env \"{{envName}}\" 的生成代理配置保存到 {{outputPath}}。",
|
|
127
|
+
"savedWithAppEntryCreated": "已将 env \"{{envName}}\" 的生成代理配置保存到 {{outputPath}},并创建可编辑的入口配置 {{appConfigPath}}。",
|
|
128
|
+
"savedWithAppEntryMigrated": "已将 env \"{{envName}}\" 的生成代理配置保存到 {{outputPath}},并将入口配置迁移为 {{appConfigPath}}。",
|
|
129
|
+
"savedNginxBundleCreated": "已将 env \"{{envName}}\" 的 nginx 代理文件保存到 {{entryDir}},并创建可编辑的入口配置 {{appConfigPath}}。",
|
|
130
|
+
"savedNginxBundleUpdated": "已将 env \"{{envName}}\" 的 nginx 代理文件保存到 {{entryDir}},并刷新可编辑的入口配置 {{appConfigPath}}。",
|
|
131
|
+
"savedCaddyBundleCreated": "已将 env \"{{envName}}\" 的 caddy 代理文件保存到 {{entryDir}},并创建可编辑的入口配置 {{appConfigPath}}。",
|
|
132
|
+
"savedCaddyBundleMigrated": "已将 env \"{{envName}}\" 的 caddy 代理文件保存到 {{entryDir}},并将入口配置迁移为 {{appConfigPath}}。",
|
|
133
|
+
"savedCaddyBundleUpdated": "已将 env \"{{envName}}\" 的 caddy 代理文件保存到 {{entryDir}},并刷新可编辑的入口配置 {{appConfigPath}}。",
|
|
134
|
+
"failed": "为 env \"{{envName}}\" 生成代理配置失败。",
|
|
135
|
+
"installingProvider": "正在将共享代理配置安装到 {{provider}}...",
|
|
136
|
+
"providerInstalled": "已将共享代理配置安装到 {{provider}} 主配置 {{configPath}}。",
|
|
137
|
+
"providerAlreadyInstalled": "共享代理配置已存在于 {{provider}} 主配置 {{configPath}} 中。",
|
|
138
|
+
"installProviderFailed": "将共享代理配置安装到 {{provider}} 失败。",
|
|
139
|
+
"reloadingProvider": "正在校验并重载 {{provider}}...",
|
|
140
|
+
"providerReloaded": "已校验并重载 {{provider}}。",
|
|
141
|
+
"reloadProviderFailed": "校验并重载 {{provider}} 失败。"
|
|
142
|
+
},
|
|
143
|
+
"errors": {
|
|
144
|
+
"httpEnvUnsupported": "无法在当前机器上为 \"{{envName}}\" 生成代理配置,因为这个 env 只有 API 连接。",
|
|
145
|
+
"sshEnvUnsupported": "暂时无法为 \"{{envName}}\" 生成代理配置,因为 SSH env 还没有实现。",
|
|
146
|
+
"invalidProxyPort": "代理入口端口 \"{{port}}\" 无效。请使用 1 到 65535 之间的整数。",
|
|
147
|
+
"missingAppPort": "env \"{{envName}}\" 缺少 appPort。请先保存或更新应用端口后再生成代理配置。",
|
|
148
|
+
"missingVersion": "无法确定 env \"{{envName}}\" 的应用版本。请先运行 `nb env update {{envName}}`,然后再试一次。",
|
|
149
|
+
"appEntryMissingInclude": "可编辑入口配置 {{appConfigPath}} 没有引用 {{generatedConfigPath}}。请把托管的 generated 配置引用补回入口配置中,然后重新执行该命令。",
|
|
150
|
+
"nginxOutputUnsupported": "nginx provider 不支持 `--output`。它会把 `app.conf`、`public/index-v1.html`、`public/index-v2.html` 和 `nocobase.conf` 写入 `~/.nocobase/proxy/nginx/<env>/`。",
|
|
151
|
+
"caddyOutputUnsupported": "caddy provider 不支持 `--output`。它会把 `app.caddy`、`generated.caddy`、`public/index-v1.html`、`public/index-v2.html` 和 `nocobase.caddy` 写入 `~/.nocobase/proxy/caddy/<env>/`。",
|
|
152
|
+
"nginxAppEntryMissingManagedBlock": "可编辑的 nginx 入口配置 {{appConfigPath}} 不包含 NocoBase 的托管区块。请恢复这个托管区块,或删除该文件后重新执行 `nb env proxy`。"
|
|
153
|
+
}
|
|
154
|
+
},
|
|
119
155
|
"shared": {
|
|
120
|
-
"missingCommand": "无法执行 `{{action}}`,因为找不到 {{displayName}} 可执行文件。请先安装 {{displayName}},或更新 `nb config set {{configKey}} <path>` 后重试。"
|
|
156
|
+
"missingCommand": "无法执行 `{{action}}`,因为找不到 {{displayName}} 可执行文件。请先安装 {{displayName}},或更新 `nb config set {{configKey}} <path>` 后重试。",
|
|
157
|
+
"dockerDaemonUnavailable": "无法执行 `{{action}}`,因为 Docker 已安装,但 Docker daemon 尚未运行。请先启动 Docker Desktop 或 Docker daemon 服务,然后重试。详情:{{details}}",
|
|
158
|
+
"targetEnv": "正在使用 env \"{{envName}}\"。",
|
|
159
|
+
"crossEnv": {
|
|
160
|
+
"prompt": "当前 env 是 \"{{currentEnv}}\",但该命令通过 --env 指向了 \"{{requestedEnv}}\"。要在不切换当前 env 的情况下继续吗?",
|
|
161
|
+
"refusal": "拒绝对 env \"{{requestedEnv}}\" 执行该命令,因为当前 env 是 \"{{currentEnv}}\",且当前 agent 会话无法进行交互确认。\n\n出于安全考虑,agent 不会自动切换 env,也不会替你自动补上 --yes。\n\n如果要继续:\n- 请先自行执行 `nb env use {{requestedEnv}}`,然后重新运行该命令,或\n- 使用相同命令并追加 `--env {{requestedEnv}} --yes`,以确认这是一次性的跨 env 操作。"
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
"license": {
|
|
165
|
+
"activate": {
|
|
166
|
+
"interactive": {
|
|
167
|
+
"notice": {
|
|
168
|
+
"hostnameLabel": "❯ 主机名",
|
|
169
|
+
"instanceIdLabel": "❯ 实例 ID",
|
|
170
|
+
"copyHintWithHostname": "校验或激活 license key 时,请复制这个主机名和实例 ID。",
|
|
171
|
+
"copyHintWithoutHostname": "校验或激活 license key 时,请复制这个实例 ID。"
|
|
172
|
+
},
|
|
173
|
+
"prompts": {
|
|
174
|
+
"provideMethod": {
|
|
175
|
+
"message": "你想通过哪种方式提供 license key?",
|
|
176
|
+
"keyOption": "直接粘贴 license key",
|
|
177
|
+
"fileOption": "从文件读取 key"
|
|
178
|
+
},
|
|
179
|
+
"key": {
|
|
180
|
+
"message": "License Key",
|
|
181
|
+
"transformer": "已输入 {{count}} 个字符",
|
|
182
|
+
"required": "必须提供 license key。"
|
|
183
|
+
},
|
|
184
|
+
"keyFile": {
|
|
185
|
+
"message": "license key 文件路径",
|
|
186
|
+
"required": "必须提供 license key 文件路径。"
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
"errors": {
|
|
191
|
+
"provideKeyOrKeyFile": "请通过 --key 或 --key-file 继续。",
|
|
192
|
+
"emptyInput": "license key 输入为空。",
|
|
193
|
+
"activationFailed": "为 env \"{{envName}}\" 激活 license 失败:{{reason}}。",
|
|
194
|
+
"reasons": {
|
|
195
|
+
"keyStatus": "license key 状态为 {{status}}",
|
|
196
|
+
"envMismatch": "license key 与当前实例环境不匹配",
|
|
197
|
+
"domainMismatch": "license key 与当前应用域名不匹配",
|
|
198
|
+
"licenseStatus": "license 状态为 {{status}}",
|
|
199
|
+
"validationFailed": "license 校验失败"
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
"messages": {
|
|
203
|
+
"activated": "已为 env \"{{envName}}\" 激活 license。",
|
|
204
|
+
"savedLicenseKey": "license key 已保存到 {{licenseKeyPath}}"
|
|
205
|
+
}
|
|
206
|
+
}
|
|
121
207
|
},
|
|
122
208
|
"download": {
|
|
123
209
|
"failures": {
|
|
@@ -236,14 +322,18 @@
|
|
|
236
322
|
"lang": {
|
|
237
323
|
"message": "你想使用哪种语言?"
|
|
238
324
|
},
|
|
239
|
-
"
|
|
240
|
-
"message": "
|
|
241
|
-
"placeholder": "./<env>/
|
|
325
|
+
"appPath": {
|
|
326
|
+
"message": "应用要放到哪里?(相对路径基于 {{root}})",
|
|
327
|
+
"placeholder": "./<env>/"
|
|
242
328
|
},
|
|
243
329
|
"appPort": {
|
|
244
330
|
"message": "应用要使用哪个端口?",
|
|
245
331
|
"placeholder": "13000"
|
|
246
332
|
},
|
|
333
|
+
"appPublicPath": {
|
|
334
|
+
"message": "应用的子路径是什么?(例如 /nocobase/)",
|
|
335
|
+
"placeholder": "/ 或 /nocobase/"
|
|
336
|
+
},
|
|
247
337
|
"storagePath": {
|
|
248
338
|
"message": "上传文件和本地存储目录要放到哪里?",
|
|
249
339
|
"placeholder": "./<env>/storage/"
|
|
@@ -325,10 +415,14 @@
|
|
|
325
415
|
"message": "这个环境要使用什么 `--env` 标识?",
|
|
326
416
|
"placeholder": "local"
|
|
327
417
|
},
|
|
328
|
-
"
|
|
329
|
-
"message": "
|
|
330
|
-
"
|
|
331
|
-
"
|
|
418
|
+
"setupMode": {
|
|
419
|
+
"message": "你想用哪种方式配置这个环境?",
|
|
420
|
+
"installNewLabel": "新安装",
|
|
421
|
+
"installNewHint": "从零安装一个新的应用,适合首次部署、试用或新建本地开发环境。",
|
|
422
|
+
"manageLocalLabel": "本机接管",
|
|
423
|
+
"manageLocalHint": "将本机已有应用纳入 nb 管理,后续可统一执行安装、升级和启动等操作。接管过程中会重新下载应用代码或镜像并升级应用,storage 会在需要时自动创建。",
|
|
424
|
+
"connectRemoteLabel": "远程连接",
|
|
425
|
+
"connectRemoteHint": "只保存远程应用的连接信息,不在本机安装或接管应用。"
|
|
332
426
|
},
|
|
333
427
|
"installSkills": {
|
|
334
428
|
"message": "是否安装 NocoBase AI coding skills(nocobase/skills)?"
|
|
@@ -344,22 +438,22 @@
|
|
|
344
438
|
"webUi": {
|
|
345
439
|
"pageTitle": "配置供 Coding Agents 使用的 NocoBase",
|
|
346
440
|
"documentHeading": "配置供 Coding Agents 使用的 NocoBase",
|
|
347
|
-
"documentHint": "
|
|
441
|
+
"documentHint": "安装一个新的应用、接管本机已有应用,或连接远程应用,让 Coding Agents 可以在当前工作区中访问和操作 NocoBase。",
|
|
348
442
|
"gettingStarted": {
|
|
349
443
|
"title": "开始设置",
|
|
350
|
-
"description": "
|
|
444
|
+
"description": "选择新安装、本机接管,或远程连接。"
|
|
351
445
|
},
|
|
352
446
|
"connectExistingApp": {
|
|
353
|
-
"title": "
|
|
354
|
-
"description": "
|
|
447
|
+
"title": "连接与认证",
|
|
448
|
+
"description": "填写应用访问地址并选择认证方式。"
|
|
355
449
|
},
|
|
356
450
|
"createNewApp": {
|
|
357
|
-
"title": "
|
|
358
|
-
"description": "
|
|
451
|
+
"title": "应用环境信息",
|
|
452
|
+
"description": "设置应用的基础信息、存储位置和运行端口。"
|
|
359
453
|
},
|
|
360
454
|
"downloadAppFiles": {
|
|
361
|
-
"title": "
|
|
362
|
-
"description": "
|
|
455
|
+
"title": "应用来源和版本",
|
|
456
|
+
"description": "选择应用的获取方式,以及要使用的来源和版本。"
|
|
363
457
|
},
|
|
364
458
|
"configureDatabase": {
|
|
365
459
|
"title": "配置数据库",
|
|
@@ -370,6 +464,12 @@
|
|
|
370
464
|
"description": "设置第一个管理员账号。"
|
|
371
465
|
}
|
|
372
466
|
}
|
|
467
|
+
},
|
|
468
|
+
"env": {
|
|
469
|
+
"messages": {
|
|
470
|
+
"noEnvsConfigured": "尚未配置任何 env。",
|
|
471
|
+
"noEnvsConfiguredHelp": "请先运行 `nb init --ui` 创建一个。"
|
|
472
|
+
}
|
|
373
473
|
}
|
|
374
474
|
},
|
|
375
475
|
"apiCommandCompat": {
|