Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/mrt-save-credentials.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@salesforce/b2c-cli': minor
'@salesforce/b2c-dx-docs': patch
---

Add `mrt save-credentials` command to save MRT API credentials to the ~/.mobify file
44 changes: 35 additions & 9 deletions docs/cli/mrt.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Commands for managing Managed Runtime (MRT) projects, environments, and bundles
| `mrt env access-control` | `list` | Manage access control headers |
| `mrt bundle` | `deploy`, `list`, `history`, `download` | Manage bundles and deployments |
| `mrt tail-logs` | | Tail real-time application logs |
| `mrt save-credentials` | | Save MRT credentials to ~/.mobify |
| `mrt user` | `profile`, `api-key`, `email-prefs` | Manage user settings |

## Global MRT Flags
Expand Down Expand Up @@ -55,15 +56,9 @@ MRT commands use API key authentication. The API key is configured in the Manage

Provide the API key via one of these methods:

1. **Command-line flag**: `--api-key your-api-key`
2. **Environment variable**: `export MRT_API_KEY=your-api-key`
3. **Mobify config file**: `~/.mobify` with `api_key` field

```json
{
"api_key": "your-mrt-api-key"
}
```
1. **Save credentials** (recommended): `b2c mrt save-credentials --user you@example.com --api-key your-api-key`
2. **Command-line flag**: `--api-key your-api-key`
3. **Environment variable**: `export MRT_API_KEY=your-api-key`

For complete setup instructions, see the [Authentication Guide](/guide/authentication#managed-runtime-api-key).

Expand Down Expand Up @@ -539,6 +534,37 @@ b2c mrt tail-logs -p my-storefront -e staging --json

---

## Save Credentials

### b2c mrt save-credentials

Save MRT credentials (username and API key) to the `~/.mobify` file. Prompts for confirmation before overwriting an existing file.

```bash
# Save credentials
b2c mrt save-credentials --user user@example.com --api-key abc123

# Overwrite without confirmation
b2c mrt save-credentials --user user@example.com --api-key abc123 --yes

# Save to a custom credentials file
b2c mrt save-credentials --user user@example.com --api-key abc123 --credentials-file ./my-creds

# Save for a specific cloud origin (writes to ~/.mobify--<hostname>)
b2c mrt save-credentials --user user@example.com --api-key abc123 --cloud-origin https://cloud-staging.example.com
```

**Flags:**
| Flag | Description |
|------|-------------|
| `--user` | MRT username (email). Required. |
| `--api-key` | MRT API key. Required. |
| `--cloud-origin` | MRT cloud origin URL. Determines the credentials file path (e.g., `~/.mobify--<hostname>`). |
| `--credentials-file` | Explicit path to credentials file (overrides default `~/.mobify`). |
| `--yes`, `-y` | Overwrite existing credentials without confirmation. |

---

## User Commands

### b2c mrt user profile
Expand Down
8 changes: 4 additions & 4 deletions docs/guide/authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -374,11 +374,11 @@ MRT commands use a separate API key system.
### Configuring the API Key

```bash
# Environment variable
export MRT_API_KEY=your-mrt-api-key
# Save credentials to ~/.mobify
b2c mrt save-credentials --user your-email@example.com --api-key your-mrt-api-key

# Or in ~/.mobify config file
echo '{"api_key": "your-mrt-api-key"}' > ~/.mobify
# Or use an environment variable
export MRT_API_KEY=your-mrt-api-key
```

## Quick Start Example
Expand Down
21 changes: 2 additions & 19 deletions packages/b2c-cli/src/commands/code/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,16 @@
* SPDX-License-Identifier: Apache-2
* For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
*/
import * as readline from 'node:readline';
import {Args, Flags} from '@oclif/core';
import {InstanceCommand} from '@salesforce/b2c-tooling-sdk/cli';
import {deleteCodeVersion} from '@salesforce/b2c-tooling-sdk/operations/code';
import {t, withDocs} from '../../i18n/index.js';

/**
* Simple confirmation prompt.
*/
async function confirm(message: string): Promise<boolean> {
const rl = readline.createInterface({
input: process.stdin,
output: process.stderr,
});

return new Promise((resolve) => {
rl.question(`${message} `, (answer) => {
rl.close();
resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
});
});
}
import {confirm} from '../../prompts.js';

export default class CodeDelete extends InstanceCommand<typeof CodeDelete> {
static hiddenAliases = ['code:delete'];

static args = {

Check warning on line 15 in packages/b2c-cli/src/commands/code/delete.ts

View workflow job for this annotation

GitHub Actions / test (22.x)

Expected "args" to come before "hiddenAliases"

Check warning on line 15 in packages/b2c-cli/src/commands/code/delete.ts

View workflow job for this annotation

GitHub Actions / test (24.x)

Expected "args" to come before "hiddenAliases"
codeVersion: Args.string({
description: 'Code version ID to delete',
required: true,
Expand Down Expand Up @@ -75,7 +58,7 @@
const confirmed = await this.operations.confirm(
t(
'commands.code.delete.confirm',
'Are you sure you want to delete code version "{{codeVersion}}" on {{hostname}}? (y/n)',
'Are you sure you want to delete code version "{{codeVersion}}" on {{hostname}}?',
{codeVersion, hostname},
),
);
Expand Down
21 changes: 2 additions & 19 deletions packages/b2c-cli/src/commands/mrt/env/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,11 @@
* SPDX-License-Identifier: Apache-2
* For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
*/
import * as readline from 'node:readline';
import {Args, Flags} from '@oclif/core';
import {MrtCommand} from '@salesforce/b2c-tooling-sdk/cli';
import {deleteEnv} from '@salesforce/b2c-tooling-sdk/operations/mrt';
import {t, withDocs} from '../../../i18n/index.js';

/**
* Simple confirmation prompt.
*/
async function confirm(message: string): Promise<boolean> {
const rl = readline.createInterface({
input: process.stdin,
output: process.stderr,
});

return new Promise((resolve) => {
rl.question(`${message} `, (answer) => {
rl.close();
resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
});
});
}
import {confirm} from '../../../prompts.js';

/**
* Delete an environment (target) from a Managed Runtime project.
Expand Down Expand Up @@ -83,7 +66,7 @@ export default class MrtEnvDelete extends MrtCommand<typeof MrtEnvDelete> {
const confirmed = await this.operations.confirm(
t(
'commands.mrt.env.delete.confirm',
'Are you sure you want to delete environment "{{slug}}" from {{project}}? (y/n)',
'Are you sure you want to delete environment "{{slug}}" from {{project}}?',
{
slug,
project,
Expand Down
19 changes: 1 addition & 18 deletions packages/b2c-cli/src/commands/mrt/env/redirect/clone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,11 @@
* SPDX-License-Identifier: Apache-2
* For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
*/
import * as readline from 'node:readline';
import {Flags} from '@oclif/core';
import {MrtCommand} from '@salesforce/b2c-tooling-sdk/cli';
import {cloneRedirects, type CloneRedirectsResult} from '@salesforce/b2c-tooling-sdk/operations/mrt';
import {t, withDocs} from '../../../../i18n/index.js';

/**
* Prompt for confirmation.
*/
async function confirm(message: string): Promise<boolean> {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});

return new Promise((resolve) => {
rl.question(`${message} (y/N): `, (answer) => {
rl.close();
resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
});
});
}
import {confirm} from '../../../../prompts.js';

/**
* Clone redirects from one environment to another.
Expand Down
19 changes: 1 addition & 18 deletions packages/b2c-cli/src/commands/mrt/env/redirect/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,11 @@
* SPDX-License-Identifier: Apache-2
* For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
*/
import * as readline from 'node:readline';
import {Args, Flags} from '@oclif/core';
import {MrtCommand} from '@salesforce/b2c-tooling-sdk/cli';
import {deleteRedirect} from '@salesforce/b2c-tooling-sdk/operations/mrt';
import {t, withDocs} from '../../../../i18n/index.js';

/**
* Prompt for confirmation.
*/
async function confirm(message: string): Promise<boolean> {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});

return new Promise((resolve) => {
rl.question(`${message} (y/N): `, (answer) => {
rl.close();
resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
});
});
}
import {confirm} from '../../../../prompts.js';

/**
* Delete a redirect from an MRT environment.
Expand Down
21 changes: 2 additions & 19 deletions packages/b2c-cli/src/commands/mrt/project/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,11 @@
* SPDX-License-Identifier: Apache-2
* For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
*/
import * as readline from 'node:readline';
import {Args, Flags} from '@oclif/core';
import {MrtCommand} from '@salesforce/b2c-tooling-sdk/cli';
import {deleteProject} from '@salesforce/b2c-tooling-sdk/operations/mrt';
import {t, withDocs} from '../../../i18n/index.js';

/**
* Simple confirmation prompt.
*/
async function confirm(message: string): Promise<boolean> {
const rl = readline.createInterface({
input: process.stdin,
output: process.stderr,
});

return new Promise((resolve) => {
rl.question(`${message} `, (answer) => {
rl.close();
resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
});
});
}
import {confirm} from '../../../prompts.js';

/**
* Delete result for JSON output.
Expand Down Expand Up @@ -78,7 +61,7 @@ export default class MrtProjectDelete extends MrtCommand<typeof MrtProjectDelete
// Confirm deletion unless --force is specified
if (!force && !this.jsonEnabled()) {
const confirmed = await confirm(
t('commands.mrt.project.delete.confirm', 'Are you sure you want to delete project "{{slug}}"? (y/n)', {slug}),
t('commands.mrt.project.delete.confirm', 'Are you sure you want to delete project "{{slug}}"?', {slug}),
);

if (!confirmed) {
Expand Down
19 changes: 1 addition & 18 deletions packages/b2c-cli/src/commands/mrt/project/member/remove.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,11 @@
* SPDX-License-Identifier: Apache-2
* For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
*/
import * as readline from 'node:readline';
import {Args, Flags} from '@oclif/core';
import {MrtCommand} from '@salesforce/b2c-tooling-sdk/cli';
import {removeMember} from '@salesforce/b2c-tooling-sdk/operations/mrt';
import {t, withDocs} from '../../../../i18n/index.js';

/**
* Prompt for confirmation.
*/
async function confirm(message: string): Promise<boolean> {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});

return new Promise((resolve) => {
rl.question(`${message} (y/N): `, (answer) => {
rl.close();
resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
});
});
}
import {confirm} from '../../../../prompts.js';

/**
* Remove a member from an MRT project.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,11 @@
* SPDX-License-Identifier: Apache-2
* For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
*/
import * as readline from 'node:readline';
import {Args, Flags} from '@oclif/core';
import {MrtCommand} from '@salesforce/b2c-tooling-sdk/cli';
import {deleteNotification} from '@salesforce/b2c-tooling-sdk/operations/mrt';
import {t, withDocs} from '../../../../i18n/index.js';

/**
* Prompt for confirmation.
*/
async function confirm(message: string): Promise<boolean> {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});

return new Promise((resolve) => {
rl.question(`${message} (y/N): `, (answer) => {
rl.close();
resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
});
});
}
import {confirm} from '../../../../prompts.js';

/**
* Delete a notification from an MRT project.
Expand Down
Loading
Loading