Skip to content

```#12

Merged
ThePlenkov merged 1 commit intomainfrom
feature/atc-checks
Dec 23, 2025
Merged

```#12
ThePlenkov merged 1 commit intomainfrom
feature/atc-checks

Conversation

@ThePlenkov
Copy link
Member

@ThePlenkov ThePlenkov commented Dec 23, 2025

User description

chore(git): remove abapgit-examples submodule

Remove github/abapgit-examples submodule from .gitmodules and repository



___

### **PR Type**
Enhancement, Bug fix


___

### **Description**
- Migrate ADT CLI commands from v1 to v2 client API
  - Update transport request creation/retrieval to use new ADK context pattern
  - Fix response schema mismatches in CTS configuration endpoints
  - Stub out lock/unlock/outline/research-sessions commands pending v2 migration

- Fix test data structures to match actual API response schemas
  - Wrap transport response in `root` property per TransportmanagmentSingleSchema
  - Update mock data references in deduplication tests

- Remove deprecated response plugins (FileStorage, Transform)
  - Clean up unused plugin exports and type definitions
  - Retain logging plugins for continued use

- Update CLI test to handle async createCLI function

- Improve type safety with explicit casting for schema mismatches


___

### Diagram Walkthrough


```mermaid
flowchart LR
  A["v1 Client API"] -->|"Migrate to"| B["v2 Client API"]
  B -->|"Update context pattern"| C["AdkContext with client property"]
  D["Test Data"] -->|"Wrap in root"| E["Schema-compliant responses"]
  F["Deprecated Plugins"] -->|"Remove"| G["FileStorage & Transform"]
  H["Type Mismatches"] -->|"Add casting"| I["Type-safe property access"]
  C --> J["CTS Commands Updated"]
  E --> K["Tests Fixed"]
  G --> L["Cleaner Exports"]
  I --> M["Config Endpoints Fixed"]

File Walkthrough

Relevant files
Tests
3 files
transport-import.test.ts
Wrap transport response in root property                                 
+27/-22 
cli.test.ts
Make createCLI test async                                                               
+2/-2     
mock-e2e.test.ts
Remove deprecated serialize/deserialize test                         
+1/-10   
Enhancement
13 files
create.ts
Update ADK transport creation API call                                     
+3/-4     
release.ts
Update ADK transport retrieval API call                                   
+2/-3     
set.ts
Update ADK transport get API call                                               
+2/-3     
lock.ts
Stub lock command pending v2 migration                                     
+12/-90 
outline.ts
Stub outline command pending v2 migration                               
+10/-82 
research-sessions.ts
Stub research-sessions command pending v2 migration           
+18/-465
index.ts
Stub unlock command pending v2 migration                                 
+12/-113
index.ts
Export only ConfigLoader from loader module                           
+1/-1     
index.ts
Remove unused Package type export                                               
+1/-1     
index.ts
Remove deprecated plugin type exports                                       
+0/-4     
file-storage.ts
Delete deprecated FileStoragePlugin                                           
+0/-76   
index.ts
Remove FileStorage and Transform plugin exports                   
+0/-4     
transform.ts
Delete deprecated TransformPlugin                                               
+0/-22   
Bug_fix
8 files
config-set.ts
Fix response schema and add type casting                                 
+5/-2     
config.ts
Handle nested configuration response structure                     
+20/-4   
get.ts
Handle wrapped package response structure                               
+9/-5     
index.ts
Fix system information method call                                             
+4/-2     
search.ts
Handle multiple response shapes for search results             
+10/-1   
validation.ts
Add type casting for optional plugin version                         
+4/-3     
errors.ts
Add override keyword to cause property                                     
+1/-1     
atc.test.ts
Update Accept headers to wildcard                                               
+3/-3     
Configuration_changes
1 files
tsconfig.json
Add adt-schemas project reference                                               
+3/-0     

chore(git): remove abapgit-examples submodule

Remove github/abapgit-examples submodule from .gitmodules and repository
```
@ThePlenkov ThePlenkov marked this pull request as ready for review December 23, 2025 16:57
@ThePlenkov ThePlenkov merged commit 0b07d06 into main Dec 23, 2025
1 check failed
@qodo-code-review
Copy link

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
🟢
No security concerns identified No security vulnerabilities detected by AI analysis. Human verification advised for critical code.
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Unsafe schema casting: The new code bypasses schema/type checking via as unknown as ... and then uses the
response shape, which may cause runtime failures if the API response differs without
additional validation/guards.

Referred Code
const configDetailsRaw = await client.adt.cts.transportrequests.searchconfiguration.configurations.getById(configId);

// Response has nested structure - extract configuration object
// Cast to expected shape for property access
type ConfigDetails = {
  configuration?: {
    properties?: { property?: Array<{ key?: string; _text?: string; isMandatory?: boolean }> };
    createdBy?: string;
    createdAt?: string;
    changedBy?: string;
    changedAt?: string;
  };
};
const configDetails = (configDetailsRaw as ConfigDetails)?.configuration;

// Convert properties to map for easy access
const properties = propertiesToMap(configDetails as Record<string, unknown>);

// Edit mode - launch interactive editor
if (options.edit) {
  const initialConfig = propertiesToConfigState(properties, configDetails);


 ... (clipped 16 lines)

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status:
Unstructured error output: The new stubbed command emits unstructured console.error messages (including user-provided
objectName), which may not meet structured logging requirements depending on how CLI
output is treated in your logging/auditing model.

Referred Code
// TODO: Migrate to v2 client when lock/unlock contracts are available
// This command requires v1-specific features: searchObjectsDetailed, lockObject
// See: docs/plans/active/2025-12-20-adt-cli-api-compatibility.md

async function lockObject(objectName: string): Promise<void> {
  // Stub implementation - command needs migration to v2 client
  console.error(`❌ Lock command is temporarily disabled pending v2 client migration.`);
  console.error(`   Object: ${objectName}`);
  console.error(`💡 Use SAP GUI transaction SE80 or SM12 to manage locks.`);
  process.exit(1);
}

export function createLockCommand(): Command {
  const command = new Command('lock');

  command
    .description('Lock a SAP object by name (temporarily disabled)')
    .argument('<objectName>', 'Name of the object to lock (e.g., ZIF_PETSTORE)')
    .action(async (objectName: string) => {
      await lockObject(objectName);
    });

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Type-bypass on PUT: The PUT request body is forced into the client contract type via as unknown as ... without
runtime validation, which could allow malformed/unsafe payloads to be sent if upstream
data is unexpected.

Referred Code
const configData = buildConfigurationData(newProps);

// Cast to unknown to bypass schema mismatch - TODO: align schema with actual API
await client.adt.cts.transportrequests.searchconfiguration.configurations.put(
  configId,
  configData as unknown as Parameters<typeof client.adt.cts.transportrequests.searchconfiguration.configurations.put>[1]
);

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-code-review
Copy link

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
Stubbing out commands causes regression

The PR stubs out the lock, unlock, outline, and research-sessions commands due
to missing features in the new v2 client API, causing a functional regression.
It is suggested to either implement the missing features in the v2 client or
postpone the migration.

Examples:

packages/adt-cli/src/lib/commands/lock.ts [3-13]
// TODO: Migrate to v2 client when lock/unlock contracts are available
// This command requires v1-specific features: searchObjectsDetailed, lockObject
// See: docs/plans/active/2025-12-20-adt-cli-api-compatibility.md

async function lockObject(objectName: string): Promise<void> {
  // Stub implementation - command needs migration to v2 client
  console.error(`❌ Lock command is temporarily disabled pending v2 client migration.`);
  console.error(`   Object: ${objectName}`);
  console.error(`💡 Use SAP GUI transaction SE80 or SM12 to manage locks.`);
  process.exit(1);

 ... (clipped 1 lines)
packages/adt-cli/src/lib/commands/outline.ts [3-16]
// TODO: Migrate to v2 client when outline contracts are available
// This command requires v1-specific features: searchObjectsDetailed, ObjectRegistry
// See: docs/plans/active/2025-12-20-adt-cli-api-compatibility.md

export const outlineCommand = new Command('outline')
  .argument('<objectName>', 'ABAP object name to show outline for')
  .description('Show object structure outline (temporarily disabled)')
  .action(async (objectName: string) => {
    // Stub implementation - command needs migration to v2 client
    console.error(`❌ Outline command is temporarily disabled pending v2 client migration.`);

 ... (clipped 4 lines)

Solution Walkthrough:

Before:

// packages/adt-cli/src/lib/commands/lock.ts

// TODO: Migrate to v2 client when lock/unlock contracts are available
async function lockObject(objectName: string): Promise<void> {
  // Stub implementation - command needs migration to v2 client
  console.error(`❌ Lock command is temporarily disabled pending v2 client migration.`);
  console.error(`💡 Use SAP GUI transaction SE80 or SM12 to manage locks.`);
  process.exit(1);
}

export function createLockCommand(): Command {
  return new Command('lock')
    .description('Lock a SAP object by name (temporarily disabled)')
    .action(async (objectName: string) => {
      await lockObject(objectName);
    });
}

After:

// packages/adt-cli/src/lib/commands/lock.ts
import { AdtClientImpl } from '@abapify/adt-client'; // Reverting to v1 client for this command

async function lockObject(objectName: string, options: any, command: any) {
  try {
    console.log(`🔒 Locking object: ${objectName}`);
    const client = new AdtClientImpl({ ... }); // v1 client

    // Search for the object using ADT client search function
    const result = await client.repository.searchObjectsDetailed(...);
    // ... find exact match and URI

    // Lock the object
    const lockHandle = await client.repository.lockObject(objectUri);
    console.log(`✅ SUCCESS! Object ${objectName} locked`);
  } catch (error) {
    console.error(`❌ Lock failed:`, error);
    process.exit(1);
  }
}
Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies a significant functional regression where four commands (lock, unlock, outline, research-sessions) are stubbed out, which is a critical drawback of the v2 client migration.

High
Possible issue
Prevent runtime error on nullish response

Use optional chaining and a nullish coalescing fallback to an empty object when
extracting pkgData to prevent potential runtime errors if the pkg response is
nullish.

packages/adt-cli/src/lib/commands/package/get.ts [31-44]

 // Extract package data - response is wrapped in { package: ... }
-const pkgData = (pkg as { package?: Record<string, unknown> }).package ?? pkg;
+const pkgData = (pkg as { package?: Record<string, unknown> })?.package ?? pkg ?? {};
 if (route) {
   const page = route.page(pkgData, { name });
   render(page);
 } else {
   // Fallback: simple output
   const pkgAny = pkgData as Record<string, unknown>;
   console.log(`📦 Package: ${pkgAny.name || name}`);
   console.log(`   Type: ${pkgAny.type || 'N/A'}`);
   console.log(`   Description: ${pkgAny.description || 'N/A'}`);
   const attrs = pkgAny.attributes as Record<string, unknown> | undefined;
   console.log(`   Package Type: ${attrs?.packageType || 'N/A'}`);
 }
  • Apply / Chat
Suggestion importance[1-10]: 5

__

Why: The suggestion correctly identifies a potential runtime error if pkg is nullish and proposes a more robust way to handle it using optional chaining and a final fallback to an empty object, improving code safety.

Low
General
Use consistent variable after type casting

Consistently use the pluginWithVersion variable for accessing both name and
version properties in the warning message to improve code readability and
consistency after type casting.

packages/adt-cli/src/lib/config/validation.ts [84-90]

 // Validate version if specified (version is optional on PluginSpec)
 const pluginWithVersion = plugin as { name: string; version?: string; config?: unknown };
 if (pluginWithVersion.version && !this.isValidSemver(pluginWithVersion.version)) {
   warnings.push(
-    `Plugin ${plugin.name} has invalid version format: ${pluginWithVersion.version}`
+    `Plugin ${pluginWithVersion.name} has invalid version format: ${pluginWithVersion.version}`
   );
 }
  • Apply / Chat
Suggestion importance[1-10]: 3

__

Why: The suggestion improves code consistency and readability by using the same variable (pluginWithVersion) after a type cast, which is a good practice, although the impact is minor.

Low
  • More

@ThePlenkov
Copy link
Member Author

Findings Acknowledged ✅

Thanks for the automated review!

Will Address:

  1. Stubbed Commands (High Priority) - The , , , and commands are intentionally stubbed as part of the v2 client migration. These will be re-enabled once the corresponding contracts are available. Tracked in the migration plan.

  2. Nullish Response Handling - Good catch on the optional chaining for pkgData. Will apply the safer pattern:

    const pkgData = (pkg as { package?: Record<string, unknown> })?.package ?? pkg ?? {};
  3. Consistent Variable Usage - Minor but valid. Will use pluginWithVersion.name for consistency after the type cast.


Reviewed by: @pplenkov

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant