@nocobase/cli 2.2.0-test.16 → 3.0.0-alpha.1
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/app/start.js +1 -21
- package/dist/commands/config/set.js +1 -1
- package/dist/commands/init.js +12 -121
- package/dist/commands/install.js +39 -55
- package/dist/commands/portal/config.js +88 -0
- package/dist/commands/portal/create.js +7 -6
- package/dist/commands/portal/deploy.js +2 -2
- package/dist/commands/portal/destroy.js +6 -6
- package/dist/commands/portal/dev.js +3 -3
- package/dist/commands/portal/index.js +1 -1
- package/dist/commands/portal/info.js +3 -3
- package/dist/commands/portal/list.js +5 -5
- package/dist/commands/portal/pull.js +11 -4
- package/dist/commands/portal/push.js +4 -4
- package/dist/lib/api-client.js +7 -0
- package/dist/lib/env-auth.js +2 -2
- package/dist/lib/env-config.js +1 -1
- package/dist/lib/env-proxy.js +68 -6
- package/dist/lib/managed-env-file.js +58 -2
- package/dist/lib/managed-init-env.js +1 -1
- package/dist/lib/naming.js +9 -0
- package/dist/lib/portal-config.js +133 -0
- package/dist/lib/portal-configure.js +117 -0
- package/dist/lib/portal-create.js +24 -79
- package/dist/lib/portal-deploy.js +23 -15
- package/dist/lib/portal-destroy.js +3 -3
- package/dist/lib/portal-dev.js +3 -3
- package/dist/lib/portal-info.js +2 -2
- package/dist/lib/portal-list.js +32 -18
- package/dist/lib/portal-source.js +150 -43
- package/dist/lib/proxy-caddy.js +2 -0
- package/dist/lib/proxy-nginx.js +1 -0
- package/dist/locale/en-US.json +67 -43
- package/dist/locale/zh-CN.json +59 -35
- package/nocobase-ctl.config.json +111 -0
- package/package.json +4 -3
- package/dist/lib/portal-template.js +0 -190
|
@@ -0,0 +1,88 @@
|
|
|
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
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
10
|
+
import { getCurrentEnvName, getEnv } from '../../lib/auth-store.js';
|
|
11
|
+
import { resolveDefaultConfigScope } from '../../lib/cli-home.js';
|
|
12
|
+
import { translateCli } from '../../lib/cli-locale.js';
|
|
13
|
+
import { ensureCrossEnvConfirmed, hasExplicitEnvSelection } from '../../lib/env-guard.js';
|
|
14
|
+
import { configurePortalWorkspace } from '../../lib/portal-configure.js';
|
|
15
|
+
import { printInfo, printSuccess } from '../../lib/ui.js';
|
|
16
|
+
const portalConfigureText = (key, values, fallback) => translateCli(`commands.portalConfigure.${key}`, values, { fallback });
|
|
17
|
+
export default class PortalConfig extends Command {
|
|
18
|
+
static summary = 'Update portal source configuration';
|
|
19
|
+
static examples = [
|
|
20
|
+
'<%= config.bin %> <%= command.id %> customer --source-storage nocobase',
|
|
21
|
+
'<%= config.bin %> <%= command.id %> customer --source-storage git --git-repo git@github.com:nocobase/customer-portal.git',
|
|
22
|
+
'<%= config.bin %> <%= command.id %> customer --git-branch main --git-path portals/customer',
|
|
23
|
+
];
|
|
24
|
+
static args = {
|
|
25
|
+
portal: Args.string({
|
|
26
|
+
required: true,
|
|
27
|
+
description: 'Portal name',
|
|
28
|
+
}),
|
|
29
|
+
};
|
|
30
|
+
static flags = {
|
|
31
|
+
env: Flags.string({
|
|
32
|
+
char: 'e',
|
|
33
|
+
description: 'CLI env name; omitted uses the current env',
|
|
34
|
+
}),
|
|
35
|
+
yes: Flags.boolean({
|
|
36
|
+
char: 'y',
|
|
37
|
+
description: 'Confirm using --env when it targets a different env than the current env',
|
|
38
|
+
default: false,
|
|
39
|
+
}),
|
|
40
|
+
'source-storage': Flags.string({
|
|
41
|
+
description: 'Where portal source code is managed',
|
|
42
|
+
options: ['nocobase', 'git'],
|
|
43
|
+
}),
|
|
44
|
+
'git-repo': Flags.string({
|
|
45
|
+
description: 'Git repository URL used when --source-storage=git',
|
|
46
|
+
}),
|
|
47
|
+
'git-branch': Flags.string({
|
|
48
|
+
description: 'Git branch used when --source-storage=git',
|
|
49
|
+
}),
|
|
50
|
+
'git-path': Flags.string({
|
|
51
|
+
description: 'Directory inside the Git repository for this portal; defaults to the repository root',
|
|
52
|
+
}),
|
|
53
|
+
};
|
|
54
|
+
async run() {
|
|
55
|
+
const { args, flags } = await this.parse(PortalConfig);
|
|
56
|
+
const requestedEnv = hasExplicitEnvSelection(this.argv) ? flags.env : undefined;
|
|
57
|
+
const confirmed = await ensureCrossEnvConfirmed({
|
|
58
|
+
command: this,
|
|
59
|
+
requestedEnv,
|
|
60
|
+
yes: flags.yes,
|
|
61
|
+
});
|
|
62
|
+
if (!confirmed) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const scope = resolveDefaultConfigScope();
|
|
66
|
+
const envName = requestedEnv ?? (await getCurrentEnvName({ scope }));
|
|
67
|
+
const env = await getEnv(envName, { scope });
|
|
68
|
+
if (!env) {
|
|
69
|
+
this.error(portalConfigureText(requestedEnv ? 'errors.envNotConfigured' : 'errors.noEnvConfigured', { envName }, requestedEnv
|
|
70
|
+
? `Env "${envName}" is not configured. Run \`nb env add ${envName} --api-base-url <url>\` first.`
|
|
71
|
+
: 'No NocoBase env is configured yet. Run `nb init --ui` to create one first.'));
|
|
72
|
+
}
|
|
73
|
+
const result = await configurePortalWorkspace({
|
|
74
|
+
portal: args.portal,
|
|
75
|
+
env,
|
|
76
|
+
envName,
|
|
77
|
+
cliVersion: String(this.config.pjson.version ?? '').trim(),
|
|
78
|
+
sourceStorage: flags['source-storage'],
|
|
79
|
+
gitRepo: flags['git-repo'],
|
|
80
|
+
gitBranch: flags['git-branch'],
|
|
81
|
+
gitPath: flags['git-path'],
|
|
82
|
+
});
|
|
83
|
+
printSuccess(portalConfigureText('messages.updated', { portal: result.portal, portalDir: result.portalDir }, `Portal "${result.portal}" configuration updated at ${result.portalDir}/portal.config.json.`));
|
|
84
|
+
printInfo(result.remoteSynced
|
|
85
|
+
? portalConfigureText('messages.remoteSynced', undefined, 'Remote portal record: synced')
|
|
86
|
+
: portalConfigureText('messages.remoteSkipped', undefined, 'Remote portal record: not found; local config only'));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -16,7 +16,7 @@ import { printInfo, printSuccess } from '../../lib/ui.js';
|
|
|
16
16
|
const DEFAULT_PORTAL_TEMPLATE = '@nocobase/portal-template-default';
|
|
17
17
|
const portalCreateText = (key, values, fallback) => translateCli(`commands.portalCreate.${key}`, values, { fallback });
|
|
18
18
|
export default class PortalCreate extends Command {
|
|
19
|
-
static summary = 'Create a local
|
|
19
|
+
static summary = 'Create a local AI portal from a template';
|
|
20
20
|
static examples = [
|
|
21
21
|
'<%= config.bin %> <%= command.id %> customer',
|
|
22
22
|
'<%= config.bin %> <%= command.id %> customer --template @nocobase/portal-template-default',
|
|
@@ -26,7 +26,7 @@ export default class PortalCreate extends Command {
|
|
|
26
26
|
static args = {
|
|
27
27
|
portal: Args.string({
|
|
28
28
|
required: true,
|
|
29
|
-
description: 'Portal name
|
|
29
|
+
description: 'AI Portal name',
|
|
30
30
|
}),
|
|
31
31
|
};
|
|
32
32
|
static flags = {
|
|
@@ -47,11 +47,11 @@ export default class PortalCreate extends Command {
|
|
|
47
47
|
description: 'Portal display title; defaults to a title generated from the portal slug',
|
|
48
48
|
}),
|
|
49
49
|
force: Flags.boolean({
|
|
50
|
-
description: 'Delete the existing
|
|
50
|
+
description: 'Delete the existing portal and recreate it',
|
|
51
51
|
default: false,
|
|
52
52
|
}),
|
|
53
53
|
'source-storage': Flags.string({
|
|
54
|
-
description: 'Where
|
|
54
|
+
description: 'Where portal source code is managed',
|
|
55
55
|
options: ['nocobase', 'git'],
|
|
56
56
|
default: 'nocobase',
|
|
57
57
|
}),
|
|
@@ -62,7 +62,7 @@ export default class PortalCreate extends Command {
|
|
|
62
62
|
description: 'Git branch used when --source-storage=git',
|
|
63
63
|
}),
|
|
64
64
|
'git-path': Flags.string({
|
|
65
|
-
description: 'Directory inside the Git repository for this
|
|
65
|
+
description: 'Directory inside the Git repository for this portal; defaults to the repository root',
|
|
66
66
|
}),
|
|
67
67
|
};
|
|
68
68
|
async run() {
|
|
@@ -76,7 +76,8 @@ export default class PortalCreate extends Command {
|
|
|
76
76
|
if (!confirmed) {
|
|
77
77
|
return;
|
|
78
78
|
}
|
|
79
|
-
const
|
|
79
|
+
const scope = resolveDefaultConfigScope();
|
|
80
|
+
const env = await getEnv(flags.env, { scope });
|
|
80
81
|
if (!env) {
|
|
81
82
|
this.error(flags.env
|
|
82
83
|
? portalCreateText('errors.envNotConfigured', { envName: flags.env }, `Env "${flags.env}" is not configured. Run \`nb env add ${flags.env} --api-base-url <url>\` first.`)
|
|
@@ -17,7 +17,7 @@ import { listPortalWorkspaces } from '../../lib/portal-list.js';
|
|
|
17
17
|
import { printSuccess } from '../../lib/ui.js';
|
|
18
18
|
const portalDeployText = (key, values, fallback) => translateCli(`commands.portalDeploy.${key}`, values, { fallback });
|
|
19
19
|
export default class PortalDeploy extends Command {
|
|
20
|
-
static summary = 'Build and deploy a
|
|
20
|
+
static summary = 'Build and deploy a portal';
|
|
21
21
|
static examples = [
|
|
22
22
|
'<%= config.bin %> <%= command.id %> customer',
|
|
23
23
|
'<%= config.bin %> <%= command.id %> customer --env dev --yes',
|
|
@@ -25,7 +25,7 @@ export default class PortalDeploy extends Command {
|
|
|
25
25
|
static args = {
|
|
26
26
|
portal: Args.string({
|
|
27
27
|
required: true,
|
|
28
|
-
description: 'Portal name
|
|
28
|
+
description: 'Portal name',
|
|
29
29
|
}),
|
|
30
30
|
};
|
|
31
31
|
static flags = {
|
|
@@ -20,11 +20,11 @@ async function ensureDestroyConfirmed(options) {
|
|
|
20
20
|
return true;
|
|
21
21
|
}
|
|
22
22
|
if (!isInteractiveTerminal()) {
|
|
23
|
-
options.command.error(portalDestroyText('errors.confirmationRequired', undefined, 'Refusing to destroy a
|
|
23
|
+
options.command.error(portalDestroyText('errors.confirmationRequired', undefined, 'Refusing to destroy a portal in non-interactive mode without --yes.'));
|
|
24
24
|
}
|
|
25
25
|
try {
|
|
26
26
|
return Boolean(await confirm({
|
|
27
|
-
message: portalDestroyText('prompts.confirm', { portal: options.portal }, `Destroy
|
|
27
|
+
message: portalDestroyText('prompts.confirm', { portal: options.portal }, `Destroy portal "${options.portal}" and delete its storage directory?`),
|
|
28
28
|
default: false,
|
|
29
29
|
}));
|
|
30
30
|
}
|
|
@@ -33,7 +33,7 @@ async function ensureDestroyConfirmed(options) {
|
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
export default class PortalDestroy extends Command {
|
|
36
|
-
static summary = 'Destroy a
|
|
36
|
+
static summary = 'Destroy a portal record and local files';
|
|
37
37
|
static examples = [
|
|
38
38
|
'<%= config.bin %> <%= command.id %> customer --yes',
|
|
39
39
|
'<%= config.bin %> <%= command.id %> customer --env dev --yes',
|
|
@@ -42,7 +42,7 @@ export default class PortalDestroy extends Command {
|
|
|
42
42
|
static args = {
|
|
43
43
|
portal: Args.string({
|
|
44
44
|
required: true,
|
|
45
|
-
description: 'Portal name
|
|
45
|
+
description: 'Portal name',
|
|
46
46
|
}),
|
|
47
47
|
};
|
|
48
48
|
static flags = {
|
|
@@ -56,7 +56,7 @@ export default class PortalDestroy extends Command {
|
|
|
56
56
|
default: false,
|
|
57
57
|
}),
|
|
58
58
|
force: Flags.boolean({
|
|
59
|
-
description: 'Ignore missing
|
|
59
|
+
description: 'Ignore missing portal records or local files',
|
|
60
60
|
default: false,
|
|
61
61
|
}),
|
|
62
62
|
};
|
|
@@ -99,6 +99,6 @@ export default class PortalDestroy extends Command {
|
|
|
99
99
|
printInfo(portalDestroyText('messages.app', { app: result.app }, `App: ${result.app}`));
|
|
100
100
|
printInfo(portalDestroyText('messages.base', { base: result.portalBase }, `Base: ${result.portalBase}`));
|
|
101
101
|
printInfo(portalDestroyText('messages.record', { status: result.recordDeleted ? 'deleted' : 'missing' }, `Record: ${result.recordDeleted ? 'deleted' : 'missing'}`));
|
|
102
|
-
printInfo(portalDestroyText('messages.workspace', { dir: result.portalDir, status: result.workspaceDeleted ? 'deleted' : 'missing' }, `
|
|
102
|
+
printInfo(portalDestroyText('messages.workspace', { dir: result.portalDir, status: result.workspaceDeleted ? 'deleted' : 'missing' }, `Portal files: ${result.workspaceDeleted ? 'deleted' : 'missing'} (${result.portalDir})`));
|
|
103
103
|
}
|
|
104
104
|
}
|
|
@@ -15,7 +15,7 @@ import { devPortalWorkspace } from '../../lib/portal-dev.js';
|
|
|
15
15
|
import { printInfo } from '../../lib/ui.js';
|
|
16
16
|
const portalDevText = (key, values, fallback) => translateCli(`commands.portalDev.${key}`, values, { fallback });
|
|
17
17
|
export default class PortalDev extends Command {
|
|
18
|
-
static summary = 'Start a
|
|
18
|
+
static summary = 'Start a portal in development mode';
|
|
19
19
|
static examples = [
|
|
20
20
|
'<%= config.bin %> <%= command.id %> customer',
|
|
21
21
|
'<%= config.bin %> <%= command.id %> customer --env dev --yes',
|
|
@@ -23,7 +23,7 @@ export default class PortalDev extends Command {
|
|
|
23
23
|
static args = {
|
|
24
24
|
portal: Args.string({
|
|
25
25
|
required: true,
|
|
26
|
-
description: 'Portal name
|
|
26
|
+
description: 'Portal name',
|
|
27
27
|
}),
|
|
28
28
|
};
|
|
29
29
|
static flags = {
|
|
@@ -60,7 +60,7 @@ export default class PortalDev extends Command {
|
|
|
60
60
|
portal: args.portal,
|
|
61
61
|
env,
|
|
62
62
|
onStart: (result) => {
|
|
63
|
-
printInfo(portalDevText('messages.starting', { portal: result.portal }, `Starting
|
|
63
|
+
printInfo(portalDevText('messages.starting', { portal: result.portal }, `Starting portal "${result.portal}"...`));
|
|
64
64
|
printInfo(portalDevText('messages.mode', { mode: result.mode }, `Mode: ${result.mode}`));
|
|
65
65
|
printInfo(portalDevText('messages.app', { app: result.app }, `App: ${result.app}`));
|
|
66
66
|
printInfo(portalDevText('messages.base', { base: result.portalBase }, `Base: ${result.portalBase}`));
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { Command, loadHelpClass } from '@oclif/core';
|
|
10
10
|
export default class Portal extends Command {
|
|
11
|
-
static summary = 'Manage
|
|
11
|
+
static summary = 'Manage portals';
|
|
12
12
|
async run() {
|
|
13
13
|
await this.parse(Portal);
|
|
14
14
|
const Help = await loadHelpClass(this.config);
|
|
@@ -15,7 +15,7 @@ import { findPortalListItem, formatPortalInfo } from '../../lib/portal-info.js';
|
|
|
15
15
|
import { listPortalWorkspaces, toPortalOutputItem } from '../../lib/portal-list.js';
|
|
16
16
|
const portalInfoText = (key, values, fallback) => translateCli(`commands.portalInfo.${key}`, values, { fallback });
|
|
17
17
|
export default class PortalInfo extends Command {
|
|
18
|
-
static summary = 'Show
|
|
18
|
+
static summary = 'Show portal record and local file details';
|
|
19
19
|
static examples = [
|
|
20
20
|
'<%= config.bin %> <%= command.id %> customer',
|
|
21
21
|
'<%= config.bin %> <%= command.id %> customer --env dev --yes',
|
|
@@ -24,7 +24,7 @@ export default class PortalInfo extends Command {
|
|
|
24
24
|
static args = {
|
|
25
25
|
portal: Args.string({
|
|
26
26
|
required: true,
|
|
27
|
-
description: 'Portal name
|
|
27
|
+
description: 'Portal name',
|
|
28
28
|
}),
|
|
29
29
|
};
|
|
30
30
|
static flags = {
|
|
@@ -40,7 +40,7 @@ export default class PortalInfo extends Command {
|
|
|
40
40
|
'json-output': Flags.boolean({
|
|
41
41
|
char: 'j',
|
|
42
42
|
aliases: ['json'],
|
|
43
|
-
description: 'Print
|
|
43
|
+
description: 'Print portal details as JSON',
|
|
44
44
|
default: false,
|
|
45
45
|
}),
|
|
46
46
|
};
|
|
@@ -21,7 +21,7 @@ function formatBoolean(value) {
|
|
|
21
21
|
return value ? 'yes' : 'no';
|
|
22
22
|
}
|
|
23
23
|
export default class PortalList extends Command {
|
|
24
|
-
static summary = 'List
|
|
24
|
+
static summary = 'List portal records and local sync status';
|
|
25
25
|
static examples = [
|
|
26
26
|
'<%= config.bin %> <%= command.id %>',
|
|
27
27
|
'<%= config.bin %> <%= command.id %> --env dev --yes',
|
|
@@ -40,7 +40,7 @@ export default class PortalList extends Command {
|
|
|
40
40
|
'json-output': Flags.boolean({
|
|
41
41
|
char: 'j',
|
|
42
42
|
aliases: ['json'],
|
|
43
|
-
description: 'Print
|
|
43
|
+
description: 'Print portal records as JSON',
|
|
44
44
|
default: false,
|
|
45
45
|
}),
|
|
46
46
|
};
|
|
@@ -74,13 +74,13 @@ export default class PortalList extends Command {
|
|
|
74
74
|
return;
|
|
75
75
|
}
|
|
76
76
|
if (!outputItems.length) {
|
|
77
|
-
printInfo(portalListText('messages.empty', undefined, 'No
|
|
77
|
+
printInfo(portalListText('messages.empty', undefined, 'No portal records found.'));
|
|
78
78
|
return;
|
|
79
79
|
}
|
|
80
80
|
this.log(renderTable([
|
|
81
81
|
portalListText('table.name', undefined, 'Name'),
|
|
82
82
|
portalListText('table.url', undefined, 'URL'),
|
|
83
|
-
portalListText('table.
|
|
83
|
+
portalListText('table.portalType', undefined, 'Portal type'),
|
|
84
84
|
portalListText('table.sourceStorage', undefined, 'Source storage'),
|
|
85
85
|
portalListText('table.path', undefined, 'Local path'),
|
|
86
86
|
portalListText('table.enabled', undefined, 'Enabled'),
|
|
@@ -88,7 +88,7 @@ export default class PortalList extends Command {
|
|
|
88
88
|
], outputItems.map((item) => [
|
|
89
89
|
item.name,
|
|
90
90
|
item.url,
|
|
91
|
-
item.
|
|
91
|
+
item.portalType,
|
|
92
92
|
item.sourceStorage,
|
|
93
93
|
item.localPath,
|
|
94
94
|
formatBoolean(item.enabled),
|
|
@@ -15,16 +15,17 @@ import { pullPortalSource } from '../../lib/portal-source.js';
|
|
|
15
15
|
import { printInfo, printSuccess } from '../../lib/ui.js';
|
|
16
16
|
const portalPullText = (key, values, fallback) => translateCli(`commands.portalPull.${key}`, values, { fallback });
|
|
17
17
|
export default class PortalPull extends Command {
|
|
18
|
-
static summary = 'Pull
|
|
18
|
+
static summary = 'Pull portal source into local files';
|
|
19
19
|
static examples = [
|
|
20
20
|
'<%= config.bin %> <%= command.id %> customer',
|
|
21
21
|
'<%= config.bin %> <%= command.id %> customer --env prod --yes',
|
|
22
22
|
'<%= config.bin %> <%= command.id %> customer --force',
|
|
23
|
+
'<%= config.bin %> <%= command.id %> customer --no-install',
|
|
23
24
|
];
|
|
24
25
|
static args = {
|
|
25
26
|
portal: Args.string({
|
|
26
27
|
required: true,
|
|
27
|
-
description: 'Portal name
|
|
28
|
+
description: 'Portal name',
|
|
28
29
|
}),
|
|
29
30
|
};
|
|
30
31
|
static flags = {
|
|
@@ -38,9 +39,14 @@ export default class PortalPull extends Command {
|
|
|
38
39
|
default: false,
|
|
39
40
|
}),
|
|
40
41
|
force: Flags.boolean({
|
|
41
|
-
description: 'Delete the existing local
|
|
42
|
+
description: 'Delete the existing local files and pull them again',
|
|
42
43
|
default: false,
|
|
43
44
|
}),
|
|
45
|
+
install: Flags.boolean({
|
|
46
|
+
description: 'Run pnpm install after pulling the portal source',
|
|
47
|
+
default: true,
|
|
48
|
+
allowNo: true,
|
|
49
|
+
}),
|
|
44
50
|
};
|
|
45
51
|
async run() {
|
|
46
52
|
const { args, flags } = await this.parse(PortalPull);
|
|
@@ -67,11 +73,12 @@ export default class PortalPull extends Command {
|
|
|
67
73
|
envName,
|
|
68
74
|
cliVersion: String(this.config.pjson.version ?? '').trim(),
|
|
69
75
|
force: flags.force,
|
|
76
|
+
installDependencies: flags.install,
|
|
70
77
|
});
|
|
71
78
|
if (!result.changed) {
|
|
72
79
|
printInfo(result.noopReason ?? portalPullText('messages.noop', undefined, 'No pull is needed.'));
|
|
73
80
|
return;
|
|
74
81
|
}
|
|
75
|
-
printSuccess(portalPullText('messages.pulled', { portal: result.portal, portalDir: result.portalDir }, `Pulled
|
|
82
|
+
printSuccess(portalPullText('messages.pulled', { portal: result.portal, portalDir: result.portalDir }, `Pulled portal source "${result.portal}" into ${result.portalDir}.`));
|
|
76
83
|
}
|
|
77
84
|
}
|
|
@@ -15,7 +15,7 @@ import { pushPortalSource } from '../../lib/portal-source.js';
|
|
|
15
15
|
import { printInfo, printSuccess } from '../../lib/ui.js';
|
|
16
16
|
const portalPushText = (key, values, fallback) => translateCli(`commands.portalPush.${key}`, values, { fallback });
|
|
17
17
|
export default class PortalPush extends Command {
|
|
18
|
-
static summary = 'Push local
|
|
18
|
+
static summary = 'Push local portal source changes to source storage';
|
|
19
19
|
static examples = [
|
|
20
20
|
'<%= config.bin %> <%= command.id %> customer',
|
|
21
21
|
'<%= config.bin %> <%= command.id %> customer --env prod --yes',
|
|
@@ -24,7 +24,7 @@ export default class PortalPush extends Command {
|
|
|
24
24
|
static args = {
|
|
25
25
|
portal: Args.string({
|
|
26
26
|
required: true,
|
|
27
|
-
description: 'Portal name
|
|
27
|
+
description: 'Portal name',
|
|
28
28
|
}),
|
|
29
29
|
};
|
|
30
30
|
static flags = {
|
|
@@ -73,7 +73,7 @@ export default class PortalPush extends Command {
|
|
|
73
73
|
return;
|
|
74
74
|
}
|
|
75
75
|
printSuccess(portalPushText('messages.pushed', { portal: result.portal, sourceRevision: result.sourceRevision ?? '' }, result.sourceRevision
|
|
76
|
-
? `Pushed
|
|
77
|
-
: `Pushed
|
|
76
|
+
? `Pushed portal source "${result.portal}" (${result.sourceRevision}).`
|
|
77
|
+
: `Pushed portal source "${result.portal}".`));
|
|
78
78
|
}
|
|
79
79
|
}
|
package/dist/lib/api-client.js
CHANGED
|
@@ -199,6 +199,13 @@ async function createMultipartBody(flags, operation) {
|
|
|
199
199
|
if (value === undefined) {
|
|
200
200
|
continue;
|
|
201
201
|
}
|
|
202
|
+
if (Array.isArray(value)) {
|
|
203
|
+
for (const item of value) {
|
|
204
|
+
formData.append(parameter.name, typeof item === 'object' ? JSON.stringify(item) : String(item));
|
|
205
|
+
}
|
|
206
|
+
hasValues = hasValues || value.length > 0;
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
202
209
|
formData.append(parameter.name, typeof value === 'object' ? JSON.stringify(value) : String(value));
|
|
203
210
|
hasValues = true;
|
|
204
211
|
}
|
package/dist/lib/env-auth.js
CHANGED
|
@@ -32,12 +32,12 @@ function buildDeviceVerificationPathFromApiBaseUrl(apiBaseUrl) {
|
|
|
32
32
|
const subappMatch = url.pathname.match(/^(.*)\/api\/__app\/([^/]+)\/?$/);
|
|
33
33
|
if (subappMatch) {
|
|
34
34
|
const publicPath = (subappMatch[1] || '').replace(/\/+$/, '');
|
|
35
|
-
return `${publicPath}/apps/${subappMatch[2]}/idpOAuth/device`;
|
|
35
|
+
return `${publicPath}/settings/apps/${subappMatch[2]}/idpOAuth/device`;
|
|
36
36
|
}
|
|
37
37
|
const appMatch = url.pathname.match(/^(.*)\/api\/?$/);
|
|
38
38
|
if (appMatch) {
|
|
39
39
|
const publicPath = (appMatch[1] || '').replace(/\/+$/, '');
|
|
40
|
-
return `${publicPath}/idpOAuth/device`;
|
|
40
|
+
return `${publicPath}/settings/idpOAuth/device`;
|
|
41
41
|
}
|
|
42
42
|
return undefined;
|
|
43
43
|
}
|