@nocobase/cli 2.2.0-alpha.5 → 2.2.0-alpha.7
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/snippets/proxy-location.conf +1 -0
- package/dist/commands/app/start.js +4 -1
- package/dist/commands/env/info.js +11 -1
- package/dist/commands/init.js +11 -1
- package/dist/commands/install.js +27 -95
- package/dist/commands/proxy/caddy/generate.js +12 -4
- package/dist/commands/proxy/nginx/generate.js +12 -4
- package/dist/commands/source/download.js +2 -2
- package/dist/lib/auth-store.js +61 -0
- package/dist/lib/cli-config.js +3 -1
- package/dist/lib/env-config.js +5 -0
- package/dist/lib/env-proxy-config.js +48 -0
- package/dist/lib/env-proxy.js +10 -0
- package/dist/lib/prompt-catalog-terminal.js +32 -19
- package/dist/lib/prompt-web-ui.js +13 -2
- package/dist/lib/proxy-caddy.js +53 -7
- package/dist/lib/proxy-nginx.js +53 -7
- package/dist/locale/en-US.json +37 -37
- package/dist/locale/zh-CN.json +37 -37
- package/package.json +2 -2
|
@@ -37,6 +37,9 @@ function buildLicenseSyncArgv(envName, options) {
|
|
|
37
37
|
}
|
|
38
38
|
function resolveHookCommand(value) {
|
|
39
39
|
const text = String(value ?? '').trim();
|
|
40
|
+
if (text === 'init') {
|
|
41
|
+
return text;
|
|
42
|
+
}
|
|
40
43
|
if (text === 'app:restart' || text === 'app:upgrade') {
|
|
41
44
|
return text;
|
|
42
45
|
}
|
|
@@ -225,7 +228,7 @@ export default class AppStart extends Command {
|
|
|
225
228
|
}),
|
|
226
229
|
'hook-command': Flags.string({
|
|
227
230
|
hidden: true,
|
|
228
|
-
options: ['app:start', 'app:restart', 'app:upgrade'],
|
|
231
|
+
options: ['init', 'app:start', 'app:restart', 'app:upgrade'],
|
|
229
232
|
}),
|
|
230
233
|
};
|
|
231
234
|
async run() {
|
|
@@ -170,8 +170,13 @@ export default class EnvInfo extends Command {
|
|
|
170
170
|
'auth.accessToken': authGroup.accessToken,
|
|
171
171
|
'auth.refreshToken': authGroup.refreshToken,
|
|
172
172
|
};
|
|
173
|
+
const envGroup = {
|
|
174
|
+
name: runtime.envName,
|
|
175
|
+
kind: runtime.kind,
|
|
176
|
+
};
|
|
173
177
|
const output = {
|
|
174
178
|
ok: true,
|
|
179
|
+
name: runtime.envName,
|
|
175
180
|
env: runtime.envName,
|
|
176
181
|
kind: runtime.kind,
|
|
177
182
|
app: serializeGroup(appGroup),
|
|
@@ -197,6 +202,11 @@ export default class EnvInfo extends Command {
|
|
|
197
202
|
this.log(JSON.stringify(output, null, 2));
|
|
198
203
|
return;
|
|
199
204
|
}
|
|
200
|
-
this.log([
|
|
205
|
+
this.log([
|
|
206
|
+
createGroupTable('Env', envGroup),
|
|
207
|
+
createGroupTable('App', appGroup),
|
|
208
|
+
createGroupTable('DB', dbGroup),
|
|
209
|
+
createGroupTable('API', apiGroup),
|
|
210
|
+
].join('\n\n'));
|
|
201
211
|
}
|
|
202
212
|
}
|
package/dist/commands/init.js
CHANGED
|
@@ -16,7 +16,8 @@ import { getEnv, upsertEnv } from "../lib/auth-store.js";
|
|
|
16
16
|
import { runPromptCatalog, } from "../lib/prompt-catalog.js";
|
|
17
17
|
import { applyCliLocale, localeText, translateCli } from "../lib/cli-locale.js";
|
|
18
18
|
import { resolveConfiguredEnvPath, resolveDefaultConfigScope, resolveEnvRelativePath } from '../lib/cli-home.js';
|
|
19
|
-
import { resolveDefaultApiHost, resolveDefaultUiHost } from '../lib/cli-config.js';
|
|
19
|
+
import { getCliConfigValue, resolveDefaultApiHost, resolveDefaultUiHost } from '../lib/cli-config.js';
|
|
20
|
+
import { resolveOfficialDockerRegistry } from '../lib/docker-image.js';
|
|
20
21
|
import { areConfiguredPathsEquivalent, deriveConfiguredSourcePath, deriveConfiguredStoragePath, inferConfiguredAppPathFromLegacyConfig, } from '../lib/env-paths.js';
|
|
21
22
|
import { formatMissingManagedAppEnvMessage } from '../lib/app-runtime.js';
|
|
22
23
|
import { runPromptCatalogWebUI } from "../lib/prompt-web-ui.js";
|
|
@@ -697,6 +698,12 @@ Prompt modes:
|
|
|
697
698
|
if (flags.yes && !Object.prototype.hasOwnProperty.call(downloadSeed, 'source')) {
|
|
698
699
|
downloadSeed.source = 'docker';
|
|
699
700
|
}
|
|
701
|
+
const builtinDbImageRegistry = String(presetValues.dockerRegistry ?? '').trim() ||
|
|
702
|
+
resolveOfficialDockerRegistry(await getCliConfigValue('nb-image-registry'));
|
|
703
|
+
if (!Object.prototype.hasOwnProperty.call(presetValues, 'dockerRegistry')) {
|
|
704
|
+
out.dockerRegistry = builtinDbImageRegistry;
|
|
705
|
+
}
|
|
706
|
+
out.builtinDbImageRegistry = builtinDbImageRegistry;
|
|
700
707
|
const dbInitial = await Install.buildDbPromptInitialValues({
|
|
701
708
|
flags,
|
|
702
709
|
downloadResults: downloadSeed,
|
|
@@ -704,6 +711,9 @@ Prompt modes:
|
|
|
704
711
|
warnOnPortFallback: false,
|
|
705
712
|
});
|
|
706
713
|
for (const [key, value] of Object.entries(dbInitial)) {
|
|
714
|
+
if (key === 'builtinDbImage') {
|
|
715
|
+
continue;
|
|
716
|
+
}
|
|
707
717
|
if (!Object.prototype.hasOwnProperty.call(presetValues, key)) {
|
|
708
718
|
out[key] = value;
|
|
709
719
|
}
|
package/dist/commands/install.js
CHANGED
|
@@ -180,6 +180,10 @@ function defaultBuiltinDbImageForDialect(value, options) {
|
|
|
180
180
|
function defaultDbDatabaseForDialect(value) {
|
|
181
181
|
return String(value ?? '').trim() === 'kingbase' ? 'kingbase' : DEFAULT_INSTALL_DB_DATABASE;
|
|
182
182
|
}
|
|
183
|
+
function supportsDbSchemaPrompt(value) {
|
|
184
|
+
const dialect = String(value ?? '').trim();
|
|
185
|
+
return dialect === 'postgres' || dialect === 'kingbase';
|
|
186
|
+
}
|
|
183
187
|
function defaultDbHostForBuiltinDb(values) {
|
|
184
188
|
return values.builtinDb ? DEFAULT_INSTALL_BUILTIN_DB_HOST : DEFAULT_INSTALL_DB_HOST;
|
|
185
189
|
}
|
|
@@ -536,7 +540,9 @@ export default class Install extends Command {
|
|
|
536
540
|
type: 'text',
|
|
537
541
|
message: installText('prompts.builtinDbImage.message'),
|
|
538
542
|
placeholder: installText('prompts.builtinDbImage.placeholder'),
|
|
539
|
-
initialValue: (values) => defaultBuiltinDbImageForDialect(values.dbDialect
|
|
543
|
+
initialValue: (values) => defaultBuiltinDbImageForDialect(values.dbDialect, {
|
|
544
|
+
registry: String(values.builtinDbImageRegistry ?? '').trim() || undefined,
|
|
545
|
+
}),
|
|
540
546
|
hidden: (values) => !values.builtinDb || !supportsBuiltinDbDialect(values.dbDialect),
|
|
541
547
|
required: true,
|
|
542
548
|
},
|
|
@@ -586,7 +592,7 @@ export default class Install extends Command {
|
|
|
586
592
|
type: 'text',
|
|
587
593
|
message: installText('prompts.dbSchema.message'),
|
|
588
594
|
placeholder: installText('prompts.dbSchema.placeholder'),
|
|
589
|
-
hidden: (values) =>
|
|
595
|
+
hidden: (values) => !supportsDbSchemaPrompt(values.dbDialect),
|
|
590
596
|
},
|
|
591
597
|
dbTablePrefix: {
|
|
592
598
|
type: 'text',
|
|
@@ -2253,6 +2259,13 @@ export default class Install extends Command {
|
|
|
2253
2259
|
}
|
|
2254
2260
|
await this.config.runCommand('env:update', [params.envName]);
|
|
2255
2261
|
}
|
|
2262
|
+
buildAppStartArgv(params) {
|
|
2263
|
+
const argv = ['--env', params.envName, '--yes', '--no-sync-licensed-plugins', '--hook-command', 'init'];
|
|
2264
|
+
if (params.verbose) {
|
|
2265
|
+
argv.push('--verbose');
|
|
2266
|
+
}
|
|
2267
|
+
return argv;
|
|
2268
|
+
}
|
|
2256
2269
|
async runInstallHookIfNeeded(params) {
|
|
2257
2270
|
const appPath = Install.resolveAbsoluteAppPath(params.envName, params.appResults);
|
|
2258
2271
|
const savedHookScript = Install.toOptionalPromptString(params.appResults.hookScript);
|
|
@@ -2497,7 +2510,6 @@ export default class Install extends Command {
|
|
|
2497
2510
|
const parsed = {
|
|
2498
2511
|
...flags,
|
|
2499
2512
|
};
|
|
2500
|
-
const defaultApiHost = await resolveDefaultApiHost();
|
|
2501
2513
|
if (parsed['skip-auth'] && (parsed['access-token'] !== undefined || parsed.token !== undefined)) {
|
|
2502
2514
|
this.error('--skip-auth cannot be used with --access-token or --token.');
|
|
2503
2515
|
}
|
|
@@ -2577,8 +2589,7 @@ export default class Install extends Command {
|
|
|
2577
2589
|
dbResults.dbUser = builtinDbPlan.dbUser;
|
|
2578
2590
|
dbResults.dbPassword = builtinDbPlan.dbPassword;
|
|
2579
2591
|
}
|
|
2580
|
-
let
|
|
2581
|
-
let localAppPlan;
|
|
2592
|
+
let shouldStartApp = false;
|
|
2582
2593
|
if (source === 'docker' || source === 'npm' || source === 'git') {
|
|
2583
2594
|
this.logStage('Preparing application');
|
|
2584
2595
|
if (source === 'docker') {
|
|
@@ -2590,111 +2601,28 @@ export default class Install extends Command {
|
|
|
2590
2601
|
printInfo('Application image ready.');
|
|
2591
2602
|
}
|
|
2592
2603
|
if (!parsed['prepare-only']) {
|
|
2593
|
-
|
|
2594
|
-
hookName: 'beforeAppInstall',
|
|
2595
|
-
envName,
|
|
2596
|
-
source,
|
|
2597
|
-
appResults,
|
|
2598
|
-
downloadResults,
|
|
2599
|
-
dbResults,
|
|
2600
|
-
rootResults,
|
|
2601
|
-
envAddResults,
|
|
2602
|
-
defaultApiHost,
|
|
2603
|
-
});
|
|
2604
|
-
dockerAppPlan = await this.installDockerApp({
|
|
2605
|
-
envName,
|
|
2606
|
-
dockerNetworkName,
|
|
2607
|
-
dockerContainerPrefix,
|
|
2608
|
-
appResults,
|
|
2609
|
-
downloadResults,
|
|
2610
|
-
dbResults,
|
|
2611
|
-
rootResults,
|
|
2612
|
-
builtinDbPlan,
|
|
2613
|
-
force: parsed.force,
|
|
2614
|
-
commandStdio,
|
|
2615
|
-
});
|
|
2616
|
-
appResults.appKey = dockerAppPlan.appKey;
|
|
2617
|
-
appResults.timeZone = dockerAppPlan.timeZone;
|
|
2604
|
+
shouldStartApp = true;
|
|
2618
2605
|
}
|
|
2619
2606
|
}
|
|
2620
2607
|
else if (source === 'npm' || source === 'git') {
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
? Install.resolveLocalProjectRoot({
|
|
2624
|
-
envName,
|
|
2625
|
-
appResults,
|
|
2626
|
-
downloadResults,
|
|
2627
|
-
})
|
|
2628
|
-
: await this.downloadLocalApp({
|
|
2608
|
+
if (!parsed['skip-download'] && !parsed['prepare-only']) {
|
|
2609
|
+
await this.downloadLocalApp({
|
|
2629
2610
|
envName,
|
|
2630
2611
|
appResults,
|
|
2631
2612
|
downloadResults,
|
|
2632
2613
|
verbose: parsed.verbose,
|
|
2633
2614
|
});
|
|
2634
|
-
if (!parsed['skip-download'] && !parsed['prepare-only']) {
|
|
2635
2615
|
printInfo('Application files ready.');
|
|
2636
2616
|
}
|
|
2637
2617
|
if (!parsed['prepare-only']) {
|
|
2638
|
-
|
|
2639
|
-
hookName: 'beforeAppInstall',
|
|
2640
|
-
envName,
|
|
2641
|
-
source,
|
|
2642
|
-
appResults,
|
|
2643
|
-
downloadResults,
|
|
2644
|
-
dbResults,
|
|
2645
|
-
rootResults,
|
|
2646
|
-
envAddResults,
|
|
2647
|
-
projectRoot,
|
|
2648
|
-
defaultApiHost,
|
|
2649
|
-
});
|
|
2650
|
-
localAppPlan = await this.startLocalApp({
|
|
2651
|
-
envName,
|
|
2652
|
-
source: localSource,
|
|
2653
|
-
projectRoot,
|
|
2654
|
-
appResults,
|
|
2655
|
-
dbResults,
|
|
2656
|
-
rootResults,
|
|
2657
|
-
commandStdio,
|
|
2658
|
-
});
|
|
2659
|
-
appResults.appKey = localAppPlan.appKey;
|
|
2660
|
-
appResults.timeZone = localAppPlan.timeZone;
|
|
2618
|
+
shouldStartApp = true;
|
|
2661
2619
|
}
|
|
2662
2620
|
}
|
|
2663
2621
|
}
|
|
2664
2622
|
else {
|
|
2665
2623
|
this.logDetail('Skipped app download and install.');
|
|
2666
2624
|
}
|
|
2667
|
-
if (
|
|
2668
|
-
this.logStage('Starting NocoBase');
|
|
2669
|
-
await this.waitForAppHealthCheck(Install.resolveApiBaseUrl({
|
|
2670
|
-
appResults,
|
|
2671
|
-
envAddResults,
|
|
2672
|
-
defaultApiHost,
|
|
2673
|
-
}), {
|
|
2674
|
-
containerName: dockerAppPlan?.containerName,
|
|
2675
|
-
verbose: parsed.verbose,
|
|
2676
|
-
});
|
|
2677
|
-
const displayApiBaseUrl = Install.resolveApiBaseUrl({
|
|
2678
|
-
appResults,
|
|
2679
|
-
envAddResults,
|
|
2680
|
-
defaultApiHost,
|
|
2681
|
-
});
|
|
2682
|
-
printInfo(`NocoBase is ready at ${formatInstallDisplayUrl(displayApiBaseUrl)}`);
|
|
2683
|
-
appResults.setupState = 'installed';
|
|
2684
|
-
await this.runInstallHookIfNeeded({
|
|
2685
|
-
hookName: 'afterAppStart',
|
|
2686
|
-
envName,
|
|
2687
|
-
source,
|
|
2688
|
-
appResults,
|
|
2689
|
-
downloadResults,
|
|
2690
|
-
dbResults,
|
|
2691
|
-
rootResults,
|
|
2692
|
-
envAddResults,
|
|
2693
|
-
projectRoot: localAppPlan?.projectRoot,
|
|
2694
|
-
defaultApiHost,
|
|
2695
|
-
});
|
|
2696
|
-
}
|
|
2697
|
-
if (dockerAppPlan || localAppPlan || builtinDbPlan) {
|
|
2625
|
+
if (shouldStartApp || builtinDbPlan) {
|
|
2698
2626
|
await this.saveInstalledEnv({
|
|
2699
2627
|
envName,
|
|
2700
2628
|
appResults,
|
|
@@ -2704,10 +2632,14 @@ export default class Install extends Command {
|
|
|
2704
2632
|
envAddResults,
|
|
2705
2633
|
});
|
|
2706
2634
|
}
|
|
2635
|
+
if (shouldStartApp) {
|
|
2636
|
+
this.logStage('Starting NocoBase');
|
|
2637
|
+
await this.config.runCommand('app:start', this.buildAppStartArgv({ envName, verbose: parsed.verbose }));
|
|
2638
|
+
}
|
|
2707
2639
|
await this.syncInstalledEnvConnection({
|
|
2708
2640
|
envName,
|
|
2709
2641
|
envAddResults,
|
|
2710
|
-
appReady:
|
|
2642
|
+
appReady: shouldStartApp,
|
|
2711
2643
|
skipAuth: Boolean(parsed['skip-auth']),
|
|
2712
2644
|
});
|
|
2713
2645
|
if (!parsed['prepare-only']) {
|
|
@@ -2716,7 +2648,7 @@ export default class Install extends Command {
|
|
|
2716
2648
|
if (parsed['prepare-only']) {
|
|
2717
2649
|
printInfo(`Preparation complete for "${envName}". Activate the license, then run \`nb app start --env ${envName}\`.`);
|
|
2718
2650
|
}
|
|
2719
|
-
else if (!
|
|
2651
|
+
else if (!shouldStartApp) {
|
|
2720
2652
|
printInfo(`Install config for "${envName}" has been saved.`);
|
|
2721
2653
|
}
|
|
2722
2654
|
}
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { Command, Flags } from '@oclif/core';
|
|
10
10
|
import { formatMissingManagedAppEnvMessage, resolveManagedAppRuntime, } from '../../../lib/app-runtime.js';
|
|
11
|
+
import { resolveEnvProxyEntry, setEnvProxyEntry } from '../../../lib/auth-store.js';
|
|
12
|
+
import { resolveDefaultConfigScope } from '../../../lib/cli-home.js';
|
|
11
13
|
import { getCaddyProxyDriver, writeManualCaddyProxyBundle, writeCaddyProxyBundle, resolveCaddyProxyRuntimeContext, } from '../../../lib/proxy-caddy.js';
|
|
12
14
|
import { normalizeProxyListenPort } from '../../../lib/proxy-nginx.js';
|
|
13
15
|
import { announceTargetEnv, failTask, startTask, succeedTask } from '../../../lib/ui.js';
|
|
@@ -129,12 +131,18 @@ export default class ProxyCaddyGenerate extends Command {
|
|
|
129
131
|
announceTargetEnv(runtime.envName);
|
|
130
132
|
startTask(`Generating caddy proxy config for env "${runtime.envName}" with the ${driver} driver...`);
|
|
131
133
|
try {
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
134
|
+
const savedAppEntryOptions = resolveEnvProxyEntry(runtime.env.config, 'caddy');
|
|
135
|
+
const appEntryOptions = {
|
|
136
|
+
host: flags.host?.trim() || savedAppEntryOptions?.host,
|
|
137
|
+
port: normalizedPort ?? (savedAppEntryOptions?.port !== undefined ? String(savedAppEntryOptions.port) : undefined),
|
|
138
|
+
};
|
|
139
|
+
const { bundle, status } = await writeCaddyProxyBundle(runtime, appEntryOptions, runtimeContext, {
|
|
136
140
|
cdnBaseUrl: flags['cdn-base-url']?.trim() || undefined,
|
|
137
141
|
});
|
|
142
|
+
await setEnvProxyEntry(runtime.envName, 'caddy', {
|
|
143
|
+
host: appEntryOptions.host,
|
|
144
|
+
port: appEntryOptions.port ? Number(appEntryOptions.port) : undefined,
|
|
145
|
+
}, { scope: resolveDefaultConfigScope() });
|
|
138
146
|
succeedTask(status === 'created'
|
|
139
147
|
? `Saved caddy proxy files for env "${runtime.envName}" under ${bundle.entryDir}, and created app.caddy at ${bundle.appConfigPath}.`
|
|
140
148
|
: `Saved caddy proxy files for env "${runtime.envName}" under ${bundle.entryDir}, and refreshed app.caddy at ${bundle.appConfigPath}.`);
|
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { Command, Flags } from '@oclif/core';
|
|
10
10
|
import { formatMissingManagedAppEnvMessage, resolveManagedAppRuntime, } from '../../../lib/app-runtime.js';
|
|
11
|
+
import { resolveDefaultConfigScope } from '../../../lib/cli-home.js';
|
|
11
12
|
import { getNginxProxyDriver, normalizeProxyListenPort, resolveNginxProxyRuntimeContext, writeManualNginxProxyBundle, writeNginxProxyBundle, } from '../../../lib/proxy-nginx.js';
|
|
13
|
+
import { resolveEnvProxyEntry, setEnvProxyEntry } from '../../../lib/auth-store.js';
|
|
12
14
|
import { announceTargetEnv, failTask, startTask, succeedTask } from '../../../lib/ui.js';
|
|
13
15
|
export default class ProxyNginxGenerate extends Command {
|
|
14
16
|
static summary = 'Generate nginx proxy files for one managed env';
|
|
@@ -132,13 +134,19 @@ export default class ProxyNginxGenerate extends Command {
|
|
|
132
134
|
announceTargetEnv(runtime.envName);
|
|
133
135
|
startTask(`Generating nginx proxy config for env "${runtime.envName}" with the ${driver} driver...`);
|
|
134
136
|
try {
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
137
|
+
const savedAppEntryOptions = resolveEnvProxyEntry(runtime.env.config, 'nginx');
|
|
138
|
+
const appEntryOptions = {
|
|
139
|
+
host: flags.host?.trim() || savedAppEntryOptions?.host,
|
|
140
|
+
port: normalizedPort ?? (savedAppEntryOptions?.port !== undefined ? String(savedAppEntryOptions.port) : undefined),
|
|
141
|
+
};
|
|
142
|
+
const { bundle, status } = await writeNginxProxyBundle(runtime, appEntryOptions, runtimeContext, {
|
|
139
143
|
cdnBaseUrl: flags['cdn-base-url']?.trim() || undefined,
|
|
140
144
|
force: flags.force,
|
|
141
145
|
});
|
|
146
|
+
await setEnvProxyEntry(runtime.envName, 'nginx', {
|
|
147
|
+
host: appEntryOptions.host,
|
|
148
|
+
port: appEntryOptions.port ? Number(appEntryOptions.port) : undefined,
|
|
149
|
+
}, { scope: resolveDefaultConfigScope() });
|
|
142
150
|
succeedTask(status === 'created'
|
|
143
151
|
? `Saved nginx proxy files for env "${runtime.envName}" under ${bundle.entryDir}, and created editable app entry config at ${bundle.appConfigPath}.`
|
|
144
152
|
: `Saved nginx proxy files for env "${runtime.envName}" under ${bundle.entryDir}, and refreshed editable app entry config at ${bundle.appConfigPath}.`);
|
|
@@ -345,8 +345,8 @@ export default class SourceDownload extends Command {
|
|
|
345
345
|
label: downloadText('prompts.dockerPlatform.autoLabel'),
|
|
346
346
|
hint: downloadText('prompts.dockerPlatform.autoHint'),
|
|
347
347
|
},
|
|
348
|
-
{ value: 'linux/amd64', label: '
|
|
349
|
-
{ value: 'linux/arm64', label: '
|
|
348
|
+
{ value: 'linux/amd64', label: 'amd64' },
|
|
349
|
+
{ value: 'linux/arm64', label: 'arm64' },
|
|
350
350
|
],
|
|
351
351
|
initialValue: DEFAULT_DOCKER_PLATFORM,
|
|
352
352
|
yesInitialValue: DEFAULT_DOCKER_PLATFORM,
|
package/dist/lib/auth-store.js
CHANGED
|
@@ -11,6 +11,7 @@ import path from 'node:path';
|
|
|
11
11
|
import { resolveAppPublicPath } from './app-public-path.js';
|
|
12
12
|
import { resolveCliHomeDir, resolveConfiguredEnvPath, resolveEnvRelativePath } from './cli-home.js';
|
|
13
13
|
import { normalizeCliLocale } from './cli-locale.js';
|
|
14
|
+
import { normalizeEnvProxyConfig, normalizeEnvProxyProviderConfig, } from './env-proxy-config.js';
|
|
14
15
|
import { inferConfiguredAppPathFromLegacyConfig, resolveConfiguredAppPath, resolveConfiguredSourcePath, resolveConfiguredStoragePath, } from './env-paths.js';
|
|
15
16
|
import { ENV_CONFIG_SCHEMA_VERSION, normalizeEnvConfigSchemaVersion } from './env-config.js';
|
|
16
17
|
import { cleanupCurrentSessionAfterEnvRemoval, resolveEffectiveCurrentEnv, setSessionCurrentEnv, } from './session-store.js';
|
|
@@ -81,12 +82,14 @@ function normalizeEnvConfigEntry(entry) {
|
|
|
81
82
|
const normalizedKind = resolveEnvKind(entry);
|
|
82
83
|
const apiBaseUrl = readEnvApiBaseUrl(entry);
|
|
83
84
|
const schemaVersion = normalizeEnvConfigSchemaVersion(entry.schemaVersion);
|
|
85
|
+
const proxy = normalizeEnvProxyConfig(entry.proxy);
|
|
84
86
|
return {
|
|
85
87
|
...rest,
|
|
86
88
|
...(schemaVersion ? { schemaVersion } : {}),
|
|
87
89
|
...(normalizedKind ? { kind: normalizedKind } : {}),
|
|
88
90
|
...(apiBaseUrl !== undefined ? { apiBaseUrl } : {}),
|
|
89
91
|
...(normalizeOptionalString(entry.appPublicPath) ? { appPublicPath: resolveAppPublicPath(entry.appPublicPath) } : {}),
|
|
92
|
+
...(proxy ? { proxy } : {}),
|
|
90
93
|
};
|
|
91
94
|
}
|
|
92
95
|
function normalizeAuthConfig(config) {
|
|
@@ -516,6 +519,64 @@ export async function setEnvRuntime(envName, runtime, options = {}) {
|
|
|
516
519
|
};
|
|
517
520
|
await saveAuthConfig(config, options);
|
|
518
521
|
}
|
|
522
|
+
export function resolveEnvProxyEntry(config, provider) {
|
|
523
|
+
const proxy = normalizeEnvProxyConfig(config?.proxy);
|
|
524
|
+
const resolved = {
|
|
525
|
+
...(proxy?.host ? { host: proxy.host } : {}),
|
|
526
|
+
...(proxy?.port !== undefined ? { port: proxy.port } : {}),
|
|
527
|
+
...((provider === 'nginx' ? proxy?.nginx : proxy?.caddy) ?? {}),
|
|
528
|
+
};
|
|
529
|
+
return Object.keys(resolved).length > 0 ? resolved : undefined;
|
|
530
|
+
}
|
|
531
|
+
export async function setEnvProxyEntry(envName, provider, entry, options = {}) {
|
|
532
|
+
await writeEnv(envName, (previous) => {
|
|
533
|
+
const currentProxy = normalizeEnvProxyConfig(previous?.proxy) ?? {};
|
|
534
|
+
const nextEntry = normalizeEnvProxyProviderConfig(entry);
|
|
535
|
+
const nextProxy = { ...currentProxy };
|
|
536
|
+
if (nextEntry && 'host' in nextEntry) {
|
|
537
|
+
const host = normalizeOptionalString(nextEntry.host);
|
|
538
|
+
if (host) {
|
|
539
|
+
nextProxy.host = host;
|
|
540
|
+
}
|
|
541
|
+
else {
|
|
542
|
+
delete nextProxy.host;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
if (nextEntry && 'port' in nextEntry) {
|
|
546
|
+
const portValue = nextEntry.port;
|
|
547
|
+
const port = typeof portValue === 'number' && Number.isInteger(portValue) && portValue >= 1 && portValue <= 65535
|
|
548
|
+
? portValue
|
|
549
|
+
: undefined;
|
|
550
|
+
if (port !== undefined) {
|
|
551
|
+
nextProxy.port = port;
|
|
552
|
+
}
|
|
553
|
+
else {
|
|
554
|
+
delete nextProxy.port;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
const providerConfig = nextEntry && Object.keys(nextEntry).some((key) => key !== 'host' && key !== 'port')
|
|
558
|
+
? Object.fromEntries(Object.entries(nextEntry).filter(([key]) => key !== 'host' && key !== 'port'))
|
|
559
|
+
: undefined;
|
|
560
|
+
if (provider === 'nginx') {
|
|
561
|
+
if (providerConfig && Object.keys(providerConfig).length > 0) {
|
|
562
|
+
nextProxy.nginx = providerConfig;
|
|
563
|
+
}
|
|
564
|
+
else {
|
|
565
|
+
delete nextProxy.nginx;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
else if (providerConfig && Object.keys(providerConfig).length > 0) {
|
|
569
|
+
nextProxy.caddy = providerConfig;
|
|
570
|
+
}
|
|
571
|
+
else {
|
|
572
|
+
delete nextProxy.caddy;
|
|
573
|
+
}
|
|
574
|
+
return {
|
|
575
|
+
...previous,
|
|
576
|
+
proxy: nextProxy,
|
|
577
|
+
};
|
|
578
|
+
}, options);
|
|
579
|
+
}
|
|
519
580
|
export async function clearEnvRootSetup(envName, options = {}) {
|
|
520
581
|
const config = await loadExactAuthConfig(options);
|
|
521
582
|
const current = config.envs[envName];
|
package/dist/lib/cli-config.js
CHANGED
|
@@ -242,7 +242,9 @@ export function getEffectiveCliConfigValue(config, key) {
|
|
|
242
242
|
case 'docker.container-prefix':
|
|
243
243
|
return trimValue(config.name) || DEFAULT_DOCKER_CONTAINER_PREFIX;
|
|
244
244
|
case 'nb-image-registry':
|
|
245
|
-
return explicit ??
|
|
245
|
+
return explicit ?? (resolveCliLocale(undefined, { configuredLocale: trimValue(config.settings?.locale) }) === 'zh-CN'
|
|
246
|
+
? 'aliyun'
|
|
247
|
+
: DEFAULT_NB_IMAGE_REGISTRY);
|
|
246
248
|
case 'nb-image-variant':
|
|
247
249
|
return explicit ?? DEFAULT_NB_IMAGE_VARIANT;
|
|
248
250
|
case 'bin.docker':
|
package/dist/lib/env-config.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
|
+
import { normalizeEnvProxyConfig } from './env-proxy-config.js';
|
|
9
10
|
import { resolveAppPublicPath } from './app-public-path.js';
|
|
10
11
|
const STRING_ENV_CONFIG_KEYS = [
|
|
11
12
|
'source',
|
|
@@ -110,5 +111,9 @@ export function buildStoredEnvConfig(input) {
|
|
|
110
111
|
if ((authType === 'basic' || authType === 'token') && accessToken) {
|
|
111
112
|
envConfig.accessToken = accessToken;
|
|
112
113
|
}
|
|
114
|
+
const proxy = normalizeEnvProxyConfig(input.proxy);
|
|
115
|
+
if (proxy) {
|
|
116
|
+
envConfig.proxy = proxy;
|
|
117
|
+
}
|
|
113
118
|
return envConfig;
|
|
114
119
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
function normalizeOptionalString(value) {
|
|
10
|
+
const normalized = String(value ?? '').trim();
|
|
11
|
+
return normalized || undefined;
|
|
12
|
+
}
|
|
13
|
+
function normalizeOptionalPort(value) {
|
|
14
|
+
const normalized = normalizeOptionalString(value);
|
|
15
|
+
if (!normalized || !/^\d+$/.test(normalized)) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
const port = Number(normalized);
|
|
19
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
return port;
|
|
23
|
+
}
|
|
24
|
+
export function normalizeEnvProxyProviderConfig(value) {
|
|
25
|
+
if (!value || typeof value !== 'object') {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
return { ...value };
|
|
29
|
+
}
|
|
30
|
+
export function normalizeEnvProxyConfig(value) {
|
|
31
|
+
if (!value || typeof value !== 'object') {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
const proxy = value;
|
|
35
|
+
const host = normalizeOptionalString(proxy.host);
|
|
36
|
+
const port = normalizeOptionalPort(proxy.port);
|
|
37
|
+
const nginx = normalizeEnvProxyProviderConfig(proxy.nginx);
|
|
38
|
+
const caddy = normalizeEnvProxyProviderConfig(proxy.caddy);
|
|
39
|
+
if (!host && port === undefined && !nginx && !caddy) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
...(host ? { host } : {}),
|
|
44
|
+
...(port !== undefined ? { port } : {}),
|
|
45
|
+
...(nginx ? { nginx } : {}),
|
|
46
|
+
...(caddy ? { caddy } : {}),
|
|
47
|
+
};
|
|
48
|
+
}
|
package/dist/lib/env-proxy.js
CHANGED
|
@@ -487,6 +487,7 @@ function rewriteHtmlAssetPublicPath(html, currentPublicPath, nextPublicPath) {
|
|
|
487
487
|
}
|
|
488
488
|
function buildNginxManagedConfigBlock(context) {
|
|
489
489
|
const v2PublicPathNoTrailingSlash = trimTrailingSlash(context.v2PublicPath);
|
|
490
|
+
const apiBasePathNoTrailingSlash = trimTrailingSlash(context.apiBasePath);
|
|
490
491
|
const appPublicPathNoTrailingSlash = trimTrailingSlash(context.appPublicPath);
|
|
491
492
|
const isRootMounted = context.appPublicPath === '/';
|
|
492
493
|
const appPublicPathRedirectBlock = isRootMounted
|
|
@@ -525,6 +526,10 @@ function buildNginxManagedConfigBlock(context) {
|
|
|
525
526
|
` include ${context.snippetsDir}/proxy-location.conf;`,
|
|
526
527
|
' }',
|
|
527
528
|
'',
|
|
529
|
+
` location = ${apiBasePathNoTrailingSlash} {`,
|
|
530
|
+
` return 308 ${context.apiBasePath}$is_args$args;`,
|
|
531
|
+
' }',
|
|
532
|
+
'',
|
|
528
533
|
` location ^~ ${context.apiBasePath} {`,
|
|
529
534
|
` proxy_pass ${context.backendUrl};`,
|
|
530
535
|
` include ${context.snippetsDir}/proxy-location.conf;`,
|
|
@@ -989,6 +994,7 @@ function buildNginxOtherLocation(appPublicPath, v2PublicPath, modernClientPrefix
|
|
|
989
994
|
function renderNginxLocationTemplate(context) {
|
|
990
995
|
const proxyPassBlock = buildNginxProxyPassBlock(context.proxyHost, context.apiPort);
|
|
991
996
|
const wsProxyPassTarget = `http://${context.proxyHost}:${context.apiPort}${context.wsPath}`;
|
|
997
|
+
const apiBasePathNoTrailingSlash = trimTrailingSlash(context.apiBasePath);
|
|
992
998
|
return ` location ~* ^${context.appPublicPath}storage/uploads/(.*\\.md)$ {
|
|
993
999
|
alias ${context.uploadsPath}/$1;
|
|
994
1000
|
default_type text/markdown;
|
|
@@ -1034,6 +1040,10 @@ function renderNginxLocationTemplate(context) {
|
|
|
1034
1040
|
${proxyPassBlock}
|
|
1035
1041
|
}${context.otherLocation}
|
|
1036
1042
|
|
|
1043
|
+
location = ${apiBasePathNoTrailingSlash} {
|
|
1044
|
+
return 308 ${context.apiBasePath}$is_args$args;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1037
1047
|
location ^~ ${context.apiBasePath} {
|
|
1038
1048
|
${proxyPassBlock}
|
|
1039
1049
|
}
|