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
7 changes: 3 additions & 4 deletions packages/adt-cli/src/lib/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,10 @@ import { refreshCommand } from './commands/auth/refresh';
// Add '@abapify/adt-export/commands/export' to adt.config.ts commands array to enable
import { createCliLogger, AVAILABLE_COMPONENTS } from './utils/logger-config';
import { setCliContext } from './utils/adt-client-v2';
import { existsSync } from 'fs';
import { existsSync, readFileSync } from 'node:fs';
import { resolve } from 'node:path';
import { loadCommandPlugins, loadStaticPlugins } from './plugin-loader';
import type { CliCommandPlugin } from '@abapify/adt-plugin';
import { readFileSync } from 'fs';
import { resolve } from 'path';

// Check for insecure SSL flag in stored session and apply it globally
function applyInsecureSslFlag(): void {
Expand Down Expand Up @@ -79,7 +78,7 @@ ${globalOptions}
}

function getResolvedConfigPath(argv: string[]): string | undefined {
const configArgIndex = argv.findIndex((arg) => arg === '--config');
const configArgIndex = argv.indexOf('--config');
if (configArgIndex !== -1) {
return argv[configArgIndex + 1];
}
Expand Down
87 changes: 36 additions & 51 deletions packages/adt-config/src/config-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,8 @@ function mergeLocalConfig(
...baseConfig,
...overlayConfig,
destinations: {
...(baseConfig.destinations || {}),
...(overlayConfig.destinations || {}),
...baseConfig.destinations,
...overlayConfig.destinations,
},
};
}
Expand Down Expand Up @@ -226,6 +226,35 @@ export interface LoadConfigOptions {
cwd?: string;
}

/**
* Try loading a config file from an explicit path (JSON or TS/JS).
*/
async function loadExplicitConfig(
configPath: string,
): Promise<AdtConfig | null> {
if (configPath.endsWith('.json')) {
return loadJsonConfig(configPath);
}
return loadTsConfig(configPath);
}

/**
* Discover a config file by trying multiple extensions in priority order:
* .ts → .js → .json
*/
async function discoverConfig(
basePath: string,
baseName: string,
): Promise<AdtConfig | null> {
const tsConfig = await loadTsConfig(join(basePath, `${baseName}.ts`));
if (tsConfig) return tsConfig;

const jsConfig = await loadTsConfig(join(basePath, `${baseName}.js`));
if (jsConfig) return jsConfig;

return loadJsonConfig(join(basePath, `${baseName}.json`));
}

/**
* Load configuration with precedence:
* 1. Explicit configPath (if provided via --config flag)
Expand All @@ -246,17 +275,9 @@ export async function loadConfig(
// If explicit config path provided, use it directly
if (opts.configPath) {
const configPath = resolve(cwd, opts.configPath);
if (configPath.endsWith('.json')) {
const jsonConfig = loadJsonConfig(configPath);
if (jsonConfig) {
return createLoadedConfig(mergeWithGlobal(jsonConfig));
}
} else {
// Assume TS/JS config
const tsConfig = await loadTsConfig(configPath);
if (tsConfig) {
return createLoadedConfig(mergeWithGlobal(tsConfig));
}
const config = await loadExplicitConfig(configPath);
if (config) {
return createLoadedConfig(mergeWithGlobal(config));
}
// Config path specified but file not found/loadable - continue with auto-discovery
console.warn(
Expand All @@ -265,46 +286,10 @@ export async function loadConfig(
}

// Discover base local config (adt.config.*)
let baseLocalConfig: AdtConfig | null = null;

const tsConfigPath = join(cwd, 'adt.config.ts');
const tsConfig = await loadTsConfig(tsConfigPath);
if (tsConfig) {
baseLocalConfig = tsConfig;
} else {
const jsConfigPath = join(cwd, 'adt.config.js');
const jsConfig = await loadTsConfig(jsConfigPath);
if (jsConfig) {
baseLocalConfig = jsConfig;
} else {
const jsonConfigPath = join(cwd, 'adt.config.json');
const jsonConfig = loadJsonConfig(jsonConfigPath);
if (jsonConfig) {
baseLocalConfig = jsonConfig;
}
}
}
const baseLocalConfig = await discoverConfig(cwd, 'adt.config');

// Discover optional local override (.adt/config.*)
let localOverrideConfig: AdtConfig | null = null;

const dotAdtTsConfigPath = join(cwd, '.adt', 'config.ts');
const dotAdtTsConfig = await loadTsConfig(dotAdtTsConfigPath);
if (dotAdtTsConfig) {
localOverrideConfig = dotAdtTsConfig;
} else {
const dotAdtJsConfigPath = join(cwd, '.adt', 'config.js');
const dotAdtJsConfig = await loadTsConfig(dotAdtJsConfigPath);
if (dotAdtJsConfig) {
localOverrideConfig = dotAdtJsConfig;
} else {
const dotAdtJsonConfigPath = join(cwd, '.adt', 'config.json');
const dotAdtJsonConfig = loadJsonConfig(dotAdtJsonConfigPath);
if (dotAdtJsonConfig) {
localOverrideConfig = dotAdtJsonConfig;
}
}
}
const localOverrideConfig = await discoverConfig(join(cwd, '.adt'), 'config');

// Discover optional destinations directory (.adt/destinations/*.json)
const destinationsDirConfig = loadDestinationsDirectory(cwd);
Expand Down
11 changes: 6 additions & 5 deletions packages/adt-plugin-abapgit/src/lib/handlers/objects/prog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@ export const programHandler = createHandler(AdkProgram, {
fromAbapGit: ({ PROGDIR, TPOOL }) => {
// Extract description from TPOOL (text pool) if available
// TPOOL.item can be a single object or an array
const descriptionEntry = Array.isArray(TPOOL?.item)
? TPOOL.item.find((t: { ID?: string }) => t.ID === 'R')
: TPOOL?.item?.ID === 'R'
? TPOOL.item
: undefined;
let descriptionEntry: { ID?: string; ENTRY?: string } | undefined;
if (Array.isArray(TPOOL?.item)) {
descriptionEntry = TPOOL.item.find((t: { ID?: string }) => t.ID === 'R');
} else if (TPOOL?.item?.ID === 'R') {
descriptionEntry = TPOOL.item;
}

// SUBC can be parsed as number or string depending on XML parser
const subc = String(PROGDIR?.SUBC ?? '');
Expand Down
76 changes: 38 additions & 38 deletions packages/ts-xsd/src/xml/build-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,43 @@
* element to be emitted without a prefix, the xmlns declaration is still
* required for the document to be in the correct namespace.
*/
/**
* Collect prefixes used by elements and attributes in the tree (recursive walk).
*/
function collectUsedPrefixes(

Check failure on line 154 in packages/ts-xsd/src/xml/build-utils.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this function to reduce its Cognitive Complexity from 16 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=abapify_adt-cli&issues=AZzuPZ1HuzevaEjDht_g&open=AZzuPZ1HuzevaEjDht_g&pullRequest=83
node: XmlElement,
usedPrefixes: Set<string>,
): void {
// Check the element's own tag for a prefix
const tagParts = node.tagName.split(':');
if (tagParts.length === 2) {
usedPrefixes.add(tagParts[0]);
}

// Check attributes (skip xmlns declarations themselves)
if (node.attributes) {
for (const attr of Array.from(node.attributes)) {
if (attr.name.startsWith('xmlns:') || attr.name === 'xmlns') {
continue;
}
const attrParts = attr.name.split(':');
if (attrParts.length === 2) {
usedPrefixes.add(attrParts[0]);
}
}
}

// Recurse into child elements
if (node.childNodes) {
for (const child of Array.from(node.childNodes)) {
if (child.nodeType === 1) {
collectUsedPrefixes(child as XmlElement, usedPrefixes);
}
}
}
}

export function stripUnusedNamespaces(

Check failure on line 187 in packages/ts-xsd/src/xml/build-utils.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this function to reduce its Cognitive Complexity from 19 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=abapify_adt-cli&issues=AZzuPZ1IuzevaEjDht_h&open=AZzuPZ1IuzevaEjDht_h&pullRequest=83
root: XmlElement,
schema?: SchemaLike,
): void {
Expand All @@ -164,49 +200,13 @@
}
}

function walk(node: XmlElement): void {
// Check the element's own tag for a prefix
const tagParts = node.tagName.split(':');
if (tagParts.length === 2) {
usedPrefixes.add(tagParts[0]);
}

// Check attributes (skip xmlns declarations themselves)
const attrs = node.attributes;
if (attrs) {
for (let i = 0; i < attrs.length; i++) {
const attr = attrs[i];
if (attr.name.startsWith('xmlns:') || attr.name === 'xmlns') {
continue;
}
const attrParts = attr.name.split(':');
if (attrParts.length === 2) {
usedPrefixes.add(attrParts[0]);
}
}
}

// Recurse into child elements
const children = node.childNodes;
if (children) {
for (let i = 0; i < children.length; i++) {
const child = children[i];
if (child.nodeType === 1) {
// ELEMENT_NODE
walk(child as XmlElement);
}
}
}
}

walk(root);
collectUsedPrefixes(root, usedPrefixes);

// Remove xmlns:prefix declarations where prefix is not used
const toRemove: string[] = [];
const attrs = root.attributes;
if (attrs) {
for (let i = 0; i < attrs.length; i++) {
const attr = attrs[i];
for (const attr of Array.from(attrs)) {
if (attr.name.startsWith('xmlns:')) {
const pfx = attr.name.substring(6);
if (!usedPrefixes.has(pfx)) {
Expand Down
Loading