Skip to content

feat(create): add interactive prompting and connection checking for system management commands#4949

Open
korotkovao wants to merge 42 commits into
mainfrom
feat/system-commands-interactive
Open

feat(create): add interactive prompting and connection checking for system management commands#4949
korotkovao wants to merge 42 commits into
mainfrom
feat/system-commands-interactive

Conversation

@korotkovao

@korotkovao korotkovao commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

#4948

Summary

Enhances the @sap-ux/create CLI's system management commands (add system, update system, remove system) with interactive prompting and connection verification.

Key Changes

  • Interactive Mode: All system commands now support fully interactive prompting when flags are not provided
  • Connection Verification: add system and update system now verify backend connectivity before saving (with --skip-check flag to bypass)
  • Safety Confirmation: remove system now prompts for confirmation (with --force flag to bypass)
  • Backward Compatible: All existing flag-based usage continues to work unchanged

Examples

Add System - Interactive mode:
```bash
npx @sap-ux/create add system

Prompts for: name, URL, client, type, auth method, username, serviceKey

Verifies connection before saving

```

Update System - Mixed mode (some flags + prompts):
```bash
npx @sap-ux/create update system --name "My System" --url https://updated.example.com

Prompts only for missing fields

Verifies connection before saving

```

Remove System - With confirmation:
```bash
npx @sap-ux/create remove system --name "My System"

Prompts: "Are you sure you want to remove system 'My System'?"

```

Testing

  • ✅ All 27 unit tests passing
  • ✅ Manual testing completed (see MANUAL_TESTING.md - not committed)
  • ✅ Backward compatibility verified with existing flag-based usage
  • ✅ Connection checking verified against real backend systems

Changeset

  • Minor version bump for @sap-ux/create
  • No breaking changes

- Add interactive prompts when flags not provided for add/update/remove system
- Add connection verification with --skip-check flag
- Add confirmation prompt for remove with --force flag
- All existing flag-based usage remains unchanged
- Mock prompts and connection check modules
- Update tests to handle interactive flows
- Add tests for --skip-check and --force flags
- All 27 tests passing
- Add changeset for minor version bump
- Update README with new interactive mode examples
- Update SKILL.md (auto-generated)
- Add MANUAL_TESTING.md to .gitignore
@changeset-bot

changeset-bot Bot commented Jul 15, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: c73d6a7

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@sap-ux/create Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@hyperspace-pr-bot

Copy link
Copy Markdown
Contributor

Summary

The following content is AI-generated and provides a summary of the pull request:


Description

Enhances the @sap-ux/create CLI's system management commands (add system, update system, remove system) with interactive prompting and connection verification.

Key changes:

  • Interactive Mode: All three system commands now support fully interactive prompting via prompts when CLI flags are not provided, enabling a guided experience without requiring upfront flags.
  • Connection Verification: add system and update system now verify backend connectivity before saving. A new --skip-check flag allows bypassing this check.
  • Safety Confirmation: remove system now prompts for confirmation before deleting. A new --force flag skips the confirmation prompt.
  • --name and --url no longer required options: Previously marked as requiredOption, these are now optional to support interactive fallback.
  • New utility modules system-prompts.ts and system-connection.ts provide shared prompt and connection-checking logic.
  • Unit tests updated and extended to cover interactive mode, connection checking, and confirmation flows (mocking prompts and system-connection utilities).
  • README.md and SKILL.md documentation updated to reflect interactive mode examples and new flags.

Examples:

# Fully interactive
npx @sap-ux/create add system

# Connection check bypass
npx @sap-ux/create add system --name "My System" --url https://example.com --skip-check

# Remove with confirmation bypass
npx @sap-ux/create remove system --name "My System" --force

Type of change

  • Bug (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds a new feature)
  • Breaking change (Bug or New feature that would cause existing functionality/consumers to not work as expected)
  • Non-Breaking chores (Changes to tools, libraries, build process, documentation, etc)
  • None of the above (Reviewers might ask for more clarification)

How have you tested?

  • All existing unit tests updated to mock interactive prompts (prompts) and connection utilities (system-connection)
  • New unit tests added covering: connection check pass/fail flows, --skip-check flag, confirmation prompt for remove system, and declining confirmation
  • Backward compatibility verified: all existing flag-based usage continues to work unchanged

Checklist:

  • The code conforms to the general development principles
  • Supplied as many details as possible on this change
  • The code is easy to read and maintainable by others
  • Corresponding changes to the documentation has been done
  • Already existing and new unit tests pass locally

  • 🔄 Regenerate and Update Summary
  • ✏️ Insert as PR Description (deletes this comment)
  • 🗑️ Delete comment
PR Bot Information

Version: 1.27.6

  • Event Trigger: pull_request.opened
  • LLM: anthropic--claude-4.6-sonnet
  • File Content Strategy: Full file content
  • Output Template: Repository PR Template
  • Summary Prompt: Default Prompt
  • Correlation ID: 0c61f820-8042-11f1-9166-ced18f7e4ceb

@hyperspace-pr-bot hyperspace-pr-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR introduces interactive prompting and connection verification for add system, update system, and remove system commands. Several substantive issues were identified and commented:

  1. Changeset missing required prefix — the summary line must start with FEAT: or CI validation will fail.
  2. replaceEnvVariables called too late in add system — URL validation and the duplicate-system lookup both run before env-var references are expanded, meaning env-var URLs would fail the new URL() check and the duplicate check would use the unexpanded string.
  3. CLI option defaults silently suppress interactive prompts--type, --auth, and --connection-type all have default values registered on .option(), so params.systemType, params.authenticationType, and params.connectionType are never undefined even when the user omits those flags. As a result, promptForSystemConfig never prompts for those fields in interactive mode.
  4. || instead of ?? for credential fallback in update system — falsy values (e.g. empty-string password) would incorrectly fall back to the stored credential rather than using the explicitly supplied empty value.
  5. Test assertion on prompt type: 'select' in the remove-system confirmation test likely does not match the actual prompt type, making the assertion vacuous.
  6. Mismatch between expected error message and code path in the update-system "no fields" test — the test expects 'At least one field must be selected' but the source code's guard (!Object.keys(patchRecord).length) logs a different message; the two paths need to be reconciled.
PR Bot Information

Version: 1.27.6

  • Event Trigger: pull_request.opened
  • LLM: anthropic--claude-4.6-sonnet
  • File Content Strategy: Full file content
  • Agent Instructions:
  • Correlation ID: 0c61f820-8042-11f1-9166-ced18f7e4ceb

Comment thread packages/create/src/cli/add/system.ts Outdated
Comment thread packages/create/src/cli/update/system.ts Outdated
Comment thread packages/create/src/cli/update/system.ts Outdated
Comment thread packages/create/test/unit/cli/remove/system.test.ts
Comment thread packages/create/test/unit/cli/update/system.test.ts
Comment thread .changeset/interactive-system-prompts.md Outdated
- Add system-prompts.ts with interactive prompting functions
- Add system-connection.ts with connection verification
- Move replaceEnvVariables() before URL validation and duplicate check (fixes env var expansion timing)
- Replace || with ?? for nullish coalescing in credential fallback
- Use empty strings instead of undefined for clearCredentials
- Fix test assertion: change 'select' to 'confirm' for remove prompt
korotkovao and others added 6 commits July 16, 2026 11:26
…for system management

Address code review feedback from IainSAP (PR #4949):

1. **Add system name uniqueness validation**
   - Check that system name is unique when adding a new system (both in prompts and when provided via flag)
   - Check that system name is unique when updating (excluding current system)
   - Case-insensitive comparison to prevent near-duplicates

2. **Add comprehensive prompt input validations**
   - validateNonEmpty: Ensures required fields are not empty
   - validateUrl: Validates URL format using native URL constructor
   - validateSystemNameUniqueness: Checks name uniqueness for new systems
   - validateSystemNameUniquenessForUpdate: Checks name uniqueness when updating

3. **Apply validations to prompts**
   - promptForSystemConfig: name (with uniqueness check) and url validation
   - promptForSystemIdentifier: url validation
   - promptForFieldUpdates: name (uniqueness for update), username, and password validation

4. **Validate flags when provided**
   - Add name uniqueness check in addSystem() when name is provided via --name flag
   - Existing URL validation continues to work for --url flag

All tests pass, lint clean.
…flags

When updating a system and providing --name flag, validate that the new name
doesn't conflict with other existing systems (excluding the current system
being updated).

This completes the validation coverage for both add and update operations,
whether using prompts or flags.
Extract common uniqueness check logic into a shared helper function to reduce
code duplication and improve maintainability. This addresses potential
SonarQube code duplication issues.

Changes:
- Add checkSystemNameUniqueness() helper function with optional exclude parameter
- Refactor validateSystemNameUniqueness() to use the helper
- Refactor validateSystemNameUniquenessForUpdate() to use the helper

All tests pass, lint clean.
Add validation to reject system names that are empty or contain only whitespace
when provided via flags. This validation was already present in prompts but was
missing from the flag-based flow.

Validates in both add and update operations before attempting to save the system.
Add extensive test coverage for new validation functions to meet SonarQube
quality gate requirements (80% coverage on new code).

New tests cover:
- System name uniqueness validation (case-insensitive, add and update flows)
- Empty and whitespace-only name rejection
- URL format validation
- Username and password non-empty validation
- Graceful degradation when service is unavailable
- Update name validation that excludes current system

Coverage for system-prompts.ts improved from 56.57% to 98.68%.
All 246 tests passing.
return true;
} catch (error) {
// If we can't check uniqueness, allow it through
// (better to let the user proceed than block on a check failure)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is a good idea ...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, updated in 6063c0d

Based on team feedback, this refactors system name validation to avoid duplication:

- Created isSystemNameTaken() in inquirer-common as single source of truth
- Reused validateClient() from project-input-validator (was missing before)
- Added client field validation to system prompts
- Updated all tests with proper mocks for isSystemNameTaken
- Both inquirer-common and create packages build successfully
- All 51 system-prompts tests pass

Benefits:
✅ Single source of truth - isSystemNameTaken() can be used by all packages
✅ Reuses existing validateClient from project-input-validator
✅ No new package created (as requested)
✅ Client validation properly enforced (was missing)

Addresses feedback from:
- Cian: extract the logic into a function maybe in common utils
- Iain: extract the validators to a shared module for reuse
Fixes a bug where client validation was bypassed when the --client flag was
used. The validation only ran for interactive prompts but not for flag values.

Changes:
- Import validateClient from @sap-ux/project-input-validator
- Add validation check after URL validation in add system command
- Validate that client is either empty or 3 digits (000-999)
- Show clear error message for invalid client format
- Add unit tests for invalid, valid, and empty client scenarios

Manual Testing:
✅ Invalid client '12' is rejected with clear error message
✅ Valid client '100' is accepted
✅ Empty client '' is accepted

Note: Unit tests added but cannot run due to pre-existing import issue in test
file (unrelated to this fix): @sap-ux/btp-utils missing isAbapODataDestination export
Per Cian's feedback, changed error handling to be more conservative:
- If we cannot check for duplicate names (store access fails), block the operation
- Previously allowed through on error (graceful degradation) which could create duplicates
- Now returns clear error message: 'Unable to check system name uniqueness. Please try again.'

Changes:
- Removed try-catch from isSystemNameTaken() - let errors propagate
- Added try-catch in validation functions with appropriate error message
- Updated test: 'should reject on service error' instead of 'should allow through'
- Updated JSDoc to document that function throws on store access failure

Test Results:
✅ All 51 tests pass
✅ Coverage: 94.66% (above 80% requirement)
✅ 0 lint errors

Addresses: #4949 (comment)
const service = await getService<BackendSystem, BackendSystemKey>({
entityName: 'system'
});
const allSystems = await service.getAll();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs to specify all 3 connection types

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, good point, updated

korotkovao and others added 5 commits July 16, 2026 16:18
Fixed incomplete mocks in 6 test files that were causing module loading errors.
The mocks only provided specific exports but Jest ESM requires all exports to be present.

Issue: When mocking '@sap-ux/btp-utils' and '@sap-ux/project-access', only specific
functions were mocked (e.g., isAppStudio), but the modules export many more functions.
When Jest tried to load the source modules, it failed with 'does not provide an export' errors.

Solution: Import the real module and spread it into the mock, then override specific
functions. This preserves all exports while allowing targeted mocking.

Pattern:
  const actualModule = await import('@sap-ux/module');
  jest.unstable_mockModule('@sap-ux/module', () => ({
    ...actualModule,
    specificFunction: mockFn
  }));

Fixed files:
- test/unit/cli/add/system.test.ts (btp-utils)
- test/unit/cli/update/system.test.ts (btp-utils)
- test/unit/cli/remove/system.test.ts (btp-utils)
- test/unit/cli/list/system.test.ts (btp-utils)
- test/unit/cli/get/system.test.ts (btp-utils)
- test/unit/cli/create-fiori.test.ts (project-access)

Test Results:
✅ Before: 29/33 test suites passing (4 failed to load)
✅ After: 33/33 test suites passing
✅ Before: 216/216 tests (in passing suites)
✅ After: 249/249 tests passing
…ckages

Implemented code reuse for system name validation as requested in code review.
All packages now use the common isSystemNameTaken function with proper
connection type filtering.

Changes:
- Enhanced isSystemNameTaken to accept optional SystemNameValidationOptions
- Defaults to checking all 3 connection types (abap_catalog, odata_service, generic_host)
- Supports custom connection type filtering for specific use cases
- Supports excludeSystem option for update scenarios

Fixed:
- create/add/system.ts: Replaced inline duplicate logic with common function
- create/update/system.ts: Replaced inline duplicate logic with common function
- odata-service-inquirer: Fixed bug (was using exact match, now case-insensitive + trim)

Verified:
- All 3 connection types properly checked
- Case-insensitive matching works
- Name trimming works
- excludeSystem option works for updates
- 11/11 manual CLI tests passed

Related: Code review feedback from Cian Morrin
Fixed lint errors by removing unused type imports that were only needed
for type annotations but not actually used in the code.

Changes:
- create/add/system.ts: Remove unused SystemNameValidationOptions import
- create/update/system.ts: Remove unused SystemNameValidationOptions import
- create/utils/system-prompts.ts: Remove unused SystemNameValidationOptions import
- odata-service-inquirer/validators.ts: Remove unused SystemNameValidationOptions import

Lint results:
- odata-service-inquirer: 0 errors (was 1 error)
- create: 0 errors (was 3 errors)
…mmands

Fixes SonarQube code smells in packages/create:

1. Reduced cognitive complexity in add/system.ts (17→≤15)
   - Extract validateSystemConfig() helper for field validation
   - Extract checkForDuplicates() helper for duplicate checking

2. Reduced cognitive complexity in update/system.ts (27→≤15)
   - Extract buildPatchFromParams() for CLI flag validation
   - Extract determinePatch() for update flow control
   - Extract verifyCredentialsUpdate() for connection verification

3. Fixed exception handling in system-prompts.ts
   - Added proper error logging with console.error()
   - Maintained user-friendly error messages for service failures

4. Maintained correct empty string handling
   - Optional fields (client, username, password) convert "" to undefined
   - Used ternary pattern instead of nullish coalescing where needed

Changes:
- packages/create/src/cli/add/system.ts
- packages/create/src/cli/update/system.ts
- packages/create/src/cli/utils/system-prompts.ts

Verification:
✅ Build passes (pnpm build)
✅ Lint passes (0 errors, pre-existing warnings only)
✅ All tests pass (249/249)
✅ Coverage maintained at 93.18%
✅ No breaking changes, full backward compatibility
const service = await getService<BackendSystem, BackendSystemKey>({
entityName: 'system'
});
const allSystems = await service.getAll({

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does filtering here make sense , the name should be globally unique for name?

korotkovao and others added 5 commits July 17, 2026 12:22
…force global uniqueness

- Rename isSystemNameTaken to systemNameExists across all packages for better clarity
- Remove connection type filtering to enforce global system name uniqueness
- Revert unnecessary one-liner extraction in odata-service-inquirer
- Fix lint issues: add @throws type annotation and use nullish coalescing operator

This addresses code review feedback to prevent confusing duplicate system names
across different connection types. System names must now be globally unique.

Files modified:
- packages/inquirer-common/src/validators/system-name-validator.ts
- packages/inquirer-common/src/index.ts
- packages/odata-service-inquirer/src/prompts/datasources/sap-system/validators.ts
- packages/create/src/cli/add/system.ts
- packages/create/src/cli/update/system.ts
- packages/create/src/cli/utils/system-prompts.ts
- packages/create/test/unit/cli/utils/system-prompts.test.ts
Replace ternary expressions with nullish coalescing operator (??) while
preserving correct behavior for empty strings. Empty strings from prompts
are converted to undefined, but explicitly provided empty strings are preserved.

This addresses SonarQube code smells (3 minor issues on lines 234, 238, 239)
for better code consistency and maintainability.

Changes:
- client: Use ?? with fallback to || for empty string handling
- username: Use ?? with fallback to || for empty string handling
- password: Use ?? with fallback to || for empty string handling
…ure feedback

Per Iain's code review:
- Revert odata-service-inquirer to original implementation (no shared validation)
- Remove system-name-validator from inquirer-common (avoiding circular deps with store)
- Move validation logic to create package where it's needed for add/update operations
- Preserve excludeSystem logic for update scenarios

Changes:
- Moved system-name-validator from inquirer-common to create/src/cli/utils/
- Reverted odata-service-inquirer to original isSystemNameInUse implementation
- Updated all create package imports to use local validation
- Removed inquirer-common dependency on @sap-ux/store

Note: Per Iain's feedback, connection manager (sap-systems-ext) validation should
also be updated to remove connection type filtering and potentially share code.
This will be addressed in follow-up work with Cian.
…tion

Address code review feedback by consolidating system name uniqueness
validation into a single reusable function in the store package.

Changes:
- Add isSystemNameInUse() function in @sap-ux/store/utils/system-name
- Update @sap-ux/create to use centralized validation for add/update
- Update @sap-ux/sap-systems-ext to use centralized validation
- Remove filtering to ensure global name uniqueness across all systems
- Maintain case-insensitive comparison with trimming
- Support excluding current system in update scenarios
- Revert odata-service-inquirer to keep original implementation

Review feedback addressed:
- Centralized validation logic (Cian, Iain)
- No connection type filtering for global uniqueness (Iain)
- No circular dependencies - validated dependency chain (Iain)
- Kept odata-service-inquirer unchanged (Iain)

Testing:
- All packages: 449/449 unit tests pass (100%)
- Lint: 0 errors (only pre-existing warnings)
- Build: All packages build successfully
- Coverage: >80% maintained (create: 90.24% for system-prompts)
- VSIX: Built successfully (4.32 MB)

BREAKING CHANGE: None - fully backward compatible
* @returns true if name already exists, false otherwise
* @throws {Error} if unable to check the store
*/
export async function isSystemNameInUse(systemName: string): Promise<boolean> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which would you prefer @IainSAP ?
Keep the filtering behavior (restore the original logic) or global uniqueness?

Comment thread packages/inquirer-common/package.json Outdated
"@sap-ux/logger": "workspace:*",
"@sap-ux/project-access": "workspace:*",
"@sap-ux/odata-service-writer": "workspace:*",
"@sap-ux/store": "workspace:*",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, removed

Comment thread packages/inquirer-common/tsconfig.json Outdated
"path": "../project-access"
},
{
"path": "../store"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, removed

Per Iain's review feedback, the store dependency is not needed in
inquirer-common package. The validation logic is now centralized in
the store package and consumed directly by create and sap-systems-ext.

Changes:
- Remove @sap-ux/store from package.json dependencies
- Remove store from tsconfig.json references

This avoids potential circular dependency issues and keeps
inquirer-common focused on its core functionality.
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants