catalyst-relay 0.5.8 → 0.5.9

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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/types/result.ts","../src/types/config.ts","../src/core/auth/basic/basic.ts","../src/core/auth/sso/slsClient.ts","../src/core/auth/sso/types.ts","../src/core/auth/sso/kerberos.ts","../src/core/auth/sso/certificate.ts","../src/core/auth/sso/pkcs7.ts","../src/core/auth/sso/storage.ts","../src/core/auth/sso/sso.ts","../src/core/auth/saml/types.ts","../src/core/auth/saml/browser.ts","../src/core/auth/saml/cookies.ts","../src/core/auth/saml/saml.ts","../src/core/auth/factory.ts","../src/core/session/types.ts","../src/core/utils/xml.ts","../src/core/utils/csrf.ts","../src/core/utils/headers.ts","../src/core/utils/logging.ts","../src/core/utils/content.ts","../src/core/session/login.ts","../src/core/session/refresh.ts","../src/client/methods/lifecycle/login.ts","../src/client/methods/lifecycle/logout.ts","../src/client/methods/lifecycle/refreshSession.ts","../src/client/methods/session/exportSessionState.ts","../src/client/methods/session/importSessionState.ts","../src/core/adt/types.ts","../src/core/adt/helpers.ts","../src/core/adt/craud/read.ts","../src/core/adt/craud/lock.ts","../src/core/adt/craud/create.ts","../src/core/adt/craud/update.ts","../src/core/adt/craud/delete.ts","../src/core/adt/craud/activation.ts","../src/core/adt/craud/syntaxCheck.ts","../src/core/adt/discovery/tree/packageStats.ts","../src/core/adt/discovery/packages.ts","../src/core/adt/discovery/tree/parsers.ts","../src/core/adt/discovery/tree/childPackages.ts","../src/core/adt/discovery/tree/virtualFolders.ts","../src/core/adt/discovery/tree/index.ts","../src/core/adt/transports/transports.ts","../src/core/adt/data_extraction/previewParser.ts","../src/core/adt/data_extraction/dataPreview.ts","../src/core/adt/data_extraction/freestyle.ts","../src/core/adt/data_extraction/queryBuilder.ts","../src/core/adt/data_extraction/distinct.ts","../src/core/adt/data_extraction/count.ts","../src/core/adt/discovery/searchObjects.ts","../src/core/adt/discovery/whereUsed.ts","../src/core/adt/transports/createTransport.ts","../src/core/adt/transports/parseTransportTasks.ts","../src/core/adt/transports/removeFromTransport.ts","../src/core/adt/transports/deleteTransport.ts","../src/core/adt/craud/gitDiff.ts","../src/client/methods/craud/read.ts","../src/client/methods/craud/create.ts","../src/client/methods/craud/update.ts","../src/client/methods/craud/upsert.ts","../src/client/methods/craud/activate.ts","../src/client/methods/craud/delete.ts","../src/client/methods/craud/checkSyntax.ts","../src/client/methods/discovery/getPackages.ts","../src/client/methods/discovery/getTree.ts","../src/client/methods/discovery/getPackageStats.ts","../src/client/methods/discovery/getTransports.ts","../src/client/methods/preview/previewData.ts","../src/client/methods/preview/getDistinctValues.ts","../src/client/methods/preview/countRows.ts","../src/client/methods/search/search.ts","../src/client/methods/search/whereUsed.ts","../src/client/methods/transport/createTransport.ts","../src/client/methods/transport/deleteTransport.ts","../src/client/methods/transport/removeFromTransport.ts","../src/client/methods/diff/gitDiff.ts","../src/client/methods/config/getObjectConfig.ts","../src/client/methods/internal/cookies.ts","../src/client/methods/internal/autoRefresh.ts","../src/client/helpers.ts","../src/client/methods/internal/request.ts","../src/client/client.ts","../src/client/index.ts"],"sourcesContent":["/**\r\n * Catalyst-Relay\r\n *\r\n * TypeScript middleware for SAP ADT integration.\r\n * Can be used as a library (direct imports) or as an HTTP server.\r\n *\r\n * @example Library usage\r\n * ```typescript\r\n * import { createClient } from 'catalyst-relay';\r\n *\r\n * const [client, error] = createClient({\r\n * url: 'https://sap-server:443',\r\n * client: '100',\r\n * auth: { type: 'basic', username: 'user', password: 'pass' }\r\n * });\r\n * if (error) throw error;\r\n *\r\n * const [session, loginError] = await client.login();\r\n * if (loginError) throw loginError;\r\n *\r\n * const [data, readError] = await client.read([\r\n * { name: 'ZTEST_VIEW', extension: 'asddls' }\r\n * ]);\r\n * ```\r\n *\r\n * @example Server usage\r\n * ```bash\r\n * bun run src/server.ts\r\n * ```\r\n */\r\n\r\n// Core exports\r\nexport { createClient } from './core';\r\nexport type { ADTClient } from './core';\r\n\r\n// Logging control\r\nexport { activateLogging, deactivateLogging } from './core';\r\n\r\n// Config types\r\nexport type {\r\n AuthType,\r\n AuthConfig,\r\n BasicAuthConfig,\r\n SamlAuthConfig,\r\n SsoAuthConfig,\r\n ClientConfig,\r\n} from './types/config';\r\n\r\n// Request types\r\nexport type {\r\n ObjectRef,\r\n ObjectContent,\r\n TreeQuery,\r\n PreviewSQL,\r\n} from './types/requests';\r\n\r\n// Response wrappers\r\nexport type {\r\n ApiResponse,\r\n SuccessResponse,\r\n ErrorResponse,\r\n ErrorCode,\r\n} from './types/responses';\r\n\r\n// Result types\r\nexport type { Result, AsyncResult } from './types/result';\r\n\r\n// Session types\r\nexport type { Session, ExportableSessionState } from './core/session/types';\r\n\r\n// ADT domain types\r\nexport type {\r\n ObjectMetadata,\r\n ObjectWithContent,\r\n UpsertResult,\r\n ActivationResult,\r\n ActivationMessage,\r\n Transport,\r\n Package,\r\n DataFrame,\r\n ColumnInfo,\r\n DistinctResult,\r\n SearchResult,\r\n SearchOptions,\r\n Dependency,\r\n DiffResult,\r\n TransportConfig,\r\n TransportObject,\r\n ObjectConfig,\r\n // Tree types\r\n TreeResponse,\r\n PackageNode,\r\n FolderNode,\r\n ObjectNode,\r\n} from './core/adt';\r\n\r\n// Query builder (optional helper for data preview)\r\nexport { buildSQLQuery } from './core/adt';\r\nexport type { DataPreviewQuery, QueryFilter, BasicFilter, BetweenFilter, ListFilter, Sorting, Aggregation, Parameter } from './core/adt';\r\n\r\n// Result utilities\r\nexport { ok, err } from './types/result';\r\n","/**\r\n * Result type for error handling (Go-style tuples)\r\n *\r\n * Usage:\r\n * const [data, error] = await someFunction();\r\n * if (error) {\r\n * console.error(error);\r\n * return;\r\n * }\r\n * // data is guaranteed non-null\r\n */\r\n\r\nexport type Result<T, E extends Error = Error> = [T, null] | [null, E];\r\n\r\n/**\r\n * Async result type alias for convenience\r\n */\r\nexport type AsyncResult<T, E extends Error = Error> = Promise<Result<T, E>>;\r\n\r\n/**\r\n * Create a success result\r\n */\r\nexport function ok<T>(value: T): Result<T, never> {\r\n return [value, null];\r\n}\r\n\r\n/**\r\n * Create an error result\r\n */\r\nexport function err<E extends Error = Error>(error: E): Result<never, E> {\r\n return [null, error];\r\n}\r\n\r\nexport function resolveAll<T, E extends Error = Error>(results: Result<T, E>[]): Result<T[], AggregateError> {\r\n const [successes, errors]: [T[], E[]] = [[], []];\r\n for (const [val, err] of results) {\r\n if (err !== null) {\r\n errors.push(err);\r\n continue;\r\n }\r\n successes.push(val!);\r\n }\r\n if (errors.length) {\r\n const messages = errors.map((e, i) => `[${i + 1}] ${e.message}`).join('\\n');\r\n return err(new AggregateError(errors, `Multiple upsert errors:\\n${messages}`));\r\n }\r\n return ok(successes);\r\n}\r\n\r\nexport async function resolveAllAsync<T, E extends Error = Error>(resultPromises: AsyncResult<T, E>[]): AsyncResult<T[], AggregateError> {\r\n const results = await Promise.all(resultPromises);\r\n return resolveAll(results);\r\n}","import { z } from 'zod';\r\n\r\n/**\r\n * Authentication types supported by SAP ADT\r\n */\r\nexport type AuthType = 'basic' | 'saml' | 'sso';\r\n\r\n/**\r\n * Basic authentication configuration\r\n */\r\nexport interface BasicAuthConfig {\r\n type: 'basic';\r\n username: string;\r\n password: string;\r\n}\r\n\r\n/**\r\n * CSS selectors for SAML login form\r\n */\r\nexport interface SamlFormSelectors {\r\n /** CSS selector for username input field */\r\n username: string;\r\n /** CSS selector for password input field */\r\n password: string;\r\n /** CSS selector for submit button */\r\n submit: string;\r\n}\r\n\r\n/**\r\n * SAML provider configuration\r\n */\r\nexport interface SamlProviderConfig {\r\n /** Whether to ignore HTTPS certificate errors */\r\n ignoreHttpsErrors: boolean;\r\n /** CSS selectors for login form elements */\r\n formSelectors: SamlFormSelectors;\r\n}\r\n\r\n/**\r\n * SAML authentication configuration\r\n */\r\nexport interface SamlAuthConfig {\r\n type: 'saml';\r\n /** SAML username (often an email address) - used for browser login */\r\n username: string;\r\n /** SAML password */\r\n password: string;\r\n /** SAP system username - used for object creation (adtcore:responsible) */\r\n sapUser: string;\r\n /** Optional custom provider configuration for non-standard login forms */\r\n providerConfig?: SamlProviderConfig;\r\n}\r\n\r\n/**\r\n * SSO (Kerberos) authentication configuration\r\n */\r\nexport interface SsoAuthConfig {\r\n type: 'sso';\r\n /** Secure Login Server URL (e.g., https://sapsso.corp.example.com) */\r\n slsUrl: string;\r\n /** SLS profile name (default: SAPSSO_P) */\r\n profile?: string;\r\n /** Kerberos service principal name override */\r\n servicePrincipalName?: string;\r\n /** Force certificate re-enrollment even if valid cert exists */\r\n forceEnroll?: boolean;\r\n /** @deprecated Use slsUrl instead */\r\n certificate?: string;\r\n}\r\n\r\n/**\r\n * Union of all auth configurations\r\n */\r\nexport type AuthConfig = BasicAuthConfig | SamlAuthConfig | SsoAuthConfig;\r\n\r\n/**\r\n * Auto-refresh configuration for session keepalive\r\n */\r\nexport interface AutoRefreshConfig {\r\n /** Enable automatic session refresh (default: true) */\r\n enabled: boolean;\r\n /** Refresh interval in milliseconds (default: 7200000 = 2 hours) */\r\n intervalMs?: number;\r\n}\r\n\r\n/**\r\n * Client configuration for connecting to SAP ADT\r\n */\r\nexport interface ClientConfig {\r\n /** ADT server URL (e.g., https://server:port) */\r\n url: string;\r\n /** SAP client number (e.g., '100') */\r\n client: string;\r\n /** Authentication configuration */\r\n auth: AuthConfig;\r\n /** Request timeout in milliseconds (default: 30000) */\r\n timeout?: number;\r\n /** Skip SSL verification (dev only) */\r\n insecure?: boolean;\r\n /** Auto-refresh configuration for session keepalive (default: enabled with 2-hour interval) */\r\n autoRefresh?: AutoRefreshConfig;\r\n}\r\n\r\n/**\r\n * Zod schema for SAML form selectors\r\n */\r\nconst samlFormSelectorsSchema = z.object({\r\n username: z.string().min(1),\r\n password: z.string().min(1),\r\n submit: z.string().min(1),\r\n});\r\n\r\n/**\r\n * Zod schema for SAML provider configuration\r\n */\r\nconst samlProviderConfigSchema = z.object({\r\n ignoreHttpsErrors: z.boolean(),\r\n formSelectors: samlFormSelectorsSchema,\r\n});\r\n\r\n/**\r\n * Zod schema for runtime validation of ClientConfig\r\n */\r\nexport const clientConfigSchema = z.object({\r\n url: z.string().url(),\r\n client: z.string().min(1).max(3),\r\n auth: z.discriminatedUnion('type', [\r\n z.object({\r\n type: z.literal('basic'),\r\n username: z.string().min(1),\r\n password: z.string().min(1),\r\n }),\r\n z.object({\r\n type: z.literal('saml'),\r\n username: z.string().min(1),\r\n password: z.string().min(1),\r\n sapUser: z.string().min(1),\r\n providerConfig: samlProviderConfigSchema.optional(),\r\n }),\r\n z.object({\r\n type: z.literal('sso'),\r\n slsUrl: z.string().url(),\r\n profile: z.string().optional(),\r\n servicePrincipalName: z.string().optional(),\r\n forceEnroll: z.boolean().optional(),\r\n certificate: z.string().optional(),\r\n }),\r\n ]),\r\n timeout: z.number().positive().optional(),\r\n insecure: z.boolean().optional(),\r\n autoRefresh: z.object({\r\n enabled: z.boolean(),\r\n intervalMs: z.number().positive().optional(),\r\n }).optional(),\r\n});\r\n","import type { AuthStrategy } from '../types';\r\n\r\n/**\r\n * Basic authentication strategy\r\n *\r\n * Implements HTTP Basic Auth using username/password credentials.\r\n * Credentials are base64-encoded and sent in the Authorization header.\r\n *\r\n * Reference: RFC 7617\r\n */\r\nexport class BasicAuth implements AuthStrategy {\r\n readonly type = 'basic' as const;\r\n private authHeader: string;\r\n\r\n /**\r\n * Create a Basic Auth strategy\r\n * @param username - SAP username\r\n * @param password - SAP password\r\n */\r\n constructor(username: string, password: string) {\r\n if (!username || !password) {\r\n throw new Error('BasicAuth requires both username and password');\r\n }\r\n\r\n const credentials = `${username}:${password}`;\r\n const encoded = btoa(credentials);\r\n this.authHeader = `Basic ${encoded}`;\r\n }\r\n\r\n /**\r\n * Get Authorization header with Basic credentials\r\n * @returns Headers object with Authorization field\r\n */\r\n getAuthHeaders(): Record<string, string> {\r\n return {\r\n Authorization: this.authHeader,\r\n };\r\n }\r\n}\r\n","/**\r\n * SAP Secure Login Server (SLS) client\r\n *\r\n * Handles communication with SLS for certificate enrollment:\r\n * 1. Authenticate using Kerberos SPNEGO\r\n * 2. Submit CSR to get signed certificate\r\n *\r\n * Uses Node.js https module for all HTTP requests (same as client.ts)\r\n * for consistent behavior across Node.js, Electron (VS Code), and Bun.\r\n */\r\n\r\nimport * as https from 'https';\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { SlsConfig, SlsAuthResponse, CertificateMaterial } from './types';\r\nimport { SLS_DEFAULTS } from './types';\r\nimport { getSpnegoToken, extractSpnFromUrl } from './kerberos';\r\nimport { generateKeypair, createCsr, getCurrentUsername } from './certificate';\r\nimport { parsePkcs7Certificates } from './pkcs7';\r\n\r\n/**\r\n * Make HTTP request using Node.js https module.\r\n * Same approach as client.ts for consistency.\r\n */\r\nasync function httpsRequest(\r\n url: string,\r\n options: {\r\n method: string;\r\n headers: Record<string, string>;\r\n body?: Buffer | undefined;\r\n rejectUnauthorized?: boolean | undefined;\r\n }\r\n): Promise<{ status: number; headers: Record<string, string | string[]>; body: Buffer; cookies: string[] }> {\r\n const urlObj = new URL(url);\r\n\r\n return new Promise((resolve, reject) => {\r\n const req = https.request({\r\n hostname: urlObj.hostname,\r\n port: urlObj.port || 443,\r\n path: urlObj.pathname + urlObj.search,\r\n method: options.method,\r\n headers: options.headers,\r\n rejectUnauthorized: options.rejectUnauthorized ?? true,\r\n }, (res) => {\r\n const chunks: Buffer[] = [];\r\n res.on('data', chunk => chunks.push(chunk));\r\n res.on('end', () => {\r\n const body = Buffer.concat(chunks);\r\n\r\n // Extract cookies from set-cookie headers\r\n const cookies: string[] = [];\r\n const setCookieHeader = res.headers['set-cookie'];\r\n if (setCookieHeader) {\r\n for (const cookie of setCookieHeader) {\r\n const cookieValue = cookie.split(';')[0];\r\n if (cookieValue) {\r\n cookies.push(cookieValue);\r\n }\r\n }\r\n }\r\n\r\n resolve({\r\n status: res.statusCode || 0,\r\n headers: res.headers as Record<string, string | string[]>,\r\n body,\r\n cookies,\r\n });\r\n });\r\n });\r\n\r\n req.on('error', reject);\r\n\r\n if (options.body) {\r\n req.write(options.body);\r\n }\r\n req.end();\r\n });\r\n}\r\n\r\n/**\r\n * SLS client options\r\n */\r\ninterface SlsClientConfig {\r\n /** SLS configuration */\r\n config: SlsConfig;\r\n /** Skip SSL verification (required for most corporate environments) */\r\n insecure?: boolean;\r\n}\r\n\r\n/**\r\n * Enroll a client certificate from SLS\r\n *\r\n * Performs the full certificate enrollment flow:\r\n * 1. Authenticate to SLS using Kerberos SPNEGO\r\n * 2. Generate RSA keypair\r\n * 3. Create CSR with current username\r\n * 4. Submit CSR to SLS\r\n * 5. Parse PKCS#7 response to extract certificates\r\n *\r\n * @param options - SLS client configuration\r\n * @returns Certificate material (full chain + private key) or error\r\n *\r\n * @example\r\n * ```typescript\r\n * const [certs, error] = await enrollCertificate({\r\n * config: { slsUrl: 'https://sapsso.corp.example.com' },\r\n * insecure: true,\r\n * });\r\n *\r\n * if (error) {\r\n * console.error('Enrollment failed:', error.message);\r\n * return;\r\n * }\r\n *\r\n * // Use certificates for mTLS\r\n * ```\r\n */\r\nexport async function enrollCertificate(\r\n options: SlsClientConfig\r\n): AsyncResult<CertificateMaterial> {\r\n const { config, insecure = false } = options;\r\n const profile = config.profile ?? SLS_DEFAULTS.PROFILE;\r\n\r\n // Step 1: Authenticate with Kerberos (also captures session cookies)\r\n const [authResult, authErr] = await authenticateToSls(config, profile, insecure);\r\n if (authErr) return err(authErr);\r\n\r\n // Step 2: Generate keypair\r\n const keySize = authResult.response.clientConfig.keySize ?? SLS_DEFAULTS.KEY_SIZE;\r\n const keypair = generateKeypair(keySize);\r\n\r\n // Step 3: Create CSR\r\n const username = getCurrentUsername();\r\n const csrDer = createCsr(keypair, username);\r\n\r\n // Step 4: Submit CSR and get certificate (pass cookies from auth step - like Python's session)\r\n const [certData, certErr] = await requestCertificate(config, profile, csrDer, authResult.cookies, insecure);\r\n if (certErr) return err(certErr);\r\n\r\n // Step 5: Parse PKCS#7 response\r\n const [certs, parseErr] = parsePkcs7Certificates(certData);\r\n if (parseErr) return err(parseErr);\r\n\r\n return ok({\r\n fullChain: certs.fullChain,\r\n privateKey: keypair.privateKeyPem,\r\n });\r\n}\r\n\r\n/**\r\n * Result from SLS authentication, includes cookies for session persistence\r\n */\r\ninterface SlsAuthResult {\r\n response: SlsAuthResponse;\r\n cookies: string[]; // Cookies to pass to subsequent requests (like Python's session)\r\n}\r\n\r\n/**\r\n * Authenticate to SLS using Kerberos SPNEGO\r\n */\r\nasync function authenticateToSls(\r\n config: SlsConfig,\r\n profile: string,\r\n insecure: boolean = false\r\n): AsyncResult<SlsAuthResult> {\r\n // Get SPNEGO token\r\n const spn = config.servicePrincipalName ?? extractSpnFromUrl(config.slsUrl);\r\n const [token, tokenErr] = await getSpnegoToken(spn);\r\n if (tokenErr) return err(tokenErr);\r\n\r\n // Build auth URL\r\n const authUrl = `${config.slsUrl}${SLS_DEFAULTS.LOGIN_ENDPOINT}?profile=${profile}`;\r\n\r\n try {\r\n const response = await httpsRequest(authUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Authorization': `Negotiate ${token}`,\r\n 'Accept': '*/*',\r\n },\r\n rejectUnauthorized: !insecure,\r\n });\r\n\r\n if (response.status < 200 || response.status >= 300) {\r\n const text = response.body.toString('utf-8');\r\n return err(new Error(`SLS authentication failed: ${response.status} - ${text}`));\r\n }\r\n\r\n const authResponse = JSON.parse(response.body.toString('utf-8')) as SlsAuthResponse;\r\n return ok({ response: authResponse, cookies: response.cookies });\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n return err(new Error(`SLS authentication request failed: ${message}`));\r\n }\r\n}\r\n\r\n/**\r\n * Request certificate from SLS by submitting CSR\r\n */\r\nasync function requestCertificate(\r\n config: SlsConfig,\r\n profile: string,\r\n csrDer: Buffer,\r\n cookies: string[], // Session cookies from authentication (like Python's session)\r\n insecure: boolean = false\r\n): AsyncResult<Buffer> {\r\n const certUrl = `${config.slsUrl}${SLS_DEFAULTS.CERTIFICATE_ENDPOINT}?profile=${profile}`;\r\n\r\n try {\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/pkcs10',\r\n 'Content-Length': String(csrDer.length),\r\n 'Accept': '*/*',\r\n };\r\n\r\n // Pass cookies from auth step - like Python's requests.Session() does automatically\r\n if (cookies.length > 0) {\r\n headers['Cookie'] = cookies.join('; ');\r\n }\r\n\r\n const response = await httpsRequest(certUrl, {\r\n method: 'POST',\r\n headers,\r\n body: csrDer,\r\n rejectUnauthorized: !insecure,\r\n });\r\n\r\n if (response.status < 200 || response.status >= 300) {\r\n const text = response.body.toString('utf-8');\r\n return err(new Error(`Certificate request failed: ${response.status} - ${text}`));\r\n }\r\n\r\n return ok(response.body);\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n return err(new Error(`Certificate request failed: ${message}`));\r\n }\r\n}\r\n","/**\r\n * SSO authentication types\r\n *\r\n * Types for Kerberos-based SSO authentication with SAP Secure Login Server (SLS).\r\n */\r\n\r\n/**\r\n * Secure Login Server (SLS) configuration\r\n */\r\nexport interface SlsConfig {\r\n /** SLS server URL (e.g., https://sapsso.corp.example.com:443) */\r\n slsUrl: string;\r\n /** SLS profile name (default: SAPSSO_P) */\r\n profile?: string;\r\n /** Service principal name for Kerberos (e.g., HTTP/sapsso.corp.example.com) */\r\n servicePrincipalName?: string;\r\n}\r\n\r\n/**\r\n * Default SLS configuration values\r\n */\r\nexport const SLS_DEFAULTS = {\r\n PROFILE: 'SAPSSO_P',\r\n LOGIN_ENDPOINT: '/SecureLoginServer/slc3/doLogin',\r\n CERTIFICATE_ENDPOINT: '/SecureLoginServer/slc2/getCertificate',\r\n KEY_SIZE: 2048,\r\n} as const;\r\n\r\n/**\r\n * SLS authentication response from doLogin endpoint\r\n */\r\nexport interface SlsAuthResponse {\r\n clientConfig: {\r\n keySize?: number;\r\n };\r\n}\r\n\r\n/**\r\n * mTLS certificate material for use with undici Agent\r\n */\r\nexport interface CertificateMaterial {\r\n /** PEM-encoded client certificate + CA chain */\r\n fullChain: string;\r\n /** PEM-encoded private key */\r\n privateKey: string;\r\n}\r\n\r\n/**\r\n * Certificate file paths on disk\r\n */\r\nexport interface CertificatePaths {\r\n /** Path to client certificate + CA chain PEM file */\r\n fullChainPath: string;\r\n /** Path to private key PEM file */\r\n keyPath: string;\r\n}\r\n\r\n/**\r\n * Result of certificate enrollment - either material or paths\r\n */\r\nexport type CertificateResult = CertificateMaterial | CertificatePaths;\r\n\r\n/**\r\n * Options for SLS client operations\r\n */\r\nexport interface SlsClientOptions {\r\n /** SLS configuration */\r\n config: SlsConfig;\r\n /** Skip SSL verification (dev only) */\r\n insecure?: boolean;\r\n}\r\n\r\n/**\r\n * Get the base directory for certificate storage\r\n * Uses the user's home directory to ensure consistent location regardless of CWD.\r\n * Falls back to relative path if home dir not available.\r\n */\r\nfunction getCertificateBaseDir(): string {\r\n // Use HOME on Unix, USERPROFILE on Windows, or fallback to relative path\r\n const homeDir = process.env['HOME'] ?? process.env['USERPROFILE'] ?? '.';\r\n return `${homeDir}/.catalyst/certificates/sso`;\r\n}\r\n\r\n/**\r\n * Certificate storage directory structure\r\n */\r\nexport const CERTIFICATE_STORAGE = {\r\n get BASE_DIR(): string { return getCertificateBaseDir(); },\r\n FULL_CHAIN_SUFFIX: '_full_chain.pem',\r\n KEY_SUFFIX: '_key.pem',\r\n} as const;\r\n","/**\r\n * Kerberos SPNEGO token generation\r\n *\r\n * Generates SPNEGO tokens for authenticating to SAP Secure Login Server.\r\n * Uses the kerberos npm package (optional peer dependency).\r\n *\r\n * Platform support:\r\n * - Windows: Uses SSPI (native Windows authentication)\r\n * - Linux/macOS: Uses MIT Kerberos (requires kinit)\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\n\r\n/**\r\n * Kerberos client interface matching the kerberos npm package\r\n */\r\ninterface KerberosClient {\r\n step(token: string): Promise<string | null>;\r\n wrap(message: string, options?: unknown): Promise<string>;\r\n unwrap(message: string): Promise<string>;\r\n}\r\n\r\n/**\r\n * Kerberos module interface\r\n */\r\ninterface KerberosModule {\r\n initializeClient(\r\n service: string,\r\n options?: { mechOID?: string }\r\n ): Promise<KerberosClient>;\r\n}\r\n\r\n/**\r\n * Lazily load kerberos module\r\n *\r\n * @returns Kerberos module or null if not installed\r\n */\r\nasync function loadKerberosModule(): AsyncResult<KerberosModule> {\r\n try {\r\n // Dynamic import to avoid hard dependency\r\n // eslint-disable-next-line @typescript-eslint/no-require-imports\r\n const kerberosModule = require('kerberos') as KerberosModule;\r\n return ok(kerberosModule);\r\n } catch {\r\n return err(new Error(\r\n 'kerberos package is not installed. ' +\r\n 'Install it with: npm install kerberos'\r\n ));\r\n }\r\n}\r\n\r\n/**\r\n * Generate SPNEGO token for Kerberos authentication\r\n *\r\n * Creates a base64-encoded SPNEGO token that can be used in\r\n * Authorization: Negotiate headers for authenticating to SLS.\r\n *\r\n * @param servicePrincipalName - SPN to authenticate to (e.g., HTTP/sapsso.corp.example.com)\r\n * @returns Base64-encoded SPNEGO token or error\r\n *\r\n * @example\r\n * ```typescript\r\n * const [token, error] = await getSpnegoToken('HTTP/sapsso.corp.example.com');\r\n * if (error) {\r\n * console.error('Failed to get SPNEGO token:', error.message);\r\n * return;\r\n * }\r\n *\r\n * // Use in Authorization header\r\n * fetch(url, {\r\n * headers: {\r\n * Authorization: `Negotiate ${token}`\r\n * }\r\n * });\r\n * ```\r\n */\r\nexport async function getSpnegoToken(servicePrincipalName: string): AsyncResult<string> {\r\n const [kerberos, loadErr] = await loadKerberosModule();\r\n if (loadErr) return err(loadErr);\r\n\r\n try {\r\n // Initialize Kerberos client for the given SPN\r\n const client = await kerberos.initializeClient(servicePrincipalName);\r\n\r\n // Step with empty token to get initial SPNEGO token\r\n const token = await client.step('');\r\n\r\n if (!token) {\r\n return err(new Error('Failed to generate SPNEGO token: empty response'));\r\n }\r\n\r\n return ok(token);\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n return err(new Error(`Kerberos authentication failed: ${message}`));\r\n }\r\n}\r\n\r\n/**\r\n * Extract SPN from SLS URL\r\n *\r\n * Generates HTTP service principal name from the SLS URL hostname.\r\n *\r\n * @param slsUrl - SLS server URL\r\n * @returns Service principal name (e.g., HTTP/hostname.example.com)\r\n *\r\n * @example\r\n * ```typescript\r\n * const spn = extractSpnFromUrl('https://sapsso.corp.example.com:443');\r\n * // Returns: 'HTTP/sapsso.corp.example.com'\r\n * ```\r\n */\r\nexport function extractSpnFromUrl(slsUrl: string): string {\r\n const url = new URL(slsUrl);\r\n return `HTTP/${url.hostname}`;\r\n}\r\n","/**\r\n * Certificate generation for SSO authentication\r\n *\r\n * Generates RSA keypairs and PKCS#10 Certificate Signing Requests (CSR)\r\n * for SAP Secure Login Server certificate enrollment.\r\n */\r\n\r\nimport forge from 'node-forge';\r\nimport { SLS_DEFAULTS } from './types';\r\n\r\n/**\r\n * Generated keypair with private key in PEM format\r\n */\r\nexport interface GeneratedKeypair {\r\n /** Private key in PEM format (PKCS#8) */\r\n privateKeyPem: string;\r\n /** forge private key object for signing */\r\n privateKey: forge.pki.rsa.PrivateKey;\r\n /** forge public key object */\r\n publicKey: forge.pki.rsa.PublicKey;\r\n}\r\n\r\n/**\r\n * Generate an RSA keypair\r\n *\r\n * @param keySize - Key size in bits (default: 2048)\r\n * @returns Generated keypair with PEM-encoded private key\r\n *\r\n * @example\r\n * ```typescript\r\n * const keypair = generateKeypair(2048);\r\n * console.log(keypair.privateKeyPem);\r\n * ```\r\n */\r\nexport function generateKeypair(keySize: number = SLS_DEFAULTS.KEY_SIZE): GeneratedKeypair {\r\n const keypair = forge.pki.rsa.generateKeyPair({ bits: keySize, e: 0x10001 });\r\n\r\n const privateKeyPem = forge.pki.privateKeyToPem(keypair.privateKey);\r\n\r\n return {\r\n privateKeyPem,\r\n privateKey: keypair.privateKey,\r\n publicKey: keypair.publicKey,\r\n };\r\n}\r\n\r\n/**\r\n * Create a Certificate Signing Request (CSR)\r\n *\r\n * Generates a PKCS#10 CSR with:\r\n * - Subject: CN=<username>\r\n * - Key Usage: digitalSignature, keyEncipherment\r\n * - Extended Key Usage: clientAuth (OID 1.3.6.1.5.5.7.3.2)\r\n *\r\n * @param keypair - RSA keypair to use for the CSR\r\n * @param username - Username for the certificate subject (CN)\r\n * @returns DER-encoded CSR as Buffer\r\n *\r\n * @example\r\n * ```typescript\r\n * const keypair = generateKeypair(2048);\r\n * const csrDer = createCsr(keypair, 'JOHNDOE');\r\n * ```\r\n */\r\nexport function createCsr(keypair: GeneratedKeypair, username: string): Buffer {\r\n const csr = forge.pki.createCertificationRequest();\r\n\r\n // Set subject (Common Name = username)\r\n csr.publicKey = keypair.publicKey;\r\n csr.setSubject([{\r\n name: 'commonName',\r\n value: username,\r\n }]);\r\n\r\n // Add Key Usage extension\r\n csr.setAttributes([{\r\n name: 'extensionRequest',\r\n extensions: [\r\n {\r\n name: 'keyUsage',\r\n digitalSignature: true,\r\n keyEncipherment: true,\r\n },\r\n {\r\n name: 'extKeyUsage',\r\n clientAuth: true,\r\n },\r\n ],\r\n }]);\r\n\r\n // Sign the CSR with SHA-256\r\n csr.sign(keypair.privateKey, forge.md.sha256.create());\r\n\r\n // Convert to DER format\r\n const csrAsn1 = forge.pki.certificationRequestToAsn1(csr);\r\n const csrDer = forge.asn1.toDer(csrAsn1);\r\n\r\n return Buffer.from(csrDer.getBytes(), 'binary');\r\n}\r\n\r\n/**\r\n * Get current Windows username\r\n *\r\n * @returns Username from environment or 'unknown'\r\n */\r\nexport function getCurrentUsername(): string {\r\n return process.env['USERNAME'] ?? process.env['USER'] ?? 'unknown';\r\n}\r\n","/**\r\n * PKCS#7 certificate parsing\r\n *\r\n * Parses PKCS#7 SignedData structures returned by SAP Secure Login Server\r\n * to extract client certificates and CA chain.\r\n */\r\n\r\nimport forge from 'node-forge';\r\nimport type { Result } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\n\r\n/**\r\n * Parsed certificate chain\r\n */\r\nexport interface ParsedCertificates {\r\n /** PEM-encoded client certificate + CA chain */\r\n fullChain: string;\r\n /** PEM-encoded client certificate only */\r\n clientCert: string;\r\n /** PEM-encoded CA chain (intermediate + root) */\r\n caChain: string;\r\n}\r\n\r\n/**\r\n * Parse PKCS#7 certificate data from SLS response\r\n *\r\n * SLS returns a base64-encoded PKCS#7 structure containing:\r\n * - Client certificate (first cert)\r\n * - CA certificate chain (remaining certs)\r\n *\r\n * @param data - Raw response data from SLS (may be base64-encoded)\r\n * @returns Parsed certificates or error\r\n *\r\n * @example\r\n * ```typescript\r\n * const [certs, error] = parsePkcs7Certificates(responseBuffer);\r\n * if (error) {\r\n * console.error('Parse failed:', error.message);\r\n * return;\r\n * }\r\n *\r\n * console.log(certs.clientCert); // PEM client cert\r\n * console.log(certs.caChain); // PEM CA chain\r\n * console.log(certs.fullChain); // Both combined\r\n * ```\r\n */\r\nexport function parsePkcs7Certificates(data: Buffer): Result<ParsedCertificates> {\r\n try {\r\n // Clean and decode the data\r\n // SLS returns base64-encoded PKCS#7 with possible whitespace\r\n const dataString = data.toString('utf-8').replace(/\\r?\\n/g, '').trim();\r\n const derBytes = forge.util.decode64(dataString);\r\n\r\n // Parse PKCS#7 structure\r\n const p7Asn1 = forge.asn1.fromDer(derBytes);\r\n const p7 = forge.pkcs7.messageFromAsn1(p7Asn1);\r\n\r\n // Extract certificates from SignedData\r\n if (!('certificates' in p7) || !p7.certificates || p7.certificates.length === 0) {\r\n return err(new Error('No certificates found in PKCS#7 structure'));\r\n }\r\n\r\n const certificates = p7.certificates as forge.pki.Certificate[];\r\n\r\n // First certificate is the client cert, rest are CA chain\r\n const clientCert = certificates[0];\r\n const caCerts = certificates.slice(1);\r\n\r\n if (!clientCert) {\r\n return err(new Error('No client certificate found in PKCS#7 structure'));\r\n }\r\n\r\n // Convert to PEM format\r\n const clientCertPem = forge.pki.certificateToPem(clientCert);\r\n const caChainPem = caCerts\r\n .map(cert => forge.pki.certificateToPem(cert))\r\n .join('');\r\n\r\n return ok({\r\n clientCert: clientCertPem,\r\n caChain: caChainPem,\r\n fullChain: clientCertPem + caChainPem,\r\n });\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n return err(new Error(`Failed to parse PKCS#7 certificates: ${message}`));\r\n }\r\n}\r\n","/**\r\n * Certificate storage\r\n *\r\n * Persists and retrieves mTLS certificates from the filesystem.\r\n */\r\n\r\nimport { readFile, writeFile, mkdir, stat } from 'node:fs/promises';\r\nimport { join } from 'node:path';\r\nimport type { AsyncResult, Result } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { CertificateMaterial, CertificatePaths } from './types';\r\nimport { CERTIFICATE_STORAGE } from './types';\r\nimport { getCurrentUsername } from './certificate';\r\n\r\n/**\r\n * Get certificate file paths for a user\r\n *\r\n * @param username - Username (defaults to current user)\r\n * @returns Certificate file paths\r\n */\r\nexport function getCertificatePaths(username?: string): CertificatePaths {\r\n const user = username ?? getCurrentUsername();\r\n return {\r\n fullChainPath: join(CERTIFICATE_STORAGE.BASE_DIR, `${user}${CERTIFICATE_STORAGE.FULL_CHAIN_SUFFIX}`),\r\n keyPath: join(CERTIFICATE_STORAGE.BASE_DIR, `${user}${CERTIFICATE_STORAGE.KEY_SUFFIX}`),\r\n };\r\n}\r\n\r\n/**\r\n * Save certificates to filesystem\r\n *\r\n * @param material - Certificate material to save\r\n * @param username - Username (defaults to current user)\r\n * @returns File paths or error\r\n *\r\n * @example\r\n * ```typescript\r\n * const [paths, error] = await saveCertificates(material);\r\n * if (error) {\r\n * console.error('Save failed:', error.message);\r\n * return;\r\n * }\r\n *\r\n * console.log('Saved to:', paths.fullChainPath, paths.keyPath);\r\n * ```\r\n */\r\nexport async function saveCertificates(\r\n material: CertificateMaterial,\r\n username?: string\r\n): AsyncResult<CertificatePaths> {\r\n const paths = getCertificatePaths(username);\r\n\r\n try {\r\n // Ensure directory exists\r\n await mkdir(CERTIFICATE_STORAGE.BASE_DIR, { recursive: true });\r\n\r\n // Write certificate files\r\n await writeFile(paths.fullChainPath, material.fullChain, 'utf-8');\r\n await writeFile(paths.keyPath, material.privateKey, { encoding: 'utf-8', mode: 0o600 });\r\n\r\n return ok(paths);\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n return err(new Error(`Failed to save certificates: ${message}`));\r\n }\r\n}\r\n\r\n/**\r\n * Load certificates from filesystem\r\n *\r\n * @param username - Username (defaults to current user)\r\n * @returns Certificate material or error\r\n *\r\n * @example\r\n * ```typescript\r\n * const [material, error] = await loadCertificates();\r\n * if (error) {\r\n * // Certificates don't exist, need to enroll\r\n * return;\r\n * }\r\n *\r\n * // Use loaded certificates\r\n * ```\r\n */\r\nexport async function loadCertificates(username?: string): AsyncResult<CertificateMaterial> {\r\n const paths = getCertificatePaths(username);\r\n\r\n try {\r\n const [fullChain, privateKey] = await Promise.all([\r\n readFile(paths.fullChainPath, 'utf-8'),\r\n readFile(paths.keyPath, 'utf-8'),\r\n ]);\r\n\r\n return ok({ fullChain, privateKey });\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n return err(new Error(`Failed to load certificates: ${message}`));\r\n }\r\n}\r\n\r\n/**\r\n * Check if certificates exist for a user\r\n *\r\n * @param username - Username (defaults to current user)\r\n * @returns True if certificates exist\r\n */\r\nexport async function certificatesExist(username?: string): Promise<boolean> {\r\n const paths = getCertificatePaths(username);\r\n\r\n try {\r\n await Promise.all([\r\n stat(paths.fullChainPath),\r\n stat(paths.keyPath),\r\n ]);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Check if a certificate is expired or will expire soon\r\n *\r\n * @param certPem - PEM-encoded certificate\r\n * @param bufferDays - Days before expiry to consider as \"expiring soon\" (default: 1)\r\n * @returns True if expired or expiring soon\r\n */\r\nexport function isCertificateExpired(certPem: string, bufferDays: number = 1): Result<boolean> {\r\n try {\r\n // Import forge dynamically to avoid loading it if not needed\r\n // eslint-disable-next-line @typescript-eslint/no-require-imports\r\n const forge = require('node-forge');\r\n\r\n const cert = forge.pki.certificateFromPem(certPem);\r\n const notAfter = cert.validity.notAfter as Date;\r\n const bufferMs = bufferDays * 24 * 60 * 60 * 1000;\r\n const expiryThreshold = new Date(Date.now() + bufferMs);\r\n\r\n return ok(notAfter <= expiryThreshold);\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n return err(new Error(`Failed to check certificate expiry: ${message}`));\r\n }\r\n}\r\n","/**\r\n * SSO (Single Sign-On) authentication strategy\r\n *\r\n * Implements Kerberos-based SSO for SAP systems using mTLS certificates\r\n * obtained from SAP Secure Login Server (SLS).\r\n *\r\n * Authentication flow:\r\n * 1. Check for existing valid certificates\r\n * 2. If missing or expired, enroll new certificate via SLS\r\n * 3. Use mTLS for all subsequent ADT requests\r\n *\r\n * Platform support:\r\n * - Windows: Uses SSPI for Kerberos (requires Active Directory)\r\n * - Linux/macOS: Uses MIT Kerberos (requires kinit)\r\n *\r\n * @example\r\n * ```typescript\r\n * const auth = new SsoAuth({\r\n * slsUrl: 'https://sapsso.corp.example.com',\r\n * });\r\n *\r\n * // Enroll certificate (or load from cache)\r\n * const [, error] = await auth.performLogin(fetch);\r\n * if (error) {\r\n * console.error('SSO failed:', error.message);\r\n * return;\r\n * }\r\n *\r\n * // Get certificates for mTLS\r\n * const certs = auth.getCertificates();\r\n * ```\r\n */\r\n\r\nimport type { AuthStrategy } from '../types';\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { SlsConfig, CertificateMaterial } from './types';\r\nimport { enrollCertificate } from './slsClient';\r\nimport { loadCertificates, saveCertificates, certificatesExist, isCertificateExpired } from './storage';\r\n\r\n/**\r\n * SSO authentication configuration\r\n */\r\nexport interface SsoAuthConfig {\r\n /** Secure Login Server URL */\r\n slsUrl: string;\r\n /** SLS profile (default: SAPSSO_P) */\r\n profile?: string;\r\n /** Service principal name override */\r\n servicePrincipalName?: string;\r\n /** Skip SSL verification (required for most corporate environments) */\r\n insecure?: boolean;\r\n /** Force certificate re-enrollment even if valid cert exists */\r\n forceEnroll?: boolean;\r\n /** Return certificate contents instead of saving to files */\r\n returnContents?: boolean;\r\n}\r\n\r\n/**\r\n * SSO authentication strategy using Kerberos and mTLS\r\n */\r\nexport class SsoAuth implements AuthStrategy {\r\n readonly type = 'sso' as const;\r\n private config: SsoAuthConfig;\r\n private certificates: CertificateMaterial | null = null;\r\n\r\n /**\r\n * Create an SSO Auth strategy\r\n *\r\n * @param config - SSO authentication configuration\r\n */\r\n constructor(config: SsoAuthConfig) {\r\n if (!config.slsUrl) {\r\n throw new Error('SsoAuth requires slsUrl');\r\n }\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Get auth headers for SSO\r\n *\r\n * SSO uses mTLS for authentication, not headers.\r\n * Returns empty headers - the mTLS agent handles auth.\r\n */\r\n getAuthHeaders(): Record<string, string> {\r\n return {};\r\n }\r\n\r\n /**\r\n * Get mTLS certificates\r\n *\r\n * Returns the certificate material after successful login.\r\n * Used by ADT client to create an mTLS agent.\r\n *\r\n * @returns Certificate material or null if not enrolled\r\n */\r\n getCertificates(): CertificateMaterial | null {\r\n return this.certificates;\r\n }\r\n\r\n /**\r\n * Perform SSO login via certificate enrollment\r\n *\r\n * Checks for existing valid certificates and enrolls new ones if needed.\r\n *\r\n * @param _fetchFn - Unused, kept for interface compatibility\r\n * @returns Success/error tuple\r\n */\r\n async performLogin(_fetchFn: typeof fetch): AsyncResult<void, Error> {\r\n // Check for existing certificates\r\n if (!this.config.forceEnroll) {\r\n const [loadResult, loadErr] = await this.tryLoadExistingCertificates();\r\n if (!loadErr && loadResult) {\r\n this.certificates = loadResult;\r\n return ok(undefined);\r\n }\r\n }\r\n\r\n // Enroll new certificate\r\n const slsConfig: SlsConfig = {\r\n slsUrl: this.config.slsUrl,\r\n };\r\n if (this.config.profile) {\r\n slsConfig.profile = this.config.profile;\r\n }\r\n if (this.config.servicePrincipalName) {\r\n slsConfig.servicePrincipalName = this.config.servicePrincipalName;\r\n }\r\n\r\n const [material, enrollErr] = await enrollCertificate({\r\n config: slsConfig,\r\n insecure: this.config.insecure ?? false,\r\n });\r\n\r\n if (enrollErr) {\r\n return err(enrollErr);\r\n }\r\n\r\n // Save certificates to filesystem (unless returnContents is true)\r\n if (!this.config.returnContents) {\r\n const [, saveErr] = await saveCertificates(material);\r\n if (saveErr) {\r\n return err(saveErr);\r\n }\r\n }\r\n\r\n this.certificates = material;\r\n return ok(undefined);\r\n }\r\n\r\n /**\r\n * Try to load and validate existing certificates\r\n */\r\n private async tryLoadExistingCertificates(): AsyncResult<CertificateMaterial> {\r\n // Check if files exist\r\n const exists = await certificatesExist();\r\n if (!exists) {\r\n return err(new Error('No existing certificates found'));\r\n }\r\n\r\n // Load certificates\r\n const [material, loadErr] = await loadCertificates();\r\n if (loadErr) {\r\n return err(loadErr);\r\n }\r\n\r\n // Check expiry\r\n const [isExpired, expiryErr] = isCertificateExpired(material.fullChain);\r\n if (expiryErr) {\r\n return err(expiryErr);\r\n }\r\n\r\n if (isExpired) {\r\n return err(new Error('Certificate is expired or expiring soon'));\r\n }\r\n\r\n return ok(material);\r\n }\r\n}\r\n","/**\r\n * SAML authentication types\r\n *\r\n * Defines provider configurations and form selectors for SAML browser automation.\r\n */\r\n\r\n/**\r\n * CSS selectors for login form elements\r\n *\r\n * Used by Playwright to locate and fill login form fields.\r\n */\r\nexport interface FormSelectors {\r\n /** CSS selector for username input field */\r\n username: string;\r\n /** CSS selector for password input field */\r\n password: string;\r\n /** CSS selector for submit button */\r\n submit: string;\r\n}\r\n\r\n/**\r\n * Default SAP IDP form selectors\r\n *\r\n * Used when no custom selectors are configured for a system.\r\n */\r\nexport const DEFAULT_FORM_SELECTORS: FormSelectors = {\r\n username: '#j_username',\r\n password: '#j_password',\r\n submit: '#logOnFormSubmit',\r\n};\r\n\r\n/**\r\n * Configuration for a SAML provider\r\n *\r\n * Defines how to interact with a specific SAP system's login page.\r\n */\r\nexport interface SamlProviderConfig {\r\n /** Whether to ignore HTTPS certificate errors */\r\n ignoreHttpsErrors: boolean;\r\n /** CSS selectors for login form elements */\r\n formSelectors: FormSelectors;\r\n}\r\n\r\n/**\r\n * Default SAML provider configuration\r\n *\r\n * Used when no SAML config is specified for a system.\r\n */\r\nexport const DEFAULT_PROVIDER_CONFIG: SamlProviderConfig = {\r\n ignoreHttpsErrors: false,\r\n formSelectors: DEFAULT_FORM_SELECTORS,\r\n};\r\n\r\n/**\r\n * Playwright cookie structure\r\n *\r\n * Matches Playwright's Cookie type for interoperability.\r\n */\r\nexport interface PlaywrightCookie {\r\n name: string;\r\n value: string;\r\n domain: string;\r\n path: string;\r\n expires: number;\r\n httpOnly: boolean;\r\n secure: boolean;\r\n sameSite: 'Strict' | 'Lax' | 'None';\r\n}\r\n\r\n/**\r\n * Result of SAML browser login\r\n */\r\nexport interface SamlLoginResult {\r\n /** Session cookies from successful login */\r\n cookies: PlaywrightCookie[];\r\n}\r\n","/**\r\n * SAML browser automation\r\n *\r\n * Implements headless browser login flow using Playwright.\r\n * Dynamically imports Playwright to avoid requiring it when not using SAML.\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { PlaywrightCookie, SamlProviderConfig } from './types';\r\nimport { DEFAULT_PROVIDER_CONFIG } from './types';\r\n\r\n/** Timeouts for browser automation */\r\nconst TIMEOUTS = {\r\n PAGE_LOAD: 60_000,\r\n FORM_SELECTOR: 10_000,\r\n} as const;\r\n\r\n/**\r\n * Credentials for SAML login\r\n */\r\nexport interface SamlCredentials {\r\n username: string;\r\n password: string;\r\n}\r\n\r\n/**\r\n * Options for SAML browser login\r\n */\r\nexport interface SamlBrowserLoginOptions {\r\n /** SAP system base URL */\r\n baseUrl: string;\r\n /** Login credentials */\r\n credentials: SamlCredentials;\r\n /** Optional custom provider config (overrides auto-detection) */\r\n providerConfig?: SamlProviderConfig;\r\n /** Whether to run browser in headless mode (default: true) */\r\n headless?: boolean;\r\n}\r\n\r\n/**\r\n * Perform SAML login using headless browser automation\r\n *\r\n * Launches a Chromium browser, navigates to the SAP login page,\r\n * fills in credentials, and extracts session cookies.\r\n *\r\n * @param options - Login options including URL and credentials\r\n * @returns Session cookies on success, error on failure\r\n *\r\n * @example\r\n * ```typescript\r\n * const [cookies, error] = await performBrowserLogin({\r\n * baseUrl: 'https://sap-system.example.com',\r\n * credentials: { username: 'user@example.com', password: 'secret' }\r\n * });\r\n * if (error) {\r\n * console.error('Login failed:', error.message);\r\n * return;\r\n * }\r\n * // Use cookies for authenticated requests\r\n * ```\r\n */\r\nexport async function performBrowserLogin(\r\n options: SamlBrowserLoginOptions\r\n): AsyncResult<PlaywrightCookie[], Error> {\r\n const { baseUrl, credentials, headless = true } = options;\r\n const config = options.providerConfig ?? DEFAULT_PROVIDER_CONFIG;\r\n\r\n // Dynamically import Playwright to avoid requiring it when not using SAML.\r\n let playwright;\r\n try {\r\n playwright = await import('playwright');\r\n } catch {\r\n return err(\r\n new Error(\r\n 'Playwright is required for SAML authentication but is not installed. ' +\r\n 'Install it with: npm install playwright'\r\n )\r\n );\r\n }\r\n\r\n const browserArgs = config.ignoreHttpsErrors\r\n ? ['--ignore-certificate-errors', '--disable-web-security']\r\n : [];\r\n\r\n let browser;\r\n try {\r\n browser = await playwright.chromium.launch({\r\n headless,\r\n args: browserArgs,\r\n });\r\n } catch (launchError) {\r\n return err(\r\n new Error(\r\n `Failed to launch browser: ${launchError instanceof Error ? launchError.message : String(launchError)}`\r\n )\r\n );\r\n }\r\n\r\n try {\r\n const context = await browser.newContext({\r\n ignoreHTTPSErrors: config.ignoreHttpsErrors,\r\n });\r\n const page = await context.newPage();\r\n\r\n // Navigate to SAP login page.\r\n const loginUrl = `${baseUrl}/sap/bc/adt/compatibility/graph`;\r\n try {\r\n await page.goto(loginUrl, {\r\n timeout: TIMEOUTS.PAGE_LOAD,\r\n waitUntil: 'domcontentloaded',\r\n });\r\n } catch {\r\n return err(new Error('Failed to load login page. Please check if the server is online.'));\r\n }\r\n\r\n // Wait for and fill login form.\r\n try {\r\n await page.waitForSelector(config.formSelectors.username, {\r\n timeout: TIMEOUTS.FORM_SELECTOR,\r\n });\r\n } catch {\r\n return err(new Error('Login form not found. The page may have changed or loaded incorrectly.'));\r\n }\r\n\r\n await page.fill(config.formSelectors.username, credentials.username);\r\n await page.fill(config.formSelectors.password, credentials.password);\r\n await page.click(config.formSelectors.submit);\r\n\r\n // Wait for login to complete.\r\n await page.waitForLoadState('networkidle');\r\n\r\n // Extract cookies.\r\n const cookies = await context.cookies();\r\n\r\n return ok(cookies as PlaywrightCookie[]);\r\n } finally {\r\n await browser.close();\r\n }\r\n}\r\n","/**\r\n * Cookie extraction and formatting for SAML authentication\r\n *\r\n * Converts Playwright cookies to AuthCookie format used by the rest of the codebase.\r\n */\r\n\r\nimport type { AuthCookie } from '../types';\r\nimport type { PlaywrightCookie } from './types';\r\n\r\n/**\r\n * Convert Playwright cookies to AuthCookie format\r\n *\r\n * @param playwrightCookies - Cookies from Playwright browser context\r\n * @returns Array of AuthCookie objects\r\n */\r\nexport function toAuthCookies(playwrightCookies: PlaywrightCookie[]): AuthCookie[] {\r\n return playwrightCookies.map((cookie) => ({\r\n name: cookie.name,\r\n value: cookie.value,\r\n domain: cookie.domain,\r\n path: cookie.path,\r\n }));\r\n}\r\n\r\n/**\r\n * Format cookies as Cookie header value\r\n *\r\n * @param cookies - Array of AuthCookie objects\r\n * @returns Cookie header string (e.g., \"name1=value1; name2=value2\")\r\n */\r\nexport function formatCookieHeader(cookies: AuthCookie[]): string {\r\n return cookies.map((c) => `${c.name}=${c.value}`).join('; ');\r\n}\r\n","/**\r\n * SAML authentication strategy\r\n *\r\n * Implements SAML-based SSO for SAP systems using browser automation.\r\n * Requires Playwright for headless browser login.\r\n *\r\n * @example\r\n * ```typescript\r\n * // With default SAP IDP selectors\r\n * const auth = new SamlAuth({\r\n * username: 'user@example.com',\r\n * password: 'secret',\r\n * baseUrl: 'https://sap-system.example.com',\r\n * });\r\n *\r\n * // With custom form selectors\r\n * const auth = new SamlAuth({\r\n * username: 'user@example.com',\r\n * password: 'secret',\r\n * baseUrl: 'https://sap-system.example.com',\r\n * providerConfig: {\r\n * ignoreHttpsErrors: true,\r\n * formSelectors: {\r\n * username: '#custom-user-field',\r\n * password: '#custom-pass-field',\r\n * submit: '#custom-submit-btn',\r\n * },\r\n * },\r\n * });\r\n *\r\n * // Perform login\r\n * const [, error] = await auth.performLogin(fetch);\r\n * if (error) {\r\n * console.error('Login failed:', error.message);\r\n * }\r\n * ```\r\n */\r\n\r\nimport type { AuthStrategy, AuthCookie } from '../types';\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { SamlProviderConfig } from './types';\r\nimport { performBrowserLogin } from './browser';\r\nimport { toAuthCookies, formatCookieHeader } from './cookies';\r\n\r\n/**\r\n * Configuration for SAML authentication\r\n */\r\nexport interface SamlAuthConfig {\r\n /** SAML username (often an email address) - used for browser login */\r\n username: string;\r\n /** SAML password */\r\n password: string;\r\n /** SAP system username - used for object creation (adtcore:responsible) */\r\n sapUser: string;\r\n /** SAP system base URL */\r\n baseUrl: string;\r\n /** Optional custom provider configuration */\r\n providerConfig?: SamlProviderConfig;\r\n}\r\n\r\n/**\r\n * SAML authentication strategy\r\n */\r\nexport class SamlAuth implements AuthStrategy {\r\n readonly type = 'saml' as const;\r\n private cookies: AuthCookie[] = [];\r\n private config: SamlAuthConfig;\r\n\r\n /**\r\n * Create a SAML Auth strategy\r\n *\r\n * @param config - SAML authentication configuration\r\n */\r\n constructor(config: SamlAuthConfig) {\r\n if (!config.username || !config.password) {\r\n throw new Error('SamlAuth requires both username and password');\r\n }\r\n if (!config.sapUser) {\r\n throw new Error('SamlAuth requires sapUser (SAP system username for object creation)');\r\n }\r\n if (!config.baseUrl) {\r\n throw new Error('SamlAuth requires baseUrl');\r\n }\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Get SAP system username\r\n *\r\n * Used for object creation (adtcore:responsible) instead of the SAML email.\r\n */\r\n getSapUser(): string {\r\n return this.config.sapUser;\r\n }\r\n\r\n /**\r\n * Get auth headers for SAML\r\n *\r\n * After successful login, includes Cookie header with session cookies.\r\n */\r\n getAuthHeaders(): Record<string, string> {\r\n if (this.cookies.length === 0) {\r\n return {};\r\n }\r\n return {\r\n Cookie: formatCookieHeader(this.cookies),\r\n };\r\n }\r\n\r\n /**\r\n * Get authentication cookies\r\n *\r\n * @returns Array of cookies obtained during SAML login\r\n */\r\n getCookies(): AuthCookie[] {\r\n return this.cookies;\r\n }\r\n\r\n /**\r\n * Perform SAML login using headless browser automation\r\n *\r\n * Launches a Chromium browser, navigates to the SAP login page,\r\n * fills in credentials, and extracts session cookies.\r\n *\r\n * @param _fetchFn - Unused, kept for interface compatibility\r\n * @returns Success/error tuple\r\n */\r\n async performLogin(_fetchFn: typeof fetch): AsyncResult<void, Error> {\r\n const [playwrightCookies, loginError] = await performBrowserLogin({\r\n baseUrl: this.config.baseUrl,\r\n credentials: {\r\n username: this.config.username,\r\n password: this.config.password,\r\n },\r\n ...(this.config.providerConfig && { providerConfig: this.config.providerConfig }),\r\n });\r\n\r\n if (loginError) {\r\n return err(loginError);\r\n }\r\n\r\n this.cookies = toAuthCookies(playwrightCookies);\r\n\r\n if (this.cookies.length === 0) {\r\n return err(new Error('SAML login succeeded but no cookies were returned'));\r\n }\r\n\r\n return ok(undefined);\r\n }\r\n}\r\n","import type { AuthConfig } from '../../types/config';\r\nimport type { AuthStrategy } from './types';\r\nimport { BasicAuth } from './basic';\r\nimport { SsoAuth, type SsoAuthConfig } from './sso';\r\nimport { SamlAuth } from './saml';\r\n\r\n/**\r\n * Options for creating an authentication strategy\r\n */\r\nexport interface CreateAuthOptions {\r\n /** Authentication configuration */\r\n config: AuthConfig;\r\n /** Base URL of the SAP system (required for SAML) */\r\n baseUrl?: string;\r\n /** Skip SSL verification (dev only) */\r\n insecure?: boolean;\r\n}\r\n\r\n/**\r\n * Create an authentication strategy based on configuration\r\n *\r\n * Factory function that instantiates the appropriate auth strategy\r\n * based on the auth config type (basic, saml, or sso).\r\n *\r\n * @param options - Authentication options including config and optional baseUrl\r\n * @returns Configured authentication strategy\r\n * @throws Error if config type is invalid or required fields are missing\r\n *\r\n * @example\r\n * ```typescript\r\n * // Basic auth\r\n * const auth = createAuthStrategy({\r\n * config: { type: 'basic', username: 'DEVELOPER', password: 'secret' }\r\n * });\r\n *\r\n * // SAML auth (requires baseUrl)\r\n * const auth = createAuthStrategy({\r\n * config: { type: 'saml', username: 'user@example.com', password: 'secret' },\r\n * baseUrl: 'https://sap-system.example.com'\r\n * });\r\n *\r\n * // SSO auth (Kerberos + mTLS)\r\n * const auth = createAuthStrategy({\r\n * config: {\r\n * type: 'sso',\r\n * slsUrl: 'https://sapsso.corp.example.com'\r\n * },\r\n * insecure: true\r\n * });\r\n * ```\r\n */\r\nexport function createAuthStrategy(options: CreateAuthOptions): AuthStrategy {\r\n const { config, baseUrl, insecure } = options;\r\n\r\n switch (config.type) {\r\n case 'basic':\r\n return new BasicAuth(config.username, config.password);\r\n\r\n case 'saml':\r\n if (!baseUrl) {\r\n throw new Error('SAML authentication requires baseUrl');\r\n }\r\n return new SamlAuth({\r\n username: config.username,\r\n password: config.password,\r\n sapUser: config.sapUser,\r\n baseUrl,\r\n ...(config.providerConfig && { providerConfig: config.providerConfig }),\r\n });\r\n\r\n case 'sso': {\r\n const ssoConfig: SsoAuthConfig = {\r\n slsUrl: config.slsUrl,\r\n };\r\n if (config.profile) {\r\n ssoConfig.profile = config.profile;\r\n }\r\n if (config.servicePrincipalName) {\r\n ssoConfig.servicePrincipalName = config.servicePrincipalName;\r\n }\r\n if (config.forceEnroll) {\r\n ssoConfig.forceEnroll = config.forceEnroll;\r\n }\r\n if (insecure) {\r\n ssoConfig.insecure = insecure;\r\n }\r\n return new SsoAuth(ssoConfig);\r\n }\r\n\r\n default: {\r\n const _exhaustive: never = config;\r\n throw new Error(`Unknown auth type: ${(_exhaustive as AuthConfig).type}`);\r\n }\r\n }\r\n}\r\n","/**\r\n * Session management type definitions\r\n */\r\n\r\nimport type { AuthType } from '../../types';\r\n\r\n/**\r\n * Session data returned after successful login\r\n */\r\nexport interface Session {\r\n /** Unique session identifier */\r\n sessionId: string;\r\n /** Authenticated username */\r\n username: string;\r\n /** Session expiration timestamp */\r\n expiresAt: number;\r\n}\r\n\r\n/**\r\n * Session entry stored in memory\r\n */\r\nexport interface SessionEntry {\r\n /** The ADT client instance (typed as unknown until client is implemented) */\r\n client: unknown;\r\n /** Last activity timestamp for timeout tracking */\r\n lastActivity: Date;\r\n /** Authentication type used for this session */\r\n authType: AuthType;\r\n}\r\n\r\n/**\r\n * Configuration for session manager\r\n *\r\n * Session timeouts vary by authentication type:\r\n * - Basic: 3 hours (SAP server default)\r\n * - SSO: 3 hours (certificate-based, same as basic)\r\n * - SAML: 30 minutes (IDP session typically shorter)\r\n */\r\nexport interface SessionConfig {\r\n /** Session timeout in seconds for Basic and SSO auth (default: 10800 = 3 hours) */\r\n sessionTimeout: number;\r\n /** Session timeout in seconds for SAML auth (default: 1800 = 30 minutes) */\r\n samlSessionTimeout: number;\r\n /** Cleanup interval in seconds (default: 60) */\r\n cleanupInterval: number;\r\n}\r\n\r\n/**\r\n * Default session configuration values\r\n */\r\nexport const DEFAULT_SESSION_CONFIG: SessionConfig = {\r\n sessionTimeout: 10800, // 3 hours (Basic/SSO)\r\n samlSessionTimeout: 1800, // 30 minutes (SAML)\r\n cleanupInterval: 60, // 1 minute\r\n};\r\n\r\n/**\r\n * Serializable session state for export/import across processes\r\n *\r\n * Used to transfer authenticated session state from daemon to CLI processes,\r\n * allowing session reuse without re-authentication.\r\n */\r\nexport interface ExportableSessionState {\r\n csrfToken: string;\r\n session: Session;\r\n cookies: Array<{ name: string; value: string }>;\r\n authType: AuthType;\r\n ssoCertPaths?: { fullChainPath: string; keyPath: string };\r\n}\r\n","/**\n * XML Parsing Utilities\n *\n * Secure XML parsing and manipulation for ADT responses.\n * Uses @xmldom/xmldom for cross-platform XML parsing.\n */\n\nimport { DOMParser } from '@xmldom/xmldom';\nimport type { Result } from '../../types/result';\nimport { ok, err } from '../../types/result';\n\n/**\n * Securely parse XML string into a Document object (throws on error)\n *\n * @param xmlString - The XML string to parse\n * @returns Parsed XML Document\n * @throws Error if XML is malformed\n * @deprecated Use safeParseXml for Result-based error handling\n */\nexport function parseXml(xmlString: string): Document {\n if (!xmlString || xmlString.trim().length === 0) {\n throw new Error('Empty XML string provided');\n }\n\n const parser = new DOMParser();\n const doc = parser.parseFromString(xmlString, 'text/xml');\n\n // Check for parser errors\n const parseError = doc.getElementsByTagName('parsererror');\n if (parseError.length > 0) {\n const errorNode = parseError[0];\n const errorText = errorNode?.textContent || 'Unknown XML parsing error';\n throw new Error(`XML parsing failed: ${errorText}`);\n }\n\n return doc;\n}\n\n/**\n * Safely parse XML string into a Document object\n *\n * @param xmlString - The XML string to parse\n * @returns Result tuple with Document or Error\n */\nexport function safeParseXml(xmlString: string): Result<Document, Error> {\n // Validate input.\n if (!xmlString || xmlString.trim().length === 0) {\n return err(new Error('Empty XML string provided'));\n }\n\n try {\n // Parse XML string.\n const parser = new DOMParser();\n const doc = parser.parseFromString(xmlString, 'text/xml');\n\n // Check for parser errors.\n const parseError = doc.getElementsByTagName('parsererror');\n if (parseError.length > 0) {\n const errorNode = parseError[0];\n const errorText = errorNode?.textContent || 'Unknown XML parsing error';\n return err(new Error(`XML parsing failed: ${errorText}`));\n }\n\n return ok(doc);\n } catch (error) {\n if (error instanceof Error) {\n return err(error);\n }\n return err(new Error('Unknown XML parsing error'));\n }\n}\n\n/**\n * Extract LOCK_HANDLE from ADT XML response\n *\n * @param xml - XML string containing lock handle\n * @returns Result tuple with lock handle or error\n */\nexport function extractLockHandle(xml: string): Result<string, Error> {\n // Validate input.\n if (!xml) {\n return err(new Error('Empty XML provided'));\n }\n\n // Parse XML response.\n const [doc, parseErr] = safeParseXml(xml);\n if (parseErr) { return err(parseErr); }\n\n // Find LOCK_HANDLE element.\n const lockHandleElements = doc.getElementsByTagName('LOCK_HANDLE');\n if (lockHandleElements.length === 0) {\n return err(new Error('LOCK_HANDLE element not found in XML'));\n }\n\n // Extract and validate lock handle value.\n const lockHandleElement = lockHandleElements[0];\n const lockHandle = lockHandleElement?.textContent;\n if (!lockHandle || lockHandle.trim().length === 0) {\n return err(new Error('LOCK_HANDLE element is empty'));\n }\n\n return ok(lockHandle.trim());\n}\n\n/**\n * Extract error message from ADT XML error response\n *\n * @param xml - XML string containing error message\n * @returns Error message or default message\n */\nexport function extractError(xml: string): string {\n // Handle empty input.\n if (!xml) {\n return 'No error message found';\n }\n\n // Parse XML response.\n const [doc, parseErr] = safeParseXml(xml);\n if (parseErr) {\n return 'Failed to parse error XML';\n }\n\n // Find message element.\n const messageElements = doc.getElementsByTagName('message');\n if (messageElements.length === 0) {\n return 'No message found';\n }\n\n // Extract message text.\n const messageElement = messageElements[0];\n const message = messageElement?.textContent;\n return message || 'No message found';\n}\n\n/**\n * Escape special XML characters\n *\n * @param str - String to escape\n * @returns XML-safe string\n */\nexport function escapeXml(str: string): string {\n // Handle empty input.\n if (!str) {\n return '';\n }\n\n // Replace special XML characters with entities.\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n}\n\n/**\n * Convert a dictionary to ABAP-style XML\n *\n * This creates XML in the format expected by SAP ADT endpoints:\n * <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n * <asx:abap xmlns:asx=\"http://www.sap.com/abapxml\" version=\"1.0\">\n * <asx:values>\n * <DATA>\n * <KEY>value</KEY>\n * </DATA>\n * </asx:values>\n * </asx:abap>\n *\n * @param data - Key-value pairs to convert to XML\n * @param root - Root element name (default: \"DATA\")\n * @returns ABAP-formatted XML string\n */\nexport function dictToAbapXml(data: Record<string, string>, root: string = 'DATA'): string {\n // Build inner XML elements from key-value pairs.\n const innerElements = Object.entries(data)\n .map(([key, value]) => {\n if (value) {\n return `<${key}>${escapeXml(value)}</${key}>`;\n }\n return `<${key}/>`;\n })\n .join('\\n ');\n\n // Return complete ABAP XML structure.\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<asx:abap xmlns:asx=\"http://www.sap.com/abapxml\" version=\"1.0\">\n <asx:values>\n <${root}>\n ${innerElements}\n </${root}>\n </asx:values>\n</asx:abap>`;\n}\n","/**\n * CSRF Token Constants\n *\n * Constants for CSRF token handling with SAP ADT endpoints.\n */\n\n/**\n * Special value to request a CSRF token from the server\n *\n * When sent in the x-csrf-token header, SAP returns a valid token\n * in the response headers.\n */\nexport const FETCH_CSRF_TOKEN = 'fetch';\n\n/**\n * HTTP header name for CSRF token\n *\n * Used both for requesting tokens (with FETCH_CSRF_TOKEN value)\n * and sending tokens with authenticated requests.\n */\nexport const CSRF_TOKEN_HEADER = 'x-csrf-token';\n","/**\r\n * HTTP Header Utilities for ADT Requests\r\n *\r\n * Provides header building utilities and constants for SAP ADT HTTP requests.\r\n * Centralizes header management to avoid duplication across client code.\r\n */\r\n\r\nimport { CSRF_TOKEN_HEADER, FETCH_CSRF_TOKEN } from './csrf';\r\nimport type { AuthConfig } from '../../types/config';\r\n\r\n// Mimic Eclipse ADT plugin for compatibility\r\nexport const BASE_HEADERS = {\r\n 'Accept': '*/*',\r\n 'X-sap-adt-sessiontype': 'stateful',\r\n 'User-Agent': 'Eclipse/4.34.0 ADT/3.46.0',\r\n 'X-sap-adt-profiling': 'server-time',\r\n} as const;\r\n\r\n// Default request timeout in milliseconds\r\nexport const DEFAULT_TIMEOUT = 30000;\r\n\r\n/**\r\n * Build request headers with auth and CSRF token\r\n *\r\n * @param baseHeaders - Base headers to include in all requests\r\n * @param customHeaders - Request-specific headers\r\n * @param auth - Authentication config (for basic auth header)\r\n * @param csrfToken - Current CSRF token (if available)\r\n * @returns Combined headers object\r\n */\r\nexport function buildRequestHeaders(\r\n baseHeaders: Record<string, string>,\r\n customHeaders?: Record<string, string>,\r\n auth?: AuthConfig,\r\n csrfToken?: string | null\r\n): Record<string, string> {\r\n // Merge base and custom headers.\r\n const headers: Record<string, string> = {\r\n ...baseHeaders,\r\n ...(customHeaders ?? {}),\r\n };\r\n\r\n // Add basic auth header if using basic authentication.\r\n if (auth?.type === 'basic') {\r\n // Use btoa for base64 encoding (web standard, available in both Node 18+ and Bun)\r\n const credentials = btoa(`${auth.username}:${auth.password}`);\r\n headers['Authorization'] = `Basic ${credentials}`;\r\n }\r\n\r\n // Add CSRF token if we have one (but not the 'fetch' placeholder).\r\n // Don't overwrite if custom headers already set the CSRF token (e.g., for token refresh).\r\n if (csrfToken && csrfToken !== FETCH_CSRF_TOKEN && !customHeaders?.[CSRF_TOKEN_HEADER]) {\r\n headers[CSRF_TOKEN_HEADER] = csrfToken;\r\n }\r\n\r\n return headers;\r\n}\r\n\r\n/**\r\n * Extract CSRF token from response headers\r\n *\r\n * SAP returns token in both upper and lowercase variations,\r\n * so we need to check both.\r\n *\r\n * @param headers - Response headers from SAP ADT server\r\n * @returns Extracted CSRF token or null if not found\r\n */\r\nexport function extractCsrfToken(headers: Headers): string | null {\r\n // Try both upper and lowercase header names.\r\n const token = headers.get(CSRF_TOKEN_HEADER) ||\r\n headers.get(CSRF_TOKEN_HEADER.toLowerCase());\r\n\r\n // Ignore the fetch token itself.\r\n if (!token || token === FETCH_CSRF_TOKEN) {\r\n return null;\r\n }\r\n\r\n return token;\r\n}\r\n","/**\r\n * Logging Utility — Debug logging with activation control\r\n *\r\n * Logs are silent by default. Call activateLogging() to enable console output.\r\n */\r\n\r\nlet isActive = false;\r\n\r\n/**\r\n * Enable debug logging to console\r\n */\r\nexport function activateLogging(): void {\r\n isActive = true;\r\n}\r\n\r\n/**\r\n * Disable debug logging (default state)\r\n */\r\nexport function deactivateLogging(): void {\r\n isActive = false;\r\n}\r\n\r\n/**\r\n * Check if logging is currently active\r\n */\r\nexport function isLoggingActive(): boolean {\r\n return isActive;\r\n}\r\n\r\n/**\r\n * Log a debug message (only prints when logging is active)\r\n */\r\nexport function debug(message: string): void {\r\n if (isActive) {\r\n console.log(`[DEBUG] ${message}`);\r\n }\r\n}\r\n\r\n/**\r\n * Log a debug error message (only prints when logging is active)\r\n */\r\nexport function debugError(message: string, cause?: unknown): void {\r\n if (!isActive) return;\r\n\r\n console.error(`[DEBUG] ${message}`);\r\n if (cause !== undefined) {\r\n console.error(`[DEBUG] Cause:`, cause);\r\n }\r\n}\r\n","/**\r\n * Content normalization utilities\r\n *\r\n * Used for comparing object content between server and local versions.\r\n * SAP servers may insert whitespace variations (carriage returns, extra spaces)\r\n * that shouldn't be considered meaningful differences.\r\n */\r\n\r\n/**\r\n * Normalize content for comparison\r\n *\r\n * Replaces all consecutive whitespace (spaces, tabs, newlines, carriage returns)\r\n * with a single space. Trims leading/trailing whitespace.\r\n *\r\n * @param content - Raw content string\r\n * @returns Normalized content with single spaces\r\n */\r\nexport function normalizeContent(content: string): string {\r\n return content.replace(/\\s+/g, ' ').trim();\r\n}\r\n","/**\r\n * Session Lifecycle Operations\r\n *\r\n * Internal helpers for login/logout/session reset operations.\r\n * Used by ADTClient to manage session state.\r\n *\r\n * Handles:\r\n * - CSRF token fetching (auth-type-aware endpoints)\r\n * - Basic, SAML, and SSO authentication login flows\r\n * - Session reset on 500 errors\r\n * - Auth-type-aware session timeouts\r\n * - Logout/cleanup\r\n */\r\n\r\nimport type { AuthConfig, AuthType } from '../../types/config';\r\nimport type { Session } from './types';\r\nimport { DEFAULT_SESSION_CONFIG } from './types';\r\nimport type { AsyncResult } from '../../types/result';\r\nimport { ok, err } from '../../types/result';\r\nimport {\r\n FETCH_CSRF_TOKEN,\r\n CSRF_TOKEN_HEADER,\r\n extractCsrfToken,\r\n debug,\r\n} from '../utils';\r\n\r\n// Request function type signature (provided by client.ts)\r\ntype RequestFn = (options: {\r\n method: 'GET' | 'POST' | 'PUT' | 'DELETE';\r\n path: string;\r\n params?: Record<string, string | number>;\r\n headers?: Record<string, string>;\r\n body?: string;\r\n}) => AsyncResult<Response, Error>;\r\n\r\n// Session state management (provided by client.ts)\r\nexport interface SessionState {\r\n csrfToken: string | null;\r\n session: Session | null;\r\n config: { auth: AuthConfig };\r\n}\r\n\r\n/**\r\n * Fetch CSRF token from SAP ADT server\r\n *\r\n * Endpoint and content type vary by auth type:\r\n * - SAML: /sap/bc/adt/core/http/sessions\r\n * - Basic/SSO: /sap/bc/adt/compatibility/graph\r\n *\r\n * @param state - Session state to update with new token\r\n * @param request - HTTP request function from client\r\n * @returns CSRF token string or error\r\n */\r\nexport async function fetchCsrfToken(\r\n state: SessionState,\r\n request: RequestFn\r\n): AsyncResult<string, Error> {\r\n // Select endpoint based on authentication type.\r\n const endpoint = state.config.auth.type === 'saml'\r\n ? '/sap/bc/adt/core/http/sessions'\r\n : '/sap/bc/adt/compatibility/graph';\r\n\r\n // Select content type based on authentication type.\r\n const contentType = state.config.auth.type === 'saml'\r\n ? 'application/vnd.sap.adt.core.http.session.v3+xml'\r\n : 'application/xml';\r\n\r\n // Build request headers with CSRF token fetch flag.\r\n const headers = {\r\n [CSRF_TOKEN_HEADER]: FETCH_CSRF_TOKEN,\r\n 'Content-Type': contentType,\r\n 'Accept': contentType,\r\n };\r\n\r\n // Execute CSRF token request.\r\n const [response, requestErr] = await request({\r\n method: 'GET',\r\n path: endpoint,\r\n headers,\r\n });\r\n\r\n if (requestErr) {\r\n return err(new Error(`Failed to fetch CSRF token: ${requestErr.message}`));\r\n }\r\n\r\n if (!response.ok) {\r\n const text = await response.text();\r\n return err(new Error(`CSRF token fetch failed with status ${response.status}: ${text}`));\r\n }\r\n\r\n // Extract CSRF token from response headers.\r\n const token = extractCsrfToken(response.headers);\r\n debug(`CSRF token from headers: ${token ? token.substring(0, 20) + '...' : 'null'}`);\r\n if (!token) {\r\n // Debug: show all headers\r\n debug('Response headers:');\r\n response.headers.forEach((value, key) => debug(` ${key}: ${value.substring(0, 50)}`));\r\n return err(new Error('Invalid credentials'));\r\n }\r\n\r\n // Update session state with new token.\r\n state.csrfToken = token;\r\n debug(`Stored CSRF token in state: ${state.csrfToken?.substring(0, 20)}...`);\r\n\r\n return ok(token);\r\n}\r\n\r\n/**\r\n * Get session timeout based on authentication type\r\n *\r\n * @param authType - Authentication type\r\n * @returns Session timeout in milliseconds\r\n */\r\nexport function getSessionTimeout(authType: AuthType): number {\r\n switch (authType) {\r\n case 'saml':\r\n return DEFAULT_SESSION_CONFIG.samlSessionTimeout * 1000;\r\n case 'basic':\r\n case 'sso':\r\n return DEFAULT_SESSION_CONFIG.sessionTimeout * 1000;\r\n default: {\r\n const _exhaustive: never = authType;\r\n return DEFAULT_SESSION_CONFIG.sessionTimeout * 1000;\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Extract username from authentication config\r\n *\r\n * @param auth - Authentication config\r\n * @returns Username for session (SAP user for SAML, username for basic, system user for SSO)\r\n */\r\nfunction extractUsername(auth: AuthConfig): string {\r\n switch (auth.type) {\r\n case 'basic':\r\n return auth.username;\r\n case 'saml':\r\n // For SAML, use sapUser (actual SAP username) not username (email for browser login)\r\n return auth.sapUser;\r\n case 'sso':\r\n // For SSO, username comes from Kerberos/system\r\n return process.env['USERNAME'] ?? process.env['USER'] ?? 'SSO_USER';\r\n default: {\r\n const _exhaustive: never = auth;\r\n return '';\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Login to SAP ADT server\r\n *\r\n * Supports all authentication types:\r\n * - Basic: Username/password via Authorization header\r\n * - SAML: Browser automation (cookies already set by auth strategy)\r\n * - SSO: Kerberos/mTLS (certificates already loaded by auth strategy)\r\n *\r\n * For SAML and SSO, the auth strategy's performLogin() is called\r\n * before this function, so authentication is already complete.\r\n * This function fetches the CSRF token and creates the session.\r\n *\r\n * @param state - Session state to update\r\n * @param request - HTTP request function from client\r\n * @returns Session object or error\r\n */\r\nexport async function login(\r\n state: SessionState,\r\n request: RequestFn\r\n): AsyncResult<Session, Error> {\r\n // Fetch CSRF token from SAP server.\r\n // Endpoint varies by auth type (handled in fetchCsrfToken).\r\n const [token, tokenErr] = await fetchCsrfToken(state, request);\r\n if (tokenErr) {\r\n return err(tokenErr);\r\n }\r\n\r\n // Extract username from authentication config.\r\n const username = extractUsername(state.config.auth);\r\n\r\n // Calculate session expiration based on auth type.\r\n const timeout = getSessionTimeout(state.config.auth.type);\r\n\r\n // Create session object.\r\n const session: Session = {\r\n sessionId: token,\r\n username,\r\n expiresAt: Date.now() + timeout,\r\n };\r\n\r\n // Update session state.\r\n state.session = session;\r\n\r\n return ok(session);\r\n}\r\n\r\n/**\r\n * Logout from SAP ADT server\r\n *\r\n * Calls the SAP logoff endpoint and clears local state.\r\n *\r\n * @param state - Session state to clear\r\n * @param request - HTTP request function from client\r\n * @returns void or error\r\n */\r\nexport async function logout(\r\n state: SessionState,\r\n request: RequestFn\r\n): AsyncResult<void, Error> {\r\n // Execute logout request to SAP server.\r\n const [response, requestErr] = await request({\r\n method: 'POST',\r\n path: '/sap/public/bc/icf/logoff',\r\n });\r\n\r\n if (requestErr) {\r\n return err(new Error(`Logout failed: ${requestErr.message}`));\r\n }\r\n\r\n if (!response.ok) {\r\n const text = await response.text();\r\n return err(new Error(`Logout failed with status ${response.status}: ${text}`));\r\n }\r\n\r\n // Clear local session state.\r\n state.csrfToken = null;\r\n state.session = null;\r\n\r\n return ok(undefined);\r\n}\r\n\r\n/**\r\n * Reset session by logging out and back in\r\n *\r\n * Called automatically on 500 errors to recover from session expiration.\r\n *\r\n * @param state - Session state to reset\r\n * @param request - HTTP request function from client\r\n * @returns void or error\r\n */\r\nexport async function sessionReset(\r\n state: SessionState,\r\n request: RequestFn\r\n): AsyncResult<void, Error> {\r\n // Attempt to logout from current session.\r\n await logout(state, request);\r\n\r\n // Clear session state regardless of logout result.\r\n state.csrfToken = null;\r\n state.session = null;\r\n\r\n // Re-login to establish new session.\r\n const [, loginErr] = await login(state, request);\r\n if (loginErr) {\r\n return err(loginErr);\r\n }\r\n\r\n return ok(undefined);\r\n}\r\n","/**\r\n * Session Refresh via Reentrance Ticket\r\n *\r\n * Fetches a reentrance ticket from SAP ADT to keep the session alive.\r\n * Eclipse ADT uses this mechanism to maintain sessions across extended periods.\r\n *\r\n * Endpoint: GET /sap/bc/adt/security/reentranceticket\r\n * - Returns a base64-encoded SSO ticket\r\n * - Refreshes server-side session cookies (MYSAPSSO2)\r\n */\r\n\r\nimport type { AsyncResult } from '../../types/result';\r\nimport type { SessionState } from './login';\r\nimport { getSessionTimeout } from './login';\r\nimport { ok, err } from '../../types/result';\r\nimport { debug } from '../utils';\r\n\r\n// Request function type signature (provided by client.ts)\r\ntype RequestFn = (options: {\r\n method: 'GET' | 'POST' | 'PUT' | 'DELETE';\r\n path: string;\r\n params?: Record<string, string | number>;\r\n headers?: Record<string, string>;\r\n body?: string;\r\n}) => AsyncResult<Response, Error>;\r\n\r\nconst REENTRANCE_TICKET_PATH = '/sap/bc/adt/security/reentranceticket';\r\n\r\n/**\r\n * Result of a session refresh operation\r\n */\r\nexport interface RefreshResult {\r\n /** Base64-encoded reentrance ticket */\r\n ticket: string;\r\n /** Updated session expiration timestamp (ms since epoch) */\r\n expiresAt: number;\r\n}\r\n\r\n/**\r\n * Refresh session by fetching a reentrance ticket\r\n *\r\n * Calls the SAP ADT reentrance ticket endpoint to extend the session lifetime.\r\n * The server responds with an SSO ticket and refreshes the MYSAPSSO2 cookie.\r\n *\r\n * @param state - Session state to update\r\n * @param request - HTTP request function from client\r\n * @returns RefreshResult with ticket and new expiration, or error\r\n */\r\nexport async function refreshSession(\r\n state: SessionState,\r\n request: RequestFn\r\n): AsyncResult<RefreshResult, Error> {\r\n if (!state.session) {\r\n return err(new Error('Not logged in'));\r\n }\r\n\r\n debug('Fetching reentrance ticket to refresh session...');\r\n\r\n const [response, reqErr] = await request({\r\n method: 'GET',\r\n path: REENTRANCE_TICKET_PATH,\r\n headers: { 'Accept': 'text/plain' },\r\n });\r\n\r\n if (reqErr) {\r\n return err(new Error(`Session refresh failed: ${reqErr.message}`));\r\n }\r\n\r\n if (!response.ok) {\r\n const text = await response.text();\r\n return err(new Error(`Session refresh failed (${response.status}): ${text}`));\r\n }\r\n\r\n // Extract ticket from response body\r\n const ticket = await response.text();\r\n debug(`Received reentrance ticket: ${ticket.substring(0, 20)}...`);\r\n\r\n // Update session expiration based on auth type\r\n const timeout = getSessionTimeout(state.config.auth.type);\r\n state.session.expiresAt = Date.now() + timeout;\r\n\r\n debug(`Session refreshed, new expiration: ${new Date(state.session.expiresAt).toISOString()}`);\r\n\r\n return ok({ ticket, expiresAt: state.session.expiresAt });\r\n}\r\n","/**\r\n * Client login method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { Session } from '../../../core/session/types';\r\nimport type { ClientContext, SsoCerts } from '../../types';\r\nimport { ok, err } from '../../../types/result';\r\nimport * as sessionOps from '../../../core/session';\r\nimport { debug } from '../../../core/utils';\r\n\r\n// Default auto-refresh interval: 30 min\r\nconst DEFAULT_REFRESH_INTERVAL = 30 * 60 * 1000;\r\n\r\nexport async function login(\r\n ctx: ClientContext,\r\n setSsoCerts: (certs: SsoCerts) => void\r\n): AsyncResult<Session> {\r\n const { authStrategy } = ctx.state;\r\n\r\n // For SSO and SAML, perform initial authentication (certificate enrollment or browser login)\r\n if (authStrategy.performLogin) {\r\n const [, loginErr] = await authStrategy.performLogin(fetch);\r\n if (loginErr) {\r\n return err(loginErr);\r\n }\r\n }\r\n\r\n // For SAML, transfer cookies from auth strategy to client cookie store\r\n if (authStrategy.type === 'saml' && authStrategy.getCookies) {\r\n const cookies = authStrategy.getCookies();\r\n for (const cookie of cookies) {\r\n ctx.state.cookies.set(cookie.name, cookie.value);\r\n }\r\n debug(`Transferred ${cookies.length} SAML cookies to client`);\r\n }\r\n\r\n // For SSO with mTLS, store certificates for use in requests\r\n if (authStrategy.type === 'sso' && authStrategy.getCertificates) {\r\n const certs = authStrategy.getCertificates();\r\n if (certs) {\r\n setSsoCerts({\r\n cert: certs.fullChain,\r\n key: certs.privateKey,\r\n });\r\n debug('Stored mTLS certificates for SSO authentication');\r\n }\r\n }\r\n\r\n const [session, loginErr] = await sessionOps.login(ctx.state, ctx.request);\r\n if (loginErr) {\r\n return err(loginErr);\r\n }\r\n\r\n // Start auto-refresh if enabled (default: true)\r\n const autoRefresh = ctx.state.config.autoRefresh ?? { enabled: true };\r\n if (autoRefresh.enabled) {\r\n const interval = autoRefresh.intervalMs ?? DEFAULT_REFRESH_INTERVAL;\r\n ctx.startAutoRefresh(interval);\r\n debug(`Auto-refresh started with ${interval}ms interval`);\r\n }\r\n\r\n return ok(session);\r\n}\r\n","/**\r\n * Client logout method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { ClientContext } from '../../types';\r\nimport * as sessionOps from '../../../core/session';\r\n\r\nexport async function logout(ctx: ClientContext): AsyncResult<void> {\r\n ctx.stopAutoRefresh();\r\n return sessionOps.logout(ctx.state, ctx.request);\r\n}\r\n","/**\r\n * Client session refresh method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { ClientContext } from '../../types';\r\nimport type { RefreshResult } from '../../../core/session/refresh';\r\nimport { err } from '../../../types/result';\r\nimport * as sessionOps from '../../../core/session';\r\n\r\nexport async function refreshSession(ctx: ClientContext): AsyncResult<RefreshResult> {\r\n if (!ctx.state.session) {\r\n return err(new Error('Not logged in'));\r\n }\r\n return sessionOps.refreshSession(ctx.state, ctx.request);\r\n}\r\n","/**\r\n * Export session state for persistence across processes\r\n */\r\n\r\nimport type { ExportableSessionState } from '../../../core/session/types';\r\nimport type { ClientContext, SsoCerts } from '../../types';\r\nimport { getCertificatePaths } from '../../../core/auth/sso/storage';\r\n\r\nexport function exportSessionState(\r\n ctx: ClientContext,\r\n ssoCerts: SsoCerts | undefined\r\n): ExportableSessionState | null {\r\n if (!ctx.state.session || !ctx.state.csrfToken) return null;\r\n\r\n // Convert cookies Map to array format\r\n const cookies: Array<{ name: string; value: string }> = [];\r\n for (const [name, value] of ctx.state.cookies) {\r\n cookies.push({ name, value });\r\n }\r\n\r\n const state: ExportableSessionState = {\r\n csrfToken: ctx.state.csrfToken,\r\n session: ctx.state.session,\r\n cookies,\r\n authType: ctx.state.authStrategy.type,\r\n };\r\n\r\n // For SSO, include certificate paths (not contents for security)\r\n if (ctx.state.authStrategy.type === 'sso' && ssoCerts) {\r\n state.ssoCertPaths = getCertificatePaths();\r\n }\r\n\r\n return state;\r\n}\r\n","/**\r\n * Import session state from persistence\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { ExportableSessionState } from '../../../core/session/types';\r\nimport type { ClientContext, SsoCerts } from '../../types';\r\nimport { ok, err } from '../../../types/result';\r\nimport { debug, CSRF_TOKEN_HEADER, FETCH_CSRF_TOKEN, extractCsrfToken } from '../../../core/utils';\r\n\r\n// Default auto-refresh interval: 30 min\r\nconst DEFAULT_REFRESH_INTERVAL = 30 * 60 * 1000;\r\n\r\nexport async function importSessionState(\r\n ctx: ClientContext,\r\n state: ExportableSessionState,\r\n setSsoCerts: (certs: SsoCerts) => void\r\n): AsyncResult<boolean> {\r\n debug(`importSessionState: starting import`);\r\n\r\n // Validate session hasn't expired\r\n if (state.session.expiresAt <= Date.now()) {\r\n debug(`importSessionState: session expired`);\r\n return err(new Error('Session has expired'));\r\n }\r\n debug(`importSessionState: session expiry OK (expires at ${state.session.expiresAt})`);\r\n\r\n // Restore session state\r\n ctx.state.session = state.session;\r\n ctx.state.csrfToken = state.csrfToken;\r\n debug(`importSessionState: restored session and CSRF token`);\r\n\r\n // Restore cookies from array to Map\r\n ctx.state.cookies.clear();\r\n for (const cookie of state.cookies) {\r\n ctx.state.cookies.set(cookie.name, cookie.value);\r\n }\r\n debug(`importSessionState: restored ${state.cookies.length} cookies`);\r\n\r\n // For SSO, load certificates from paths\r\n if (state.authType === 'sso' && state.ssoCertPaths) {\r\n debug(`importSessionState: loading SSO certs from ${state.ssoCertPaths.fullChainPath}`);\r\n try {\r\n const fs = await import('fs/promises');\r\n const [fullChain, key] = await Promise.all([\r\n fs.readFile(state.ssoCertPaths.fullChainPath, 'utf-8'),\r\n fs.readFile(state.ssoCertPaths.keyPath, 'utf-8'),\r\n ]);\r\n setSsoCerts({ cert: fullChain, key });\r\n debug(`importSessionState: SSO certs loaded successfully`);\r\n } catch (certErr) {\r\n debug(`importSessionState: SSO cert load failed: ${certErr}`);\r\n return err(new Error(`Failed to load SSO certificates: ${certErr instanceof Error ? certErr.message : String(certErr)}`));\r\n }\r\n }\r\n\r\n // Fetch fresh CSRF token using the restored session cookies\r\n // The cached CSRF token is tied to the original process, so we need a new one\r\n debug(`importSessionState: fetching fresh CSRF token...`);\r\n\r\n const [response, reqErr] = await ctx.request({\r\n method: 'GET',\r\n path: '/sap/bc/adt/compatibility/graph',\r\n headers: {\r\n [CSRF_TOKEN_HEADER]: FETCH_CSRF_TOKEN,\r\n },\r\n });\r\n debug(`importSessionState: CSRF fetch completed`);\r\n\r\n if (reqErr) {\r\n debug(`importSessionState: CSRF fetch error: ${reqErr.message}`);\r\n ctx.state.session = null;\r\n ctx.state.csrfToken = null;\r\n ctx.state.cookies.clear();\r\n return err(new Error(`Session validation failed: ${reqErr.message}`));\r\n }\r\n\r\n if (!response.ok) {\r\n debug(`importSessionState: CSRF fetch failed with status ${response.status}`);\r\n ctx.state.session = null;\r\n ctx.state.csrfToken = null;\r\n ctx.state.cookies.clear();\r\n return err(new Error(`Session validation failed with status ${response.status}`));\r\n }\r\n\r\n // Extract and store the new CSRF token\r\n const newToken = extractCsrfToken(response.headers);\r\n if (!newToken) {\r\n debug(`importSessionState: no CSRF token in response headers`);\r\n ctx.state.session = null;\r\n ctx.state.csrfToken = null;\r\n ctx.state.cookies.clear();\r\n return err(new Error('Session validation failed: no CSRF token returned'));\r\n }\r\n\r\n ctx.state.csrfToken = newToken;\r\n debug(`importSessionState: new CSRF token obtained: ${newToken.substring(0, 20)}...`);\r\n\r\n // Start auto-refresh if enabled\r\n const autoRefresh = ctx.state.config.autoRefresh ?? { enabled: true };\r\n if (autoRefresh.enabled) {\r\n const interval = autoRefresh.intervalMs ?? DEFAULT_REFRESH_INTERVAL;\r\n ctx.startAutoRefresh(interval);\r\n debug(`Auto-refresh started with ${interval}ms interval (after import)`);\r\n }\r\n\r\n debug(`importSessionState: import complete`);\r\n return ok(true);\r\n}\r\n","// ADT Object Type Configuration — metadata for SAP development objects\r\n\r\nimport type { AsyncResult } from '../../types/result';\r\n\r\n// Client interface for ADT requests\r\nexport interface AdtRequestor {\r\n request(options: {\r\n method: 'GET' | 'POST' | 'PUT' | 'DELETE';\r\n path: string;\r\n params?: Record<string, string | number>;\r\n headers?: Record<string, string>;\r\n body?: string;\r\n }): AsyncResult<Response, Error>;\r\n}\r\n\r\n// Configuration for a specific SAP object type\r\nexport interface ObjectConfig {\r\n /** ADT endpoint path (e.g., 'ddic/ddl/sources') */\r\n endpoint: string;\r\n /** XML namespace for creation requests */\r\n nameSpace: string;\r\n /** Root element name for creation XML */\r\n rootName: string;\r\n /** SAP ADT object type identifier (e.g., 'DDLS/DF') */\r\n type: string;\r\n /** Human-readable label (e.g., 'View') */\r\n label: string;\r\n /** File extension (e.g., 'asddls') */\r\n extension: string;\r\n /** Data preview endpoint (if supported) */\r\n dpEndpoint?: string;\r\n /** Data preview parameter name (if supported) */\r\n dpParam?: string;\r\n}\r\n\r\n/**\r\n * Result of upsert operation\r\n */\r\nexport interface UpsertResult {\r\n name: string;\r\n extension: string;\r\n status: 'created' | 'updated' | 'unchanged';\r\n transport?: string;\r\n}\r\n\r\n/**\r\n * Supported object types\r\n */\r\nexport type ConfiguredExtension = 'asddls' | 'asdcls' | 'astabldt' | 'astablds' | 'aclass' | 'asprog';\r\n\r\n/**\r\n * Object type labels\r\n */\r\nexport enum ObjectTypeLabel {\r\n VIEW = 'View',\r\n ACCESS_CONTROL = 'Access Control',\r\n TABLE = 'Table',\r\n STRUCTURE = 'Structure',\r\n CLASS = 'Class',\r\n PROGRAM = 'ABAP Program',\r\n}\r\n\r\n/**\r\n * Configuration map for all supported object types\r\n *\r\n * Maps file extensions to their ADT configuration.\r\n * This is the central registry for object type metadata.\r\n */\r\nexport const OBJECT_CONFIG_MAP: Record<ConfiguredExtension, ObjectConfig> = {\r\n 'asddls': {\r\n endpoint: 'ddic/ddl/sources',\r\n nameSpace: 'xmlns:ddl=\"http://www.sap.com/adt/ddic/ddlsources\"',\r\n rootName: 'ddl:ddlSource',\r\n type: 'DDLS/DF',\r\n label: ObjectTypeLabel.VIEW,\r\n extension: 'asddls',\r\n dpEndpoint: 'cds',\r\n dpParam: 'ddlSourceName',\r\n },\r\n 'asdcls': {\r\n endpoint: 'acm/dcl/sources',\r\n nameSpace: 'xmlns:dcl=\"http://www.sap.com/adt/acm/dclsources\"',\r\n rootName: 'dcl:dclSource',\r\n type: 'DCLS/DL',\r\n label: ObjectTypeLabel.ACCESS_CONTROL,\r\n extension: 'asdcls',\r\n },\r\n 'aclass': {\r\n endpoint: 'oo/classes',\r\n nameSpace: 'xmlns:class=\"http://www.sap.com/adt/oo/classes\"',\r\n rootName: 'class:abapClass',\r\n type: 'CLAS/OC',\r\n label: ObjectTypeLabel.CLASS,\r\n extension: 'aclass',\r\n },\r\n 'astabldt': {\r\n endpoint: 'ddic/tables',\r\n nameSpace: 'xmlns:blue=\"http://www.sap.com/wbobj/blue\"',\r\n rootName: 'blue:blueSource',\r\n type: 'TABL/DT',\r\n label: ObjectTypeLabel.TABLE,\r\n extension: 'astabldt',\r\n dpEndpoint: 'ddic',\r\n dpParam: 'ddicEntityName',\r\n },\r\n 'astablds': {\r\n endpoint: 'ddic/structures',\r\n nameSpace: 'xmlns:blue=\"http://www.sap.com/wbobj/blue\"',\r\n rootName: 'blue:blueSource',\r\n type: 'STRU/D',\r\n label: ObjectTypeLabel.STRUCTURE,\r\n extension: 'astablds',\r\n },\r\n 'asprog': {\r\n endpoint: 'programs/programs',\r\n nameSpace: 'xmlns:program=\"http://www.sap.com/adt/programs/programs\"',\r\n rootName: 'program:abapProgram',\r\n type: 'PROG/P',\r\n label: ObjectTypeLabel.PROGRAM,\r\n extension: 'asprog',\r\n },\r\n};\r\n\r\n/**\r\n * Get object configuration by extension\r\n *\r\n * @param extension - File extension (e.g., 'asddls')\r\n * @returns Configuration or null if not found\r\n */\r\nexport function getConfigByExtension(extension: string): ObjectConfig | null {\r\n return OBJECT_CONFIG_MAP[extension as ConfiguredExtension] ?? null;\r\n}\r\n\r\n/**\r\n * Get object configuration by ADT type\r\n *\r\n * @param type - ADT type identifier (e.g., 'DDLS/DF')\r\n * @returns Configuration or null if not found\r\n */\r\nexport function getConfigByType(type: string): ObjectConfig | null {\r\n for (const config of Object.values(OBJECT_CONFIG_MAP)) {\r\n if (config.type === type) {\r\n return config;\r\n }\r\n }\r\n return null;\r\n}\r\n\r\n/**\r\n * Get all configured extensions\r\n *\r\n * @returns Array of supported extensions\r\n */\r\nexport function getAllExtensions(): ConfiguredExtension[] {\r\n return Object.keys(OBJECT_CONFIG_MAP) as ConfiguredExtension[];\r\n}\r\n\r\n/**\r\n * Get all configured ADT types\r\n *\r\n * @returns Array of supported ADT types\r\n */\r\nexport function getAllTypes(): string[] {\r\n return Object.values(OBJECT_CONFIG_MAP).map(config => config.type);\r\n}\r\n\r\n/**\r\n * Check if extension is supported\r\n *\r\n * @param extension - Extension to check\r\n * @returns True if supported\r\n */\r\nexport function isExtensionSupported(extension: string): extension is ConfiguredExtension {\r\n return extension in OBJECT_CONFIG_MAP;\r\n}\r\n","/**\n * ADT Helpers — shared utilities for ADT operations\n *\n * Internal helpers used across multiple ADT files.\n * Not exported from the adt/ barrel.\n */\n\nimport type { AsyncResult } from '../../types/result';\nimport { extractError } from '../utils/xml';\nimport { getConfigByExtension } from './types';\nimport type { ObjectConfig } from './types';\n\n/**\n * Check response for errors and return text content\n */\nexport async function checkResponse(\n response: Response | null,\n requestErr: Error | null,\n operation: string\n): AsyncResult<string, Error> {\n // Handle request errors.\n if (requestErr) return [null, requestErr];\n if (!response) return [null, new Error(`${operation}: No response`)];\n\n // Handle HTTP errors.\n if (!response.ok) {\n const text = await response.text();\n const errorMsg = extractError(text);\n // Include status and raw text if no message found for debugging\n if (errorMsg === 'No message found' || errorMsg === 'Failed to parse error XML') {\n return [null, new Error(`${operation}: HTTP ${response.status} - ${text.substring(0, 500)}`)];\n }\n return [null, new Error(`${operation}: ${errorMsg}`)];\n }\n\n // Return successful response text.\n return [await response.text(), null];\n}\n\n/**\n * Validate extension and return config\n */\nexport function requireConfig(extension: string): [ObjectConfig, null] | [null, Error] {\n // Lookup configuration for extension.\n const config = getConfigByExtension(extension);\n if (!config) return [null, new Error(`Unsupported extension: ${extension}`)];\n\n // Return valid configuration.\n return [config, null];\n}\n","/**\r\n * POST /objects/read — Read object source content\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { ObjectRef } from '../../../types/requests';\r\nimport type { AdtRequestor } from '../types';\r\nimport { checkResponse, requireConfig } from '../helpers';\r\n\r\n/**\r\n * Object metadata\r\n */\r\nexport interface ObjectMetadata {\r\n name: string;\r\n extension: string;\r\n package: string;\r\n description?: string;\r\n createdBy?: string;\r\n createdAt?: string;\r\n modifiedBy?: string;\r\n modifiedAt?: string;\r\n}\r\n\r\n/**\r\n * Object with content (read response)\r\n */\r\nexport interface ObjectWithContent extends ObjectMetadata {\r\n content: string;\r\n}\r\n\r\n/**\r\n * Read object source content\r\n *\r\n * @param client - ADT client\r\n * @param object - Object reference (name + extension)\r\n * @returns Object with content or error\r\n */\r\nexport async function readObject(\r\n client: AdtRequestor,\r\n object: ObjectRef\r\n): AsyncResult<ObjectWithContent, Error> {\r\n // Validate object extension is supported.\r\n const [config, configErr] = requireConfig(object.extension);\r\n if (configErr) return err(configErr);\r\n\r\n // Execute GET request for object source content.\r\n const [response, requestErr] = await client.request({\r\n method: 'GET',\r\n path: `/sap/bc/adt/${config.endpoint}/${object.name}/source/main`,\r\n headers: { 'Accept': 'text/plain' },\r\n });\r\n\r\n // Validate successful response and extract content.\r\n const [content, checkErr] = await checkResponse(\r\n response,\r\n requestErr,\r\n `Failed to read ${config.label} ${object.name}`\r\n );\r\n if (checkErr) return err(checkErr);\r\n\r\n // Build result object with content.\r\n const result: ObjectWithContent = {\r\n name: object.name,\r\n extension: object.extension,\r\n package: '',\r\n content,\r\n };\r\n\r\n return ok(result);\r\n}\r\n","/**\r\n * Lock/Unlock — Object lock management for editing\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { ObjectRef } from '../../../types/requests';\r\nimport type { AdtRequestor } from '../types';\r\nimport { extractLockHandle } from '../../utils/xml';\r\nimport { checkResponse, requireConfig } from '../helpers';\r\nimport { debug } from '../../utils/logging';\r\n\r\n/**\r\n * Lock an object for editing\r\n *\r\n * @param client - ADT client\r\n * @param object - Object reference (name + extension)\r\n * @returns Lock handle string or error\r\n */\r\nexport async function lockObject(\r\n client: AdtRequestor,\r\n object: ObjectRef\r\n): AsyncResult<string, Error> {\r\n // Validate object extension is supported.\r\n const [config, configErr] = requireConfig(object.extension);\r\n if (configErr) return err(configErr);\r\n\r\n // Execute lock request.\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: `/sap/bc/adt/${config.endpoint}/${object.name}/source/main`,\r\n params: {\r\n '_action': 'LOCK',\r\n 'accessMode': 'MODIFY',\r\n },\r\n headers: {\r\n 'Accept': 'application/*,application/vnd.sap.as+xml;charset=UTF-8;dataname=com.sap.adt.lock.result',\r\n },\r\n });\r\n\r\n // Validate successful response.\r\n const [text, checkErr] = await checkResponse(\r\n response,\r\n requestErr,\r\n `Failed to lock ${config.label} ${object.name}`\r\n );\r\n if (checkErr) return err(checkErr);\r\n\r\n // Extract lock handle from XML response.\r\n const [lockHandle, extractErr] = extractLockHandle(text);\r\n if (extractErr) {\r\n return err(new Error(`Failed to extract lock handle: ${extractErr.message}`));\r\n }\r\n debug(`Lock acquired: handle=${lockHandle}`);\r\n\r\n return ok(lockHandle);\r\n}\r\n\r\n/**\r\n * Unlock an object after editing\r\n *\r\n * @param client - ADT client\r\n * @param object - Object reference (name + extension)\r\n * @param lockHandle - Lock handle from lockObject()\r\n * @returns void or error\r\n */\r\nexport async function unlockObject(\r\n client: AdtRequestor,\r\n object: ObjectRef,\r\n lockHandle: string\r\n): AsyncResult<void, Error> {\r\n // Validate object extension is supported.\r\n const [config, configErr] = requireConfig(object.extension);\r\n if (configErr) return err(configErr);\r\n\r\n // Execute unlock request.\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: `/sap/bc/adt/${config.endpoint}/${object.name}/source/main`,\r\n params: {\r\n '_action': 'UNLOCK',\r\n 'lockHandle': lockHandle,\r\n },\r\n });\r\n\r\n // Validate successful response.\r\n const [_, checkErr] = await checkResponse(\r\n response,\r\n requestErr,\r\n `Failed to unlock ${config.label} ${object.name}`\r\n );\r\n if (checkErr) return err(checkErr);\r\n\r\n return ok(undefined);\r\n}\r\n","/**\r\n * Create — Create new SAP development object\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { ObjectContent } from '../../../types/requests';\r\nimport type { AdtRequestor } from '../types';\r\nimport { escapeXml } from '../../utils/xml';\r\nimport { checkResponse, requireConfig } from '../helpers';\r\n\r\n/**\r\n * Create a new object in SAP\r\n *\r\n * @param client - ADT client\r\n * @param object - Object with content (name, extension, content, description)\r\n * @param packageName - Target package\r\n * @param transport - Transport request (required for non-$TMP packages)\r\n * @param username - Creating user\r\n * @returns void or error\r\n */\r\nexport async function createObject(\r\n client: AdtRequestor,\r\n object: ObjectContent,\r\n packageName: string,\r\n transport: string | undefined,\r\n username: string\r\n): AsyncResult<void, Error> {\r\n // Validate object extension is supported.\r\n const [config, configErr] = requireConfig(object.extension);\r\n if (configErr) return err(configErr);\r\n\r\n // Default empty description if not provided.\r\n const description = object.description ?? '';\r\n\r\n // Build XML request body with object metadata.\r\n const body = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<${config.rootName} ${config.nameSpace}\r\n xmlns:adtcore=\"http://www.sap.com/adt/core\"\r\n adtcore:description=\"${escapeXml(description)}\"\r\n adtcore:language=\"EN\"\r\n adtcore:name=\"${object.name.toUpperCase()}\"\r\n adtcore:type=\"${config.type}\"\r\n adtcore:responsible=\"${username.toUpperCase()}\">\r\n\r\n <adtcore:packageRef adtcore:name=\"${packageName}\"/>\r\n\r\n</${config.rootName}>`;\r\n\r\n // Add transport parameter if provided.\r\n const params: Record<string, string> = {};\r\n if (transport) {\r\n params['corrNr'] = transport;\r\n }\r\n\r\n // Execute create request.\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: `/sap/bc/adt/${config.endpoint}`,\r\n params,\r\n headers: { 'Content-Type': 'application/*' },\r\n body: body.trim(),\r\n });\r\n\r\n // Validate successful response.\r\n const [_, checkErr] = await checkResponse(\r\n response,\r\n requestErr,\r\n `Failed to create ${config.label} ${object.name}`\r\n );\r\n if (checkErr) return err(checkErr);\r\n\r\n return ok(undefined);\r\n}\r\n","/**\r\n * Update — Update existing SAP development object\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { ObjectContent } from '../../../types/requests';\r\nimport type { AdtRequestor } from '../types';\r\nimport { checkResponse, requireConfig } from '../helpers';\r\nimport { debug } from '../../utils/logging';\r\n\r\n/**\r\n * Update an existing object's source content\r\n *\r\n * @param client - ADT client\r\n * @param object - Object with new content\r\n * @param lockHandle - Lock handle from lockObject()\r\n * @param transport - Transport request (required for non-$TMP packages)\r\n * @returns void or error\r\n */\r\nexport async function updateObject(\r\n client: AdtRequestor,\r\n object: ObjectContent,\r\n lockHandle: string,\r\n transport: string | undefined\r\n): AsyncResult<void, Error> {\r\n // Validate object extension is supported.\r\n const [config, configErr] = requireConfig(object.extension);\r\n if (configErr) return err(configErr);\r\n\r\n // Build request parameters with lock handle.\r\n const params: Record<string, string> = {\r\n 'lockHandle': lockHandle,\r\n };\r\n if (transport) {\r\n params['corrNr'] = transport;\r\n }\r\n\r\n // Execute update request to ADT server.\r\n debug(`Update ${object.name}: content length=${object.content?.length ?? 0}`);\r\n const [response, requestErr] = await client.request({\r\n method: 'PUT',\r\n path: `/sap/bc/adt/${config.endpoint}/${object.name}/source/main`,\r\n params,\r\n headers: { 'Content-Type': '*/*' },\r\n body: object.content,\r\n });\r\n debug(`Update response: ${response?.status ?? 'no response'}, err=${requestErr?.message ?? 'none'}`);\r\n\r\n // Validate successful response.\r\n const [_, checkErr] = await checkResponse(\r\n response,\r\n requestErr,\r\n `Failed to update ${config.label} ${object.name}`\r\n );\r\n if (checkErr) return err(checkErr);\r\n\r\n return ok(undefined);\r\n}\r\n","/**\r\n * Delete — Delete SAP development object\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { ObjectRef } from '../../../types/requests';\r\nimport type { AdtRequestor } from '../types';\r\nimport { checkResponse, requireConfig } from '../helpers';\r\n\r\n/**\r\n * Delete an object from SAP\r\n *\r\n * @param client - ADT client\r\n * @param object - Object reference (name + extension)\r\n * @param lockHandle - Lock handle from lockObject()\r\n * @param transport - Transport request (required for non-$TMP packages)\r\n * @returns void or error\r\n */\r\nexport async function deleteObject(\r\n client: AdtRequestor,\r\n object: ObjectRef,\r\n lockHandle: string,\r\n transport: string | undefined\r\n): AsyncResult<void, Error> {\r\n // Validate object extension is supported.\r\n const [config, configErr] = requireConfig(object.extension);\r\n if (configErr) return err(configErr);\r\n\r\n // Build request parameters with lock handle.\r\n const params: Record<string, string> = {\r\n 'lockHandle': lockHandle,\r\n };\r\n if (transport) {\r\n params['corrNr'] = transport;\r\n }\r\n\r\n // Execute delete request.\r\n const [response, requestErr] = await client.request({\r\n method: 'DELETE',\r\n path: `/sap/bc/adt/${config.endpoint}/${object.name}/source/main`,\r\n params,\r\n headers: { 'Accept': 'text/plain' },\r\n });\r\n\r\n // Validate successful response.\r\n const [_, checkErr] = await checkResponse(\r\n response,\r\n requestErr,\r\n `Failed to delete ${config.label} ${object.name}`\r\n );\r\n if (checkErr) return err(checkErr);\r\n\r\n return ok(undefined);\r\n}\r\n","// ADT Activation — activate ADT objects\r\n\r\nimport type { Result, AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { ObjectRef } from '../../../types/requests';\r\nimport type { AdtRequestor } from '../types';\r\nimport { getConfigByExtension } from '../types';\r\nimport { extractError, safeParseXml } from '../../utils/xml';\r\nimport { debug } from '../../utils/logging';\r\n\r\n/**\r\n * Result of activation operation\r\n */\r\nexport interface ActivationResult {\r\n name: string;\r\n extension: string;\r\n status: 'success' | 'warning' | 'error';\r\n messages: ActivationMessage[];\r\n}\r\n\r\nexport interface ActivationMessage {\r\n severity: 'error' | 'warning' | 'info';\r\n text: string;\r\n line?: number;\r\n column?: number;\r\n}\r\n\r\nexport async function activateObjects(\r\n client: AdtRequestor,\r\n objects: ObjectRef[]\r\n): AsyncResult<ActivationResult[], Error> {\r\n // Handle empty input.\r\n if (objects.length === 0) {\r\n return ok([]);\r\n }\r\n\r\n // Validate object extension is supported.\r\n const extension = objects[0]!.extension;\r\n const config = getConfigByExtension(extension);\r\n if (!config) return err(new Error(`Unsupported extension: ${extension}`));\r\n\r\n // Verify all objects have same extension for batch activation.\r\n for (const obj of objects) {\r\n if (obj.extension !== extension) {\r\n return err(new Error('All objects must have the same extension for batch activation'));\r\n }\r\n }\r\n\r\n // Build XML request body with object references.\r\n const objectRefs = objects.map(obj => `<adtcore:objectReference\r\n adtcore:uri=\"/sap/bc/adt/${config.endpoint}/${obj.name.toLowerCase()}\"\r\n adtcore:type=\"${config.type}\"\r\n adtcore:name=\"${obj.name}\"\r\n adtcore:description=\"*\"/>`).join('\\n ');\r\n\r\n const body = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n <adtcore:objectReferences xmlns:adtcore=\"http://www.sap.com/adt/core\">\r\n ${objectRefs}\r\n </adtcore:objectReferences>`;\r\n\r\n // Execute activation request.\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: '/sap/bc/adt/activation',\r\n params: {\r\n 'method': 'activate',\r\n 'preAuditRequested': 'true',\r\n },\r\n headers: {\r\n 'Content-Type': 'application/xml',\r\n 'Accept': 'application/xml',\r\n },\r\n body,\r\n });\r\n\r\n // Validate successful response.\r\n if (requestErr) { return err(requestErr); }\r\n const text = await response.text();\r\n debug(`Activation response status: ${response.status}`);\r\n debug(`Activation response: ${text.substring(0, 500)}`);\r\n if (!response.ok) {\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Activation failed: ${errorMsg}`));\r\n }\r\n\r\n // Parse activation results from response.\r\n const [results, parseErr] = extractActivationErrors(objects, text, extension);\r\n if (parseErr) { return err(parseErr); }\r\n return ok(results);\r\n}\r\n\r\n// Parse activation response XML for errors\r\nfunction extractActivationErrors(\r\n objects: ObjectRef[],\r\n xml: string,\r\n _extension: string\r\n): Result<ActivationResult[], Error> {\r\n // Parse XML response.\r\n const [doc, parseErr] = safeParseXml(xml);\r\n if (parseErr) { return err(parseErr); }\r\n\r\n // Initialize error map with empty arrays for each object.\r\n const errorMap: Map<string, ActivationMessage[]> = new Map();\r\n objects.forEach(obj => errorMap.set(obj.name.toLowerCase(), []));\r\n\r\n // Extract message elements and prepare regex for position parsing.\r\n const msgElements = doc.getElementsByTagName('msg');\r\n const startRegex = /#start=(\\d+),(\\d+)/;\r\n\r\n // Process each message element.\r\n for (let i = 0; i < msgElements.length; i++) {\r\n const msg = msgElements[i];\r\n if (!msg) continue;\r\n\r\n // Skip warning messages (type 'W').\r\n const type = msg.getAttribute('type');\r\n if (type === 'W') continue;\r\n\r\n // Extract object description and href for position info.\r\n const objDescr = msg.getAttribute('objDescr');\r\n const href = msg.getAttribute('href');\r\n if (!objDescr || !href) continue;\r\n\r\n // Parse line and column from href.\r\n let line: number | undefined;\r\n let column: number | undefined;\r\n const match = startRegex.exec(href);\r\n if (match && match[1] && match[2]) {\r\n line = parseInt(match[1], 10);\r\n column = parseInt(match[2], 10);\r\n }\r\n if (!line || !column) continue;\r\n\r\n // Find matching object by name.\r\n const matchingObj = objects.find(obj =>\r\n objDescr.toLowerCase().includes(obj.name.toLowerCase())\r\n );\r\n if (!matchingObj) continue;\r\n\r\n // Extract message text elements.\r\n const shortTextElements = msg.getElementsByTagName('txt');\r\n for (let j = 0; j < shortTextElements.length; j++) {\r\n const txt = shortTextElements[j];\r\n if (!txt) continue;\r\n\r\n const text = txt.textContent;\r\n if (!text) continue;\r\n\r\n // Build activation message with severity and position.\r\n const message: ActivationMessage = {\r\n severity: type === 'E' ? 'error' : 'warning',\r\n text,\r\n line,\r\n column,\r\n };\r\n\r\n // Add message to object's error list.\r\n const messages = errorMap.get(matchingObj.name.toLowerCase()) || [];\r\n messages.push(message);\r\n errorMap.set(matchingObj.name.toLowerCase(), messages);\r\n }\r\n }\r\n\r\n // Build final results with status based on message severity.\r\n const results: ActivationResult[] = objects.map(obj => {\r\n const messages = errorMap.get(obj.name.toLowerCase()) || [];\r\n const hasErrors = messages.some(m => m.severity === 'error');\r\n\r\n return {\r\n name: obj.name,\r\n extension: obj.extension,\r\n status: hasErrors ? 'error' : messages.length > 0 ? 'warning' : 'success',\r\n messages,\r\n };\r\n });\r\n\r\n return ok(results);\r\n}\r\n","// ADT Syntax Check — check objects for errors and warnings without activation\r\n\r\nimport type { Result, AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { ObjectRef } from '../../../types/requests';\r\nimport type { AdtRequestor } from '../types';\r\nimport { getConfigByExtension } from '../types';\r\nimport type { ActivationMessage } from './activation';\r\nimport { readObject } from './read';\r\nimport { extractError, safeParseXml } from '../../utils/xml';\r\nimport { debug } from '../../utils/logging';\r\n\r\n// Result of syntax check operation\r\nexport interface CheckResult {\r\n name: string;\r\n extension: string;\r\n status: 'success' | 'warning' | 'error';\r\n messages: ActivationMessage[];\r\n}\r\n\r\nexport async function checkSyntax(\r\n client: AdtRequestor,\r\n objects: ObjectRef[]\r\n): AsyncResult<CheckResult[], Error> {\r\n // Handle empty input.\r\n if (objects.length === 0) {\r\n return ok([]);\r\n }\r\n\r\n // Validate object extension is supported.\r\n const extension = objects[0]!.extension;\r\n const config = getConfigByExtension(extension);\r\n if (!config) return err(new Error(`Unsupported extension: ${extension}`));\r\n\r\n // Verify all objects have same extension for batch check.\r\n for (const obj of objects) {\r\n if (obj.extension !== extension) {\r\n return err(new Error('All objects must have the same extension for batch syntax check'));\r\n }\r\n }\r\n\r\n // Read source code for each object.\r\n const sources: Map<string, string> = new Map();\r\n for (const obj of objects) {\r\n const [result, readErr] = await readObject(client, obj);\r\n if (readErr) return err(new Error(`Failed to read ${obj.name}: ${readErr.message}`));\r\n sources.set(obj.name.toLowerCase(), result.content);\r\n }\r\n\r\n // Build XML request body with inline source code.\r\n const objectRefs = objects.map(obj => {\r\n const uri = `/sap/bc/adt/${config.endpoint}/${obj.name.toLowerCase()}`;\r\n const sourceUri = `${uri}/source/main`;\r\n const content = sources.get(obj.name.toLowerCase()) ?? '';\r\n const encoded = Buffer.from(content).toString('base64');\r\n\r\n return `<chkrun:checkObject adtcore:uri=\"${uri}\" chkrun:version=\"active\">\r\n <chkrun:artifacts>\r\n <chkrun:artifact chkrun:contentType=\"text/plain; charset=utf-8\" chkrun:uri=\"${sourceUri}\">\r\n <chkrun:content>${encoded}</chkrun:content>\r\n </chkrun:artifact>\r\n </chkrun:artifacts>\r\n </chkrun:checkObject>`;\r\n }).join('\\n ');\r\n\r\n const body = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<chkrun:checkObjectList xmlns:chkrun=\"http://www.sap.com/adt/checkrun\"\r\n xmlns:adtcore=\"http://www.sap.com/adt/core\">\r\n ${objectRefs}\r\n</chkrun:checkObjectList>`;\r\n\r\n // Execute syntax check request.\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: '/sap/bc/adt/checkruns',\r\n params: {\r\n 'reporters': 'abapCheckRun',\r\n },\r\n headers: {\r\n 'Content-Type': 'application/vnd.sap.adt.checkobjects+xml',\r\n 'Accept': 'application/vnd.sap.adt.checkmessages+xml',\r\n },\r\n body,\r\n });\r\n\r\n // Validate successful response.\r\n if (requestErr) { return err(requestErr); }\r\n const text = await response.text();\r\n debug(`Syntax check response status: ${response.status}`);\r\n debug(`Syntax check response: ${text.substring(0, 500)}`);\r\n if (!response.ok) {\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Syntax check failed: ${errorMsg}`));\r\n }\r\n\r\n // Parse check results from response.\r\n const [results, parseErr] = extractCheckMessages(objects, text);\r\n if (parseErr) { return err(parseErr); }\r\n return ok(results);\r\n}\r\n\r\n// Parse check run response XML for messages\r\nfunction extractCheckMessages(\r\n objects: ObjectRef[],\r\n xml: string\r\n): Result<CheckResult[], Error> {\r\n // Parse XML response.\r\n const [doc, parseErr] = safeParseXml(xml);\r\n if (parseErr) { return err(parseErr); }\r\n\r\n // Initialize message map with empty arrays for each object.\r\n const messageMap: Map<string, ActivationMessage[]> = new Map();\r\n objects.forEach(obj => messageMap.set(obj.name.toLowerCase(), []));\r\n\r\n // Try both namespaced and non-namespaced tag names.\r\n let msgElements = doc.getElementsByTagName('chkrun:checkMessage');\r\n if (msgElements.length === 0) {\r\n msgElements = doc.getElementsByTagName('checkMessage');\r\n }\r\n\r\n const startRegex = /#start=(\\d+),(\\d+)/;\r\n\r\n // Process each message element.\r\n for (let i = 0; i < msgElements.length; i++) {\r\n const msg = msgElements[i];\r\n if (!msg) continue;\r\n\r\n // Extract severity from type attribute.\r\n const type = msg.getAttribute('chkrun:type') ?? msg.getAttribute('type');\r\n if (!type) continue;\r\n\r\n // Extract URI for position info and object matching.\r\n const uri = msg.getAttribute('chkrun:uri') ?? msg.getAttribute('uri') ?? '';\r\n\r\n // Parse line and column from URI fragment.\r\n let line: number | undefined;\r\n let column: number | undefined;\r\n const match = startRegex.exec(uri);\r\n if (match && match[1] && match[2]) {\r\n line = parseInt(match[1], 10);\r\n column = parseInt(match[2], 10);\r\n }\r\n\r\n // Find matching object by name in URI.\r\n const matchingObj = objects.find(obj =>\r\n uri.toLowerCase().includes(obj.name.toLowerCase())\r\n );\r\n if (!matchingObj) continue;\r\n\r\n // Extract message text from shortText attribute.\r\n const text = msg.getAttribute('chkrun:shortText') ?? msg.getAttribute('shortText');\r\n if (!text) continue;\r\n\r\n // Build check message with severity and position.\r\n const message: ActivationMessage = {\r\n severity: type === 'E' ? 'error' : type === 'W' ? 'warning' : 'info',\r\n text,\r\n ...(line !== undefined && { line }),\r\n ...(column !== undefined && { column }),\r\n };\r\n\r\n // Add message to object's list.\r\n const messages = messageMap.get(matchingObj.name.toLowerCase()) || [];\r\n messages.push(message);\r\n messageMap.set(matchingObj.name.toLowerCase(), messages);\r\n }\r\n\r\n // Build final results with status based on message severity.\r\n const results: CheckResult[] = objects.map(obj => {\r\n const messages = messageMap.get(obj.name.toLowerCase()) || [];\r\n const hasErrors = messages.some(m => m.severity === 'error');\r\n\r\n return {\r\n name: obj.name,\r\n extension: obj.extension,\r\n status: hasErrors ? 'error' : messages.length > 0 ? 'warning' : 'success',\r\n messages,\r\n };\r\n });\r\n\r\n return ok(results);\r\n}\r\n","/**\r\n * PackageStats — Get stats for specific packages\r\n *\r\n * Uses virtualfolders/contents endpoint with package names in preselection:\r\n * - counter attribute = recursive object count (includes subpackages)\r\n * - text attribute = package description\r\n */\r\n\r\nimport type { AsyncResult } from '../../../../types/result';\r\nimport { ok, err } from '../../../../types/result';\r\nimport type { AdtRequestor } from '../../types';\r\nimport type { PackageNode } from './types';\r\nimport { extractError, safeParseXml } from '../../../utils/xml';\r\n\r\n/**\r\n * Construct request body for fetching specific packages by name.\r\n *\r\n * SAP quirk: With only 1 package in preselection, SAP drills INTO that package.\r\n * With 2+ packages, it returns those packages as top-level results.\r\n * We add an empty value when only 1 package is requested to get the correct behavior.\r\n */\r\nfunction constructPackageStatsBody(packageNames: string[]): string {\r\n // Ensure at least 2 values - SAP needs 2+ to return packages as results\r\n // SRIS_TEST_DATA_VFS_EMPTY is a known empty SAP package that won't add noise\r\n const names = packageNames.length === 1\r\n ? [...packageNames, 'SRIS_TEST_DATA_VFS_EMPTY']\r\n : packageNames;\r\n\r\n const values = names\r\n .map(name => ` <vfs:value>${name}</vfs:value>`)\r\n .join('\\n');\r\n\r\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<vfs:virtualFoldersRequest xmlns:vfs=\"http://www.sap.com/adt/ris/virtualFolders\" objectSearchPattern=\"*\">\r\n <vfs:preselection facet=\"package\">\r\n${values}\r\n </vfs:preselection>\r\n <vfs:facetorder>\r\n <vfs:facet>package</vfs:facet>\r\n <vfs:facet>group</vfs:facet>\r\n <vfs:facet>type</vfs:facet>\r\n </vfs:facetorder>\r\n</vfs:virtualFoldersRequest>`;\r\n}\r\n\r\n/**\r\n * Parse package stats from virtualfolders response.\r\n */\r\nfunction parsePackageStats(xml: string): PackageNode[] {\r\n const [doc, parseErr] = safeParseXml(xml);\r\n if (parseErr) return [];\r\n\r\n const packages: PackageNode[] = [];\r\n const virtualFolders = doc.getElementsByTagName('vfs:virtualFolder');\r\n\r\n for (let i = 0; i < virtualFolders.length; i++) {\r\n const vf = virtualFolders[i];\r\n if (!vf) continue;\r\n\r\n const facet = vf.getAttribute('facet')?.toUpperCase();\r\n if (facet !== 'PACKAGE') continue;\r\n\r\n const name = vf.getAttribute('name');\r\n if (!name) continue;\r\n\r\n const countAttr = vf.getAttribute('counter');\r\n const count = countAttr ? parseInt(countAttr, 10) : 0;\r\n const description = vf.getAttribute('text');\r\n\r\n const pkg: PackageNode = {\r\n name,\r\n numContents: count,\r\n };\r\n if (description) pkg.description = description;\r\n packages.push(pkg);\r\n }\r\n\r\n return packages;\r\n}\r\n\r\n/**\r\n * Get stats for a single package.\r\n */\r\nexport async function getPackageStats(\r\n client: AdtRequestor,\r\n packageName: string\r\n): AsyncResult<PackageNode, Error>;\r\n\r\n/**\r\n * Get stats for multiple packages.\r\n */\r\nexport async function getPackageStats(\r\n client: AdtRequestor,\r\n packageNames: string[]\r\n): AsyncResult<PackageNode[], Error>;\r\n\r\n/**\r\n * Get stats for one or more packages (name, description, numContents).\r\n *\r\n * Efficiently fetches only the requested packages by putting their names\r\n * in the preselection, rather than fetching all packages.\r\n */\r\nexport async function getPackageStats(\r\n client: AdtRequestor,\r\n packageNames: string | string[]\r\n): AsyncResult<PackageNode | PackageNode[], Error> {\r\n const isSingle = typeof packageNames === 'string';\r\n const names = isSingle ? [packageNames] : packageNames;\r\n if (names.length === 0) {\r\n return ok([]);\r\n }\r\n\r\n const body = constructPackageStatsBody(names);\r\n\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: '/sap/bc/adt/repository/informationsystem/virtualfolders/contents',\r\n headers: {\r\n 'Content-Type': 'application/vnd.sap.adt.repository.virtualfolders.request.v1+xml',\r\n 'Accept': 'application/vnd.sap.adt.repository.virtualfolders.result.v1+xml',\r\n },\r\n body,\r\n });\r\n\r\n if (requestErr) return err(requestErr);\r\n if (!response.ok) {\r\n const text = await response.text();\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Package stats fetch failed: ${errorMsg}`));\r\n }\r\n\r\n const xml = await response.text();\r\n const packages = parsePackageStats(xml)\r\n .filter(pkg => pkg.name !== 'SRIS_TEST_DATA_VFS_EMPTY');\r\n\r\n // Match the return type to the input type.\r\n if (isSingle) {\r\n if (packages.length === 0) {\r\n return err(new Error(`Package ${packageNames} not found`));\r\n }\r\n return ok(packages[0]!);\r\n }\r\n return ok(packages);\r\n}\r\n","/**\r\n * Packages — List available packages\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { AdtRequestor } from '../types';\r\nimport { extractError, safeParseXml } from '../../utils/xml';\r\nimport { getPackageStats } from './tree/packageStats';\r\n\r\nexport interface Package {\r\n name: string;\r\n description?: string;\r\n}\r\n\r\n/**\r\n * Get list of available packages\r\n *\r\n * Uses the ADT search API with DEVC/K object type to search for packages,\r\n * then enriches results with descriptions from the virtualfolders API.\r\n *\r\n * @param client - ADT client\r\n * @param filter - Package name filter pattern (default: '*' for all packages)\r\n * Examples: 'Z*' for custom packages, '$TMP' for local, 'ZSNAP*' for specific prefix\r\n * @returns Array of packages or error\r\n */\r\nexport interface GetPackagesOptions {\r\n filter?: string;\r\n includeDescriptions?: boolean;\r\n}\r\n\r\nexport async function getPackages(\r\n client: AdtRequestor,\r\n options: GetPackagesOptions = {}\r\n): AsyncResult<Package[], Error> {\r\n const { filter = '*', includeDescriptions = false } = options;\r\n\r\n // Build search parameters for package search.\r\n const params = new URLSearchParams([\r\n ['operation', 'quickSearch'],\r\n ['query', filter],\r\n ['maxResults', '10001'],\r\n ['objectType', 'DEVC/K'],\r\n ]);\r\n\r\n // Execute search request.\r\n const [response, requestErr] = await client.request({\r\n method: 'GET',\r\n path: `/sap/bc/adt/repository/informationsystem/search?${params.toString()}`,\r\n });\r\n\r\n // Validate successful response.\r\n if (requestErr) { return err(requestErr); }\r\n if (!response.ok) {\r\n const text = await response.text();\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Package search failed: ${errorMsg}`));\r\n }\r\n\r\n // Parse search results.\r\n const text = await response.text();\r\n const [doc, parseErr] = safeParseXml(text);\r\n if (parseErr) { return err(parseErr); }\r\n\r\n // Extract package names from object references.\r\n const packageNames: string[] = [];\r\n const objectRefs = doc.getElementsByTagNameNS('http://www.sap.com/adt/core', 'objectReference');\r\n\r\n for (let i = 0; i < objectRefs.length; i++) {\r\n const obj = objectRefs[i];\r\n if (!obj) return err(new Error('Invalid object reference in package search results'));\r\n\r\n const name = obj.getAttributeNS('http://www.sap.com/adt/core', 'name') || obj.getAttribute('adtcore:name');\r\n if (!name) return err(new Error('Package name missing in object reference'));\r\n packageNames.push(name);\r\n }\r\n\r\n if (packageNames.length === 0) return ok([]);\r\n if (!includeDescriptions) return ok(packageNames.map(name => ({ name })));\r\n\r\n // Enrich with descriptions from virtualfolders API (quickSearch doesn't return them).\r\n const [stats, statsErr] = await getPackageStats(client, packageNames);\r\n if (statsErr) {\r\n return ok(packageNames.map(name => ({ name })));\r\n }\r\n\r\n // Build lookup for descriptions.\r\n const descriptionMap = new Map<string, string>();\r\n for (const stat of stats) {\r\n if (stat.description) descriptionMap.set(stat.name, stat.description);\r\n }\r\n\r\n // Merge descriptions into results.\r\n const packages: Package[] = packageNames.map(name => {\r\n const pkg: Package = { name };\r\n const description = descriptionMap.get(name);\r\n if (description) pkg.description = description;\r\n return pkg;\r\n });\r\n\r\n return ok(packages);\r\n}\r\n","/**\r\n * Parsers — XML parsing and response transformation\r\n */\r\n\r\nimport type { Result } from '../../../../types/result';\r\nimport { ok, err } from '../../../../types/result';\r\nimport { getConfigByType } from '../../types';\r\nimport { safeParseXml } from '../../../utils/xml';\r\nimport type {\r\n TreeResponse,\r\n PackageNode,\r\n FolderNode,\r\n ObjectNode,\r\n TreeDiscoveryQuery,\r\n ParseResult,\r\n ParsedFolder,\r\n ParsedObject,\r\n} from './types';\r\n\r\n/**\r\n * Build query from package and path\r\n */\r\nexport function buildQueryFromPath(packageName: string, path?: string): TreeDiscoveryQuery {\r\n const query: TreeDiscoveryQuery = {\r\n PACKAGE: {\r\n name: packageName.startsWith('..') ? packageName : `..${packageName}`,\r\n hasChildrenOfSameFacet: false,\r\n },\r\n };\r\n\r\n if (!path) return query;\r\n\r\n const segments = path.split('/').filter(s => s.length > 0);\r\n\r\n // First segment = GROUP\r\n if (segments[0]) {\r\n query.GROUP = {\r\n name: segments[0],\r\n hasChildrenOfSameFacet: false,\r\n };\r\n }\r\n\r\n // Second segment = TYPE\r\n if (segments[1]) {\r\n query.TYPE = {\r\n name: segments[1],\r\n hasChildrenOfSameFacet: false,\r\n };\r\n }\r\n\r\n return query;\r\n}\r\n\r\n/**\r\n * Construct tree discovery request body\r\n */\r\nexport function constructTreeBody(\r\n query: TreeDiscoveryQuery,\r\n searchPattern: string,\r\n owner?: string\r\n): string {\r\n const facets: string[] = [];\r\n const specified: Record<string, string> = {};\r\n const sortedFacets = ['PACKAGE', 'GROUP', 'TYPE', 'API'];\r\n\r\n for (const facet of sortedFacets) {\r\n const value = query[facet as keyof TreeDiscoveryQuery];\r\n if (value) {\r\n specified[facet] = value.name;\r\n if (value.hasChildrenOfSameFacet) {\r\n facets.push(facet);\r\n }\r\n } else {\r\n facets.push(facet);\r\n }\r\n }\r\n\r\n // Build preselection XML for facets\r\n const preselections: string[] = [];\r\n\r\n // Add owner preselection first if specified\r\n if (owner) {\r\n preselections.push(` <vfs:preselection facet=\"owner\">\r\n <vfs:value>${owner}</vfs:value>\r\n </vfs:preselection>`);\r\n }\r\n\r\n // Add facet preselections\r\n for (const [facet, name] of Object.entries(specified)) {\r\n preselections.push(` <vfs:preselection facet=\"${facet.toLowerCase()}\">\r\n <vfs:value>${name}</vfs:value>\r\n </vfs:preselection>`);\r\n }\r\n\r\n const specifiedXml = preselections.join('\\n');\r\n\r\n // At object level (PACKAGE, GROUP, TYPE all specified), use empty facetorder\r\n // This returns objects with descriptions in the text attribute\r\n const atObjectLevel = query.PACKAGE && query.GROUP && query.TYPE;\r\n const facetorderXml = atObjectLevel || facets.length === 0\r\n ? ' <vfs:facetorder/>'\r\n : ` <vfs:facetorder>\\n${facets.map(f => ` <vfs:facet>${f.toLowerCase()}</vfs:facet>`).join('\\n')}\\n </vfs:facetorder>`;\r\n\r\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<vfs:virtualFoldersRequest xmlns:vfs=\"http://www.sap.com/adt/ris/virtualFolders\" objectSearchPattern=\"${searchPattern}\">\r\n${specifiedXml}\r\n${facetorderXml}\r\n</vfs:virtualFoldersRequest>`;\r\n}\r\n\r\n/**\r\n * Parse tree XML into structured data\r\n */\r\nexport function parseTreeXml(xml: string): Result<ParseResult, Error> {\r\n const [doc, parseErr] = safeParseXml(xml);\r\n if (parseErr) return err(parseErr);\r\n\r\n const folders: ParsedFolder[] = [];\r\n const objects: ParsedObject[] = [];\r\n\r\n // Process virtual folder elements\r\n const virtualFolders = doc.getElementsByTagName('vfs:virtualFolder');\r\n for (let i = 0; i < virtualFolders.length; i++) {\r\n const vf = virtualFolders[i];\r\n if (!vf) continue;\r\n\r\n const facet = vf.getAttribute('facet')?.toUpperCase();\r\n const name = vf.getAttribute('name');\r\n if (!name || !facet) continue;\r\n\r\n const validFacets = ['PACKAGE', 'GROUP', 'TYPE', 'API'] as const;\r\n if (!validFacets.includes(facet as typeof validFacets[number])) continue;\r\n\r\n const countAttr = vf.getAttribute('counter');\r\n const count = countAttr ? parseInt(countAttr, 10) : 0;\r\n const desc = vf.getAttribute('text');\r\n const displayNameAttr = vf.getAttribute('displayName');\r\n\r\n const technicalName = name.startsWith('..') ? name.substring(2) : name;\r\n const displayName = displayNameAttr || technicalName;\r\n\r\n const parsedFolder: ParsedFolder = {\r\n facet: facet as 'PACKAGE' | 'GROUP' | 'TYPE' | 'API',\r\n name: technicalName,\r\n displayName,\r\n count,\r\n };\r\n if (desc) parsedFolder.description = desc;\r\n folders.push(parsedFolder);\r\n }\r\n\r\n // Process object elements\r\n const objectElements = doc.getElementsByTagName('vfs:object');\r\n for (let i = 0; i < objectElements.length; i++) {\r\n const obj = objectElements[i];\r\n if (!obj) continue;\r\n\r\n const name = obj.getAttribute('name');\r\n const type = obj.getAttribute('type');\r\n if (!name || !type) continue;\r\n\r\n const config = getConfigByType(type);\r\n if (!config) continue;\r\n\r\n const text = obj.getAttribute('text');\r\n const parsedObj: ParsedObject = {\r\n name,\r\n objectType: config.label,\r\n extension: config.extension,\r\n };\r\n if (text) parsedObj.description = text;\r\n objects.push(parsedObj);\r\n }\r\n\r\n return ok({ folders, objects });\r\n}\r\n\r\n/**\r\n * Transform parsed data to TreeResponse\r\n */\r\nexport function transformToTreeResponse(parsed: ParseResult, queryPackage: string): TreeResponse {\r\n const packages: PackageNode[] = [];\r\n const folders: FolderNode[] = [];\r\n\r\n for (const folder of parsed.folders) {\r\n if (folder.facet === 'PACKAGE' && folder.name === queryPackage) continue;\r\n\r\n if (folder.facet === 'PACKAGE') {\r\n const pkg: PackageNode = {\r\n name: folder.name,\r\n numContents: folder.count,\r\n };\r\n if (folder.description) pkg.description = folder.description;\r\n packages.push(pkg);\r\n } else {\r\n folders.push({\r\n name: folder.name,\r\n displayName: folder.displayName,\r\n numContents: folder.count,\r\n });\r\n }\r\n }\r\n\r\n const objects: ObjectNode[] = parsed.objects.map(obj => {\r\n const node: ObjectNode = {\r\n name: obj.name,\r\n objectType: obj.objectType,\r\n extension: obj.extension,\r\n };\r\n if (obj.description) node.description = obj.description;\r\n return node;\r\n });\r\n\r\n return { packages, folders, objects };\r\n}\r\n","/**\r\n * ChildPackages — Fetch child packages via virtualfolders endpoint\r\n *\r\n * Unlike getSubpackages (nodestructure), this returns packages WITH counts and descriptions.\r\n *\r\n * Key difference from directly-assigned objects:\r\n * - Package preselection WITHOUT `..` prefix = child packages\r\n * - Package preselection WITH `..` prefix = directly assigned objects\r\n * - hasChildrenOfSameFacet: true = include package facet in facetorder\r\n */\r\n\r\nimport type { AsyncResult } from '../../../../types/result';\r\nimport { ok, err } from '../../../../types/result';\r\nimport type { AdtRequestor } from '../../types';\r\nimport { extractError } from '../../../utils/xml';\r\nimport type { PackageNode, TreeDiscoveryQuery } from './types';\r\nimport { constructTreeBody, parseTreeXml } from './parsers';\r\n\r\n/**\r\n * Fetch child packages for a given package using virtualfolders endpoint.\r\n *\r\n * Request format (no .. prefix = child packages):\r\n * <vfs:preselection facet=\"package\">\r\n * <vfs:value>BASIS</vfs:value>\r\n * </vfs:preselection>\r\n * <vfs:facetorder>\r\n * <vfs:facet>package</vfs:facet>\r\n * <vfs:facet>group</vfs:facet>\r\n * <vfs:facet>type</vfs:facet>\r\n * </vfs:facetorder>\r\n */\r\nexport async function fetchChildPackages(\r\n client: AdtRequestor,\r\n parentPackage: string\r\n): AsyncResult<PackageNode[], Error> {\r\n // Build query WITHOUT .. prefix and WITH hasChildrenOfSameFacet: true\r\n const query: TreeDiscoveryQuery = {\r\n PACKAGE: {\r\n name: parentPackage,\r\n hasChildrenOfSameFacet: true,\r\n },\r\n };\r\n\r\n const body = constructTreeBody(query, '*');\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: '/sap/bc/adt/repository/informationsystem/virtualfolders/contents',\r\n headers: {\r\n 'Content-Type': 'application/vnd.sap.adt.repository.virtualfolders.request.v1+xml',\r\n 'Accept': 'application/vnd.sap.adt.repository.virtualfolders.result.v1+xml',\r\n },\r\n body,\r\n });\r\n\r\n if (requestErr) return err(requestErr);\r\n if (!response.ok) {\r\n const text = await response.text();\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Failed to fetch child packages: ${errorMsg}`));\r\n }\r\n\r\n const text = await response.text();\r\n const [parsed, parseErr] = parseTreeXml(text);\r\n if (parseErr) return err(parseErr);\r\n\r\n // Filter to PACKAGE facet folders, excluding the parent package itself\r\n // The response includes a `..{parentPackage}` entry (directly assigned objects)\r\n // which, after the `..` prefix is stripped, becomes just `{parentPackage}`\r\n const parentUpper = parentPackage.toUpperCase();\r\n const packages: PackageNode[] = parsed.folders\r\n .filter(f => f.facet === 'PACKAGE' && f.name.toUpperCase() !== parentUpper)\r\n .map(f => {\r\n const pkg: PackageNode = {\r\n name: f.name,\r\n numContents: f.count,\r\n };\r\n if (f.description) pkg.description = f.description;\r\n return pkg;\r\n });\r\n\r\n return ok(packages);\r\n}\r\n","/**\r\n * VirtualFolders — Fetch folder contents\r\n */\r\n\r\nimport type { AsyncResult } from '../../../../types/result';\r\nimport { err } from '../../../../types/result';\r\nimport type { AdtRequestor } from '../../types';\r\nimport { extractError } from '../../../utils/xml';\r\nimport type { TreeDiscoveryQuery, ParseResult } from './types';\r\nimport { constructTreeBody, parseTreeXml } from './parsers';\r\n\r\n/**\r\n * Fetch virtualfolders contents\r\n */\r\nexport async function fetchVirtualFolders(\r\n client: AdtRequestor,\r\n query: TreeDiscoveryQuery,\r\n owner?: string\r\n): AsyncResult<ParseResult, Error> {\r\n const body = constructTreeBody(query, '*', owner);\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: '/sap/bc/adt/repository/informationsystem/virtualfolders/contents',\r\n headers: {\r\n 'Content-Type': 'application/vnd.sap.adt.repository.virtualfolders.request.v1+xml',\r\n 'Accept': 'application/vnd.sap.adt.repository.virtualfolders.result.v1+xml',\r\n },\r\n body,\r\n });\r\n\r\n if (requestErr) return err(requestErr);\r\n if (!response.ok) {\r\n const text = await response.text();\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Tree discovery failed: ${errorMsg}`));\r\n }\r\n\r\n const text = await response.text();\r\n return parseTreeXml(text);\r\n}\r\n","/**\r\n * Tree — Hierarchical tree browsing for packages\r\n */\r\n\r\nimport type { AsyncResult } from '../../../../types/result';\r\nimport { ok, err } from '../../../../types/result';\r\nimport type { TreeQuery } from '../../../../types/requests';\r\nimport type { AdtRequestor } from '../../types';\r\nimport type { TreeResponse, PackageNode } from './types';\r\nimport { fetchChildPackages } from './childPackages';\r\nimport { buildQueryFromPath, transformToTreeResponse } from './parsers';\r\nimport { fetchVirtualFolders } from './virtualFolders';\r\n\r\n// Re-export types\r\nexport type {\r\n TreeResponse,\r\n PackageNode,\r\n FolderNode,\r\n ObjectNode,\r\n} from './types';\r\n\r\n/**\r\n * Get hierarchical tree contents for a package.\r\n * If package is omitted, returns top-level packages only.\r\n */\r\nexport async function getTree(\r\n client: AdtRequestor,\r\n query: TreeQuery = {}\r\n): AsyncResult<TreeResponse, Error> {\r\n // If no package specified, return only top-level packages using virtualfolders\r\n // (nodestructure endpoint doesn't return object counts)\r\n if (!query.package) {\r\n const [parsed, parseErr] = await fetchVirtualFolders(client, {}, query.owner);\r\n if (parseErr) return err(parseErr);\r\n\r\n // Filter to only PACKAGE facet folders and transform to PackageNode[]\r\n const packages: PackageNode[] = parsed.folders\r\n .filter(f => f.facet === 'PACKAGE')\r\n .map(f => {\r\n const pkg: PackageNode = {\r\n name: f.name,\r\n numContents: f.count,\r\n };\r\n if (f.description) pkg.description = f.description;\r\n return pkg;\r\n });\r\n\r\n return ok({\r\n packages,\r\n folders: [],\r\n objects: [],\r\n });\r\n }\r\n\r\n // If no path specified, fetch child packages via virtualfolders\r\n let packages: PackageNode[] = [];\r\n\r\n if (!query.path) {\r\n const [childPkgs, childErr] = await fetchChildPackages(client, query.package);\r\n if (childErr) return err(childErr);\r\n packages = childPkgs;\r\n }\r\n\r\n // Build internal query from path segments\r\n const internalQuery = buildQueryFromPath(query.package, query.path);\r\n\r\n // Execute virtualfolders for folders/objects\r\n const [parsed, parseErr] = await fetchVirtualFolders(client, internalQuery, query.owner);\r\n if (parseErr) return err(parseErr);\r\n\r\n const result = transformToTreeResponse(parsed, query.package);\r\n result.packages = packages;\r\n\r\n return ok(result);\r\n}\r\n","/**\r\n * Transports — List transport requests for a package\r\n */\r\n\r\nimport type { Result, AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { AdtRequestor } from '../types';\r\n\r\n/**\r\n * Transport request\r\n */\r\nexport interface Transport {\r\n id: string;\r\n description: string;\r\n owner: string;\r\n}\r\n\r\nimport { extractError, safeParseXml } from '../../utils/xml';\r\n\r\n/**\r\n * Get transports for a package\r\n *\r\n * Uses the transportchecks endpoint to query available transports\r\n * for a given package.\r\n *\r\n * @param client - ADT client\r\n * @param packageName - Package name to query transports for\r\n * @returns Array of transports or error\r\n */\r\nexport async function getTransports(\r\n client: AdtRequestor,\r\n packageName: string\r\n): AsyncResult<Transport[], Error> {\r\n const contentType = 'application/vnd.sap.as+xml; charset=UTF-8; dataname=com.sap.adt.transport.service.checkData';\r\n\r\n // Build XML request body (same format as original SNAP-Relay-API)\r\n const body = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<asx:abap version=\"1.0\" xmlns:asx=\"http://www.sap.com/abapxml\">\r\n <asx:values>\r\n <DATA>\r\n <PGMID></PGMID>\r\n <OBJECT></OBJECT>\r\n <OBJECTNAME></OBJECTNAME>\r\n <DEVCLASS>${packageName}</DEVCLASS>\r\n <SUPER_PACKAGE></SUPER_PACKAGE>\r\n <OPERATION>I</OPERATION>\r\n <URI>/sap/bc/adt/ddic/ddl/sources/zsnap_test4transports</URI>\r\n </DATA>\r\n </asx:values>\r\n</asx:abap>`;\r\n\r\n // Execute transport check request\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: '/sap/bc/adt/cts/transportchecks',\r\n headers: {\r\n 'Accept': contentType,\r\n 'Content-Type': contentType,\r\n },\r\n body,\r\n });\r\n\r\n // Validate successful response\r\n if (requestErr) return err(requestErr);\r\n if (!response.ok) {\r\n const text = await response.text();\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Failed to fetch transports for package ${packageName}: ${errorMsg}`));\r\n }\r\n\r\n // Parse transports from response\r\n const text = await response.text();\r\n\r\n const [transports, parseErr] = extractTransports(text);\r\n if (parseErr) return err(parseErr);\r\n return ok(transports);\r\n}\r\n\r\n/**\r\n * Extract transports from XML response.\r\n *\r\n * Response contains REQ_HEADER elements with:\r\n * - TRKORR: Transport ID\r\n * - AS4USER: Owner username\r\n * - AS4TEXT: Description\r\n */\r\nfunction extractTransports(xml: string): Result<Transport[], Error> {\r\n const [doc, parseErr] = safeParseXml(xml);\r\n if (parseErr) return err(parseErr);\r\n\r\n const transports: Transport[] = [];\r\n const reqHeaders = doc.getElementsByTagName('REQ_HEADER');\r\n\r\n for (let i = 0; i < reqHeaders.length; i++) {\r\n const header = reqHeaders[i];\r\n if (!header) continue;\r\n\r\n const id = header.getElementsByTagName('TRKORR')[0]?.textContent;\r\n const owner = header.getElementsByTagName('AS4USER')[0]?.textContent;\r\n const description = header.getElementsByTagName('AS4TEXT')[0]?.textContent;\r\n if (!id) continue;\r\n\r\n transports.push({\r\n id,\r\n description: description || '',\r\n owner: owner || '',\r\n });\r\n }\r\n\r\n return ok(transports);\r\n}\r\n","/**\r\n * Preview Parser — Parse data preview XML responses\r\n *\r\n * Internal helper used by data.ts, distinct.ts, and count.ts\r\n */\r\n\r\nimport type { Result } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport { safeParseXml } from '../../utils/xml';\r\n\r\n/**\r\n * Data preview result (columnar format)\r\n */\r\nexport interface DataFrame {\r\n columns: ColumnInfo[];\r\n rows: unknown[][];\r\n totalRows?: number;\r\n}\r\n\r\nexport interface ColumnInfo {\r\n name: string;\r\n dataType: string;\r\n label?: string;\r\n}\r\n\r\n/**\r\n * Parse data preview XML response\r\n *\r\n * Handles two XML formats:\r\n * 1. Regular queries: Have <metadata> elements with column definitions\r\n * 2. Aggregate queries (COUNT, GROUP BY): No metadata, infer columns from <dataSet> elements\r\n *\r\n * @param xml - XML response from SAP\r\n * @param maxRows - Maximum rows to parse\r\n * @param isTable - Whether source is a table (affects column name attribute)\r\n * @returns DataFrame or error\r\n */\r\nexport function parseDataPreview(\r\n xml: string,\r\n maxRows: number,\r\n isTable: boolean\r\n): Result<DataFrame, Error> {\r\n // Parse XML response.\r\n const [doc, parseErr] = safeParseXml(xml);\r\n if (parseErr) { return err(parseErr); }\r\n\r\n const namespace = 'http://www.sap.com/adt/dataPreview';\r\n\r\n // Extract column metadata from response (if present).\r\n const metadataElements = doc.getElementsByTagNameNS(namespace, 'metadata');\r\n const columns: ColumnInfo[] = [];\r\n\r\n for (let i = 0; i < metadataElements.length; i++) {\r\n const meta = metadataElements[i];\r\n if (!meta) continue;\r\n\r\n // Tables use 'name', views use 'camelCaseName'.\r\n const nameAttr = isTable ? 'name' : 'camelCaseName';\r\n const name = meta.getAttributeNS(namespace, nameAttr) || meta.getAttribute('name');\r\n const dataType = meta.getAttributeNS(namespace, 'colType') || meta.getAttribute('colType');\r\n if (!name || !dataType) continue;\r\n\r\n columns.push({ name, dataType });\r\n }\r\n\r\n // Extract data values organized by column.\r\n const dataSetElements = doc.getElementsByTagNameNS(namespace, 'dataSet');\r\n\r\n // If no metadata, infer columns from dataSet elements (aggregate queries).\r\n if (columns.length === 0 && dataSetElements.length > 0) {\r\n for (let i = 0; i < dataSetElements.length; i++) {\r\n const dataSet = dataSetElements[i];\r\n if (!dataSet) continue;\r\n // Use column index as name for aggregate results.\r\n const name = dataSet.getAttributeNS(namespace, 'columnName')\r\n || dataSet.getAttribute('columnName')\r\n || `column${i}`;\r\n columns.push({ name, dataType: 'unknown' });\r\n }\r\n }\r\n\r\n // Still no columns - return empty DataFrame.\r\n if (columns.length === 0) {\r\n return ok({ columns: [], rows: [], totalRows: 0 });\r\n }\r\n\r\n const columnData: string[][] = Array.from({ length: columns.length }, () => []);\r\n\r\n for (let i = 0; i < dataSetElements.length; i++) {\r\n const dataSet = dataSetElements[i];\r\n if (!dataSet) continue;\r\n\r\n const dataElements = dataSet.getElementsByTagNameNS(namespace, 'data');\r\n for (let j = 0; j < dataElements.length; j++) {\r\n const data = dataElements[j];\r\n if (!data) continue;\r\n\r\n const value = data.textContent?.trim() || '';\r\n columnData[i]!.push(value);\r\n }\r\n }\r\n\r\n // Transform column-oriented data into row-oriented format.\r\n const rows: unknown[][] = [];\r\n const rowCount = columnData[0]?.length || 0;\r\n for (let i = 0; i < Math.min(rowCount, maxRows); i++) {\r\n const row: unknown[] = [];\r\n for (let j = 0; j < columns.length; j++) {\r\n row.push(columnData[j]![i]);\r\n }\r\n rows.push(row);\r\n }\r\n\r\n // Build final DataFrame result.\r\n const dataFrame: DataFrame = {\r\n columns,\r\n rows,\r\n totalRows: rowCount,\r\n };\r\n\r\n return ok(dataFrame);\r\n}\r\n","/**\r\n * Data Preview — Execute SQL queries against table/view data\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { PreviewSQL } from '../../../types/requests';\r\nimport type { AdtRequestor } from '../types';\r\nimport type { DataFrame } from './previewParser';\r\nimport { getConfigByExtension } from '../types';\r\nimport { extractError } from '../../utils/xml';\r\nimport { debug } from '../../utils/logging';\r\nimport { parseDataPreview } from './previewParser';\r\n\r\n/**\r\n * Execute SQL query against table/view data\r\n *\r\n * @param client - ADT client\r\n * @param query - Preview query with SQL\r\n * @returns DataFrame or error\r\n */\r\nexport async function previewData(\r\n client: AdtRequestor,\r\n query: PreviewSQL\r\n): AsyncResult<DataFrame, Error> {\r\n // Get config by objectType.\r\n const extension = query.objectType === 'table' ? 'astabldt' : 'asddls';\r\n const config = getConfigByExtension(extension);\r\n if (!config?.dpEndpoint || !config?.dpParam) {\r\n return err(new Error(`Data preview not supported for object type: ${query.objectType}`));\r\n }\r\n\r\n // Execute request with caller-provided SQL.\r\n const limit = query.limit ?? 100;\r\n debug(`Data preview: endpoint=${config.dpEndpoint}, param=${config.dpParam}=${query.objectName}`);\r\n debug(`SQL: ${query.sqlQuery}`);\r\n\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: `/sap/bc/adt/datapreview/${config.dpEndpoint}`,\r\n params: {\r\n 'rowNumber': limit,\r\n [config.dpParam]: query.objectName,\r\n },\r\n headers: {\r\n 'Accept': 'application/vnd.sap.adt.datapreview.table.v1+xml',\r\n 'Content-Type': 'text/plain',\r\n },\r\n body: query.sqlQuery,\r\n });\r\n\r\n // Handle errors.\r\n if (requestErr) { return err(requestErr); }\r\n if (!response.ok) {\r\n const text = await response.text();\r\n debug(`Data preview error response: ${text.substring(0, 500)}`);\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Data preview failed: ${errorMsg}`));\r\n }\r\n\r\n // Parse response.\r\n const text = await response.text();\r\n const [dataFrame, parseErr] = parseDataPreview(text, limit, query.objectType === 'table');\r\n if (parseErr) { return err(parseErr); }\r\n return ok(dataFrame);\r\n}\r\n","/**\r\n * Freestyle SQL Query — Execute arbitrary OpenSQL via the freestyle endpoint\r\n *\r\n * The freestyle endpoint supports full OpenSQL including COUNT(*), GROUP BY, JOINs, etc.\r\n * Use this for aggregate queries; use dataPreview.ts for simple table/view previews.\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { AdtRequestor } from '../types';\r\nimport type { DataFrame } from './previewParser';\r\nimport { extractError } from '../../utils/xml';\r\nimport { debug } from '../../utils/logging';\r\nimport { parseDataPreview } from './previewParser';\r\n\r\nconst DEFAULT_ROW_LIMIT = 100;\r\n\r\n/**\r\n * Execute arbitrary OpenSQL query via the freestyle endpoint\r\n *\r\n * @param client - ADT client\r\n * @param sqlQuery - OpenSQL SELECT statement\r\n * @param limit - Max rows to return (default 100)\r\n * @returns DataFrame or error\r\n */\r\nexport async function freestyleQuery(\r\n client: AdtRequestor,\r\n sqlQuery: string,\r\n limit = DEFAULT_ROW_LIMIT\r\n): AsyncResult<DataFrame, Error> {\r\n debug(`Freestyle query: ${sqlQuery}`);\r\n\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: '/sap/bc/adt/datapreview/freestyle',\r\n params: {\r\n 'rowNumber': limit,\r\n },\r\n headers: {\r\n 'Accept': 'application/xml, application/vnd.sap.adt.datapreview.table.v1+xml',\r\n 'Content-Type': 'text/plain',\r\n },\r\n body: sqlQuery,\r\n });\r\n\r\n if (requestErr) return err(requestErr);\r\n\r\n if (!response.ok) {\r\n const text = await response.text();\r\n debug(`Freestyle query error response: ${text.substring(0, 500)}`);\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Freestyle query failed: ${errorMsg}`));\r\n }\r\n\r\n const text = await response.text();\r\n const [dataFrame, parseErr] = parseDataPreview(text, limit, true);\r\n if (parseErr) return err(parseErr);\r\n\r\n return ok(dataFrame);\r\n}\r\n","/**\r\n * Query Builder — Optional helper for building SQL queries for data preview\r\n */\r\n\r\nimport { type Result, ok, err } from '../../../types/result';\r\nimport type { PreviewSQL } from '../../../types/requests';\r\n\r\nexport function quoteString(value: string | number): string {\r\n return typeof value == \"string\" ? \"'\" + value + \"'\" : \"\" + value;\r\n}\r\n\r\n// Where Clause Types and Converters\r\nexport type BasicFilter = {\r\n type: \"basic\";\r\n field: string;\r\n value: string | number;\r\n operator: \"=\" | \"<>\" | \"<\" | \"<=\" | \">\" | \">=\" | \"like\" | \"not like\";\r\n}\r\n\r\nexport function basicFilterToWhere(filter: BasicFilter): string {\r\n return `${filter.field} ${filter.operator} ${quoteString(filter.value)}`;\r\n}\r\n\r\nexport type BetweenFilter = {\r\n type: \"between\";\r\n field: string;\r\n minimum: string | number;\r\n maximum: string | number;\r\n}\r\n\r\nexport function betweenFilterToWhere(filter: BetweenFilter): string {\r\n return `${filter.field} between ${quoteString(filter.minimum)} and ${quoteString(filter.maximum)}`;\r\n}\r\n\r\nexport type ListFilter = {\r\n type: \"list\";\r\n field: string;\r\n values: (string | number)[];\r\n include: boolean;\r\n}\r\n\r\nexport function listFilterToWhere(filter: ListFilter): string {\r\n return `${filter.field} ${filter.include ? \"\" : \"not \"}in ( ${filter.values.map(quoteString).join(\", \")} )`;\r\n}\r\n\r\nexport type QueryFilter = BasicFilter | BetweenFilter | ListFilter;\r\n\r\nfunction queryFilterToWhere(filter: QueryFilter): string {\r\n if (filter.type === \"list\") return listFilterToWhere(filter);\r\n if (filter.type === \"between\") return betweenFilterToWhere(filter);\r\n return basicFilterToWhere(filter);\r\n}\r\n\r\nexport function queryFiltersToWhere(filters: QueryFilter[]): string {\r\n if (filters.length === 0) return \"\";\r\n return `\\nwhere ${filters.map(queryFilterToWhere).join(\" and \")}`;\r\n}\r\n\r\n// Order By Types and Converters\r\nexport type Sorting = {\r\n field: string;\r\n direction: \"ascending\" | \"descending\";\r\n}\r\n\r\nexport function sortingsToOrderBy(sortings: Sorting[]): string {\r\n if (sortings.length === 0) return \"\";\r\n return `\\norder by ${sortings.map(s => `${s.field} ${s.direction}`).join(\", \")}`;\r\n}\r\n\r\n// Aggregation Types\r\nexport type Aggregation = {\r\n field: string;\r\n function: \"count\" | \"sum\" | \"avg\" | \"min\" | \"max\";\r\n}\r\n\r\nexport function fieldsToGroupbyClause(fields: string[]): string {\r\n if (fields.length === 0) return \"\";\r\n return `\\ngroup by ${fields.join(\", \")}`;\r\n}\r\n\r\nexport function aggregationToFieldDefinition(aggregation: Aggregation): string {\r\n if (aggregation.function === \"count\") {\r\n return `count( distinct main~${aggregation.field} ) as ${aggregation.field}`;\r\n }\r\n return `${aggregation.function}( main~${aggregation.field} ) as ${aggregation.field}`;\r\n}\r\n\r\n// Parameter Types\r\nexport type Parameter = {\r\n name: string;\r\n value: string | number;\r\n}\r\n\r\nexport function parametersToSQLParams(params: Parameter[]): string {\r\n if (params.length === 0) return \"\";\r\n return `( ${params.map(p => `${p.name} = ${quoteString(p.value)}`).join(\", \")})`;\r\n}\r\n\r\n// Query Type\r\nexport type DataPreviewQuery = {\r\n objectName: string;\r\n objectType: 'table' | 'view';\r\n limit?: number;\r\n\r\n fields: string[];\r\n parameters?: Parameter[];\r\n filters?: QueryFilter[];\r\n sortings?: Sorting[];\r\n aggregations?: Aggregation[];\r\n}\r\n\r\nexport function buildSQLQuery(query: DataPreviewQuery): Result<PreviewSQL> {\r\n // Isolate filters, sortings, and aggregations with defaults.\r\n const [parameters, filters, sortings, aggregations] = [query.parameters ?? [], query.filters ?? [], query.sortings ?? [], query.aggregations ?? []];\r\n const groupingFields = query.fields.filter(f => !aggregations.find(a => a.field === f));\r\n\r\n // Do some validation.\r\n if (sortings.filter(s => !query.fields.includes(s.field)).length > 0) {\r\n return err(new Error(\"Sorting fields must be included in the selected fields.\"));\r\n }\r\n\r\n // Build main field selection.\r\n let selectClause = \"select\\n\";\r\n\r\n const fieldSelections: string[] = [];\r\n for (const field of query.fields) {\r\n const aggregation = aggregations.find(a => a.field === field);\r\n if (aggregation) {\r\n fieldSelections.push(`\\t${aggregationToFieldDefinition(aggregation)}`);\r\n continue;\r\n }\r\n fieldSelections.push(`\\tmain~${field}`);\r\n }\r\n selectClause += fieldSelections.join(\",\\n\") + `\\nfrom ${query.objectName}${parametersToSQLParams(parameters)} as main\\n`;\r\n\r\n // Build the rest of the clauses.\r\n const [whereClause, groupbyClause, orderbyClause] = [queryFiltersToWhere(filters), aggregations.length ? fieldsToGroupbyClause(groupingFields) : \"\", sortingsToOrderBy(sortings)];\r\n\r\n const result: PreviewSQL = {\r\n objectName: query.objectName,\r\n objectType: query.objectType,\r\n sqlQuery: `${selectClause}${whereClause}${groupbyClause}${orderbyClause}`,\r\n };\r\n if (query.limit !== undefined) result.limit = query.limit;\r\n return ok(result);\r\n}\r\n","/**\r\n * Distinct Values — Get distinct column values with counts\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { AdtRequestor } from '../types';\r\nimport { freestyleQuery } from './freestyle';\r\nimport { type Parameter, parametersToSQLParams } from './queryBuilder';\r\n\r\n/**\r\n * Distinct values result\r\n */\r\nexport interface DistinctResult {\r\n column: string;\r\n values: Array<{\r\n value: unknown;\r\n count: number;\r\n }>;\r\n}\r\n\r\nconst MAX_ROW_COUNT = 50000;\r\n\r\n/**\r\n * Get distinct values for a column with counts, ordered by count descending\r\n *\r\n * Uses the freestyle endpoint which supports COUNT(*) and GROUP BY.\r\n */\r\nexport async function getDistinctValues(\r\n client: AdtRequestor,\r\n objectName: string,\r\n parameters: Parameter[],\r\n column: string,\r\n _objectType: 'table' | 'view' = 'view'\r\n): AsyncResult<DistinctResult, Error> {\r\n const columnName = column.toUpperCase();\r\n const sqlQuery = `SELECT ${columnName} AS value, COUNT(*) AS value_count FROM ${objectName}${parametersToSQLParams(parameters)} GROUP BY ${columnName} ORDER BY value_count DESCENDING`;\r\n\r\n const [dataFrame, error] = await freestyleQuery(client, sqlQuery, MAX_ROW_COUNT);\r\n\r\n if (error) {\r\n return err(new Error(`Distinct values query failed: ${error.message}`));\r\n }\r\n\r\n // Transform DataFrame to DistinctResult.\r\n const values = dataFrame.rows.map(row => ({\r\n value: row[0],\r\n count: parseInt(String(row[1]), 10),\r\n }));\r\n\r\n return ok({ column, values });\r\n}\r\n","/**\r\n * Count Rows — Get total row count for table/view\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { AdtRequestor } from '../types';\r\nimport { freestyleQuery } from './freestyle';\r\nimport { type Parameter, parametersToSQLParams } from './queryBuilder';\r\n\r\n/**\r\n * Count total rows in a table or view\r\n *\r\n * Uses the freestyle endpoint which supports COUNT(*) aggregation.\r\n */\r\nexport async function countRows(\r\n client: AdtRequestor,\r\n objectName: string,\r\n _objectType: 'table' | 'view',\r\n parameters: Parameter[] = []\r\n): AsyncResult<number, Error> {\r\n const sqlQuery = `SELECT COUNT(*) AS row_count FROM ${objectName}${parametersToSQLParams(parameters)}`;\r\n\r\n const [dataFrame, error] = await freestyleQuery(client, sqlQuery, 1);\r\n\r\n if (error) {\r\n return err(new Error(`Row count query failed: ${error.message}`));\r\n }\r\n\r\n // Extract count from first row, first column.\r\n const countValue = dataFrame.rows[0]?.[0];\r\n if (countValue === undefined) {\r\n return err(new Error('No count value returned'));\r\n }\r\n\r\n const count = parseInt(String(countValue), 10);\r\n if (isNaN(count)) {\r\n return err(new Error('Invalid count value returned'));\r\n }\r\n\r\n return ok(count);\r\n}\r\n","/**\r\n * Search Objects — Quick search by name pattern\r\n */\r\n\r\nimport type { Result, AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { AdtRequestor } from '../types';\r\n\r\n/**\r\n * Search result\r\n */\r\nexport interface SearchResult {\r\n name: string;\r\n uri: string;\r\n extension: string;\r\n package: string;\r\n description?: string;\r\n objectType: string;\r\n}\r\n\r\nimport { getConfigByType, getAllTypes } from '../types';\r\nimport { extractError, safeParseXml } from '../../utils/xml';\r\n\r\n/**\r\n * Search for objects by name pattern\r\n *\r\n * @param client - ADT client\r\n * @param query - Search pattern (supports wildcards)\r\n * @param types - Optional array of object type filters\r\n * @returns Array of matching objects or error\r\n */\r\nexport interface SearchOptions {\r\n types?: string[];\r\n includePackages?: boolean;\r\n}\r\n\r\nexport async function searchObjects(\r\n client: AdtRequestor,\r\n query: string,\r\n options?: SearchOptions\r\n): AsyncResult<SearchResult[], Error> {\r\n const { types, includePackages = true } = options ?? {};\r\n // Build search parameters.\r\n const searchPattern = query || '*';\r\n const objectTypes = types && types.length > 0 ? types : getAllTypes();\r\n\r\n // Construct query parameters (matching Python reference exactly).\r\n const params: Array<[string, string]> = [\r\n ['operation', 'quickSearch'],\r\n ['query', searchPattern],\r\n ['maxResults', '10001'],\r\n ];\r\n for (const type of objectTypes) {\r\n params.push(['objectType', type]);\r\n }\r\n\r\n // Build URL search params.\r\n const urlParams = new URLSearchParams();\r\n for (const [key, value] of params) {\r\n urlParams.append(key, value);\r\n }\r\n\r\n // Execute search request.\r\n const [response, requestErr] = await client.request({\r\n method: 'GET',\r\n path: `/sap/bc/adt/repository/informationsystem/search?${urlParams.toString()}`,\r\n });\r\n\r\n // Validate successful response.\r\n if (requestErr) { return err(requestErr); }\r\n if (!response.ok) {\r\n const text = await response.text();\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Search failed: ${errorMsg}`));\r\n }\r\n\r\n // Parse search results from response.\r\n const text = await response.text();\r\n const [results, parseErr] = parseSearchResults(text);\r\n if (parseErr) { return err(parseErr); }\r\n\r\n // Enrich results with package info from object properties endpoint.\r\n if (includePackages) await enrichWithPackages(client, results);\r\n return ok(results);\r\n}\r\n\r\n// Fetch package info for results that are missing it.\r\nasync function enrichWithPackages(client: AdtRequestor, results: SearchResult[]): Promise<void> {\r\n const needsPackage = results.filter(r => !r.package);\r\n if (needsPackage.length === 0) return;\r\n\r\n // Fetch object properties in parallel.\r\n const promises = needsPackage.map(async (result) => {\r\n const encodedUri = encodeURIComponent(result.uri);\r\n const [response, reqErr] = await client.request({\r\n method: 'GET',\r\n path: `/sap/bc/adt/repository/informationsystem/objectproperties/values?uri=${encodedUri}&facet=package`,\r\n });\r\n if (reqErr || !response.ok) return;\r\n\r\n const text = await response.text();\r\n const [doc, parseErr] = safeParseXml(text);\r\n if (parseErr) return;\r\n\r\n // Package is an attribute on the opr:object element.\r\n const oprNs = 'http://www.sap.com/adt/ris/objectProperties';\r\n const objEl = doc.getElementsByTagNameNS(oprNs, 'object')[0];\r\n if (!objEl) return;\r\n\r\n const pkg = objEl.getAttribute('package');\r\n if (pkg) result.package = pkg;\r\n });\r\n\r\n await Promise.all(promises);\r\n}\r\n\r\n// Parse search results from XML.\r\nfunction parseSearchResults(xml: string): Result<SearchResult[], Error> {\r\n // Parse XML response.\r\n const [doc, parseErr] = safeParseXml(xml);\r\n if (parseErr) { return err(parseErr); }\r\n\r\n // Extract object reference elements.\r\n const results: SearchResult[] = [];\r\n const objectRefs = doc.getElementsByTagNameNS('http://www.sap.com/adt/core', 'objectReference');\r\n\r\n // Process each object reference.\r\n for (let i = 0; i < objectRefs.length; i++) {\r\n const obj = objectRefs[i];\r\n if (!obj) continue;\r\n\r\n // Extract object metadata.\r\n const name = obj.getAttributeNS('http://www.sap.com/adt/core', 'name') || obj.getAttribute('adtcore:name');\r\n const type = obj.getAttributeNS('http://www.sap.com/adt/core', 'type') || obj.getAttribute('adtcore:type');\r\n const uri = obj.getAttributeNS('http://www.sap.com/adt/core', 'uri') || obj.getAttribute('adtcore:uri');\r\n const description = obj.getAttributeNS('http://www.sap.com/adt/core', 'description') || obj.getAttribute('adtcore:description');\r\n if (!name || !type || !uri) continue;\r\n\r\n // Look up object type configuration.\r\n const config = getConfigByType(type);\r\n if (!config) continue;\r\n\r\n // Extract package reference if available.\r\n const packageRef = obj.getElementsByTagNameNS('http://www.sap.com/adt/core', 'packageRef')[0];\r\n const packageName = packageRef\r\n ? (packageRef.getAttributeNS('http://www.sap.com/adt/core', 'name') || packageRef.getAttribute('adtcore:name'))\r\n : '';\r\n\r\n // Build search result object.\r\n const result: SearchResult = {\r\n name,\r\n uri,\r\n extension: config.extension,\r\n package: packageName || '',\r\n objectType: config.label,\r\n };\r\n if (description) {\r\n result.description = description;\r\n }\r\n results.push(result);\r\n }\r\n\r\n return ok(results);\r\n}\r\n","/**\r\n * Where-Used — Find object dependencies\r\n */\r\n\r\nimport type { Result, AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { ObjectRef } from '../../../types/requests';\r\nimport type { AdtRequestor } from '../types';\r\n\r\n/**\r\n * Where-used dependency\r\n */\r\nexport interface Dependency {\r\n name: string;\r\n extension: string;\r\n package: string;\r\n usageType: string;\r\n}\r\n\r\nimport { getConfigByType, getConfigByExtension } from '../types';\r\nimport { extractError, safeParseXml } from '../../utils/xml';\r\n\r\n/**\r\n * Find where an object is used (dependencies)\r\n *\r\n * @param client - ADT client\r\n * @param object - Object to analyze\r\n * @returns Array of dependent objects or error\r\n */\r\nexport async function findWhereUsed(\r\n client: AdtRequestor,\r\n object: ObjectRef\r\n): AsyncResult<Dependency[], Error> {\r\n // Validate object extension is supported.\r\n const config = getConfigByExtension(object.extension);\r\n if (!config) {\r\n return err(new Error(`Unsupported extension: ${object.extension}`));\r\n }\r\n\r\n // Build object URI and request body.\r\n const uri = `/sap/bc/adt/${config.endpoint}/${object.name}`;\r\n const body = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n <usagereferences:usageReferenceRequest xmlns:usagereferences=\"http://www.sap.com/adt/ris/usageReferences\">\r\n <usagereferences:affectedObjects/>\r\n </usagereferences:usageReferenceRequest>`;\r\n\r\n // Execute where-used query.\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: '/sap/bc/adt/repository/informationsystem/usageReferences',\r\n params: {\r\n 'uri': uri,\r\n 'ris_request_type': 'usageReferences',\r\n },\r\n headers: {\r\n 'Content-Type': 'application/vnd.sap.adt.repository.usagereferences.request.v1+xml',\r\n 'Accept': 'application/vnd.sap.adt.repository.usagereferences.result.v1+xml',\r\n },\r\n body,\r\n });\r\n\r\n // Validate successful response.\r\n if (requestErr) { return err(requestErr); }\r\n if (!response.ok) {\r\n const text = await response.text();\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Where-used query failed: ${errorMsg}`));\r\n }\r\n\r\n // Parse dependencies from response.\r\n const text = await response.text();\r\n const [dependencies, parseErr] = parseWhereUsed(text);\r\n if (parseErr) { return err(parseErr); }\r\n return ok(dependencies);\r\n}\r\n\r\n// Parse where-used results from XML.\r\nfunction parseWhereUsed(xml: string): Result<Dependency[], Error> {\r\n // Parse XML response.\r\n const [doc, parseErr] = safeParseXml(xml);\r\n if (parseErr) { return err(parseErr); }\r\n\r\n // Extract referenced object elements.\r\n const dependencies: Dependency[] = [];\r\n const referencedObjects = doc.getElementsByTagNameNS(\r\n 'http://www.sap.com/adt/ris/usageReferences',\r\n 'referencedObject'\r\n );\r\n\r\n // Process each referenced object.\r\n for (let i = 0; i < referencedObjects.length; i++) {\r\n const refObj = referencedObjects[i];\r\n if (!refObj) continue;\r\n\r\n // Extract ADT object element.\r\n const adtObject = refObj.getElementsByTagNameNS(\r\n 'http://www.sap.com/adt/ris/usageReferences',\r\n 'adtObject'\r\n )[0];\r\n if (!adtObject) continue;\r\n\r\n // Extract object name and type.\r\n const name = adtObject.getAttributeNS('http://www.sap.com/adt/core', 'name') || adtObject.getAttribute('adtcore:name');\r\n const type = adtObject.getAttributeNS('http://www.sap.com/adt/core', 'type') || adtObject.getAttribute('adtcore:type');\r\n if (!name || !type) continue;\r\n\r\n // Look up object type configuration.\r\n const config = getConfigByType(type);\r\n if (!config) continue;\r\n\r\n // Extract package reference if available.\r\n const packageRef = adtObject.getElementsByTagNameNS('http://www.sap.com/adt/core', 'packageRef')[0];\r\n const packageName = packageRef\r\n ? (packageRef.getAttributeNS('http://www.sap.com/adt/core', 'name') || packageRef.getAttribute('adtcore:name'))\r\n : '';\r\n\r\n // Build dependency object.\r\n dependencies.push({\r\n name,\r\n extension: config.extension,\r\n package: packageName || '',\r\n usageType: 'reference',\r\n });\r\n }\r\n\r\n return ok(dependencies);\r\n}\r\n","/**\r\n * Create Transport — Create a new transport request for a package\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { AdtRequestor } from '../types';\r\nimport { dictToAbapXml, extractError } from '../../utils/xml';\r\n\r\n/**\r\n * Configuration for creating a transport\r\n */\r\nexport interface TransportConfig {\r\n /** Package name (DEVCLASS) */\r\n package: string;\r\n /** Transport description/text */\r\n description: string;\r\n}\r\n\r\n/**\r\n * Create a new transport request\r\n *\r\n * @param client - ADT client\r\n * @param config - Transport configuration\r\n * @returns Transport ID or error\r\n */\r\nexport async function createTransport(\r\n client: AdtRequestor,\r\n config: TransportConfig\r\n): AsyncResult<string, Error> {\r\n // Build XML request body.\r\n const body = dictToAbapXml({\r\n DEVCLASS: config.package,\r\n REQUEST_TEXT: config.description,\r\n REF: '',\r\n OPERATION: 'I',\r\n });\r\n\r\n // Execute transport creation request.\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: '/sap/bc/adt/cts/transports',\r\n headers: {\r\n 'Content-Type': 'application/vnd.sap.as+xml; charset=UTF-8; dataname=com.sap.adt.CreateCorrectionRequest',\r\n 'Accept': 'text/plain',\r\n },\r\n body,\r\n });\r\n\r\n // Validate response.\r\n if (requestErr) return err(requestErr);\r\n if (!response.ok) {\r\n const text = await response.text();\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Failed to create transport for ${config.package}: ${errorMsg}`));\r\n }\r\n\r\n // Extract transport ID from response.\r\n const text = await response.text();\r\n const transportId = text.trim().split('/').pop();\r\n\r\n if (!transportId) {\r\n return err(new Error('Failed to parse transport ID from response'));\r\n }\r\n\r\n return ok(transportId);\r\n}\r\n","/**\n * Parse Transport Tasks — Extract task IDs and their objects from transport XML\n */\n\nimport type { TransportObject } from './removeFromTransport';\n\nexport interface TaskContents {\n taskId: string;\n objects: TransportObject[];\n}\n\n/**\n * Parse the transport XML to extract task IDs and their objects.\n */\nexport function parseTransportTasks(doc: Document): TaskContents[] {\n const tasks: TaskContents[] = [];\n const taskElements = doc.getElementsByTagName('tm:task');\n\n for (let i = 0; i < taskElements.length; i++) {\n const taskEl = taskElements[i];\n if (!taskEl) continue;\n\n const taskId = taskEl.getAttribute('tm:number');\n if (!taskId) continue;\n\n const objects: TransportObject[] = [];\n const objectElements = taskEl.getElementsByTagName('tm:abap_object');\n\n for (let j = 0; j < objectElements.length; j++) {\n const el = objectElements[j];\n if (!el) continue;\n\n const name = el.getAttribute('tm:name');\n if (!name) continue;\n\n objects.push({\n name,\n description: el.getAttribute('tm:obj_desc') || el.getAttribute('tm:obj_info') || '',\n pgmid: el.getAttribute('tm:pgmid') || '',\n type: el.getAttribute('tm:type') || '',\n position: el.getAttribute('tm:position') || '',\n });\n }\n\n tasks.push({ taskId, objects });\n }\n\n return tasks;\n}\n","/**\r\n * Remove From Transport — Remove an object from a transport request\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { AdtRequestor } from '../types';\r\nimport { extractError, escapeXml, safeParseXml } from '../../utils/xml';\r\nimport { parseTransportTasks } from './parseTransportTasks';\r\n\r\nconst ACCEPT_HEADER = 'application/vnd.sap.adt.transportorganizer.v1+xml';\r\n\r\n/**\r\n * Object entry on a transport\r\n */\r\nexport interface TransportObject {\r\n /** Object name (e.g., 'ZSNAP_F72TG_103') */\r\n name: string;\r\n /** Object description */\r\n description: string;\r\n /** Program ID (e.g., 'R3TR') */\r\n pgmid: string;\r\n /** Object type (e.g., 'DDLS') */\r\n type: string;\r\n /** Position in the transport (e.g., '000002') */\r\n position: string;\r\n}\r\n\r\n/**\r\n * Remove a specific object entry from a transport (internal helper).\r\n * Requires full object details — used by deleteTransport and removeFromTransport.\r\n */\r\nexport async function removeTransportEntry(\r\n client: AdtRequestor,\r\n transportId: string,\r\n object: TransportObject\r\n): AsyncResult<void, Error> {\r\n const body = [\r\n '<?xml version=\"1.0\" encoding=\"ASCII\"?>',\r\n `<tm:root xmlns:tm=\"http://www.sap.com/cts/adt/tm\" tm:number=\"${escapeXml(transportId)}\" tm:useraction=\"removeobject\">`,\r\n ' <tm:request>',\r\n ` <tm:abap_object tm:name=\"${escapeXml(object.name)}\" tm:obj_desc=\"${escapeXml(object.description)}\" tm:pgmid=\"${escapeXml(object.pgmid)}\" tm:type=\"${escapeXml(object.type)}\" tm:position=\"${escapeXml(object.position)}\"/>`,\r\n ' </tm:request>',\r\n '</tm:root>',\r\n ].join('\\n');\r\n\r\n const [response, requestErr] = await client.request({\r\n method: 'PUT',\r\n path: `/sap/bc/adt/cts/transportrequests/${transportId}`,\r\n headers: {\r\n 'Accept': ACCEPT_HEADER,\r\n 'Content-Type': 'text/plain',\r\n },\r\n body,\r\n });\r\n\r\n if (requestErr) return err(requestErr);\r\n if (!response.ok) {\r\n const text = await response.text();\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Failed to remove ${object.name} from transport ${transportId}: ${errorMsg}`));\r\n }\r\n\r\n return ok(undefined);\r\n}\r\n\r\n/**\r\n * Remove an object from a transport by name.\r\n * Reads the transport XML, finds which task the object lives on, and removes it\r\n * using the task ID (not the request ID).\r\n */\r\nexport async function removeFromTransport(\r\n client: AdtRequestor,\r\n transportId: string,\r\n objectName: string\r\n): AsyncResult<void, Error> {\r\n // Fetch transport XML to get the task hierarchy.\r\n const [response, requestErr] = await client.request({\r\n method: 'GET',\r\n path: `/sap/bc/adt/cts/transportrequests/${transportId}`,\r\n headers: { 'Accept': ACCEPT_HEADER },\r\n });\r\n\r\n if (requestErr) return err(requestErr);\r\n if (!response.ok) {\r\n const text = await response.text();\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Failed to read transport ${transportId}: ${errorMsg}`));\r\n }\r\n\r\n const text = await response.text();\r\n const [doc, parseErr] = safeParseXml(text);\r\n if (parseErr) return err(parseErr);\r\n\r\n // Find which task contains the object.\r\n const tasks = parseTransportTasks(doc);\r\n for (const task of tasks) {\r\n const object = task.objects.find(o => o.name === objectName);\r\n if (!object) continue;\r\n\r\n return removeTransportEntry(client, task.taskId, object);\r\n }\r\n\r\n return err(new Error(`Object '${objectName}' not found on transport ${transportId}`));\r\n}\r\n","/**\r\n * Delete Transport — Delete a transport request\r\n *\r\n * SAP transports have a hierarchy: Request → Tasks → Objects.\r\n * To delete a request, all tasks must be deleted first.\r\n * To delete a task, all objects must be removed from it first.\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { AdtRequestor } from '../types';\r\nimport { extractError, safeParseXml } from '../../utils/xml';\r\nimport { removeTransportEntry } from './removeFromTransport';\r\nimport { parseTransportTasks } from './parseTransportTasks';\r\n\r\nconst ACCEPT_HEADER = 'application/vnd.sap.adt.transportorganizer.v1+xml';\r\n\r\n/**\r\n * Sort and compress a task to consolidate duplicate entries.\r\n *\r\n * Deleting tables creates two different entries on a transport that must be merged before removal.\r\n */\r\nasync function sortAndCompress(\r\n client: AdtRequestor,\r\n taskId: string\r\n): AsyncResult<void, Error> {\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: `/sap/bc/adt/cts/transportrequests/${taskId}/sortandcompress`,\r\n headers: { 'Accept': ACCEPT_HEADER },\r\n });\r\n\r\n if (requestErr) return err(requestErr);\r\n if (!response.ok) {\r\n const text = await response.text();\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Failed to sort and compress task ${taskId}: ${errorMsg}`));\r\n }\r\n\r\n return ok(undefined);\r\n}\r\n\r\n/**\r\n * Send a DELETE request for a transport or task.\r\n */\r\nasync function deleteRequest(\r\n client: AdtRequestor,\r\n id: string\r\n): AsyncResult<void, Error> {\r\n const [response, requestErr] = await client.request({\r\n method: 'DELETE',\r\n path: `/sap/bc/adt/cts/transportrequests/${id}`,\r\n headers: { 'Accept': ACCEPT_HEADER },\r\n });\r\n\r\n if (requestErr) return err(requestErr);\r\n if (!response.ok) {\r\n const text = await response.text();\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Failed to delete ${id}: ${errorMsg}`));\r\n }\r\n\r\n return ok(undefined);\r\n}\r\n\r\n/**\r\n * Delete a transport request\r\n *\r\n * @param client - ADT client\r\n * @param transportId - Transport request ID (e.g., 'DS4K904713')\r\n * @param removeObjects - If true, removes all objects from tasks before deleting\r\n * @returns void on success or error\r\n */\r\nexport async function deleteTransport(\r\n client: AdtRequestor,\r\n transportId: string,\r\n removeObjects = false\r\n): AsyncResult<void, Error> {\r\n // Read the transport to discover its task hierarchy.\r\n const [response, requestErr] = await client.request({\r\n method: 'GET',\r\n path: `/sap/bc/adt/cts/transportrequests/${transportId}`,\r\n headers: { 'Accept': ACCEPT_HEADER },\r\n });\r\n\r\n if (requestErr) return err(requestErr);\r\n if (!response.ok) {\r\n const text = await response.text();\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Failed to read transport ${transportId}: ${errorMsg}`));\r\n }\r\n\r\n const text = await response.text();\r\n const [doc, parseErr] = safeParseXml(text);\r\n if (parseErr) return err(parseErr);\r\n\r\n const tasks = parseTransportTasks(doc);\r\n\r\n // Process each task: sort+compress, remove objects, then delete the task.\r\n for (const task of tasks) {\r\n if (removeObjects && task.objects.length > 0) {\r\n // Consolidate duplicate entries before removal.\r\n const [, compressErr] = await sortAndCompress(client, task.taskId);\r\n if (compressErr) return err(compressErr);\r\n\r\n // Re-read the task after compression (entries and positions change).\r\n const [taskResponse, taskReadErr] = await client.request({\r\n method: 'GET',\r\n path: `/sap/bc/adt/cts/transportrequests/${task.taskId}`,\r\n headers: { 'Accept': ACCEPT_HEADER },\r\n });\r\n if (taskReadErr) return err(taskReadErr);\r\n\r\n const taskText = await taskResponse.text();\r\n const [taskDoc, taskParseErr] = safeParseXml(taskText);\r\n if (taskParseErr) return err(taskParseErr);\r\n\r\n // Extract fresh object list from the compressed task.\r\n const elements = taskDoc.getElementsByTagName('tm:abap_object');\r\n for (let i = 0; i < elements.length; i++) {\r\n const el = elements[i];\r\n if (!el) continue;\r\n const name = el.getAttribute('tm:name');\r\n if (!name) continue;\r\n\r\n const [, removeErr] = await removeTransportEntry(client, task.taskId, {\r\n name,\r\n description: el.getAttribute('tm:obj_desc') || el.getAttribute('tm:obj_info') || '',\r\n pgmid: el.getAttribute('tm:pgmid') || '',\r\n type: el.getAttribute('tm:type') || '',\r\n position: el.getAttribute('tm:position') || '',\r\n });\r\n if (removeErr) return err(removeErr);\r\n }\r\n }\r\n\r\n const [, taskErr] = await deleteRequest(client, task.taskId);\r\n if (taskErr) return err(taskErr);\r\n }\r\n\r\n // Delete the parent request.\r\n return deleteRequest(client, transportId);\r\n}\r\n","/**\r\n * Git Diff — Compare local content with server content\r\n *\r\n * Uses Myers diff algorithm to compute line-by-line differences.\r\n */\r\n\r\nimport { diffArrays, type ChangeObject } from 'diff';\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { AdtRequestor } from '../types';\r\nimport type { ObjectContent } from '../../../types/requests';\r\nimport { readObject } from './read';\r\nimport { getConfigByExtension } from '../types';\r\n\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n// Types (colocated - only used by this function)\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\n/** Base fields for all diff hunks */\r\ninterface BaseDiffHunk {\r\n /** Total number of lines in the hunk */\r\n length: number;\r\n /** Starting line in the diff output (0-indexed) */\r\n diffStart: number;\r\n /** Starting line in the local file (0-indexed) */\r\n localStart: number;\r\n}\r\n\r\n/** Addition or deletion hunk */\r\nexport interface SimpleDiffHunk extends BaseDiffHunk {\r\n type: 'addition' | 'deletion';\r\n /** Lines added or removed */\r\n changes: string[];\r\n}\r\n\r\n/** Modification hunk (deletion immediately followed by addition) */\r\nexport interface ModifiedDiffHunk extends BaseDiffHunk {\r\n type: 'modification';\r\n /** Tuple of [server_lines, local_lines] */\r\n changes: [string[], string[]];\r\n}\r\n\r\n/** Any diff hunk */\r\nexport type DiffHunk = SimpleDiffHunk | ModifiedDiffHunk;\r\n\r\n/** Result of comparing a single object */\r\nexport interface DiffResult {\r\n name: string;\r\n extension: string;\r\n label: string;\r\n diffs: DiffHunk[];\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n// Implementation\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Compute diff between server and local content\r\n *\r\n * Converts jsdiff ChangeObject[] output to the hunk format matching Python behavior.\r\n */\r\nfunction computeDiff(serverLines: string[], localLines: string[]): DiffHunk[] {\r\n const changes = diffArrays(serverLines, localLines);\r\n const hunks: DiffHunk[] = [];\r\n\r\n let diffIndex = 0;\r\n let localIndex = 0;\r\n\r\n for (let i = 0; i < changes.length; i++) {\r\n const change = changes[i] as ChangeObject<string[]>;\r\n if (!change) continue;\r\n\r\n if (!change.added && !change.removed) {\r\n // Unchanged lines - advance both indices\r\n const count = change.count ?? change.value.length;\r\n diffIndex += count;\r\n localIndex += count;\r\n continue;\r\n }\r\n\r\n if (change.removed) {\r\n // Check if next change is an addition (making this a modification)\r\n const nextChange = changes[i + 1] as ChangeObject<string[]> | undefined;\r\n\r\n if (nextChange?.added) {\r\n // Modification: deletion followed by addition\r\n const serverChanges = change.value;\r\n const localChanges = nextChange.value;\r\n const modHunk: ModifiedDiffHunk = {\r\n type: 'modification',\r\n length: serverChanges.length + localChanges.length,\r\n diffStart: diffIndex,\r\n localStart: localIndex,\r\n changes: [serverChanges, localChanges],\r\n };\r\n hunks.push(modHunk);\r\n\r\n // Advance indices and skip the next addition\r\n diffIndex += serverChanges.length + localChanges.length;\r\n localIndex += localChanges.length;\r\n i++; // Skip the addition we just processed\r\n continue;\r\n }\r\n\r\n // Pure deletion\r\n const deletionHunk: SimpleDiffHunk = {\r\n type: 'deletion',\r\n length: change.value.length,\r\n diffStart: diffIndex,\r\n localStart: localIndex,\r\n changes: change.value,\r\n };\r\n hunks.push(deletionHunk);\r\n diffIndex += change.value.length;\r\n continue;\r\n }\r\n\r\n if (!change.added) continue;\r\n\r\n // Pure addition (not preceded by deletion - handled above)\r\n const additionHunk: SimpleDiffHunk = {\r\n type: 'addition',\r\n length: change.value.length,\r\n diffStart: diffIndex,\r\n localStart: localIndex,\r\n changes: change.value,\r\n };\r\n hunks.push(additionHunk);\r\n diffIndex += change.value.length;\r\n localIndex += change.value.length;\r\n }\r\n\r\n return hunks;\r\n}\r\n\r\n/**\r\n * Compare local object content with server content\r\n *\r\n * @param client - ADT client\r\n * @param object - Object with local content to compare\r\n * @returns Diff result or error\r\n */\r\nexport async function gitDiff(\r\n client: AdtRequestor,\r\n object: ObjectContent\r\n): AsyncResult<DiffResult, Error> {\r\n // Read current server content.\r\n const [serverObj, readErr] = await readObject(client, {\r\n name: object.name,\r\n extension: object.extension,\r\n });\r\n\r\n if (readErr) {\r\n return err(new Error(`${object.name} does not exist on server`));\r\n }\r\n\r\n // Get label from config.\r\n const config = getConfigByExtension(object.extension);\r\n const label = config?.label ?? object.extension;\r\n\r\n // Split content into lines for comparison.\r\n const serverLines = serverObj.content.split('\\n');\r\n const localLines = object.content.split('\\n');\r\n\r\n // Compute diff.\r\n const diffs = computeDiff(serverLines, localLines);\r\n\r\n return ok({\r\n name: serverObj.name,\r\n extension: serverObj.extension,\r\n label,\r\n diffs,\r\n });\r\n}\r\n","/**\r\n * Read objects method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { ObjectRef } from '../../../types/requests';\r\nimport type { ObjectWithContent, AdtRequestor } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { ok, err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function read(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n objects: ObjectRef[]\r\n): AsyncResult<ObjectWithContent[]> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n\r\n const results: ObjectWithContent[] = [];\r\n for (const obj of objects) {\r\n const [result, readErr] = await adt.readObject(requestor, obj);\r\n if (readErr) return err(readErr);\r\n results.push(result);\r\n }\r\n return ok(results);\r\n}\r\n","/**\r\n * Create object method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { ObjectRef, ObjectContent } from '../../../types/requests';\r\nimport type { AdtRequestor } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { ok, err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function create(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n object: ObjectContent,\r\n packageName: string,\r\n transport?: string\r\n): AsyncResult<void> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n\r\n // Step 1: Create empty object shell\r\n const [, createErr] = await adt.createObject(requestor, object, packageName, transport, state.session.username);\r\n if (createErr) return err(createErr);\r\n\r\n // Step 2: Populate content via lock → update → unlock\r\n const objRef: ObjectRef = { name: object.name, extension: object.extension };\r\n\r\n const [lockHandle, lockErr] = await adt.lockObject(requestor, objRef);\r\n if (lockErr) return err(lockErr);\r\n\r\n const [, updateErr] = await adt.updateObject(requestor, object, lockHandle, transport);\r\n\r\n // Always unlock after update attempt\r\n const [, unlockErr] = await adt.unlockObject(requestor, objRef, lockHandle);\r\n\r\n if (updateErr) return err(updateErr);\r\n if (unlockErr) return err(unlockErr);\r\n\r\n return ok(undefined);\r\n}\r\n","/**\r\n * Update object method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { ObjectRef, ObjectContent } from '../../../types/requests';\r\nimport type { AdtRequestor } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { ok, err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function update(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n object: ObjectContent,\r\n transport?: string\r\n): AsyncResult<void> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n\r\n const objRef: ObjectRef = { name: object.name, extension: object.extension };\r\n\r\n // Lock object before update\r\n const [lockHandle, lockErr] = await adt.lockObject(requestor, objRef);\r\n if (lockErr) return err(lockErr);\r\n\r\n // Update object content\r\n const [, updateErr] = await adt.updateObject(requestor, object, lockHandle, transport);\r\n\r\n // Always unlock after update attempt\r\n const [, unlockErr] = await adt.unlockObject(requestor, objRef, lockHandle);\r\n\r\n // Return first error encountered\r\n if (updateErr) return err(updateErr);\r\n if (unlockErr) return err(unlockErr);\r\n\r\n return ok(undefined);\r\n}\r\n","/**\r\n * Upsert methods (create or update)\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { ObjectRef, ObjectContent } from '../../../types/requests';\r\nimport type { AdtRequestor, UpsertResult } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { ok, err, resolveAllAsync } from '../../../types/result';\r\nimport { normalizeContent } from '../../../core/utils';\r\nimport * as adt from '../../../core/adt';\r\nimport { create } from './create';\r\nimport { update } from './update';\r\n\r\nexport async function upsertSingle(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n object: ObjectContent,\r\n packageName: string,\r\n transport?: string\r\n): AsyncResult<UpsertResult> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n\r\n // Try to read existing object\r\n const objRef: ObjectRef = { name: object.name, extension: object.extension };\r\n const [existing] = await adt.readObject(requestor, objRef);\r\n\r\n // Object doesn't exist - create it\r\n if (!existing) {\r\n const [, createErr] = await create(state, requestor, object, packageName, transport);\r\n if (createErr) return err(createErr);\r\n\r\n const result: UpsertResult = {\r\n name: object.name,\r\n extension: object.extension,\r\n status: 'created',\r\n };\r\n if (transport) result.transport = transport;\r\n return ok(result);\r\n }\r\n\r\n // Compare normalized content to avoid unnecessary updates\r\n const serverContent = normalizeContent(existing.content);\r\n const localContent = normalizeContent(object.content);\r\n\r\n if (serverContent === localContent) {\r\n const result: UpsertResult = {\r\n name: object.name,\r\n extension: object.extension,\r\n status: 'unchanged',\r\n };\r\n if (transport) result.transport = transport;\r\n return ok(result);\r\n }\r\n\r\n // Content differs - update it\r\n const [, updateErr] = await update(state, requestor, object, transport);\r\n if (updateErr) return err(updateErr);\r\n\r\n const result: UpsertResult = {\r\n name: object.name,\r\n extension: object.extension,\r\n status: 'updated',\r\n };\r\n if (transport) result.transport = transport;\r\n return ok(result);\r\n}\r\n\r\nexport async function upsert(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n objects: ObjectContent[],\r\n packageName: string,\r\n transport?: string\r\n): AsyncResult<UpsertResult[]> {\r\n // Confirm we can execute this request.\r\n if (!state.session) return err(new Error('Not logged in'));\r\n if (objects.length === 0) return ok([]);\r\n\r\n // Dispatch all upserts in sync.\r\n const asyncResults: AsyncResult<UpsertResult>[] = [];\r\n for (const obj of objects) {\r\n if (!obj.name || !obj.extension) continue;\r\n asyncResults.push(upsertSingle(state, requestor, obj, packageName, transport));\r\n }\r\n\r\n // Await all responses.\r\n const [results, error] = await resolveAllAsync(asyncResults);\r\n if (error) return err(error);\r\n return ok(results);\r\n}\r\n","/**\r\n * Activate objects method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { ObjectRef } from '../../../types/requests';\r\nimport type { AdtRequestor, ActivationResult } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function activate(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n objects: ObjectRef[]\r\n): AsyncResult<ActivationResult[]> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n return adt.activateObjects(requestor, objects);\r\n}\r\n","/**\r\n * Delete objects method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { ObjectRef } from '../../../types/requests';\r\nimport type { AdtRequestor } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { ok, err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function deleteObjects(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n objects: ObjectRef[],\r\n transport?: string\r\n): AsyncResult<void> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n\r\n for (const obj of objects) {\r\n // Lock object before deletion\r\n const [lockHandle, lockErr] = await adt.lockObject(requestor, obj);\r\n if (lockErr) return err(lockErr);\r\n\r\n // Delete object\r\n const [, deleteErr] = await adt.deleteObject(requestor, obj, lockHandle, transport);\r\n if (deleteErr) {\r\n // Attempt to unlock on failure\r\n await adt.unlockObject(requestor, obj, lockHandle);\r\n return err(deleteErr);\r\n }\r\n }\r\n return ok(undefined);\r\n}\r\n","// Syntax check method\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { ObjectRef } from '../../../types/requests';\r\nimport type { AdtRequestor, CheckResult } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function checkSyntax(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n objects: ObjectRef[]\r\n): AsyncResult<CheckResult[]> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n return adt.checkSyntax(requestor, objects);\r\n}\r\n","/**\r\n * Get packages method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { AdtRequestor, Package, GetPackagesOptions } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function getPackages(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n options?: GetPackagesOptions\r\n): AsyncResult<Package[]> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n return adt.getPackages(requestor, options);\r\n}\r\n","/**\r\n * Get tree method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { TreeQuery } from '../../../types/requests';\r\nimport type { AdtRequestor, TreeResponse } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function getTree(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n query: TreeQuery\r\n): AsyncResult<TreeResponse> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n return adt.getTree(requestor, query);\r\n}\r\n","/**\r\n * Get package stats method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { AdtRequestor, PackageNode } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\n// Single package overload\r\nexport async function getPackageStats(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n packageName: string\r\n): AsyncResult<PackageNode>;\r\n\r\n// Multiple packages overload\r\nexport async function getPackageStats(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n packageNames: string[]\r\n): AsyncResult<PackageNode[]>;\r\n\r\n// Implementation\r\nexport async function getPackageStats(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n packageNames: string | string[]\r\n): AsyncResult<PackageNode | PackageNode[]> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n // Type assertion needed because TS can't infer overload from union\r\n return adt.getPackageStats(requestor, packageNames as string & string[]);\r\n}\r\n","/**\r\n * Get transports method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { AdtRequestor, Transport } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function getTransports(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n packageName: string\r\n): AsyncResult<Transport[]> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n return adt.getTransports(requestor, packageName);\r\n}\r\n","/**\r\n * Preview data method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { PreviewSQL } from '../../../types/requests';\r\nimport type { AdtRequestor, DataFrame } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function previewData(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n query: PreviewSQL\r\n): AsyncResult<DataFrame> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n return adt.previewData(requestor, query);\r\n}\r\n","/**\r\n * Get distinct values method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { AdtRequestor, DistinctResult, Parameter } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function getDistinctValues(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n objectName: string,\r\n parameters: Parameter[],\r\n column: string,\r\n objectType: 'table' | 'view' = 'view'\r\n): AsyncResult<DistinctResult> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n return adt.getDistinctValues(requestor, objectName, parameters, column, objectType);\r\n}\r\n","/**\r\n * Count rows method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { AdtRequestor, Parameter } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function countRows(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n objectName: string,\r\n objectType: 'table' | 'view',\r\n parameters: Parameter[] = []\r\n): AsyncResult<number> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n return adt.countRows(requestor, objectName, objectType, parameters);\r\n}\r\n","/**\r\n * Search objects method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { AdtRequestor, SearchResult, SearchOptions } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function search(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n query: string,\r\n options?: SearchOptions\r\n): AsyncResult<SearchResult[]> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n return adt.searchObjects(requestor, query, options);\r\n}\r\n","/**\r\n * Where-used analysis method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { ObjectRef } from '../../../types/requests';\r\nimport type { AdtRequestor, Dependency } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function whereUsed(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n object: ObjectRef\r\n): AsyncResult<Dependency[]> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n return adt.findWhereUsed(requestor, object);\r\n}\r\n","/**\r\n * Create transport method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { AdtRequestor, TransportConfig } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function createTransport(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n transportConfig: TransportConfig\r\n): AsyncResult<string> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n return adt.createTransport(requestor, transportConfig);\r\n}\r\n","/**\r\n * Delete transport method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { AdtRequestor } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function deleteTransport(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n transportId: string,\r\n removeObjects = false\r\n): AsyncResult<void> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n return adt.deleteTransport(requestor, transportId, removeObjects);\r\n}\r\n","/**\r\n * Remove object from transport method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { AdtRequestor } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function removeFromTransport(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n transportId: string,\r\n objectName: string\r\n): AsyncResult<void> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n return adt.removeFromTransport(requestor, transportId, objectName);\r\n}\r\n","/**\r\n * Git diff method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { ObjectContent } from '../../../types/requests';\r\nimport type { AdtRequestor, DiffResult } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { ok, err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function gitDiff(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n objects: ObjectContent[]\r\n): AsyncResult<DiffResult[]> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n if (objects.length === 0) return ok([]);\r\n\r\n const results: DiffResult[] = [];\r\n for (const obj of objects) {\r\n const [result, diffErr] = await adt.gitDiff(requestor, obj);\r\n if (diffErr) return err(diffErr);\r\n results.push(result);\r\n }\r\n return ok(results);\r\n}\r\n","/**\r\n * Get object configuration method\r\n */\r\n\r\nimport type { ObjectConfig } from '../../../core/adt';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport function getObjectConfig(): ObjectConfig[] {\r\n return Object.values(adt.OBJECT_CONFIG_MAP);\r\n}\r\n","/**\r\n * Cookie management helpers\r\n */\r\n\r\nexport function storeCookies(cookies: Map<string, string>, response: Response): void {\r\n const setCookieHeader = response.headers.get('set-cookie');\r\n if (!setCookieHeader) return;\r\n\r\n // Parse Set-Cookie header(s) - may be multiple cookies\r\n // Format: \"name=value; Path=/; HttpOnly\" or multiple separated\r\n const cookieStrings = setCookieHeader.split(/,(?=\\s*\\w+=)/);\r\n for (const cookieStr of cookieStrings) {\r\n const match = cookieStr.match(/^([^=]+)=([^;]*)/);\r\n if (match && match[1] && match[2]) {\r\n cookies.set(match[1].trim(), match[2].trim());\r\n }\r\n }\r\n}\r\n\r\nexport function buildCookieHeader(cookies: Map<string, string>): string | null {\r\n if (cookies.size === 0) return null;\r\n return Array.from(cookies.entries())\r\n .map(([name, value]) => `${name}=${value}`)\r\n .join('; ');\r\n}\r\n","/**\r\n * Auto-refresh timer management\r\n */\r\n\r\nimport type { Session } from '../../../core/session/types';\r\nimport type { RefreshResult } from '../../../core/session/refresh';\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { debug } from '../../../core/utils';\r\n\r\nexport interface AutoRefreshManager {\r\n start: (intervalMs: number) => void;\r\n stop: () => void;\r\n}\r\n\r\nexport function createAutoRefresh(\r\n getSession: () => Session | null,\r\n refreshSession: () => AsyncResult<RefreshResult>\r\n): AutoRefreshManager {\r\n let timer: ReturnType<typeof setInterval> | null = null;\r\n\r\n return {\r\n start(intervalMs: number) {\r\n this.stop();\r\n timer = setInterval(async () => {\r\n if (!getSession()) return;\r\n const [, refreshErr] = await refreshSession();\r\n if (refreshErr) {\r\n debug(`Auto-refresh failed: ${refreshErr.message}`);\r\n }\r\n }, intervalMs);\r\n // Don't keep the process alive just for auto-refresh\r\n // This allows CLI commands to exit naturally after completing their work\r\n timer.unref();\r\n },\r\n stop() {\r\n if (timer) {\r\n clearInterval(timer);\r\n timer = null;\r\n }\r\n }\r\n };\r\n}\r\n","/**\r\n * HTTP utilities for ADT client\r\n */\r\n\r\nimport * as http from 'http';\r\nimport * as https from 'https';\r\nimport type { HttpRequestOptions } from './types';\r\n\r\nexport const MAX_REDIRECTS = 5;\r\nexport const REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);\r\n\r\n/**\r\n * Make HTTP request using Node.js http/https modules.\r\n *\r\n * Why http/https modules instead of undici/fetch:\r\n * - Undici doesn't work with mTLS client certificates (tested, fails with \"unable to get local issuer certificate\")\r\n * - Node.js https module works reliably with mTLS in all environments (Node.js, Electron, Bun)\r\n * - Simpler to maintain one implementation that works everywhere\r\n */\r\nexport async function httpRequest(\r\n url: string,\r\n options: HttpRequestOptions,\r\n redirectCount = 0\r\n): Promise<Response> {\r\n if (redirectCount > MAX_REDIRECTS) {\r\n throw new Error(`Too many redirects (max ${MAX_REDIRECTS})`);\r\n }\r\n\r\n const urlObj = new URL(url);\r\n const isHttps = urlObj.protocol === 'https:';\r\n const requestFn = isHttps ? https.request : http.request;\r\n const defaultPort = isHttps ? 443 : 80;\r\n\r\n return new Promise((resolve, reject) => {\r\n const req = requestFn({\r\n hostname: urlObj.hostname,\r\n port: urlObj.port || defaultPort,\r\n path: urlObj.pathname + urlObj.search,\r\n method: options.method,\r\n headers: options.headers,\r\n cert: options.cert,\r\n key: options.key,\r\n rejectUnauthorized: options.rejectUnauthorized ?? true,\r\n timeout: options.timeout,\r\n }, (res) => {\r\n const statusCode = res.statusCode || 0;\r\n\r\n // Handle redirects\r\n if (REDIRECT_STATUSES.has(statusCode) && res.headers.location) {\r\n const redirectUrl = new URL(res.headers.location, url).toString();\r\n // For 303, always use GET; for 307/308, preserve method\r\n const redirectMethod = statusCode === 303 ? 'GET' : options.method;\r\n const redirectBody = statusCode === 303 ? undefined : options.body;\r\n\r\n httpRequest(redirectUrl, { ...options, method: redirectMethod, body: redirectBody }, redirectCount + 1)\r\n .then(resolve)\r\n .catch(reject);\r\n return;\r\n }\r\n\r\n const chunks: Buffer[] = [];\r\n res.on('data', chunk => chunks.push(chunk));\r\n res.on('end', () => {\r\n const body = Buffer.concat(chunks).toString('utf-8');\r\n // Convert to web Response\r\n const headers = new Headers();\r\n for (const [key, value] of Object.entries(res.headers)) {\r\n if (value) {\r\n if (Array.isArray(value)) {\r\n value.forEach(v => headers.append(key, v));\r\n } else {\r\n headers.set(key, value);\r\n }\r\n }\r\n }\r\n resolve(new Response(body, {\r\n status: statusCode,\r\n statusText: res.statusMessage || '',\r\n headers,\r\n }));\r\n });\r\n });\r\n\r\n req.on('error', reject);\r\n req.on('timeout', () => {\r\n req.destroy();\r\n reject(new Error('Request timeout'));\r\n });\r\n\r\n if (options.body) {\r\n req.write(options.body);\r\n }\r\n req.end();\r\n });\r\n}\r\n\r\n// Build URL search parameters with sap-client\r\nexport function buildParams(\r\n baseParams: Record<string, string | number> | undefined,\r\n clientNum: string\r\n): URLSearchParams {\r\n const params = new URLSearchParams();\r\n\r\n // Add any custom parameters from the request.\r\n if (baseParams) {\r\n for (const [key, value] of Object.entries(baseParams)) {\r\n params.append(key, String(value));\r\n }\r\n }\r\n\r\n // Always append sap-client parameter.\r\n params.append('sap-client', clientNum);\r\n\r\n return params;\r\n}\r\n\r\n// Build full URL from base URL and path\r\nexport function buildUrl(baseUrl: string, path: string, params?: URLSearchParams): string {\r\n // Construct URL from base and path.\r\n const url = new URL(path, baseUrl);\r\n\r\n // Merge query parameters: preserve existing ones from path, add new ones.\r\n if (params) {\r\n for (const [key, value] of params.entries()) {\r\n url.searchParams.append(key, value);\r\n }\r\n }\r\n\r\n return url.toString();\r\n}\r\n","/**\r\n * Core HTTP request with CSRF handling\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { ClientState, RequestOptions, SsoCerts } from '../../types';\r\nimport { ok, err } from '../../../types/result';\r\nimport {\r\n CSRF_TOKEN_HEADER,\r\n BASE_HEADERS,\r\n DEFAULT_TIMEOUT,\r\n buildRequestHeaders,\r\n debug,\r\n debugError,\r\n} from '../../../core/utils';\r\nimport * as sessionOps from '../../../core/session';\r\nimport { httpRequest, buildParams, buildUrl } from '../../helpers';\r\n\r\nexport interface RequestDependencies {\r\n state: ClientState;\r\n ssoCerts: SsoCerts | undefined;\r\n getCookieHeader: () => string | null;\r\n storeCookies: (response: Response) => void;\r\n}\r\n\r\n/**\r\n * Execute HTTP request with CSRF token injection and automatic retry on 403 errors\r\n */\r\nexport async function executeRequest(\r\n deps: RequestDependencies,\r\n options: RequestOptions,\r\n selfRequest: (options: RequestOptions) => AsyncResult<Response, Error>\r\n): AsyncResult<Response, Error> {\r\n const { state, ssoCerts, getCookieHeader, storeCookies } = deps;\r\n const { method, path, params, headers: customHeaders, body } = options;\r\n const { config } = state;\r\n\r\n // Build headers with auth and CSRF token\r\n debug(`Request ${method} ${path} - CSRF token in state: ${state.csrfToken?.substring(0, 20) || 'null'}...`);\r\n const headers = buildRequestHeaders(\r\n BASE_HEADERS,\r\n customHeaders,\r\n config.auth,\r\n state.csrfToken\r\n );\r\n debug(`CSRF header being sent: ${headers['x-csrf-token']?.substring(0, 20) || 'none'}...`);\r\n\r\n // Add stored cookies to request\r\n const cookieHeader = getCookieHeader();\r\n if (cookieHeader) {\r\n headers['Cookie'] = cookieHeader;\r\n debug(`Cookies being sent: ${cookieHeader.substring(0, 50)}...`);\r\n }\r\n\r\n // Build URL with parameters\r\n const urlParams = buildParams(params, config.client);\r\n const url = buildUrl(config.url, path, urlParams);\r\n\r\n try {\r\n // Execute HTTP request using Node.js https module\r\n debug(`Fetching URL: ${url}`);\r\n debug(`mTLS: ${!!ssoCerts}, insecure: ${config.insecure}`);\r\n\r\n const response = await httpRequest(url, {\r\n method,\r\n headers,\r\n body,\r\n cert: ssoCerts?.cert,\r\n key: ssoCerts?.key,\r\n rejectUnauthorized: !config.insecure,\r\n timeout: config.timeout ?? DEFAULT_TIMEOUT,\r\n });\r\n\r\n // Store any cookies from response\r\n storeCookies(response);\r\n\r\n // Handle CSRF token validation failure with automatic refresh\r\n if (response.status === 403) {\r\n const text = await response.text();\r\n if (text.includes('CSRF token validation failed')) {\r\n // Fetch new CSRF token\r\n const [newToken, tokenErr] = await sessionOps.fetchCsrfToken(state, selfRequest);\r\n if (tokenErr) {\r\n return err(new Error(`CSRF token refresh failed: ${tokenErr.message}`));\r\n }\r\n\r\n // Retry request with new token and cookies\r\n headers[CSRF_TOKEN_HEADER] = newToken;\r\n const retryCookieHeader = getCookieHeader();\r\n if (retryCookieHeader) {\r\n headers['Cookie'] = retryCookieHeader;\r\n }\r\n debug(`Retrying with new CSRF token: ${newToken.substring(0, 20)}...`);\r\n\r\n const retryResponse = await httpRequest(url, {\r\n method,\r\n headers,\r\n body,\r\n cert: ssoCerts?.cert,\r\n key: ssoCerts?.key,\r\n rejectUnauthorized: !config.insecure,\r\n timeout: config.timeout ?? DEFAULT_TIMEOUT,\r\n });\r\n storeCookies(retryResponse);\r\n return ok(retryResponse);\r\n }\r\n\r\n // Return 403 response if not CSRF-related\r\n return ok(new Response(text, {\r\n status: response.status,\r\n statusText: response.statusText,\r\n headers: response.headers,\r\n }));\r\n }\r\n\r\n // Handle session expiration with automatic reset\r\n if (response.status === 500) {\r\n const text = await response.text();\r\n\r\n // Attempt session reset\r\n const [, resetErr] = await sessionOps.sessionReset(state, selfRequest);\r\n if (resetErr) {\r\n return err(new Error(`Session reset failed: ${resetErr.message}`));\r\n }\r\n\r\n // Return original 500 response\r\n return ok(new Response(text, {\r\n status: response.status,\r\n statusText: response.statusText,\r\n headers: response.headers,\r\n }));\r\n }\r\n\r\n return ok(response);\r\n } catch (error) {\r\n // Log detailed error info for debugging\r\n if (error instanceof Error) {\r\n debugError(`Fetch error: ${error.name}: ${error.message}`, error.cause);\r\n if ('code' in error) {\r\n debugError(`Error code: ${(error as NodeJS.ErrnoException).code}`);\r\n }\r\n return err(error);\r\n }\r\n return err(new Error(`Network error: ${String(error)}`));\r\n }\r\n}\r\n","/**\r\n * ADT Client Core Implementation\r\n *\r\n * HTTP client for SAP ADT (ABAP Development Tools) with:\r\n * - Session management (login/logout)\r\n * - CSRF token fetching and automatic refresh\r\n * - Basic, SAML, and SSO (Kerberos + mTLS) authentication\r\n * - Automatic retry on 403 CSRF errors\r\n * - Session reset on 500 errors\r\n *\r\n * Uses Node.js https module for all HTTP requests (works reliably with mTLS).\r\n */\r\n\r\nimport type { ClientConfig } from '../types/config';\r\nimport type {\r\n ObjectRef,\r\n ObjectContent,\r\n TreeQuery,\r\n PreviewSQL,\r\n} from '../types/requests';\r\nimport type { Session, ExportableSessionState } from '../core/session/types';\r\nimport type { RefreshResult } from '../core/session/refresh';\r\nimport type {\r\n ObjectWithContent,\r\n UpsertResult,\r\n ActivationResult,\r\n CheckResult,\r\n TreeResponse,\r\n PackageNode,\r\n Transport,\r\n Package,\r\n GetPackagesOptions,\r\n DataFrame,\r\n DistinctResult,\r\n SearchResult,\r\n SearchOptions,\r\n Dependency,\r\n TransportConfig,\r\n DiffResult,\r\n ObjectConfig,\r\n Parameter,\r\n AdtRequestor,\r\n} from '../core/adt';\r\nimport type { AsyncResult } from '../types/result';\r\nimport { createAuthStrategy } from '../core/auth/factory';\r\nimport type { ClientState, ClientContext, RequestOptions, SsoCerts } from './types';\r\n\r\n// Import extracted methods\r\nimport * as lifecycleMethods from './methods/lifecycle';\r\nimport * as sessionMethods from './methods/session';\r\nimport * as craudMethods from './methods/craud';\r\nimport * as discoveryMethods from './methods/discovery';\r\nimport * as previewMethods from './methods/preview';\r\nimport * as searchMethods from './methods/search';\r\nimport * as transportMethods from './methods/transport';\r\nimport * as diffMethods from './methods/diff';\r\nimport * as configMethods from './methods/config';\r\nimport {\r\n storeCookies,\r\n buildCookieHeader,\r\n createAutoRefresh,\r\n executeRequest,\r\n} from './methods/internal';\r\nimport type { AutoRefreshManager } from './methods/internal';\r\n\r\n// ADT Client interface - provides all operations for interacting with SAP ADT servers\r\nexport interface ADTClient {\r\n /** Current session info (null if not logged in) */\r\n readonly session: Session | null;\r\n\r\n // Lifecycle\r\n login(): AsyncResult<Session>;\r\n logout(): AsyncResult<void>;\r\n refreshSession(): AsyncResult<RefreshResult>;\r\n\r\n // Session state export/import (for session caching across processes)\r\n exportSessionState(): ExportableSessionState | null;\r\n importSessionState(state: ExportableSessionState): AsyncResult<boolean>;\r\n\r\n // CRAUD Operations\r\n read(objects: ObjectRef[]): AsyncResult<ObjectWithContent[]>;\r\n create(object: ObjectContent, packageName: string, transport?: string): AsyncResult<void>;\r\n update(object: ObjectContent, transport?: string): AsyncResult<void>;\r\n upsert(objects: ObjectContent[], packageName: string, transport?: string): AsyncResult<UpsertResult[]>;\r\n activate(objects: ObjectRef[]): AsyncResult<ActivationResult[]>;\r\n checkSyntax(objects: ObjectRef[]): AsyncResult<CheckResult[]>;\r\n delete(objects: ObjectRef[], transport?: string): AsyncResult<void>;\r\n\r\n // Discovery\r\n getPackages(options?: GetPackagesOptions): AsyncResult<Package[]>;\r\n getTree(query: TreeQuery): AsyncResult<TreeResponse>;\r\n getPackageStats(packageName: string): AsyncResult<PackageNode>;\r\n getPackageStats(packageNames: string[]): AsyncResult<PackageNode[]>;\r\n getTransports(packageName: string): AsyncResult<Transport[]>;\r\n\r\n // Data Preview\r\n previewData(query: PreviewSQL): AsyncResult<DataFrame>;\r\n getDistinctValues(objectName: string, parameters: Parameter[], column: string, objectType?: 'table' | 'view'): AsyncResult<DistinctResult>;\r\n countRows(objectName: string, objectType: 'table' | 'view', parameters?: Parameter[]): AsyncResult<number>;\r\n\r\n // Search\r\n search(query: string, options?: SearchOptions): AsyncResult<SearchResult[]>;\r\n whereUsed(object: ObjectRef): AsyncResult<Dependency[]>;\r\n\r\n // Transport Management\r\n createTransport(config: TransportConfig): AsyncResult<string>;\r\n deleteTransport(transportId: string, removeObjects?: boolean): AsyncResult<void>;\r\n removeFromTransport(transportId: string, objectName: string): AsyncResult<void>;\r\n\r\n // Diff Operations\r\n gitDiff(objects: ObjectContent[]): AsyncResult<DiffResult[]>;\r\n\r\n // Configuration\r\n getObjectConfig(): ObjectConfig[];\r\n}\r\n\r\n/**\r\n * ADT Client implementation class.\r\n * Methods delegate to extracted functions in methods/ folder.\r\n */\r\nexport class ADTClientImpl implements ADTClient {\r\n private state: ClientState;\r\n private requestor: AdtRequestor;\r\n private ssoCerts: SsoCerts | undefined;\r\n private autoRefresh: AutoRefreshManager;\r\n\r\n constructor(config: ClientConfig) {\r\n // Create auth strategy from config\r\n const authOptions: Parameters<typeof createAuthStrategy>[0] = {\r\n config: config.auth,\r\n baseUrl: config.url,\r\n };\r\n if (config.insecure) {\r\n authOptions.insecure = config.insecure;\r\n }\r\n const authStrategy = createAuthStrategy(authOptions);\r\n\r\n this.state = {\r\n config,\r\n session: null,\r\n csrfToken: null,\r\n cookies: new Map(),\r\n authStrategy,\r\n };\r\n\r\n // Bind request method for use as requestor\r\n this.requestor = { request: this.request.bind(this) };\r\n\r\n // Initialize auto-refresh manager\r\n this.autoRefresh = createAutoRefresh(\r\n () => this.state.session,\r\n () => this.refreshSession()\r\n );\r\n }\r\n\r\n get session(): Session | null {\r\n return this.state.session;\r\n }\r\n\r\n // --- Private helpers (one-line delegations) ---\r\n\r\n private storeCookies(response: Response): void {\r\n storeCookies(this.state.cookies, response);\r\n }\r\n\r\n private buildCookieHeader(): string | null {\r\n return buildCookieHeader(this.state.cookies);\r\n }\r\n\r\n private startAutoRefresh(intervalMs: number): void {\r\n this.autoRefresh.start(intervalMs);\r\n }\r\n\r\n private stopAutoRefresh(): void {\r\n this.autoRefresh.stop();\r\n }\r\n\r\n private getContext(): ClientContext {\r\n return {\r\n state: this.state,\r\n ssoCerts: this.ssoCerts,\r\n request: this.request.bind(this),\r\n buildCookieHeader: this.buildCookieHeader.bind(this),\r\n storeCookies: this.storeCookies.bind(this),\r\n startAutoRefresh: this.startAutoRefresh.bind(this),\r\n stopAutoRefresh: this.stopAutoRefresh.bind(this),\r\n };\r\n }\r\n\r\n private setSsoCerts(certs: SsoCerts): void {\r\n this.ssoCerts = certs;\r\n }\r\n\r\n private async request(options: RequestOptions): AsyncResult<Response, Error> {\r\n return executeRequest(\r\n {\r\n state: this.state,\r\n ssoCerts: this.ssoCerts,\r\n getCookieHeader: this.buildCookieHeader.bind(this),\r\n storeCookies: this.storeCookies.bind(this),\r\n },\r\n options,\r\n this.request.bind(this)\r\n );\r\n }\r\n\r\n // --- Lifecycle ---\r\n\r\n async login(): AsyncResult<Session> {\r\n return lifecycleMethods.login(this.getContext(), this.setSsoCerts.bind(this));\r\n }\r\n\r\n async logout(): AsyncResult<void> {\r\n return lifecycleMethods.logout(this.getContext());\r\n }\r\n\r\n async refreshSession(): AsyncResult<RefreshResult> {\r\n return lifecycleMethods.refreshSession(this.getContext());\r\n }\r\n\r\n // --- Session State Export/Import ---\r\n\r\n exportSessionState(): ExportableSessionState | null {\r\n return sessionMethods.exportSessionState(this.getContext(), this.ssoCerts);\r\n }\r\n\r\n async importSessionState(state: ExportableSessionState): AsyncResult<boolean> {\r\n return sessionMethods.importSessionState(this.getContext(), state, this.setSsoCerts.bind(this));\r\n }\r\n\r\n // --- CRAUD Operations ---\r\n\r\n async read(objects: ObjectRef[]): AsyncResult<ObjectWithContent[]> {\r\n return craudMethods.read(this.state, this.requestor, objects);\r\n }\r\n\r\n async create(object: ObjectContent, packageName: string, transport?: string): AsyncResult<void> {\r\n return craudMethods.create(this.state, this.requestor, object, packageName, transport);\r\n }\r\n\r\n async update(object: ObjectContent, transport?: string): AsyncResult<void> {\r\n return craudMethods.update(this.state, this.requestor, object, transport);\r\n }\r\n\r\n async upsert(objects: ObjectContent[], packageName: string, transport?: string): AsyncResult<UpsertResult[]> {\r\n return craudMethods.upsert(this.state, this.requestor, objects, packageName, transport);\r\n }\r\n\r\n async activate(objects: ObjectRef[]): AsyncResult<ActivationResult[]> {\r\n return craudMethods.activate(this.state, this.requestor, objects);\r\n }\r\n\r\n async checkSyntax(objects: ObjectRef[]): AsyncResult<CheckResult[]> {\r\n return craudMethods.checkSyntax(this.state, this.requestor, objects);\r\n }\r\n\r\n async delete(objects: ObjectRef[], transport?: string): AsyncResult<void> {\r\n return craudMethods.deleteObjects(this.state, this.requestor, objects, transport);\r\n }\r\n\r\n // --- Discovery ---\r\n\r\n async getPackages(options?: GetPackagesOptions): AsyncResult<Package[]> {\r\n return discoveryMethods.getPackages(this.state, this.requestor, options);\r\n }\r\n\r\n async getTree(query: TreeQuery): AsyncResult<TreeResponse> {\r\n return discoveryMethods.getTree(this.state, this.requestor, query);\r\n }\r\n\r\n async getPackageStats(packageName: string): AsyncResult<PackageNode>;\r\n async getPackageStats(packageNames: string[]): AsyncResult<PackageNode[]>;\r\n async getPackageStats(packageNames: string | string[]): AsyncResult<PackageNode | PackageNode[]> {\r\n return discoveryMethods.getPackageStats(this.state, this.requestor, packageNames as string & string[]);\r\n }\r\n\r\n async getTransports(packageName: string): AsyncResult<Transport[]> {\r\n return discoveryMethods.getTransports(this.state, this.requestor, packageName);\r\n }\r\n\r\n // --- Data Preview ---\r\n\r\n async previewData(query: PreviewSQL): AsyncResult<DataFrame> {\r\n return previewMethods.previewData(this.state, this.requestor, query);\r\n }\r\n\r\n async getDistinctValues(objectName: string, parameters: Parameter[], column: string, objectType: 'table' | 'view' = 'view'): AsyncResult<DistinctResult> {\r\n return previewMethods.getDistinctValues(this.state, this.requestor, objectName, parameters, column, objectType);\r\n }\r\n\r\n async countRows(objectName: string, objectType: 'table' | 'view', parameters: Parameter[] = []): AsyncResult<number> {\r\n return previewMethods.countRows(this.state, this.requestor, objectName, objectType, parameters);\r\n }\r\n\r\n // --- Search ---\r\n\r\n async search(query: string, options?: SearchOptions): AsyncResult<SearchResult[]> {\r\n return searchMethods.search(this.state, this.requestor, query, options);\r\n }\r\n\r\n async whereUsed(object: ObjectRef): AsyncResult<Dependency[]> {\r\n return searchMethods.whereUsed(this.state, this.requestor, object);\r\n }\r\n\r\n // --- Transport Management ---\r\n\r\n async createTransport(transportConfig: TransportConfig): AsyncResult<string> {\r\n return transportMethods.createTransport(this.state, this.requestor, transportConfig);\r\n }\r\n\r\n async deleteTransport(transportId: string, removeObjects = false): AsyncResult<void> {\r\n return transportMethods.deleteTransport(this.state, this.requestor, transportId, removeObjects);\r\n }\r\n\r\n async removeFromTransport(transportId: string, objectName: string): AsyncResult<void> {\r\n return transportMethods.removeFromTransport(this.state, this.requestor, transportId, objectName);\r\n }\r\n\r\n // --- Diff Operations ---\r\n\r\n async gitDiff(objects: ObjectContent[]): AsyncResult<DiffResult[]> {\r\n return diffMethods.gitDiff(this.state, this.requestor, objects);\r\n }\r\n\r\n // --- Configuration ---\r\n\r\n getObjectConfig(): ObjectConfig[] {\r\n return configMethods.getObjectConfig();\r\n }\r\n}\r\n","/**\r\n * ADT Client Module\r\n *\r\n * Exports the ADTClient interface and createClient factory function.\r\n */\r\n\r\nimport type { ClientConfig } from '../types/config';\r\nimport type { Result } from '../types/result';\r\nimport { ok, err } from '../types/result';\r\nimport { clientConfigSchema } from '../types/config';\r\nimport { ADTClientImpl } from './client';\r\nimport type { ADTClient } from './client';\r\n\r\nexport type { ADTClient };\r\n\r\n// Create a new ADT client - validates config and returns client instance\r\nexport function createClient(config: ClientConfig): Result<ADTClient, Error> {\r\n // Validate config using Zod schema.\r\n const validation = clientConfigSchema.safeParse(config);\r\n if (!validation.success) {\r\n const issues = validation.error.issues.map(i => `${i.path.join('.')}: ${i.message}`).join(', ');\r\n return err(new Error(`Invalid client configuration: ${issues}`));\r\n }\r\n\r\n return ok(new ADTClientImpl(config));\r\n}\r\n"],"mappings":"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","names":["err","forge","import_node_forge","forge","forge","request","request","login","loginErr","logout","refreshSession","DEFAULT_REFRESH_INTERVAL","text","stat","text","text","parsed","parseErr","packages","text","text","text","text","text","text","text","ACCEPT_HEADER","text","result","checkSyntax","getPackages","getTree","getPackageStats","getTransports","previewData","getDistinctValues","countRows","createTransport","deleteTransport","removeFromTransport","gitDiff","refreshSession","https","buildUrl","storeCookies","buildUrl","login","logout","refreshSession","checkSyntax","getPackages","getTree","getPackageStats","getTransports","previewData","getDistinctValues","countRows","createTransport","deleteTransport","removeFromTransport","gitDiff"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/types/result.ts","../src/types/config.ts","../src/core/auth/basic/basic.ts","../src/core/auth/sso/slsClient.ts","../src/core/auth/sso/types.ts","../src/core/auth/sso/kerberos.ts","../src/core/auth/sso/certificate.ts","../src/core/auth/sso/pkcs7.ts","../src/core/auth/sso/storage.ts","../src/core/auth/sso/sso.ts","../src/core/auth/saml/types.ts","../src/core/auth/saml/browser.ts","../src/core/auth/saml/cookies.ts","../src/core/auth/saml/saml.ts","../src/core/auth/factory.ts","../src/core/session/types.ts","../src/core/utils/xml.ts","../src/core/utils/csrf.ts","../src/core/utils/headers.ts","../src/core/utils/logging.ts","../src/core/utils/content.ts","../src/core/session/login.ts","../src/core/session/refresh.ts","../src/client/methods/lifecycle/login.ts","../src/client/methods/lifecycle/logout.ts","../src/client/methods/lifecycle/refreshSession.ts","../src/client/methods/session/exportSessionState.ts","../src/client/methods/session/importSessionState.ts","../src/core/adt/types.ts","../src/core/adt/helpers.ts","../src/core/adt/craud/read.ts","../src/core/adt/craud/lock.ts","../src/core/adt/craud/create.ts","../src/core/adt/craud/update.ts","../src/core/adt/craud/delete.ts","../src/core/adt/craud/activation.ts","../src/core/adt/craud/syntaxCheck.ts","../src/core/adt/discovery/tree/packageStats.ts","../src/core/adt/discovery/packages.ts","../src/core/adt/discovery/tree/parsers.ts","../src/core/adt/discovery/tree/childPackages.ts","../src/core/adt/discovery/tree/virtualFolders.ts","../src/core/adt/discovery/tree/index.ts","../src/core/adt/transports/transports.ts","../src/core/adt/data_extraction/previewParser.ts","../src/core/adt/data_extraction/dataPreview.ts","../src/core/adt/data_extraction/freestyle.ts","../src/core/adt/data_extraction/queryBuilder.ts","../src/core/adt/data_extraction/distinct.ts","../src/core/adt/data_extraction/count.ts","../src/core/adt/discovery/searchObjects.ts","../src/core/adt/discovery/whereUsed.ts","../src/core/adt/transports/createTransport.ts","../src/core/adt/transports/parseTransportTasks.ts","../src/core/adt/transports/removeFromTransport.ts","../src/core/adt/transports/deleteTransport.ts","../src/core/adt/transports/viewTransportObjects.ts","../src/core/adt/craud/gitDiff.ts","../src/client/methods/craud/read.ts","../src/client/methods/craud/create.ts","../src/client/methods/craud/update.ts","../src/client/methods/craud/upsert.ts","../src/client/methods/craud/activate.ts","../src/client/methods/craud/delete.ts","../src/client/methods/craud/checkSyntax.ts","../src/client/methods/discovery/getPackages.ts","../src/client/methods/discovery/getTree.ts","../src/client/methods/discovery/getPackageStats.ts","../src/client/methods/discovery/getTransports.ts","../src/client/methods/preview/previewData.ts","../src/client/methods/preview/getDistinctValues.ts","../src/client/methods/preview/countRows.ts","../src/client/methods/search/search.ts","../src/client/methods/search/whereUsed.ts","../src/client/methods/transport/createTransport.ts","../src/client/methods/transport/deleteTransport.ts","../src/client/methods/transport/removeFromTransport.ts","../src/client/methods/transport/viewTransportObjects.ts","../src/client/methods/diff/gitDiff.ts","../src/client/methods/config/getObjectConfig.ts","../src/client/methods/internal/cookies.ts","../src/client/methods/internal/autoRefresh.ts","../src/client/helpers.ts","../src/client/methods/internal/request.ts","../src/client/client.ts","../src/client/index.ts"],"sourcesContent":["/**\r\n * Catalyst-Relay\r\n *\r\n * TypeScript middleware for SAP ADT integration.\r\n * Can be used as a library (direct imports) or as an HTTP server.\r\n *\r\n * @example Library usage\r\n * ```typescript\r\n * import { createClient } from 'catalyst-relay';\r\n *\r\n * const [client, error] = createClient({\r\n * url: 'https://sap-server:443',\r\n * client: '100',\r\n * auth: { type: 'basic', username: 'user', password: 'pass' }\r\n * });\r\n * if (error) throw error;\r\n *\r\n * const [session, loginError] = await client.login();\r\n * if (loginError) throw loginError;\r\n *\r\n * const [data, readError] = await client.read([\r\n * { name: 'ZTEST_VIEW', extension: 'asddls' }\r\n * ]);\r\n * ```\r\n *\r\n * @example Server usage\r\n * ```bash\r\n * bun run src/server.ts\r\n * ```\r\n */\r\n\r\n// Core exports\r\nexport { createClient } from './core';\r\nexport type { ADTClient } from './core';\r\n\r\n// Logging control\r\nexport { activateLogging, deactivateLogging } from './core';\r\n\r\n// Config types\r\nexport type {\r\n AuthType,\r\n AuthConfig,\r\n BasicAuthConfig,\r\n SamlAuthConfig,\r\n SsoAuthConfig,\r\n ClientConfig,\r\n} from './types/config';\r\n\r\n// Request types\r\nexport type {\r\n ObjectRef,\r\n ObjectContent,\r\n TreeQuery,\r\n PreviewSQL,\r\n} from './types/requests';\r\n\r\n// Response wrappers\r\nexport type {\r\n ApiResponse,\r\n SuccessResponse,\r\n ErrorResponse,\r\n ErrorCode,\r\n} from './types/responses';\r\n\r\n// Result types\r\nexport type { Result, AsyncResult } from './types/result';\r\n\r\n// Session types\r\nexport type { Session, ExportableSessionState } from './core/session/types';\r\n\r\n// ADT domain types\r\nexport type {\r\n ObjectMetadata,\r\n ObjectWithContent,\r\n UpsertResult,\r\n ActivationResult,\r\n ActivationMessage,\r\n Transport,\r\n Package,\r\n DataFrame,\r\n ColumnInfo,\r\n DistinctResult,\r\n SearchResult,\r\n SearchOptions,\r\n Dependency,\r\n DiffResult,\r\n TransportConfig,\r\n TransportObject,\r\n TaskContents,\r\n ObjectConfig,\r\n // Tree types\r\n TreeResponse,\r\n PackageNode,\r\n FolderNode,\r\n ObjectNode,\r\n} from './core/adt';\r\n\r\n// Query builder (optional helper for data preview)\r\nexport { buildSQLQuery } from './core/adt';\r\nexport type { DataPreviewQuery, QueryFilter, BasicFilter, BetweenFilter, ListFilter, Sorting, Aggregation, Parameter } from './core/adt';\r\n\r\n// Result utilities\r\nexport { ok, err } from './types/result';\r\n","/**\r\n * Result type for error handling (Go-style tuples)\r\n *\r\n * Usage:\r\n * const [data, error] = await someFunction();\r\n * if (error) {\r\n * console.error(error);\r\n * return;\r\n * }\r\n * // data is guaranteed non-null\r\n */\r\n\r\nexport type Result<T, E extends Error = Error> = [T, null] | [null, E];\r\n\r\n/**\r\n * Async result type alias for convenience\r\n */\r\nexport type AsyncResult<T, E extends Error = Error> = Promise<Result<T, E>>;\r\n\r\n/**\r\n * Create a success result\r\n */\r\nexport function ok<T>(value: T): Result<T, never> {\r\n return [value, null];\r\n}\r\n\r\n/**\r\n * Create an error result\r\n */\r\nexport function err<E extends Error = Error>(error: E): Result<never, E> {\r\n return [null, error];\r\n}\r\n\r\nexport function resolveAll<T, E extends Error = Error>(results: Result<T, E>[]): Result<T[], AggregateError> {\r\n const [successes, errors]: [T[], E[]] = [[], []];\r\n for (const [val, err] of results) {\r\n if (err !== null) {\r\n errors.push(err);\r\n continue;\r\n }\r\n successes.push(val!);\r\n }\r\n if (errors.length) {\r\n const messages = errors.map((e, i) => `[${i + 1}] ${e.message}`).join('\\n');\r\n return err(new AggregateError(errors, `Multiple upsert errors:\\n${messages}`));\r\n }\r\n return ok(successes);\r\n}\r\n\r\nexport async function resolveAllAsync<T, E extends Error = Error>(resultPromises: AsyncResult<T, E>[]): AsyncResult<T[], AggregateError> {\r\n const results = await Promise.all(resultPromises);\r\n return resolveAll(results);\r\n}","import { z } from 'zod';\r\n\r\n/**\r\n * Authentication types supported by SAP ADT\r\n */\r\nexport type AuthType = 'basic' | 'saml' | 'sso';\r\n\r\n/**\r\n * Basic authentication configuration\r\n */\r\nexport interface BasicAuthConfig {\r\n type: 'basic';\r\n username: string;\r\n password: string;\r\n}\r\n\r\n/**\r\n * CSS selectors for SAML login form\r\n */\r\nexport interface SamlFormSelectors {\r\n /** CSS selector for username input field */\r\n username: string;\r\n /** CSS selector for password input field */\r\n password: string;\r\n /** CSS selector for submit button */\r\n submit: string;\r\n}\r\n\r\n/**\r\n * SAML provider configuration\r\n */\r\nexport interface SamlProviderConfig {\r\n /** Whether to ignore HTTPS certificate errors */\r\n ignoreHttpsErrors: boolean;\r\n /** CSS selectors for login form elements */\r\n formSelectors: SamlFormSelectors;\r\n}\r\n\r\n/**\r\n * SAML authentication configuration\r\n */\r\nexport interface SamlAuthConfig {\r\n type: 'saml';\r\n /** SAML username (often an email address) - used for browser login */\r\n username: string;\r\n /** SAML password */\r\n password: string;\r\n /** SAP system username - used for object creation (adtcore:responsible) */\r\n sapUser: string;\r\n /** Optional custom provider configuration for non-standard login forms */\r\n providerConfig?: SamlProviderConfig;\r\n}\r\n\r\n/**\r\n * SSO (Kerberos) authentication configuration\r\n */\r\nexport interface SsoAuthConfig {\r\n type: 'sso';\r\n /** Secure Login Server URL (e.g., https://sapsso.corp.example.com) */\r\n slsUrl: string;\r\n /** SLS profile name (default: SAPSSO_P) */\r\n profile?: string;\r\n /** Kerberos service principal name override */\r\n servicePrincipalName?: string;\r\n /** Force certificate re-enrollment even if valid cert exists */\r\n forceEnroll?: boolean;\r\n /** @deprecated Use slsUrl instead */\r\n certificate?: string;\r\n}\r\n\r\n/**\r\n * Union of all auth configurations\r\n */\r\nexport type AuthConfig = BasicAuthConfig | SamlAuthConfig | SsoAuthConfig;\r\n\r\n/**\r\n * Auto-refresh configuration for session keepalive\r\n */\r\nexport interface AutoRefreshConfig {\r\n /** Enable automatic session refresh (default: true) */\r\n enabled: boolean;\r\n /** Refresh interval in milliseconds (default: 7200000 = 2 hours) */\r\n intervalMs?: number;\r\n}\r\n\r\n/**\r\n * Client configuration for connecting to SAP ADT\r\n */\r\nexport interface ClientConfig {\r\n /** ADT server URL (e.g., https://server:port) */\r\n url: string;\r\n /** SAP client number (e.g., '100') */\r\n client: string;\r\n /** Authentication configuration */\r\n auth: AuthConfig;\r\n /** Request timeout in milliseconds (default: 30000) */\r\n timeout?: number;\r\n /** Skip SSL verification (dev only) */\r\n insecure?: boolean;\r\n /** Auto-refresh configuration for session keepalive (default: enabled with 2-hour interval) */\r\n autoRefresh?: AutoRefreshConfig;\r\n}\r\n\r\n/**\r\n * Zod schema for SAML form selectors\r\n */\r\nconst samlFormSelectorsSchema = z.object({\r\n username: z.string().min(1),\r\n password: z.string().min(1),\r\n submit: z.string().min(1),\r\n});\r\n\r\n/**\r\n * Zod schema for SAML provider configuration\r\n */\r\nconst samlProviderConfigSchema = z.object({\r\n ignoreHttpsErrors: z.boolean(),\r\n formSelectors: samlFormSelectorsSchema,\r\n});\r\n\r\n/**\r\n * Zod schema for runtime validation of ClientConfig\r\n */\r\nexport const clientConfigSchema = z.object({\r\n url: z.string().url(),\r\n client: z.string().min(1).max(3),\r\n auth: z.discriminatedUnion('type', [\r\n z.object({\r\n type: z.literal('basic'),\r\n username: z.string().min(1),\r\n password: z.string().min(1),\r\n }),\r\n z.object({\r\n type: z.literal('saml'),\r\n username: z.string().min(1),\r\n password: z.string().min(1),\r\n sapUser: z.string().min(1),\r\n providerConfig: samlProviderConfigSchema.optional(),\r\n }),\r\n z.object({\r\n type: z.literal('sso'),\r\n slsUrl: z.string().url(),\r\n profile: z.string().optional(),\r\n servicePrincipalName: z.string().optional(),\r\n forceEnroll: z.boolean().optional(),\r\n certificate: z.string().optional(),\r\n }),\r\n ]),\r\n timeout: z.number().positive().optional(),\r\n insecure: z.boolean().optional(),\r\n autoRefresh: z.object({\r\n enabled: z.boolean(),\r\n intervalMs: z.number().positive().optional(),\r\n }).optional(),\r\n});\r\n","import type { AuthStrategy } from '../types';\r\n\r\n/**\r\n * Basic authentication strategy\r\n *\r\n * Implements HTTP Basic Auth using username/password credentials.\r\n * Credentials are base64-encoded and sent in the Authorization header.\r\n *\r\n * Reference: RFC 7617\r\n */\r\nexport class BasicAuth implements AuthStrategy {\r\n readonly type = 'basic' as const;\r\n private authHeader: string;\r\n\r\n /**\r\n * Create a Basic Auth strategy\r\n * @param username - SAP username\r\n * @param password - SAP password\r\n */\r\n constructor(username: string, password: string) {\r\n if (!username || !password) {\r\n throw new Error('BasicAuth requires both username and password');\r\n }\r\n\r\n const credentials = `${username}:${password}`;\r\n const encoded = btoa(credentials);\r\n this.authHeader = `Basic ${encoded}`;\r\n }\r\n\r\n /**\r\n * Get Authorization header with Basic credentials\r\n * @returns Headers object with Authorization field\r\n */\r\n getAuthHeaders(): Record<string, string> {\r\n return {\r\n Authorization: this.authHeader,\r\n };\r\n }\r\n}\r\n","/**\r\n * SAP Secure Login Server (SLS) client\r\n *\r\n * Handles communication with SLS for certificate enrollment:\r\n * 1. Authenticate using Kerberos SPNEGO\r\n * 2. Submit CSR to get signed certificate\r\n *\r\n * Uses Node.js https module for all HTTP requests (same as client.ts)\r\n * for consistent behavior across Node.js, Electron (VS Code), and Bun.\r\n */\r\n\r\nimport * as https from 'https';\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { SlsConfig, SlsAuthResponse, CertificateMaterial } from './types';\r\nimport { SLS_DEFAULTS } from './types';\r\nimport { getSpnegoToken, extractSpnFromUrl } from './kerberos';\r\nimport { generateKeypair, createCsr, getCurrentUsername } from './certificate';\r\nimport { parsePkcs7Certificates } from './pkcs7';\r\n\r\n/**\r\n * Make HTTP request using Node.js https module.\r\n * Same approach as client.ts for consistency.\r\n */\r\nasync function httpsRequest(\r\n url: string,\r\n options: {\r\n method: string;\r\n headers: Record<string, string>;\r\n body?: Buffer | undefined;\r\n rejectUnauthorized?: boolean | undefined;\r\n }\r\n): Promise<{ status: number; headers: Record<string, string | string[]>; body: Buffer; cookies: string[] }> {\r\n const urlObj = new URL(url);\r\n\r\n return new Promise((resolve, reject) => {\r\n const req = https.request({\r\n hostname: urlObj.hostname,\r\n port: urlObj.port || 443,\r\n path: urlObj.pathname + urlObj.search,\r\n method: options.method,\r\n headers: options.headers,\r\n rejectUnauthorized: options.rejectUnauthorized ?? true,\r\n }, (res) => {\r\n const chunks: Buffer[] = [];\r\n res.on('data', chunk => chunks.push(chunk));\r\n res.on('end', () => {\r\n const body = Buffer.concat(chunks);\r\n\r\n // Extract cookies from set-cookie headers\r\n const cookies: string[] = [];\r\n const setCookieHeader = res.headers['set-cookie'];\r\n if (setCookieHeader) {\r\n for (const cookie of setCookieHeader) {\r\n const cookieValue = cookie.split(';')[0];\r\n if (cookieValue) {\r\n cookies.push(cookieValue);\r\n }\r\n }\r\n }\r\n\r\n resolve({\r\n status: res.statusCode || 0,\r\n headers: res.headers as Record<string, string | string[]>,\r\n body,\r\n cookies,\r\n });\r\n });\r\n });\r\n\r\n req.on('error', reject);\r\n\r\n if (options.body) {\r\n req.write(options.body);\r\n }\r\n req.end();\r\n });\r\n}\r\n\r\n/**\r\n * SLS client options\r\n */\r\ninterface SlsClientConfig {\r\n /** SLS configuration */\r\n config: SlsConfig;\r\n /** Skip SSL verification (required for most corporate environments) */\r\n insecure?: boolean;\r\n}\r\n\r\n/**\r\n * Enroll a client certificate from SLS\r\n *\r\n * Performs the full certificate enrollment flow:\r\n * 1. Authenticate to SLS using Kerberos SPNEGO\r\n * 2. Generate RSA keypair\r\n * 3. Create CSR with current username\r\n * 4. Submit CSR to SLS\r\n * 5. Parse PKCS#7 response to extract certificates\r\n *\r\n * @param options - SLS client configuration\r\n * @returns Certificate material (full chain + private key) or error\r\n *\r\n * @example\r\n * ```typescript\r\n * const [certs, error] = await enrollCertificate({\r\n * config: { slsUrl: 'https://sapsso.corp.example.com' },\r\n * insecure: true,\r\n * });\r\n *\r\n * if (error) {\r\n * console.error('Enrollment failed:', error.message);\r\n * return;\r\n * }\r\n *\r\n * // Use certificates for mTLS\r\n * ```\r\n */\r\nexport async function enrollCertificate(\r\n options: SlsClientConfig\r\n): AsyncResult<CertificateMaterial> {\r\n const { config, insecure = false } = options;\r\n const profile = config.profile ?? SLS_DEFAULTS.PROFILE;\r\n\r\n // Step 1: Authenticate with Kerberos (also captures session cookies)\r\n const [authResult, authErr] = await authenticateToSls(config, profile, insecure);\r\n if (authErr) return err(authErr);\r\n\r\n // Step 2: Generate keypair\r\n const keySize = authResult.response.clientConfig.keySize ?? SLS_DEFAULTS.KEY_SIZE;\r\n const keypair = generateKeypair(keySize);\r\n\r\n // Step 3: Create CSR\r\n const username = getCurrentUsername();\r\n const csrDer = createCsr(keypair, username);\r\n\r\n // Step 4: Submit CSR and get certificate (pass cookies from auth step - like Python's session)\r\n const [certData, certErr] = await requestCertificate(config, profile, csrDer, authResult.cookies, insecure);\r\n if (certErr) return err(certErr);\r\n\r\n // Step 5: Parse PKCS#7 response\r\n const [certs, parseErr] = parsePkcs7Certificates(certData);\r\n if (parseErr) return err(parseErr);\r\n\r\n return ok({\r\n fullChain: certs.fullChain,\r\n privateKey: keypair.privateKeyPem,\r\n });\r\n}\r\n\r\n/**\r\n * Result from SLS authentication, includes cookies for session persistence\r\n */\r\ninterface SlsAuthResult {\r\n response: SlsAuthResponse;\r\n cookies: string[]; // Cookies to pass to subsequent requests (like Python's session)\r\n}\r\n\r\n/**\r\n * Authenticate to SLS using Kerberos SPNEGO\r\n */\r\nasync function authenticateToSls(\r\n config: SlsConfig,\r\n profile: string,\r\n insecure: boolean = false\r\n): AsyncResult<SlsAuthResult> {\r\n // Get SPNEGO token\r\n const spn = config.servicePrincipalName ?? extractSpnFromUrl(config.slsUrl);\r\n const [token, tokenErr] = await getSpnegoToken(spn);\r\n if (tokenErr) return err(tokenErr);\r\n\r\n // Build auth URL\r\n const authUrl = `${config.slsUrl}${SLS_DEFAULTS.LOGIN_ENDPOINT}?profile=${profile}`;\r\n\r\n try {\r\n const response = await httpsRequest(authUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Authorization': `Negotiate ${token}`,\r\n 'Accept': '*/*',\r\n },\r\n rejectUnauthorized: !insecure,\r\n });\r\n\r\n if (response.status < 200 || response.status >= 300) {\r\n const text = response.body.toString('utf-8');\r\n return err(new Error(`SLS authentication failed: ${response.status} - ${text}`));\r\n }\r\n\r\n const authResponse = JSON.parse(response.body.toString('utf-8')) as SlsAuthResponse;\r\n return ok({ response: authResponse, cookies: response.cookies });\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n return err(new Error(`SLS authentication request failed: ${message}`));\r\n }\r\n}\r\n\r\n/**\r\n * Request certificate from SLS by submitting CSR\r\n */\r\nasync function requestCertificate(\r\n config: SlsConfig,\r\n profile: string,\r\n csrDer: Buffer,\r\n cookies: string[], // Session cookies from authentication (like Python's session)\r\n insecure: boolean = false\r\n): AsyncResult<Buffer> {\r\n const certUrl = `${config.slsUrl}${SLS_DEFAULTS.CERTIFICATE_ENDPOINT}?profile=${profile}`;\r\n\r\n try {\r\n const headers: Record<string, string> = {\r\n 'Content-Type': 'application/pkcs10',\r\n 'Content-Length': String(csrDer.length),\r\n 'Accept': '*/*',\r\n };\r\n\r\n // Pass cookies from auth step - like Python's requests.Session() does automatically\r\n if (cookies.length > 0) {\r\n headers['Cookie'] = cookies.join('; ');\r\n }\r\n\r\n const response = await httpsRequest(certUrl, {\r\n method: 'POST',\r\n headers,\r\n body: csrDer,\r\n rejectUnauthorized: !insecure,\r\n });\r\n\r\n if (response.status < 200 || response.status >= 300) {\r\n const text = response.body.toString('utf-8');\r\n return err(new Error(`Certificate request failed: ${response.status} - ${text}`));\r\n }\r\n\r\n return ok(response.body);\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n return err(new Error(`Certificate request failed: ${message}`));\r\n }\r\n}\r\n","/**\r\n * SSO authentication types\r\n *\r\n * Types for Kerberos-based SSO authentication with SAP Secure Login Server (SLS).\r\n */\r\n\r\n/**\r\n * Secure Login Server (SLS) configuration\r\n */\r\nexport interface SlsConfig {\r\n /** SLS server URL (e.g., https://sapsso.corp.example.com:443) */\r\n slsUrl: string;\r\n /** SLS profile name (default: SAPSSO_P) */\r\n profile?: string;\r\n /** Service principal name for Kerberos (e.g., HTTP/sapsso.corp.example.com) */\r\n servicePrincipalName?: string;\r\n}\r\n\r\n/**\r\n * Default SLS configuration values\r\n */\r\nexport const SLS_DEFAULTS = {\r\n PROFILE: 'SAPSSO_P',\r\n LOGIN_ENDPOINT: '/SecureLoginServer/slc3/doLogin',\r\n CERTIFICATE_ENDPOINT: '/SecureLoginServer/slc2/getCertificate',\r\n KEY_SIZE: 2048,\r\n} as const;\r\n\r\n/**\r\n * SLS authentication response from doLogin endpoint\r\n */\r\nexport interface SlsAuthResponse {\r\n clientConfig: {\r\n keySize?: number;\r\n };\r\n}\r\n\r\n/**\r\n * mTLS certificate material for use with undici Agent\r\n */\r\nexport interface CertificateMaterial {\r\n /** PEM-encoded client certificate + CA chain */\r\n fullChain: string;\r\n /** PEM-encoded private key */\r\n privateKey: string;\r\n}\r\n\r\n/**\r\n * Certificate file paths on disk\r\n */\r\nexport interface CertificatePaths {\r\n /** Path to client certificate + CA chain PEM file */\r\n fullChainPath: string;\r\n /** Path to private key PEM file */\r\n keyPath: string;\r\n}\r\n\r\n/**\r\n * Result of certificate enrollment - either material or paths\r\n */\r\nexport type CertificateResult = CertificateMaterial | CertificatePaths;\r\n\r\n/**\r\n * Options for SLS client operations\r\n */\r\nexport interface SlsClientOptions {\r\n /** SLS configuration */\r\n config: SlsConfig;\r\n /** Skip SSL verification (dev only) */\r\n insecure?: boolean;\r\n}\r\n\r\n/**\r\n * Get the base directory for certificate storage\r\n * Uses the user's home directory to ensure consistent location regardless of CWD.\r\n * Falls back to relative path if home dir not available.\r\n */\r\nfunction getCertificateBaseDir(): string {\r\n // Use HOME on Unix, USERPROFILE on Windows, or fallback to relative path\r\n const homeDir = process.env['HOME'] ?? process.env['USERPROFILE'] ?? '.';\r\n return `${homeDir}/.catalyst/certificates/sso`;\r\n}\r\n\r\n/**\r\n * Certificate storage directory structure\r\n */\r\nexport const CERTIFICATE_STORAGE = {\r\n get BASE_DIR(): string { return getCertificateBaseDir(); },\r\n FULL_CHAIN_SUFFIX: '_full_chain.pem',\r\n KEY_SUFFIX: '_key.pem',\r\n} as const;\r\n","/**\r\n * Kerberos SPNEGO token generation\r\n *\r\n * Generates SPNEGO tokens for authenticating to SAP Secure Login Server.\r\n * Uses the kerberos npm package (optional peer dependency).\r\n *\r\n * Platform support:\r\n * - Windows: Uses SSPI (native Windows authentication)\r\n * - Linux/macOS: Uses MIT Kerberos (requires kinit)\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\n\r\n/**\r\n * Kerberos client interface matching the kerberos npm package\r\n */\r\ninterface KerberosClient {\r\n step(token: string): Promise<string | null>;\r\n wrap(message: string, options?: unknown): Promise<string>;\r\n unwrap(message: string): Promise<string>;\r\n}\r\n\r\n/**\r\n * Kerberos module interface\r\n */\r\ninterface KerberosModule {\r\n initializeClient(\r\n service: string,\r\n options?: { mechOID?: string }\r\n ): Promise<KerberosClient>;\r\n}\r\n\r\n/**\r\n * Lazily load kerberos module\r\n *\r\n * @returns Kerberos module or null if not installed\r\n */\r\nasync function loadKerberosModule(): AsyncResult<KerberosModule> {\r\n try {\r\n // Dynamic import to avoid hard dependency\r\n // eslint-disable-next-line @typescript-eslint/no-require-imports\r\n const kerberosModule = require('kerberos') as KerberosModule;\r\n return ok(kerberosModule);\r\n } catch {\r\n return err(new Error(\r\n 'kerberos package is not installed. ' +\r\n 'Install it with: npm install kerberos'\r\n ));\r\n }\r\n}\r\n\r\n/**\r\n * Generate SPNEGO token for Kerberos authentication\r\n *\r\n * Creates a base64-encoded SPNEGO token that can be used in\r\n * Authorization: Negotiate headers for authenticating to SLS.\r\n *\r\n * @param servicePrincipalName - SPN to authenticate to (e.g., HTTP/sapsso.corp.example.com)\r\n * @returns Base64-encoded SPNEGO token or error\r\n *\r\n * @example\r\n * ```typescript\r\n * const [token, error] = await getSpnegoToken('HTTP/sapsso.corp.example.com');\r\n * if (error) {\r\n * console.error('Failed to get SPNEGO token:', error.message);\r\n * return;\r\n * }\r\n *\r\n * // Use in Authorization header\r\n * fetch(url, {\r\n * headers: {\r\n * Authorization: `Negotiate ${token}`\r\n * }\r\n * });\r\n * ```\r\n */\r\nexport async function getSpnegoToken(servicePrincipalName: string): AsyncResult<string> {\r\n const [kerberos, loadErr] = await loadKerberosModule();\r\n if (loadErr) return err(loadErr);\r\n\r\n try {\r\n // Initialize Kerberos client for the given SPN\r\n const client = await kerberos.initializeClient(servicePrincipalName);\r\n\r\n // Step with empty token to get initial SPNEGO token\r\n const token = await client.step('');\r\n\r\n if (!token) {\r\n return err(new Error('Failed to generate SPNEGO token: empty response'));\r\n }\r\n\r\n return ok(token);\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n return err(new Error(`Kerberos authentication failed: ${message}`));\r\n }\r\n}\r\n\r\n/**\r\n * Extract SPN from SLS URL\r\n *\r\n * Generates HTTP service principal name from the SLS URL hostname.\r\n *\r\n * @param slsUrl - SLS server URL\r\n * @returns Service principal name (e.g., HTTP/hostname.example.com)\r\n *\r\n * @example\r\n * ```typescript\r\n * const spn = extractSpnFromUrl('https://sapsso.corp.example.com:443');\r\n * // Returns: 'HTTP/sapsso.corp.example.com'\r\n * ```\r\n */\r\nexport function extractSpnFromUrl(slsUrl: string): string {\r\n const url = new URL(slsUrl);\r\n return `HTTP/${url.hostname}`;\r\n}\r\n","/**\r\n * Certificate generation for SSO authentication\r\n *\r\n * Generates RSA keypairs and PKCS#10 Certificate Signing Requests (CSR)\r\n * for SAP Secure Login Server certificate enrollment.\r\n */\r\n\r\nimport forge from 'node-forge';\r\nimport { SLS_DEFAULTS } from './types';\r\n\r\n/**\r\n * Generated keypair with private key in PEM format\r\n */\r\nexport interface GeneratedKeypair {\r\n /** Private key in PEM format (PKCS#8) */\r\n privateKeyPem: string;\r\n /** forge private key object for signing */\r\n privateKey: forge.pki.rsa.PrivateKey;\r\n /** forge public key object */\r\n publicKey: forge.pki.rsa.PublicKey;\r\n}\r\n\r\n/**\r\n * Generate an RSA keypair\r\n *\r\n * @param keySize - Key size in bits (default: 2048)\r\n * @returns Generated keypair with PEM-encoded private key\r\n *\r\n * @example\r\n * ```typescript\r\n * const keypair = generateKeypair(2048);\r\n * console.log(keypair.privateKeyPem);\r\n * ```\r\n */\r\nexport function generateKeypair(keySize: number = SLS_DEFAULTS.KEY_SIZE): GeneratedKeypair {\r\n const keypair = forge.pki.rsa.generateKeyPair({ bits: keySize, e: 0x10001 });\r\n\r\n const privateKeyPem = forge.pki.privateKeyToPem(keypair.privateKey);\r\n\r\n return {\r\n privateKeyPem,\r\n privateKey: keypair.privateKey,\r\n publicKey: keypair.publicKey,\r\n };\r\n}\r\n\r\n/**\r\n * Create a Certificate Signing Request (CSR)\r\n *\r\n * Generates a PKCS#10 CSR with:\r\n * - Subject: CN=<username>\r\n * - Key Usage: digitalSignature, keyEncipherment\r\n * - Extended Key Usage: clientAuth (OID 1.3.6.1.5.5.7.3.2)\r\n *\r\n * @param keypair - RSA keypair to use for the CSR\r\n * @param username - Username for the certificate subject (CN)\r\n * @returns DER-encoded CSR as Buffer\r\n *\r\n * @example\r\n * ```typescript\r\n * const keypair = generateKeypair(2048);\r\n * const csrDer = createCsr(keypair, 'JOHNDOE');\r\n * ```\r\n */\r\nexport function createCsr(keypair: GeneratedKeypair, username: string): Buffer {\r\n const csr = forge.pki.createCertificationRequest();\r\n\r\n // Set subject (Common Name = username)\r\n csr.publicKey = keypair.publicKey;\r\n csr.setSubject([{\r\n name: 'commonName',\r\n value: username,\r\n }]);\r\n\r\n // Add Key Usage extension\r\n csr.setAttributes([{\r\n name: 'extensionRequest',\r\n extensions: [\r\n {\r\n name: 'keyUsage',\r\n digitalSignature: true,\r\n keyEncipherment: true,\r\n },\r\n {\r\n name: 'extKeyUsage',\r\n clientAuth: true,\r\n },\r\n ],\r\n }]);\r\n\r\n // Sign the CSR with SHA-256\r\n csr.sign(keypair.privateKey, forge.md.sha256.create());\r\n\r\n // Convert to DER format\r\n const csrAsn1 = forge.pki.certificationRequestToAsn1(csr);\r\n const csrDer = forge.asn1.toDer(csrAsn1);\r\n\r\n return Buffer.from(csrDer.getBytes(), 'binary');\r\n}\r\n\r\n/**\r\n * Get current Windows username\r\n *\r\n * @returns Username from environment or 'unknown'\r\n */\r\nexport function getCurrentUsername(): string {\r\n return process.env['USERNAME'] ?? process.env['USER'] ?? 'unknown';\r\n}\r\n","/**\r\n * PKCS#7 certificate parsing\r\n *\r\n * Parses PKCS#7 SignedData structures returned by SAP Secure Login Server\r\n * to extract client certificates and CA chain.\r\n */\r\n\r\nimport forge from 'node-forge';\r\nimport type { Result } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\n\r\n/**\r\n * Parsed certificate chain\r\n */\r\nexport interface ParsedCertificates {\r\n /** PEM-encoded client certificate + CA chain */\r\n fullChain: string;\r\n /** PEM-encoded client certificate only */\r\n clientCert: string;\r\n /** PEM-encoded CA chain (intermediate + root) */\r\n caChain: string;\r\n}\r\n\r\n/**\r\n * Parse PKCS#7 certificate data from SLS response\r\n *\r\n * SLS returns a base64-encoded PKCS#7 structure containing:\r\n * - Client certificate (first cert)\r\n * - CA certificate chain (remaining certs)\r\n *\r\n * @param data - Raw response data from SLS (may be base64-encoded)\r\n * @returns Parsed certificates or error\r\n *\r\n * @example\r\n * ```typescript\r\n * const [certs, error] = parsePkcs7Certificates(responseBuffer);\r\n * if (error) {\r\n * console.error('Parse failed:', error.message);\r\n * return;\r\n * }\r\n *\r\n * console.log(certs.clientCert); // PEM client cert\r\n * console.log(certs.caChain); // PEM CA chain\r\n * console.log(certs.fullChain); // Both combined\r\n * ```\r\n */\r\nexport function parsePkcs7Certificates(data: Buffer): Result<ParsedCertificates> {\r\n try {\r\n // Clean and decode the data\r\n // SLS returns base64-encoded PKCS#7 with possible whitespace\r\n const dataString = data.toString('utf-8').replace(/\\r?\\n/g, '').trim();\r\n const derBytes = forge.util.decode64(dataString);\r\n\r\n // Parse PKCS#7 structure\r\n const p7Asn1 = forge.asn1.fromDer(derBytes);\r\n const p7 = forge.pkcs7.messageFromAsn1(p7Asn1);\r\n\r\n // Extract certificates from SignedData\r\n if (!('certificates' in p7) || !p7.certificates || p7.certificates.length === 0) {\r\n return err(new Error('No certificates found in PKCS#7 structure'));\r\n }\r\n\r\n const certificates = p7.certificates as forge.pki.Certificate[];\r\n\r\n // First certificate is the client cert, rest are CA chain\r\n const clientCert = certificates[0];\r\n const caCerts = certificates.slice(1);\r\n\r\n if (!clientCert) {\r\n return err(new Error('No client certificate found in PKCS#7 structure'));\r\n }\r\n\r\n // Convert to PEM format\r\n const clientCertPem = forge.pki.certificateToPem(clientCert);\r\n const caChainPem = caCerts\r\n .map(cert => forge.pki.certificateToPem(cert))\r\n .join('');\r\n\r\n return ok({\r\n clientCert: clientCertPem,\r\n caChain: caChainPem,\r\n fullChain: clientCertPem + caChainPem,\r\n });\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n return err(new Error(`Failed to parse PKCS#7 certificates: ${message}`));\r\n }\r\n}\r\n","/**\r\n * Certificate storage\r\n *\r\n * Persists and retrieves mTLS certificates from the filesystem.\r\n */\r\n\r\nimport { readFile, writeFile, mkdir, stat } from 'node:fs/promises';\r\nimport { join } from 'node:path';\r\nimport type { AsyncResult, Result } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { CertificateMaterial, CertificatePaths } from './types';\r\nimport { CERTIFICATE_STORAGE } from './types';\r\nimport { getCurrentUsername } from './certificate';\r\n\r\n/**\r\n * Get certificate file paths for a user\r\n *\r\n * @param username - Username (defaults to current user)\r\n * @returns Certificate file paths\r\n */\r\nexport function getCertificatePaths(username?: string): CertificatePaths {\r\n const user = username ?? getCurrentUsername();\r\n return {\r\n fullChainPath: join(CERTIFICATE_STORAGE.BASE_DIR, `${user}${CERTIFICATE_STORAGE.FULL_CHAIN_SUFFIX}`),\r\n keyPath: join(CERTIFICATE_STORAGE.BASE_DIR, `${user}${CERTIFICATE_STORAGE.KEY_SUFFIX}`),\r\n };\r\n}\r\n\r\n/**\r\n * Save certificates to filesystem\r\n *\r\n * @param material - Certificate material to save\r\n * @param username - Username (defaults to current user)\r\n * @returns File paths or error\r\n *\r\n * @example\r\n * ```typescript\r\n * const [paths, error] = await saveCertificates(material);\r\n * if (error) {\r\n * console.error('Save failed:', error.message);\r\n * return;\r\n * }\r\n *\r\n * console.log('Saved to:', paths.fullChainPath, paths.keyPath);\r\n * ```\r\n */\r\nexport async function saveCertificates(\r\n material: CertificateMaterial,\r\n username?: string\r\n): AsyncResult<CertificatePaths> {\r\n const paths = getCertificatePaths(username);\r\n\r\n try {\r\n // Ensure directory exists\r\n await mkdir(CERTIFICATE_STORAGE.BASE_DIR, { recursive: true });\r\n\r\n // Write certificate files\r\n await writeFile(paths.fullChainPath, material.fullChain, 'utf-8');\r\n await writeFile(paths.keyPath, material.privateKey, { encoding: 'utf-8', mode: 0o600 });\r\n\r\n return ok(paths);\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n return err(new Error(`Failed to save certificates: ${message}`));\r\n }\r\n}\r\n\r\n/**\r\n * Load certificates from filesystem\r\n *\r\n * @param username - Username (defaults to current user)\r\n * @returns Certificate material or error\r\n *\r\n * @example\r\n * ```typescript\r\n * const [material, error] = await loadCertificates();\r\n * if (error) {\r\n * // Certificates don't exist, need to enroll\r\n * return;\r\n * }\r\n *\r\n * // Use loaded certificates\r\n * ```\r\n */\r\nexport async function loadCertificates(username?: string): AsyncResult<CertificateMaterial> {\r\n const paths = getCertificatePaths(username);\r\n\r\n try {\r\n const [fullChain, privateKey] = await Promise.all([\r\n readFile(paths.fullChainPath, 'utf-8'),\r\n readFile(paths.keyPath, 'utf-8'),\r\n ]);\r\n\r\n return ok({ fullChain, privateKey });\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n return err(new Error(`Failed to load certificates: ${message}`));\r\n }\r\n}\r\n\r\n/**\r\n * Check if certificates exist for a user\r\n *\r\n * @param username - Username (defaults to current user)\r\n * @returns True if certificates exist\r\n */\r\nexport async function certificatesExist(username?: string): Promise<boolean> {\r\n const paths = getCertificatePaths(username);\r\n\r\n try {\r\n await Promise.all([\r\n stat(paths.fullChainPath),\r\n stat(paths.keyPath),\r\n ]);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Check if a certificate is expired or will expire soon\r\n *\r\n * @param certPem - PEM-encoded certificate\r\n * @param bufferDays - Days before expiry to consider as \"expiring soon\" (default: 1)\r\n * @returns True if expired or expiring soon\r\n */\r\nexport function isCertificateExpired(certPem: string, bufferDays: number = 1): Result<boolean> {\r\n try {\r\n // Import forge dynamically to avoid loading it if not needed\r\n // eslint-disable-next-line @typescript-eslint/no-require-imports\r\n const forge = require('node-forge');\r\n\r\n const cert = forge.pki.certificateFromPem(certPem);\r\n const notAfter = cert.validity.notAfter as Date;\r\n const bufferMs = bufferDays * 24 * 60 * 60 * 1000;\r\n const expiryThreshold = new Date(Date.now() + bufferMs);\r\n\r\n return ok(notAfter <= expiryThreshold);\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error);\r\n return err(new Error(`Failed to check certificate expiry: ${message}`));\r\n }\r\n}\r\n","/**\r\n * SSO (Single Sign-On) authentication strategy\r\n *\r\n * Implements Kerberos-based SSO for SAP systems using mTLS certificates\r\n * obtained from SAP Secure Login Server (SLS).\r\n *\r\n * Authentication flow:\r\n * 1. Check for existing valid certificates\r\n * 2. If missing or expired, enroll new certificate via SLS\r\n * 3. Use mTLS for all subsequent ADT requests\r\n *\r\n * Platform support:\r\n * - Windows: Uses SSPI for Kerberos (requires Active Directory)\r\n * - Linux/macOS: Uses MIT Kerberos (requires kinit)\r\n *\r\n * @example\r\n * ```typescript\r\n * const auth = new SsoAuth({\r\n * slsUrl: 'https://sapsso.corp.example.com',\r\n * });\r\n *\r\n * // Enroll certificate (or load from cache)\r\n * const [, error] = await auth.performLogin(fetch);\r\n * if (error) {\r\n * console.error('SSO failed:', error.message);\r\n * return;\r\n * }\r\n *\r\n * // Get certificates for mTLS\r\n * const certs = auth.getCertificates();\r\n * ```\r\n */\r\n\r\nimport type { AuthStrategy } from '../types';\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { SlsConfig, CertificateMaterial } from './types';\r\nimport { enrollCertificate } from './slsClient';\r\nimport { loadCertificates, saveCertificates, certificatesExist, isCertificateExpired } from './storage';\r\n\r\n/**\r\n * SSO authentication configuration\r\n */\r\nexport interface SsoAuthConfig {\r\n /** Secure Login Server URL */\r\n slsUrl: string;\r\n /** SLS profile (default: SAPSSO_P) */\r\n profile?: string;\r\n /** Service principal name override */\r\n servicePrincipalName?: string;\r\n /** Skip SSL verification (required for most corporate environments) */\r\n insecure?: boolean;\r\n /** Force certificate re-enrollment even if valid cert exists */\r\n forceEnroll?: boolean;\r\n /** Return certificate contents instead of saving to files */\r\n returnContents?: boolean;\r\n}\r\n\r\n/**\r\n * SSO authentication strategy using Kerberos and mTLS\r\n */\r\nexport class SsoAuth implements AuthStrategy {\r\n readonly type = 'sso' as const;\r\n private config: SsoAuthConfig;\r\n private certificates: CertificateMaterial | null = null;\r\n\r\n /**\r\n * Create an SSO Auth strategy\r\n *\r\n * @param config - SSO authentication configuration\r\n */\r\n constructor(config: SsoAuthConfig) {\r\n if (!config.slsUrl) {\r\n throw new Error('SsoAuth requires slsUrl');\r\n }\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Get auth headers for SSO\r\n *\r\n * SSO uses mTLS for authentication, not headers.\r\n * Returns empty headers - the mTLS agent handles auth.\r\n */\r\n getAuthHeaders(): Record<string, string> {\r\n return {};\r\n }\r\n\r\n /**\r\n * Get mTLS certificates\r\n *\r\n * Returns the certificate material after successful login.\r\n * Used by ADT client to create an mTLS agent.\r\n *\r\n * @returns Certificate material or null if not enrolled\r\n */\r\n getCertificates(): CertificateMaterial | null {\r\n return this.certificates;\r\n }\r\n\r\n /**\r\n * Perform SSO login via certificate enrollment\r\n *\r\n * Checks for existing valid certificates and enrolls new ones if needed.\r\n *\r\n * @param _fetchFn - Unused, kept for interface compatibility\r\n * @returns Success/error tuple\r\n */\r\n async performLogin(_fetchFn: typeof fetch): AsyncResult<void, Error> {\r\n // Check for existing certificates\r\n if (!this.config.forceEnroll) {\r\n const [loadResult, loadErr] = await this.tryLoadExistingCertificates();\r\n if (!loadErr && loadResult) {\r\n this.certificates = loadResult;\r\n return ok(undefined);\r\n }\r\n }\r\n\r\n // Enroll new certificate\r\n const slsConfig: SlsConfig = {\r\n slsUrl: this.config.slsUrl,\r\n };\r\n if (this.config.profile) {\r\n slsConfig.profile = this.config.profile;\r\n }\r\n if (this.config.servicePrincipalName) {\r\n slsConfig.servicePrincipalName = this.config.servicePrincipalName;\r\n }\r\n\r\n const [material, enrollErr] = await enrollCertificate({\r\n config: slsConfig,\r\n insecure: this.config.insecure ?? false,\r\n });\r\n\r\n if (enrollErr) {\r\n return err(enrollErr);\r\n }\r\n\r\n // Save certificates to filesystem (unless returnContents is true)\r\n if (!this.config.returnContents) {\r\n const [, saveErr] = await saveCertificates(material);\r\n if (saveErr) {\r\n return err(saveErr);\r\n }\r\n }\r\n\r\n this.certificates = material;\r\n return ok(undefined);\r\n }\r\n\r\n /**\r\n * Try to load and validate existing certificates\r\n */\r\n private async tryLoadExistingCertificates(): AsyncResult<CertificateMaterial> {\r\n // Check if files exist\r\n const exists = await certificatesExist();\r\n if (!exists) {\r\n return err(new Error('No existing certificates found'));\r\n }\r\n\r\n // Load certificates\r\n const [material, loadErr] = await loadCertificates();\r\n if (loadErr) {\r\n return err(loadErr);\r\n }\r\n\r\n // Check expiry\r\n const [isExpired, expiryErr] = isCertificateExpired(material.fullChain);\r\n if (expiryErr) {\r\n return err(expiryErr);\r\n }\r\n\r\n if (isExpired) {\r\n return err(new Error('Certificate is expired or expiring soon'));\r\n }\r\n\r\n return ok(material);\r\n }\r\n}\r\n","/**\r\n * SAML authentication types\r\n *\r\n * Defines provider configurations and form selectors for SAML browser automation.\r\n */\r\n\r\n/**\r\n * CSS selectors for login form elements\r\n *\r\n * Used by Playwright to locate and fill login form fields.\r\n */\r\nexport interface FormSelectors {\r\n /** CSS selector for username input field */\r\n username: string;\r\n /** CSS selector for password input field */\r\n password: string;\r\n /** CSS selector for submit button */\r\n submit: string;\r\n}\r\n\r\n/**\r\n * Default SAP IDP form selectors\r\n *\r\n * Used when no custom selectors are configured for a system.\r\n */\r\nexport const DEFAULT_FORM_SELECTORS: FormSelectors = {\r\n username: '#j_username',\r\n password: '#j_password',\r\n submit: '#logOnFormSubmit',\r\n};\r\n\r\n/**\r\n * Configuration for a SAML provider\r\n *\r\n * Defines how to interact with a specific SAP system's login page.\r\n */\r\nexport interface SamlProviderConfig {\r\n /** Whether to ignore HTTPS certificate errors */\r\n ignoreHttpsErrors: boolean;\r\n /** CSS selectors for login form elements */\r\n formSelectors: FormSelectors;\r\n}\r\n\r\n/**\r\n * Default SAML provider configuration\r\n *\r\n * Used when no SAML config is specified for a system.\r\n */\r\nexport const DEFAULT_PROVIDER_CONFIG: SamlProviderConfig = {\r\n ignoreHttpsErrors: false,\r\n formSelectors: DEFAULT_FORM_SELECTORS,\r\n};\r\n\r\n/**\r\n * Playwright cookie structure\r\n *\r\n * Matches Playwright's Cookie type for interoperability.\r\n */\r\nexport interface PlaywrightCookie {\r\n name: string;\r\n value: string;\r\n domain: string;\r\n path: string;\r\n expires: number;\r\n httpOnly: boolean;\r\n secure: boolean;\r\n sameSite: 'Strict' | 'Lax' | 'None';\r\n}\r\n\r\n/**\r\n * Result of SAML browser login\r\n */\r\nexport interface SamlLoginResult {\r\n /** Session cookies from successful login */\r\n cookies: PlaywrightCookie[];\r\n}\r\n","/**\r\n * SAML browser automation\r\n *\r\n * Implements headless browser login flow using Playwright.\r\n * Dynamically imports Playwright to avoid requiring it when not using SAML.\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { PlaywrightCookie, SamlProviderConfig } from './types';\r\nimport { DEFAULT_PROVIDER_CONFIG } from './types';\r\n\r\n/** Timeouts for browser automation */\r\nconst TIMEOUTS = {\r\n PAGE_LOAD: 60_000,\r\n FORM_SELECTOR: 10_000,\r\n} as const;\r\n\r\n/**\r\n * Credentials for SAML login\r\n */\r\nexport interface SamlCredentials {\r\n username: string;\r\n password: string;\r\n}\r\n\r\n/**\r\n * Options for SAML browser login\r\n */\r\nexport interface SamlBrowserLoginOptions {\r\n /** SAP system base URL */\r\n baseUrl: string;\r\n /** Login credentials */\r\n credentials: SamlCredentials;\r\n /** Optional custom provider config (overrides auto-detection) */\r\n providerConfig?: SamlProviderConfig;\r\n /** Whether to run browser in headless mode (default: true) */\r\n headless?: boolean;\r\n}\r\n\r\n/**\r\n * Perform SAML login using headless browser automation\r\n *\r\n * Launches a Chromium browser, navigates to the SAP login page,\r\n * fills in credentials, and extracts session cookies.\r\n *\r\n * @param options - Login options including URL and credentials\r\n * @returns Session cookies on success, error on failure\r\n *\r\n * @example\r\n * ```typescript\r\n * const [cookies, error] = await performBrowserLogin({\r\n * baseUrl: 'https://sap-system.example.com',\r\n * credentials: { username: 'user@example.com', password: 'secret' }\r\n * });\r\n * if (error) {\r\n * console.error('Login failed:', error.message);\r\n * return;\r\n * }\r\n * // Use cookies for authenticated requests\r\n * ```\r\n */\r\nexport async function performBrowserLogin(\r\n options: SamlBrowserLoginOptions\r\n): AsyncResult<PlaywrightCookie[], Error> {\r\n const { baseUrl, credentials, headless = true } = options;\r\n const config = options.providerConfig ?? DEFAULT_PROVIDER_CONFIG;\r\n\r\n // Dynamically import Playwright to avoid requiring it when not using SAML.\r\n let playwright;\r\n try {\r\n playwright = await import('playwright');\r\n } catch {\r\n return err(\r\n new Error(\r\n 'Playwright is required for SAML authentication but is not installed. ' +\r\n 'Install it with: npm install playwright'\r\n )\r\n );\r\n }\r\n\r\n const browserArgs = config.ignoreHttpsErrors\r\n ? ['--ignore-certificate-errors', '--disable-web-security']\r\n : [];\r\n\r\n let browser;\r\n try {\r\n browser = await playwright.chromium.launch({\r\n headless,\r\n args: browserArgs,\r\n });\r\n } catch (launchError) {\r\n return err(\r\n new Error(\r\n `Failed to launch browser: ${launchError instanceof Error ? launchError.message : String(launchError)}`\r\n )\r\n );\r\n }\r\n\r\n try {\r\n const context = await browser.newContext({\r\n ignoreHTTPSErrors: config.ignoreHttpsErrors,\r\n });\r\n const page = await context.newPage();\r\n\r\n // Navigate to SAP login page.\r\n const loginUrl = `${baseUrl}/sap/bc/adt/compatibility/graph`;\r\n try {\r\n await page.goto(loginUrl, {\r\n timeout: TIMEOUTS.PAGE_LOAD,\r\n waitUntil: 'domcontentloaded',\r\n });\r\n } catch {\r\n return err(new Error('Failed to load login page. Please check if the server is online.'));\r\n }\r\n\r\n // Wait for and fill login form.\r\n try {\r\n await page.waitForSelector(config.formSelectors.username, {\r\n timeout: TIMEOUTS.FORM_SELECTOR,\r\n });\r\n } catch {\r\n return err(new Error('Login form not found. The page may have changed or loaded incorrectly.'));\r\n }\r\n\r\n await page.fill(config.formSelectors.username, credentials.username);\r\n await page.fill(config.formSelectors.password, credentials.password);\r\n await page.click(config.formSelectors.submit);\r\n\r\n // Wait for login to complete.\r\n await page.waitForLoadState('networkidle');\r\n\r\n // Extract cookies.\r\n const cookies = await context.cookies();\r\n\r\n return ok(cookies as PlaywrightCookie[]);\r\n } finally {\r\n await browser.close();\r\n }\r\n}\r\n","/**\r\n * Cookie extraction and formatting for SAML authentication\r\n *\r\n * Converts Playwright cookies to AuthCookie format used by the rest of the codebase.\r\n */\r\n\r\nimport type { AuthCookie } from '../types';\r\nimport type { PlaywrightCookie } from './types';\r\n\r\n/**\r\n * Convert Playwright cookies to AuthCookie format\r\n *\r\n * @param playwrightCookies - Cookies from Playwright browser context\r\n * @returns Array of AuthCookie objects\r\n */\r\nexport function toAuthCookies(playwrightCookies: PlaywrightCookie[]): AuthCookie[] {\r\n return playwrightCookies.map((cookie) => ({\r\n name: cookie.name,\r\n value: cookie.value,\r\n domain: cookie.domain,\r\n path: cookie.path,\r\n }));\r\n}\r\n\r\n/**\r\n * Format cookies as Cookie header value\r\n *\r\n * @param cookies - Array of AuthCookie objects\r\n * @returns Cookie header string (e.g., \"name1=value1; name2=value2\")\r\n */\r\nexport function formatCookieHeader(cookies: AuthCookie[]): string {\r\n return cookies.map((c) => `${c.name}=${c.value}`).join('; ');\r\n}\r\n","/**\r\n * SAML authentication strategy\r\n *\r\n * Implements SAML-based SSO for SAP systems using browser automation.\r\n * Requires Playwright for headless browser login.\r\n *\r\n * @example\r\n * ```typescript\r\n * // With default SAP IDP selectors\r\n * const auth = new SamlAuth({\r\n * username: 'user@example.com',\r\n * password: 'secret',\r\n * baseUrl: 'https://sap-system.example.com',\r\n * });\r\n *\r\n * // With custom form selectors\r\n * const auth = new SamlAuth({\r\n * username: 'user@example.com',\r\n * password: 'secret',\r\n * baseUrl: 'https://sap-system.example.com',\r\n * providerConfig: {\r\n * ignoreHttpsErrors: true,\r\n * formSelectors: {\r\n * username: '#custom-user-field',\r\n * password: '#custom-pass-field',\r\n * submit: '#custom-submit-btn',\r\n * },\r\n * },\r\n * });\r\n *\r\n * // Perform login\r\n * const [, error] = await auth.performLogin(fetch);\r\n * if (error) {\r\n * console.error('Login failed:', error.message);\r\n * }\r\n * ```\r\n */\r\n\r\nimport type { AuthStrategy, AuthCookie } from '../types';\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { SamlProviderConfig } from './types';\r\nimport { performBrowserLogin } from './browser';\r\nimport { toAuthCookies, formatCookieHeader } from './cookies';\r\n\r\n/**\r\n * Configuration for SAML authentication\r\n */\r\nexport interface SamlAuthConfig {\r\n /** SAML username (often an email address) - used for browser login */\r\n username: string;\r\n /** SAML password */\r\n password: string;\r\n /** SAP system username - used for object creation (adtcore:responsible) */\r\n sapUser: string;\r\n /** SAP system base URL */\r\n baseUrl: string;\r\n /** Optional custom provider configuration */\r\n providerConfig?: SamlProviderConfig;\r\n}\r\n\r\n/**\r\n * SAML authentication strategy\r\n */\r\nexport class SamlAuth implements AuthStrategy {\r\n readonly type = 'saml' as const;\r\n private cookies: AuthCookie[] = [];\r\n private config: SamlAuthConfig;\r\n\r\n /**\r\n * Create a SAML Auth strategy\r\n *\r\n * @param config - SAML authentication configuration\r\n */\r\n constructor(config: SamlAuthConfig) {\r\n if (!config.username || !config.password) {\r\n throw new Error('SamlAuth requires both username and password');\r\n }\r\n if (!config.sapUser) {\r\n throw new Error('SamlAuth requires sapUser (SAP system username for object creation)');\r\n }\r\n if (!config.baseUrl) {\r\n throw new Error('SamlAuth requires baseUrl');\r\n }\r\n this.config = config;\r\n }\r\n\r\n /**\r\n * Get SAP system username\r\n *\r\n * Used for object creation (adtcore:responsible) instead of the SAML email.\r\n */\r\n getSapUser(): string {\r\n return this.config.sapUser;\r\n }\r\n\r\n /**\r\n * Get auth headers for SAML\r\n *\r\n * After successful login, includes Cookie header with session cookies.\r\n */\r\n getAuthHeaders(): Record<string, string> {\r\n if (this.cookies.length === 0) {\r\n return {};\r\n }\r\n return {\r\n Cookie: formatCookieHeader(this.cookies),\r\n };\r\n }\r\n\r\n /**\r\n * Get authentication cookies\r\n *\r\n * @returns Array of cookies obtained during SAML login\r\n */\r\n getCookies(): AuthCookie[] {\r\n return this.cookies;\r\n }\r\n\r\n /**\r\n * Perform SAML login using headless browser automation\r\n *\r\n * Launches a Chromium browser, navigates to the SAP login page,\r\n * fills in credentials, and extracts session cookies.\r\n *\r\n * @param _fetchFn - Unused, kept for interface compatibility\r\n * @returns Success/error tuple\r\n */\r\n async performLogin(_fetchFn: typeof fetch): AsyncResult<void, Error> {\r\n const [playwrightCookies, loginError] = await performBrowserLogin({\r\n baseUrl: this.config.baseUrl,\r\n credentials: {\r\n username: this.config.username,\r\n password: this.config.password,\r\n },\r\n ...(this.config.providerConfig && { providerConfig: this.config.providerConfig }),\r\n });\r\n\r\n if (loginError) {\r\n return err(loginError);\r\n }\r\n\r\n this.cookies = toAuthCookies(playwrightCookies);\r\n\r\n if (this.cookies.length === 0) {\r\n return err(new Error('SAML login succeeded but no cookies were returned'));\r\n }\r\n\r\n return ok(undefined);\r\n }\r\n}\r\n","import type { AuthConfig } from '../../types/config';\r\nimport type { AuthStrategy } from './types';\r\nimport { BasicAuth } from './basic';\r\nimport { SsoAuth, type SsoAuthConfig } from './sso';\r\nimport { SamlAuth } from './saml';\r\n\r\n/**\r\n * Options for creating an authentication strategy\r\n */\r\nexport interface CreateAuthOptions {\r\n /** Authentication configuration */\r\n config: AuthConfig;\r\n /** Base URL of the SAP system (required for SAML) */\r\n baseUrl?: string;\r\n /** Skip SSL verification (dev only) */\r\n insecure?: boolean;\r\n}\r\n\r\n/**\r\n * Create an authentication strategy based on configuration\r\n *\r\n * Factory function that instantiates the appropriate auth strategy\r\n * based on the auth config type (basic, saml, or sso).\r\n *\r\n * @param options - Authentication options including config and optional baseUrl\r\n * @returns Configured authentication strategy\r\n * @throws Error if config type is invalid or required fields are missing\r\n *\r\n * @example\r\n * ```typescript\r\n * // Basic auth\r\n * const auth = createAuthStrategy({\r\n * config: { type: 'basic', username: 'DEVELOPER', password: 'secret' }\r\n * });\r\n *\r\n * // SAML auth (requires baseUrl)\r\n * const auth = createAuthStrategy({\r\n * config: { type: 'saml', username: 'user@example.com', password: 'secret' },\r\n * baseUrl: 'https://sap-system.example.com'\r\n * });\r\n *\r\n * // SSO auth (Kerberos + mTLS)\r\n * const auth = createAuthStrategy({\r\n * config: {\r\n * type: 'sso',\r\n * slsUrl: 'https://sapsso.corp.example.com'\r\n * },\r\n * insecure: true\r\n * });\r\n * ```\r\n */\r\nexport function createAuthStrategy(options: CreateAuthOptions): AuthStrategy {\r\n const { config, baseUrl, insecure } = options;\r\n\r\n switch (config.type) {\r\n case 'basic':\r\n return new BasicAuth(config.username, config.password);\r\n\r\n case 'saml':\r\n if (!baseUrl) {\r\n throw new Error('SAML authentication requires baseUrl');\r\n }\r\n return new SamlAuth({\r\n username: config.username,\r\n password: config.password,\r\n sapUser: config.sapUser,\r\n baseUrl,\r\n ...(config.providerConfig && { providerConfig: config.providerConfig }),\r\n });\r\n\r\n case 'sso': {\r\n const ssoConfig: SsoAuthConfig = {\r\n slsUrl: config.slsUrl,\r\n };\r\n if (config.profile) {\r\n ssoConfig.profile = config.profile;\r\n }\r\n if (config.servicePrincipalName) {\r\n ssoConfig.servicePrincipalName = config.servicePrincipalName;\r\n }\r\n if (config.forceEnroll) {\r\n ssoConfig.forceEnroll = config.forceEnroll;\r\n }\r\n if (insecure) {\r\n ssoConfig.insecure = insecure;\r\n }\r\n return new SsoAuth(ssoConfig);\r\n }\r\n\r\n default: {\r\n const _exhaustive: never = config;\r\n throw new Error(`Unknown auth type: ${(_exhaustive as AuthConfig).type}`);\r\n }\r\n }\r\n}\r\n","/**\r\n * Session management type definitions\r\n */\r\n\r\nimport type { AuthType } from '../../types';\r\n\r\n/**\r\n * Session data returned after successful login\r\n */\r\nexport interface Session {\r\n /** Unique session identifier */\r\n sessionId: string;\r\n /** Authenticated username */\r\n username: string;\r\n /** Session expiration timestamp */\r\n expiresAt: number;\r\n}\r\n\r\n/**\r\n * Session entry stored in memory\r\n */\r\nexport interface SessionEntry {\r\n /** The ADT client instance (typed as unknown until client is implemented) */\r\n client: unknown;\r\n /** Last activity timestamp for timeout tracking */\r\n lastActivity: Date;\r\n /** Authentication type used for this session */\r\n authType: AuthType;\r\n}\r\n\r\n/**\r\n * Configuration for session manager\r\n *\r\n * Session timeouts vary by authentication type:\r\n * - Basic: 3 hours (SAP server default)\r\n * - SSO: 3 hours (certificate-based, same as basic)\r\n * - SAML: 30 minutes (IDP session typically shorter)\r\n */\r\nexport interface SessionConfig {\r\n /** Session timeout in seconds for Basic and SSO auth (default: 10800 = 3 hours) */\r\n sessionTimeout: number;\r\n /** Session timeout in seconds for SAML auth (default: 1800 = 30 minutes) */\r\n samlSessionTimeout: number;\r\n /** Cleanup interval in seconds (default: 60) */\r\n cleanupInterval: number;\r\n}\r\n\r\n/**\r\n * Default session configuration values\r\n */\r\nexport const DEFAULT_SESSION_CONFIG: SessionConfig = {\r\n sessionTimeout: 10800, // 3 hours (Basic/SSO)\r\n samlSessionTimeout: 1800, // 30 minutes (SAML)\r\n cleanupInterval: 60, // 1 minute\r\n};\r\n\r\n/**\r\n * Serializable session state for export/import across processes\r\n *\r\n * Used to transfer authenticated session state from daemon to CLI processes,\r\n * allowing session reuse without re-authentication.\r\n */\r\nexport interface ExportableSessionState {\r\n csrfToken: string;\r\n session: Session;\r\n cookies: Array<{ name: string; value: string }>;\r\n authType: AuthType;\r\n ssoCertPaths?: { fullChainPath: string; keyPath: string };\r\n}\r\n","/**\n * XML Parsing Utilities\n *\n * Secure XML parsing and manipulation for ADT responses.\n * Uses @xmldom/xmldom for cross-platform XML parsing.\n */\n\nimport { DOMParser } from '@xmldom/xmldom';\nimport type { Result } from '../../types/result';\nimport { ok, err } from '../../types/result';\n\n/**\n * Securely parse XML string into a Document object (throws on error)\n *\n * @param xmlString - The XML string to parse\n * @returns Parsed XML Document\n * @throws Error if XML is malformed\n * @deprecated Use safeParseXml for Result-based error handling\n */\nexport function parseXml(xmlString: string): Document {\n if (!xmlString || xmlString.trim().length === 0) {\n throw new Error('Empty XML string provided');\n }\n\n const parser = new DOMParser();\n const doc = parser.parseFromString(xmlString, 'text/xml');\n\n // Check for parser errors\n const parseError = doc.getElementsByTagName('parsererror');\n if (parseError.length > 0) {\n const errorNode = parseError[0];\n const errorText = errorNode?.textContent || 'Unknown XML parsing error';\n throw new Error(`XML parsing failed: ${errorText}`);\n }\n\n return doc;\n}\n\n/**\n * Safely parse XML string into a Document object\n *\n * @param xmlString - The XML string to parse\n * @returns Result tuple with Document or Error\n */\nexport function safeParseXml(xmlString: string): Result<Document, Error> {\n // Validate input.\n if (!xmlString || xmlString.trim().length === 0) {\n return err(new Error('Empty XML string provided'));\n }\n\n try {\n // Parse XML string.\n const parser = new DOMParser();\n const doc = parser.parseFromString(xmlString, 'text/xml');\n\n // Check for parser errors.\n const parseError = doc.getElementsByTagName('parsererror');\n if (parseError.length > 0) {\n const errorNode = parseError[0];\n const errorText = errorNode?.textContent || 'Unknown XML parsing error';\n return err(new Error(`XML parsing failed: ${errorText}`));\n }\n\n return ok(doc);\n } catch (error) {\n if (error instanceof Error) {\n return err(error);\n }\n return err(new Error('Unknown XML parsing error'));\n }\n}\n\n/**\n * Extract LOCK_HANDLE from ADT XML response\n *\n * @param xml - XML string containing lock handle\n * @returns Result tuple with lock handle or error\n */\nexport function extractLockHandle(xml: string): Result<string, Error> {\n // Validate input.\n if (!xml) {\n return err(new Error('Empty XML provided'));\n }\n\n // Parse XML response.\n const [doc, parseErr] = safeParseXml(xml);\n if (parseErr) { return err(parseErr); }\n\n // Find LOCK_HANDLE element.\n const lockHandleElements = doc.getElementsByTagName('LOCK_HANDLE');\n if (lockHandleElements.length === 0) {\n return err(new Error('LOCK_HANDLE element not found in XML'));\n }\n\n // Extract and validate lock handle value.\n const lockHandleElement = lockHandleElements[0];\n const lockHandle = lockHandleElement?.textContent;\n if (!lockHandle || lockHandle.trim().length === 0) {\n return err(new Error('LOCK_HANDLE element is empty'));\n }\n\n return ok(lockHandle.trim());\n}\n\n/**\n * Extract error message from ADT XML error response\n *\n * @param xml - XML string containing error message\n * @returns Error message or default message\n */\nexport function extractError(xml: string): string {\n // Handle empty input.\n if (!xml) {\n return 'No error message found';\n }\n\n // Parse XML response.\n const [doc, parseErr] = safeParseXml(xml);\n if (parseErr) {\n return 'Failed to parse error XML';\n }\n\n // Find message element.\n const messageElements = doc.getElementsByTagName('message');\n if (messageElements.length === 0) {\n return 'No message found';\n }\n\n // Extract message text.\n const messageElement = messageElements[0];\n const message = messageElement?.textContent;\n return message || 'No message found';\n}\n\n/**\n * Escape special XML characters\n *\n * @param str - String to escape\n * @returns XML-safe string\n */\nexport function escapeXml(str: string): string {\n // Handle empty input.\n if (!str) {\n return '';\n }\n\n // Replace special XML characters with entities.\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;');\n}\n\n/**\n * Convert a dictionary to ABAP-style XML\n *\n * This creates XML in the format expected by SAP ADT endpoints:\n * <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n * <asx:abap xmlns:asx=\"http://www.sap.com/abapxml\" version=\"1.0\">\n * <asx:values>\n * <DATA>\n * <KEY>value</KEY>\n * </DATA>\n * </asx:values>\n * </asx:abap>\n *\n * @param data - Key-value pairs to convert to XML\n * @param root - Root element name (default: \"DATA\")\n * @returns ABAP-formatted XML string\n */\nexport function dictToAbapXml(data: Record<string, string>, root: string = 'DATA'): string {\n // Build inner XML elements from key-value pairs.\n const innerElements = Object.entries(data)\n .map(([key, value]) => {\n if (value) {\n return `<${key}>${escapeXml(value)}</${key}>`;\n }\n return `<${key}/>`;\n })\n .join('\\n ');\n\n // Return complete ABAP XML structure.\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<asx:abap xmlns:asx=\"http://www.sap.com/abapxml\" version=\"1.0\">\n <asx:values>\n <${root}>\n ${innerElements}\n </${root}>\n </asx:values>\n</asx:abap>`;\n}\n","/**\n * CSRF Token Constants\n *\n * Constants for CSRF token handling with SAP ADT endpoints.\n */\n\n/**\n * Special value to request a CSRF token from the server\n *\n * When sent in the x-csrf-token header, SAP returns a valid token\n * in the response headers.\n */\nexport const FETCH_CSRF_TOKEN = 'fetch';\n\n/**\n * HTTP header name for CSRF token\n *\n * Used both for requesting tokens (with FETCH_CSRF_TOKEN value)\n * and sending tokens with authenticated requests.\n */\nexport const CSRF_TOKEN_HEADER = 'x-csrf-token';\n","/**\r\n * HTTP Header Utilities for ADT Requests\r\n *\r\n * Provides header building utilities and constants for SAP ADT HTTP requests.\r\n * Centralizes header management to avoid duplication across client code.\r\n */\r\n\r\nimport { CSRF_TOKEN_HEADER, FETCH_CSRF_TOKEN } from './csrf';\r\nimport type { AuthConfig } from '../../types/config';\r\n\r\n// Mimic Eclipse ADT plugin for compatibility\r\nexport const BASE_HEADERS = {\r\n 'Accept': '*/*',\r\n 'X-sap-adt-sessiontype': 'stateful',\r\n 'User-Agent': 'Eclipse/4.34.0 ADT/3.46.0',\r\n 'X-sap-adt-profiling': 'server-time',\r\n} as const;\r\n\r\n// Default request timeout in milliseconds\r\nexport const DEFAULT_TIMEOUT = 30000;\r\n\r\n/**\r\n * Build request headers with auth and CSRF token\r\n *\r\n * @param baseHeaders - Base headers to include in all requests\r\n * @param customHeaders - Request-specific headers\r\n * @param auth - Authentication config (for basic auth header)\r\n * @param csrfToken - Current CSRF token (if available)\r\n * @returns Combined headers object\r\n */\r\nexport function buildRequestHeaders(\r\n baseHeaders: Record<string, string>,\r\n customHeaders?: Record<string, string>,\r\n auth?: AuthConfig,\r\n csrfToken?: string | null\r\n): Record<string, string> {\r\n // Merge base and custom headers.\r\n const headers: Record<string, string> = {\r\n ...baseHeaders,\r\n ...(customHeaders ?? {}),\r\n };\r\n\r\n // Add basic auth header if using basic authentication.\r\n if (auth?.type === 'basic') {\r\n // Use btoa for base64 encoding (web standard, available in both Node 18+ and Bun)\r\n const credentials = btoa(`${auth.username}:${auth.password}`);\r\n headers['Authorization'] = `Basic ${credentials}`;\r\n }\r\n\r\n // Add CSRF token if we have one (but not the 'fetch' placeholder).\r\n // Don't overwrite if custom headers already set the CSRF token (e.g., for token refresh).\r\n if (csrfToken && csrfToken !== FETCH_CSRF_TOKEN && !customHeaders?.[CSRF_TOKEN_HEADER]) {\r\n headers[CSRF_TOKEN_HEADER] = csrfToken;\r\n }\r\n\r\n return headers;\r\n}\r\n\r\n/**\r\n * Extract CSRF token from response headers\r\n *\r\n * SAP returns token in both upper and lowercase variations,\r\n * so we need to check both.\r\n *\r\n * @param headers - Response headers from SAP ADT server\r\n * @returns Extracted CSRF token or null if not found\r\n */\r\nexport function extractCsrfToken(headers: Headers): string | null {\r\n // Try both upper and lowercase header names.\r\n const token = headers.get(CSRF_TOKEN_HEADER) ||\r\n headers.get(CSRF_TOKEN_HEADER.toLowerCase());\r\n\r\n // Ignore the fetch token itself.\r\n if (!token || token === FETCH_CSRF_TOKEN) {\r\n return null;\r\n }\r\n\r\n return token;\r\n}\r\n","/**\r\n * Logging Utility — Debug logging with activation control\r\n *\r\n * Logs are silent by default. Call activateLogging() to enable console output.\r\n */\r\n\r\nlet isActive = false;\r\n\r\n/**\r\n * Enable debug logging to console\r\n */\r\nexport function activateLogging(): void {\r\n isActive = true;\r\n}\r\n\r\n/**\r\n * Disable debug logging (default state)\r\n */\r\nexport function deactivateLogging(): void {\r\n isActive = false;\r\n}\r\n\r\n/**\r\n * Check if logging is currently active\r\n */\r\nexport function isLoggingActive(): boolean {\r\n return isActive;\r\n}\r\n\r\n/**\r\n * Log a debug message (only prints when logging is active)\r\n */\r\nexport function debug(message: string): void {\r\n if (isActive) {\r\n console.log(`[DEBUG] ${message}`);\r\n }\r\n}\r\n\r\n/**\r\n * Log a debug error message (only prints when logging is active)\r\n */\r\nexport function debugError(message: string, cause?: unknown): void {\r\n if (!isActive) return;\r\n\r\n console.error(`[DEBUG] ${message}`);\r\n if (cause !== undefined) {\r\n console.error(`[DEBUG] Cause:`, cause);\r\n }\r\n}\r\n","/**\r\n * Content normalization utilities\r\n *\r\n * Used for comparing object content between server and local versions.\r\n * SAP servers may insert whitespace variations (carriage returns, extra spaces)\r\n * that shouldn't be considered meaningful differences.\r\n */\r\n\r\n/**\r\n * Normalize content for comparison\r\n *\r\n * Replaces all consecutive whitespace (spaces, tabs, newlines, carriage returns)\r\n * with a single space. Trims leading/trailing whitespace.\r\n *\r\n * @param content - Raw content string\r\n * @returns Normalized content with single spaces\r\n */\r\nexport function normalizeContent(content: string): string {\r\n return content.replace(/\\s+/g, ' ').trim();\r\n}\r\n","/**\r\n * Session Lifecycle Operations\r\n *\r\n * Internal helpers for login/logout/session reset operations.\r\n * Used by ADTClient to manage session state.\r\n *\r\n * Handles:\r\n * - CSRF token fetching (auth-type-aware endpoints)\r\n * - Basic, SAML, and SSO authentication login flows\r\n * - Session reset on 500 errors\r\n * - Auth-type-aware session timeouts\r\n * - Logout/cleanup\r\n */\r\n\r\nimport type { AuthConfig, AuthType } from '../../types/config';\r\nimport type { Session } from './types';\r\nimport { DEFAULT_SESSION_CONFIG } from './types';\r\nimport type { AsyncResult } from '../../types/result';\r\nimport { ok, err } from '../../types/result';\r\nimport {\r\n FETCH_CSRF_TOKEN,\r\n CSRF_TOKEN_HEADER,\r\n extractCsrfToken,\r\n debug,\r\n} from '../utils';\r\n\r\n// Request function type signature (provided by client.ts)\r\ntype RequestFn = (options: {\r\n method: 'GET' | 'POST' | 'PUT' | 'DELETE';\r\n path: string;\r\n params?: Record<string, string | number>;\r\n headers?: Record<string, string>;\r\n body?: string;\r\n}) => AsyncResult<Response, Error>;\r\n\r\n// Session state management (provided by client.ts)\r\nexport interface SessionState {\r\n csrfToken: string | null;\r\n session: Session | null;\r\n config: { auth: AuthConfig };\r\n}\r\n\r\n/**\r\n * Fetch CSRF token from SAP ADT server\r\n *\r\n * Endpoint and content type vary by auth type:\r\n * - SAML: /sap/bc/adt/core/http/sessions\r\n * - Basic/SSO: /sap/bc/adt/compatibility/graph\r\n *\r\n * @param state - Session state to update with new token\r\n * @param request - HTTP request function from client\r\n * @returns CSRF token string or error\r\n */\r\nexport async function fetchCsrfToken(\r\n state: SessionState,\r\n request: RequestFn\r\n): AsyncResult<string, Error> {\r\n // Select endpoint based on authentication type.\r\n const endpoint = state.config.auth.type === 'saml'\r\n ? '/sap/bc/adt/core/http/sessions'\r\n : '/sap/bc/adt/compatibility/graph';\r\n\r\n // Select content type based on authentication type.\r\n const contentType = state.config.auth.type === 'saml'\r\n ? 'application/vnd.sap.adt.core.http.session.v3+xml'\r\n : 'application/xml';\r\n\r\n // Build request headers with CSRF token fetch flag.\r\n const headers = {\r\n [CSRF_TOKEN_HEADER]: FETCH_CSRF_TOKEN,\r\n 'Content-Type': contentType,\r\n 'Accept': contentType,\r\n };\r\n\r\n // Execute CSRF token request.\r\n const [response, requestErr] = await request({\r\n method: 'GET',\r\n path: endpoint,\r\n headers,\r\n });\r\n\r\n if (requestErr) {\r\n return err(new Error(`Failed to fetch CSRF token: ${requestErr.message}`));\r\n }\r\n\r\n if (!response.ok) {\r\n const text = await response.text();\r\n return err(new Error(`CSRF token fetch failed with status ${response.status}: ${text}`));\r\n }\r\n\r\n // Extract CSRF token from response headers.\r\n const token = extractCsrfToken(response.headers);\r\n debug(`CSRF token from headers: ${token ? token.substring(0, 20) + '...' : 'null'}`);\r\n if (!token) {\r\n // Debug: show all headers\r\n debug('Response headers:');\r\n response.headers.forEach((value, key) => debug(` ${key}: ${value.substring(0, 50)}`));\r\n return err(new Error('Invalid credentials'));\r\n }\r\n\r\n // Update session state with new token.\r\n state.csrfToken = token;\r\n debug(`Stored CSRF token in state: ${state.csrfToken?.substring(0, 20)}...`);\r\n\r\n return ok(token);\r\n}\r\n\r\n/**\r\n * Get session timeout based on authentication type\r\n *\r\n * @param authType - Authentication type\r\n * @returns Session timeout in milliseconds\r\n */\r\nexport function getSessionTimeout(authType: AuthType): number {\r\n switch (authType) {\r\n case 'saml':\r\n return DEFAULT_SESSION_CONFIG.samlSessionTimeout * 1000;\r\n case 'basic':\r\n case 'sso':\r\n return DEFAULT_SESSION_CONFIG.sessionTimeout * 1000;\r\n default: {\r\n const _exhaustive: never = authType;\r\n return DEFAULT_SESSION_CONFIG.sessionTimeout * 1000;\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Extract username from authentication config\r\n *\r\n * @param auth - Authentication config\r\n * @returns Username for session (SAP user for SAML, username for basic, system user for SSO)\r\n */\r\nfunction extractUsername(auth: AuthConfig): string {\r\n switch (auth.type) {\r\n case 'basic':\r\n return auth.username;\r\n case 'saml':\r\n // For SAML, use sapUser (actual SAP username) not username (email for browser login)\r\n return auth.sapUser;\r\n case 'sso':\r\n // For SSO, username comes from Kerberos/system\r\n return process.env['USERNAME'] ?? process.env['USER'] ?? 'SSO_USER';\r\n default: {\r\n const _exhaustive: never = auth;\r\n return '';\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Login to SAP ADT server\r\n *\r\n * Supports all authentication types:\r\n * - Basic: Username/password via Authorization header\r\n * - SAML: Browser automation (cookies already set by auth strategy)\r\n * - SSO: Kerberos/mTLS (certificates already loaded by auth strategy)\r\n *\r\n * For SAML and SSO, the auth strategy's performLogin() is called\r\n * before this function, so authentication is already complete.\r\n * This function fetches the CSRF token and creates the session.\r\n *\r\n * @param state - Session state to update\r\n * @param request - HTTP request function from client\r\n * @returns Session object or error\r\n */\r\nexport async function login(\r\n state: SessionState,\r\n request: RequestFn\r\n): AsyncResult<Session, Error> {\r\n // Fetch CSRF token from SAP server.\r\n // Endpoint varies by auth type (handled in fetchCsrfToken).\r\n const [token, tokenErr] = await fetchCsrfToken(state, request);\r\n if (tokenErr) {\r\n return err(tokenErr);\r\n }\r\n\r\n // Extract username from authentication config.\r\n const username = extractUsername(state.config.auth);\r\n\r\n // Calculate session expiration based on auth type.\r\n const timeout = getSessionTimeout(state.config.auth.type);\r\n\r\n // Create session object.\r\n const session: Session = {\r\n sessionId: token,\r\n username,\r\n expiresAt: Date.now() + timeout,\r\n };\r\n\r\n // Update session state.\r\n state.session = session;\r\n\r\n return ok(session);\r\n}\r\n\r\n/**\r\n * Logout from SAP ADT server\r\n *\r\n * Calls the SAP logoff endpoint and clears local state.\r\n *\r\n * @param state - Session state to clear\r\n * @param request - HTTP request function from client\r\n * @returns void or error\r\n */\r\nexport async function logout(\r\n state: SessionState,\r\n request: RequestFn\r\n): AsyncResult<void, Error> {\r\n // Execute logout request to SAP server.\r\n const [response, requestErr] = await request({\r\n method: 'POST',\r\n path: '/sap/public/bc/icf/logoff',\r\n });\r\n\r\n if (requestErr) {\r\n return err(new Error(`Logout failed: ${requestErr.message}`));\r\n }\r\n\r\n if (!response.ok) {\r\n const text = await response.text();\r\n return err(new Error(`Logout failed with status ${response.status}: ${text}`));\r\n }\r\n\r\n // Clear local session state.\r\n state.csrfToken = null;\r\n state.session = null;\r\n\r\n return ok(undefined);\r\n}\r\n\r\n/**\r\n * Reset session by logging out and back in\r\n *\r\n * Called automatically on 500 errors to recover from session expiration.\r\n *\r\n * @param state - Session state to reset\r\n * @param request - HTTP request function from client\r\n * @returns void or error\r\n */\r\nexport async function sessionReset(\r\n state: SessionState,\r\n request: RequestFn\r\n): AsyncResult<void, Error> {\r\n // Attempt to logout from current session.\r\n await logout(state, request);\r\n\r\n // Clear session state regardless of logout result.\r\n state.csrfToken = null;\r\n state.session = null;\r\n\r\n // Re-login to establish new session.\r\n const [, loginErr] = await login(state, request);\r\n if (loginErr) {\r\n return err(loginErr);\r\n }\r\n\r\n return ok(undefined);\r\n}\r\n","/**\r\n * Session Refresh via Reentrance Ticket\r\n *\r\n * Fetches a reentrance ticket from SAP ADT to keep the session alive.\r\n * Eclipse ADT uses this mechanism to maintain sessions across extended periods.\r\n *\r\n * Endpoint: GET /sap/bc/adt/security/reentranceticket\r\n * - Returns a base64-encoded SSO ticket\r\n * - Refreshes server-side session cookies (MYSAPSSO2)\r\n */\r\n\r\nimport type { AsyncResult } from '../../types/result';\r\nimport type { SessionState } from './login';\r\nimport { getSessionTimeout } from './login';\r\nimport { ok, err } from '../../types/result';\r\nimport { debug } from '../utils';\r\n\r\n// Request function type signature (provided by client.ts)\r\ntype RequestFn = (options: {\r\n method: 'GET' | 'POST' | 'PUT' | 'DELETE';\r\n path: string;\r\n params?: Record<string, string | number>;\r\n headers?: Record<string, string>;\r\n body?: string;\r\n}) => AsyncResult<Response, Error>;\r\n\r\nconst REENTRANCE_TICKET_PATH = '/sap/bc/adt/security/reentranceticket';\r\n\r\n/**\r\n * Result of a session refresh operation\r\n */\r\nexport interface RefreshResult {\r\n /** Base64-encoded reentrance ticket */\r\n ticket: string;\r\n /** Updated session expiration timestamp (ms since epoch) */\r\n expiresAt: number;\r\n}\r\n\r\n/**\r\n * Refresh session by fetching a reentrance ticket\r\n *\r\n * Calls the SAP ADT reentrance ticket endpoint to extend the session lifetime.\r\n * The server responds with an SSO ticket and refreshes the MYSAPSSO2 cookie.\r\n *\r\n * @param state - Session state to update\r\n * @param request - HTTP request function from client\r\n * @returns RefreshResult with ticket and new expiration, or error\r\n */\r\nexport async function refreshSession(\r\n state: SessionState,\r\n request: RequestFn\r\n): AsyncResult<RefreshResult, Error> {\r\n if (!state.session) {\r\n return err(new Error('Not logged in'));\r\n }\r\n\r\n debug('Fetching reentrance ticket to refresh session...');\r\n\r\n const [response, reqErr] = await request({\r\n method: 'GET',\r\n path: REENTRANCE_TICKET_PATH,\r\n headers: { 'Accept': 'text/plain' },\r\n });\r\n\r\n if (reqErr) {\r\n return err(new Error(`Session refresh failed: ${reqErr.message}`));\r\n }\r\n\r\n if (!response.ok) {\r\n const text = await response.text();\r\n return err(new Error(`Session refresh failed (${response.status}): ${text}`));\r\n }\r\n\r\n // Extract ticket from response body\r\n const ticket = await response.text();\r\n debug(`Received reentrance ticket: ${ticket.substring(0, 20)}...`);\r\n\r\n // Update session expiration based on auth type\r\n const timeout = getSessionTimeout(state.config.auth.type);\r\n state.session.expiresAt = Date.now() + timeout;\r\n\r\n debug(`Session refreshed, new expiration: ${new Date(state.session.expiresAt).toISOString()}`);\r\n\r\n return ok({ ticket, expiresAt: state.session.expiresAt });\r\n}\r\n","/**\r\n * Client login method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { Session } from '../../../core/session/types';\r\nimport type { ClientContext, SsoCerts } from '../../types';\r\nimport { ok, err } from '../../../types/result';\r\nimport * as sessionOps from '../../../core/session';\r\nimport { debug } from '../../../core/utils';\r\n\r\n// Default auto-refresh interval: 30 min\r\nconst DEFAULT_REFRESH_INTERVAL = 30 * 60 * 1000;\r\n\r\nexport async function login(\r\n ctx: ClientContext,\r\n setSsoCerts: (certs: SsoCerts) => void\r\n): AsyncResult<Session> {\r\n const { authStrategy } = ctx.state;\r\n\r\n // For SSO and SAML, perform initial authentication (certificate enrollment or browser login)\r\n if (authStrategy.performLogin) {\r\n const [, loginErr] = await authStrategy.performLogin(fetch);\r\n if (loginErr) {\r\n return err(loginErr);\r\n }\r\n }\r\n\r\n // For SAML, transfer cookies from auth strategy to client cookie store\r\n if (authStrategy.type === 'saml' && authStrategy.getCookies) {\r\n const cookies = authStrategy.getCookies();\r\n for (const cookie of cookies) {\r\n ctx.state.cookies.set(cookie.name, cookie.value);\r\n }\r\n debug(`Transferred ${cookies.length} SAML cookies to client`);\r\n }\r\n\r\n // For SSO with mTLS, store certificates for use in requests\r\n if (authStrategy.type === 'sso' && authStrategy.getCertificates) {\r\n const certs = authStrategy.getCertificates();\r\n if (certs) {\r\n setSsoCerts({\r\n cert: certs.fullChain,\r\n key: certs.privateKey,\r\n });\r\n debug('Stored mTLS certificates for SSO authentication');\r\n }\r\n }\r\n\r\n const [session, loginErr] = await sessionOps.login(ctx.state, ctx.request);\r\n if (loginErr) {\r\n return err(loginErr);\r\n }\r\n\r\n // Start auto-refresh if enabled (default: true)\r\n const autoRefresh = ctx.state.config.autoRefresh ?? { enabled: true };\r\n if (autoRefresh.enabled) {\r\n const interval = autoRefresh.intervalMs ?? DEFAULT_REFRESH_INTERVAL;\r\n ctx.startAutoRefresh(interval);\r\n debug(`Auto-refresh started with ${interval}ms interval`);\r\n }\r\n\r\n return ok(session);\r\n}\r\n","/**\r\n * Client logout method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { ClientContext } from '../../types';\r\nimport * as sessionOps from '../../../core/session';\r\n\r\nexport async function logout(ctx: ClientContext): AsyncResult<void> {\r\n ctx.stopAutoRefresh();\r\n return sessionOps.logout(ctx.state, ctx.request);\r\n}\r\n","/**\r\n * Client session refresh method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { ClientContext } from '../../types';\r\nimport type { RefreshResult } from '../../../core/session/refresh';\r\nimport { err } from '../../../types/result';\r\nimport * as sessionOps from '../../../core/session';\r\n\r\nexport async function refreshSession(ctx: ClientContext): AsyncResult<RefreshResult> {\r\n if (!ctx.state.session) {\r\n return err(new Error('Not logged in'));\r\n }\r\n return sessionOps.refreshSession(ctx.state, ctx.request);\r\n}\r\n","/**\r\n * Export session state for persistence across processes\r\n */\r\n\r\nimport type { ExportableSessionState } from '../../../core/session/types';\r\nimport type { ClientContext, SsoCerts } from '../../types';\r\nimport { getCertificatePaths } from '../../../core/auth/sso/storage';\r\n\r\nexport function exportSessionState(\r\n ctx: ClientContext,\r\n ssoCerts: SsoCerts | undefined\r\n): ExportableSessionState | null {\r\n if (!ctx.state.session || !ctx.state.csrfToken) return null;\r\n\r\n // Convert cookies Map to array format\r\n const cookies: Array<{ name: string; value: string }> = [];\r\n for (const [name, value] of ctx.state.cookies) {\r\n cookies.push({ name, value });\r\n }\r\n\r\n const state: ExportableSessionState = {\r\n csrfToken: ctx.state.csrfToken,\r\n session: ctx.state.session,\r\n cookies,\r\n authType: ctx.state.authStrategy.type,\r\n };\r\n\r\n // For SSO, include certificate paths (not contents for security)\r\n if (ctx.state.authStrategy.type === 'sso' && ssoCerts) {\r\n state.ssoCertPaths = getCertificatePaths();\r\n }\r\n\r\n return state;\r\n}\r\n","/**\r\n * Import session state from persistence\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { ExportableSessionState } from '../../../core/session/types';\r\nimport type { ClientContext, SsoCerts } from '../../types';\r\nimport { ok, err } from '../../../types/result';\r\nimport { debug, CSRF_TOKEN_HEADER, FETCH_CSRF_TOKEN, extractCsrfToken } from '../../../core/utils';\r\n\r\n// Default auto-refresh interval: 30 min\r\nconst DEFAULT_REFRESH_INTERVAL = 30 * 60 * 1000;\r\n\r\nexport async function importSessionState(\r\n ctx: ClientContext,\r\n state: ExportableSessionState,\r\n setSsoCerts: (certs: SsoCerts) => void\r\n): AsyncResult<boolean> {\r\n debug(`importSessionState: starting import`);\r\n\r\n // Validate session hasn't expired\r\n if (state.session.expiresAt <= Date.now()) {\r\n debug(`importSessionState: session expired`);\r\n return err(new Error('Session has expired'));\r\n }\r\n debug(`importSessionState: session expiry OK (expires at ${state.session.expiresAt})`);\r\n\r\n // Restore session state\r\n ctx.state.session = state.session;\r\n ctx.state.csrfToken = state.csrfToken;\r\n debug(`importSessionState: restored session and CSRF token`);\r\n\r\n // Restore cookies from array to Map\r\n ctx.state.cookies.clear();\r\n for (const cookie of state.cookies) {\r\n ctx.state.cookies.set(cookie.name, cookie.value);\r\n }\r\n debug(`importSessionState: restored ${state.cookies.length} cookies`);\r\n\r\n // For SSO, load certificates from paths\r\n if (state.authType === 'sso' && state.ssoCertPaths) {\r\n debug(`importSessionState: loading SSO certs from ${state.ssoCertPaths.fullChainPath}`);\r\n try {\r\n const fs = await import('fs/promises');\r\n const [fullChain, key] = await Promise.all([\r\n fs.readFile(state.ssoCertPaths.fullChainPath, 'utf-8'),\r\n fs.readFile(state.ssoCertPaths.keyPath, 'utf-8'),\r\n ]);\r\n setSsoCerts({ cert: fullChain, key });\r\n debug(`importSessionState: SSO certs loaded successfully`);\r\n } catch (certErr) {\r\n debug(`importSessionState: SSO cert load failed: ${certErr}`);\r\n return err(new Error(`Failed to load SSO certificates: ${certErr instanceof Error ? certErr.message : String(certErr)}`));\r\n }\r\n }\r\n\r\n // Fetch fresh CSRF token using the restored session cookies\r\n // The cached CSRF token is tied to the original process, so we need a new one\r\n debug(`importSessionState: fetching fresh CSRF token...`);\r\n\r\n const [response, reqErr] = await ctx.request({\r\n method: 'GET',\r\n path: '/sap/bc/adt/compatibility/graph',\r\n headers: {\r\n [CSRF_TOKEN_HEADER]: FETCH_CSRF_TOKEN,\r\n },\r\n });\r\n debug(`importSessionState: CSRF fetch completed`);\r\n\r\n if (reqErr) {\r\n debug(`importSessionState: CSRF fetch error: ${reqErr.message}`);\r\n ctx.state.session = null;\r\n ctx.state.csrfToken = null;\r\n ctx.state.cookies.clear();\r\n return err(new Error(`Session validation failed: ${reqErr.message}`));\r\n }\r\n\r\n if (!response.ok) {\r\n debug(`importSessionState: CSRF fetch failed with status ${response.status}`);\r\n ctx.state.session = null;\r\n ctx.state.csrfToken = null;\r\n ctx.state.cookies.clear();\r\n return err(new Error(`Session validation failed with status ${response.status}`));\r\n }\r\n\r\n // Extract and store the new CSRF token\r\n const newToken = extractCsrfToken(response.headers);\r\n if (!newToken) {\r\n debug(`importSessionState: no CSRF token in response headers`);\r\n ctx.state.session = null;\r\n ctx.state.csrfToken = null;\r\n ctx.state.cookies.clear();\r\n return err(new Error('Session validation failed: no CSRF token returned'));\r\n }\r\n\r\n ctx.state.csrfToken = newToken;\r\n debug(`importSessionState: new CSRF token obtained: ${newToken.substring(0, 20)}...`);\r\n\r\n // Start auto-refresh if enabled\r\n const autoRefresh = ctx.state.config.autoRefresh ?? { enabled: true };\r\n if (autoRefresh.enabled) {\r\n const interval = autoRefresh.intervalMs ?? DEFAULT_REFRESH_INTERVAL;\r\n ctx.startAutoRefresh(interval);\r\n debug(`Auto-refresh started with ${interval}ms interval (after import)`);\r\n }\r\n\r\n debug(`importSessionState: import complete`);\r\n return ok(true);\r\n}\r\n","// ADT Object Type Configuration — metadata for SAP development objects\r\n\r\nimport type { AsyncResult } from '../../types/result';\r\n\r\n// Client interface for ADT requests\r\nexport interface AdtRequestor {\r\n request(options: {\r\n method: 'GET' | 'POST' | 'PUT' | 'DELETE';\r\n path: string;\r\n params?: Record<string, string | number>;\r\n headers?: Record<string, string>;\r\n body?: string;\r\n }): AsyncResult<Response, Error>;\r\n}\r\n\r\n// Configuration for a specific SAP object type\r\nexport interface ObjectConfig {\r\n /** ADT endpoint path (e.g., 'ddic/ddl/sources') */\r\n endpoint: string;\r\n /** XML namespace for creation requests */\r\n nameSpace: string;\r\n /** Root element name for creation XML */\r\n rootName: string;\r\n /** SAP ADT object type identifier (e.g., 'DDLS/DF') */\r\n type: string;\r\n /** Human-readable label (e.g., 'View') */\r\n label: string;\r\n /** File extension (e.g., 'asddls') */\r\n extension: string;\r\n /** Data preview endpoint (if supported) */\r\n dpEndpoint?: string;\r\n /** Data preview parameter name (if supported) */\r\n dpParam?: string;\r\n}\r\n\r\n/**\r\n * Result of upsert operation\r\n */\r\nexport interface UpsertResult {\r\n name: string;\r\n extension: string;\r\n status: 'created' | 'updated' | 'unchanged';\r\n transport?: string;\r\n}\r\n\r\n/**\r\n * Supported object types\r\n */\r\nexport type ConfiguredExtension = 'asddls' | 'asdcls' | 'astabldt' | 'astablds' | 'aclass' | 'asprog';\r\n\r\n/**\r\n * Object type labels\r\n */\r\nexport enum ObjectTypeLabel {\r\n VIEW = 'View',\r\n ACCESS_CONTROL = 'Access Control',\r\n TABLE = 'Table',\r\n STRUCTURE = 'Structure',\r\n CLASS = 'Class',\r\n PROGRAM = 'ABAP Program',\r\n}\r\n\r\n/**\r\n * Configuration map for all supported object types\r\n *\r\n * Maps file extensions to their ADT configuration.\r\n * This is the central registry for object type metadata.\r\n */\r\nexport const OBJECT_CONFIG_MAP: Record<ConfiguredExtension, ObjectConfig> = {\r\n 'asddls': {\r\n endpoint: 'ddic/ddl/sources',\r\n nameSpace: 'xmlns:ddl=\"http://www.sap.com/adt/ddic/ddlsources\"',\r\n rootName: 'ddl:ddlSource',\r\n type: 'DDLS/DF',\r\n label: ObjectTypeLabel.VIEW,\r\n extension: 'asddls',\r\n dpEndpoint: 'cds',\r\n dpParam: 'ddlSourceName',\r\n },\r\n 'asdcls': {\r\n endpoint: 'acm/dcl/sources',\r\n nameSpace: 'xmlns:dcl=\"http://www.sap.com/adt/acm/dclsources\"',\r\n rootName: 'dcl:dclSource',\r\n type: 'DCLS/DL',\r\n label: ObjectTypeLabel.ACCESS_CONTROL,\r\n extension: 'asdcls',\r\n },\r\n 'aclass': {\r\n endpoint: 'oo/classes',\r\n nameSpace: 'xmlns:class=\"http://www.sap.com/adt/oo/classes\"',\r\n rootName: 'class:abapClass',\r\n type: 'CLAS/OC',\r\n label: ObjectTypeLabel.CLASS,\r\n extension: 'aclass',\r\n },\r\n 'astabldt': {\r\n endpoint: 'ddic/tables',\r\n nameSpace: 'xmlns:blue=\"http://www.sap.com/wbobj/blue\"',\r\n rootName: 'blue:blueSource',\r\n type: 'TABL/DT',\r\n label: ObjectTypeLabel.TABLE,\r\n extension: 'astabldt',\r\n dpEndpoint: 'ddic',\r\n dpParam: 'ddicEntityName',\r\n },\r\n 'astablds': {\r\n endpoint: 'ddic/structures',\r\n nameSpace: 'xmlns:blue=\"http://www.sap.com/wbobj/blue\"',\r\n rootName: 'blue:blueSource',\r\n type: 'STRU/D',\r\n label: ObjectTypeLabel.STRUCTURE,\r\n extension: 'astablds',\r\n },\r\n 'asprog': {\r\n endpoint: 'programs/programs',\r\n nameSpace: 'xmlns:program=\"http://www.sap.com/adt/programs/programs\"',\r\n rootName: 'program:abapProgram',\r\n type: 'PROG/P',\r\n label: ObjectTypeLabel.PROGRAM,\r\n extension: 'asprog',\r\n },\r\n};\r\n\r\n/**\r\n * Get object configuration by extension\r\n *\r\n * @param extension - File extension (e.g., 'asddls')\r\n * @returns Configuration or null if not found\r\n */\r\nexport function getConfigByExtension(extension: string): ObjectConfig | null {\r\n return OBJECT_CONFIG_MAP[extension as ConfiguredExtension] ?? null;\r\n}\r\n\r\n/**\r\n * Get object configuration by ADT type\r\n *\r\n * @param type - ADT type identifier (e.g., 'DDLS/DF')\r\n * @returns Configuration or null if not found\r\n */\r\nexport function getConfigByType(type: string): ObjectConfig | null {\r\n for (const config of Object.values(OBJECT_CONFIG_MAP)) {\r\n if (config.type === type) {\r\n return config;\r\n }\r\n }\r\n return null;\r\n}\r\n\r\n/**\r\n * Get all configured extensions\r\n *\r\n * @returns Array of supported extensions\r\n */\r\nexport function getAllExtensions(): ConfiguredExtension[] {\r\n return Object.keys(OBJECT_CONFIG_MAP) as ConfiguredExtension[];\r\n}\r\n\r\n/**\r\n * Get all configured ADT types\r\n *\r\n * @returns Array of supported ADT types\r\n */\r\nexport function getAllTypes(): string[] {\r\n return Object.values(OBJECT_CONFIG_MAP).map(config => config.type);\r\n}\r\n\r\n/**\r\n * Check if extension is supported\r\n *\r\n * @param extension - Extension to check\r\n * @returns True if supported\r\n */\r\nexport function isExtensionSupported(extension: string): extension is ConfiguredExtension {\r\n return extension in OBJECT_CONFIG_MAP;\r\n}\r\n","/**\n * ADT Helpers — shared utilities for ADT operations\n *\n * Internal helpers used across multiple ADT files.\n * Not exported from the adt/ barrel.\n */\n\nimport type { AsyncResult } from '../../types/result';\nimport { extractError } from '../utils/xml';\nimport { getConfigByExtension } from './types';\nimport type { ObjectConfig } from './types';\n\n/**\n * Check response for errors and return text content\n */\nexport async function checkResponse(\n response: Response | null,\n requestErr: Error | null,\n operation: string\n): AsyncResult<string, Error> {\n // Handle request errors.\n if (requestErr) return [null, requestErr];\n if (!response) return [null, new Error(`${operation}: No response`)];\n\n // Handle HTTP errors.\n if (!response.ok) {\n const text = await response.text();\n const errorMsg = extractError(text);\n // Include status and raw text if no message found for debugging\n if (errorMsg === 'No message found' || errorMsg === 'Failed to parse error XML') {\n return [null, new Error(`${operation}: HTTP ${response.status} - ${text.substring(0, 500)}`)];\n }\n return [null, new Error(`${operation}: ${errorMsg}`)];\n }\n\n // Return successful response text.\n return [await response.text(), null];\n}\n\n/**\n * Validate extension and return config\n */\nexport function requireConfig(extension: string): [ObjectConfig, null] | [null, Error] {\n // Lookup configuration for extension.\n const config = getConfigByExtension(extension);\n if (!config) return [null, new Error(`Unsupported extension: ${extension}`)];\n\n // Return valid configuration.\n return [config, null];\n}\n","/**\r\n * POST /objects/read — Read object source content\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { ObjectRef } from '../../../types/requests';\r\nimport type { AdtRequestor } from '../types';\r\nimport { checkResponse, requireConfig } from '../helpers';\r\n\r\n/**\r\n * Object metadata\r\n */\r\nexport interface ObjectMetadata {\r\n name: string;\r\n extension: string;\r\n package: string;\r\n description?: string;\r\n createdBy?: string;\r\n createdAt?: string;\r\n modifiedBy?: string;\r\n modifiedAt?: string;\r\n}\r\n\r\n/**\r\n * Object with content (read response)\r\n */\r\nexport interface ObjectWithContent extends ObjectMetadata {\r\n content: string;\r\n}\r\n\r\n/**\r\n * Read object source content\r\n *\r\n * @param client - ADT client\r\n * @param object - Object reference (name + extension)\r\n * @returns Object with content or error\r\n */\r\nexport async function readObject(\r\n client: AdtRequestor,\r\n object: ObjectRef\r\n): AsyncResult<ObjectWithContent, Error> {\r\n // Validate object extension is supported.\r\n const [config, configErr] = requireConfig(object.extension);\r\n if (configErr) return err(configErr);\r\n\r\n // Execute GET request for object source content.\r\n const [response, requestErr] = await client.request({\r\n method: 'GET',\r\n path: `/sap/bc/adt/${config.endpoint}/${object.name}/source/main`,\r\n headers: { 'Accept': 'text/plain' },\r\n });\r\n\r\n // Validate successful response and extract content.\r\n const [content, checkErr] = await checkResponse(\r\n response,\r\n requestErr,\r\n `Failed to read ${config.label} ${object.name}`\r\n );\r\n if (checkErr) return err(checkErr);\r\n\r\n // Build result object with content.\r\n const result: ObjectWithContent = {\r\n name: object.name,\r\n extension: object.extension,\r\n package: '',\r\n content,\r\n };\r\n\r\n return ok(result);\r\n}\r\n","/**\r\n * Lock/Unlock — Object lock management for editing\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { ObjectRef } from '../../../types/requests';\r\nimport type { AdtRequestor } from '../types';\r\nimport { extractLockHandle } from '../../utils/xml';\r\nimport { checkResponse, requireConfig } from '../helpers';\r\nimport { debug } from '../../utils/logging';\r\n\r\n/**\r\n * Lock an object for editing\r\n *\r\n * @param client - ADT client\r\n * @param object - Object reference (name + extension)\r\n * @returns Lock handle string or error\r\n */\r\nexport async function lockObject(\r\n client: AdtRequestor,\r\n object: ObjectRef\r\n): AsyncResult<string, Error> {\r\n // Validate object extension is supported.\r\n const [config, configErr] = requireConfig(object.extension);\r\n if (configErr) return err(configErr);\r\n\r\n // Execute lock request.\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: `/sap/bc/adt/${config.endpoint}/${object.name}/source/main`,\r\n params: {\r\n '_action': 'LOCK',\r\n 'accessMode': 'MODIFY',\r\n },\r\n headers: {\r\n 'Accept': 'application/*,application/vnd.sap.as+xml;charset=UTF-8;dataname=com.sap.adt.lock.result',\r\n },\r\n });\r\n\r\n // Validate successful response.\r\n const [text, checkErr] = await checkResponse(\r\n response,\r\n requestErr,\r\n `Failed to lock ${config.label} ${object.name}`\r\n );\r\n if (checkErr) return err(checkErr);\r\n\r\n // Extract lock handle from XML response.\r\n const [lockHandle, extractErr] = extractLockHandle(text);\r\n if (extractErr) {\r\n return err(new Error(`Failed to extract lock handle: ${extractErr.message}`));\r\n }\r\n debug(`Lock acquired: handle=${lockHandle}`);\r\n\r\n return ok(lockHandle);\r\n}\r\n\r\n/**\r\n * Unlock an object after editing\r\n *\r\n * @param client - ADT client\r\n * @param object - Object reference (name + extension)\r\n * @param lockHandle - Lock handle from lockObject()\r\n * @returns void or error\r\n */\r\nexport async function unlockObject(\r\n client: AdtRequestor,\r\n object: ObjectRef,\r\n lockHandle: string\r\n): AsyncResult<void, Error> {\r\n // Validate object extension is supported.\r\n const [config, configErr] = requireConfig(object.extension);\r\n if (configErr) return err(configErr);\r\n\r\n // Execute unlock request.\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: `/sap/bc/adt/${config.endpoint}/${object.name}/source/main`,\r\n params: {\r\n '_action': 'UNLOCK',\r\n 'lockHandle': lockHandle,\r\n },\r\n });\r\n\r\n // Validate successful response.\r\n const [_, checkErr] = await checkResponse(\r\n response,\r\n requestErr,\r\n `Failed to unlock ${config.label} ${object.name}`\r\n );\r\n if (checkErr) return err(checkErr);\r\n\r\n return ok(undefined);\r\n}\r\n","/**\r\n * Create — Create new SAP development object\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { ObjectContent } from '../../../types/requests';\r\nimport type { AdtRequestor } from '../types';\r\nimport { escapeXml } from '../../utils/xml';\r\nimport { checkResponse, requireConfig } from '../helpers';\r\n\r\n/**\r\n * Create a new object in SAP\r\n *\r\n * @param client - ADT client\r\n * @param object - Object with content (name, extension, content, description)\r\n * @param packageName - Target package\r\n * @param transport - Transport request (required for non-$TMP packages)\r\n * @param username - Creating user\r\n * @returns void or error\r\n */\r\nexport async function createObject(\r\n client: AdtRequestor,\r\n object: ObjectContent,\r\n packageName: string,\r\n transport: string | undefined,\r\n username: string\r\n): AsyncResult<void, Error> {\r\n // Validate object extension is supported.\r\n const [config, configErr] = requireConfig(object.extension);\r\n if (configErr) return err(configErr);\r\n\r\n // Default empty description if not provided.\r\n const description = object.description ?? '';\r\n\r\n // Build XML request body with object metadata.\r\n const body = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<${config.rootName} ${config.nameSpace}\r\n xmlns:adtcore=\"http://www.sap.com/adt/core\"\r\n adtcore:description=\"${escapeXml(description)}\"\r\n adtcore:language=\"EN\"\r\n adtcore:name=\"${object.name.toUpperCase()}\"\r\n adtcore:type=\"${config.type}\"\r\n adtcore:responsible=\"${username.toUpperCase()}\">\r\n\r\n <adtcore:packageRef adtcore:name=\"${packageName}\"/>\r\n\r\n</${config.rootName}>`;\r\n\r\n // Add transport parameter if provided.\r\n const params: Record<string, string> = {};\r\n if (transport) {\r\n params['corrNr'] = transport;\r\n }\r\n\r\n // Execute create request.\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: `/sap/bc/adt/${config.endpoint}`,\r\n params,\r\n headers: { 'Content-Type': 'application/*' },\r\n body: body.trim(),\r\n });\r\n\r\n // Validate successful response.\r\n const [_, checkErr] = await checkResponse(\r\n response,\r\n requestErr,\r\n `Failed to create ${config.label} ${object.name}`\r\n );\r\n if (checkErr) return err(checkErr);\r\n\r\n return ok(undefined);\r\n}\r\n","/**\r\n * Update — Update existing SAP development object\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { ObjectContent } from '../../../types/requests';\r\nimport type { AdtRequestor } from '../types';\r\nimport { checkResponse, requireConfig } from '../helpers';\r\nimport { debug } from '../../utils/logging';\r\n\r\n/**\r\n * Update an existing object's source content\r\n *\r\n * @param client - ADT client\r\n * @param object - Object with new content\r\n * @param lockHandle - Lock handle from lockObject()\r\n * @param transport - Transport request (required for non-$TMP packages)\r\n * @returns void or error\r\n */\r\nexport async function updateObject(\r\n client: AdtRequestor,\r\n object: ObjectContent,\r\n lockHandle: string,\r\n transport: string | undefined\r\n): AsyncResult<void, Error> {\r\n // Validate object extension is supported.\r\n const [config, configErr] = requireConfig(object.extension);\r\n if (configErr) return err(configErr);\r\n\r\n // Build request parameters with lock handle.\r\n const params: Record<string, string> = {\r\n 'lockHandle': lockHandle,\r\n };\r\n if (transport) {\r\n params['corrNr'] = transport;\r\n }\r\n\r\n // Execute update request to ADT server.\r\n debug(`Update ${object.name}: content length=${object.content?.length ?? 0}`);\r\n const [response, requestErr] = await client.request({\r\n method: 'PUT',\r\n path: `/sap/bc/adt/${config.endpoint}/${object.name}/source/main`,\r\n params,\r\n headers: { 'Content-Type': '*/*' },\r\n body: object.content,\r\n });\r\n debug(`Update response: ${response?.status ?? 'no response'}, err=${requestErr?.message ?? 'none'}`);\r\n\r\n // Validate successful response.\r\n const [_, checkErr] = await checkResponse(\r\n response,\r\n requestErr,\r\n `Failed to update ${config.label} ${object.name}`\r\n );\r\n if (checkErr) return err(checkErr);\r\n\r\n return ok(undefined);\r\n}\r\n","/**\r\n * Delete — Delete SAP development object\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { ObjectRef } from '../../../types/requests';\r\nimport type { AdtRequestor } from '../types';\r\nimport { checkResponse, requireConfig } from '../helpers';\r\n\r\n/**\r\n * Delete an object from SAP\r\n *\r\n * @param client - ADT client\r\n * @param object - Object reference (name + extension)\r\n * @param lockHandle - Lock handle from lockObject()\r\n * @param transport - Transport request (required for non-$TMP packages)\r\n * @returns void or error\r\n */\r\nexport async function deleteObject(\r\n client: AdtRequestor,\r\n object: ObjectRef,\r\n lockHandle: string,\r\n transport: string | undefined\r\n): AsyncResult<void, Error> {\r\n // Validate object extension is supported.\r\n const [config, configErr] = requireConfig(object.extension);\r\n if (configErr) return err(configErr);\r\n\r\n // Build request parameters with lock handle.\r\n const params: Record<string, string> = {\r\n 'lockHandle': lockHandle,\r\n };\r\n if (transport) {\r\n params['corrNr'] = transport;\r\n }\r\n\r\n // Execute delete request.\r\n const [response, requestErr] = await client.request({\r\n method: 'DELETE',\r\n path: `/sap/bc/adt/${config.endpoint}/${object.name}/source/main`,\r\n params,\r\n headers: { 'Accept': 'text/plain' },\r\n });\r\n\r\n // Validate successful response.\r\n const [_, checkErr] = await checkResponse(\r\n response,\r\n requestErr,\r\n `Failed to delete ${config.label} ${object.name}`\r\n );\r\n if (checkErr) return err(checkErr);\r\n\r\n return ok(undefined);\r\n}\r\n","// ADT Activation — activate ADT objects\r\n\r\nimport type { Result, AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { ObjectRef } from '../../../types/requests';\r\nimport type { AdtRequestor } from '../types';\r\nimport { getConfigByExtension } from '../types';\r\nimport { extractError, safeParseXml } from '../../utils/xml';\r\nimport { debug } from '../../utils/logging';\r\n\r\n/**\r\n * Result of activation operation\r\n */\r\nexport interface ActivationResult {\r\n name: string;\r\n extension: string;\r\n status: 'success' | 'warning' | 'error';\r\n messages: ActivationMessage[];\r\n}\r\n\r\nexport interface ActivationMessage {\r\n severity: 'error' | 'warning' | 'info';\r\n text: string;\r\n line?: number;\r\n column?: number;\r\n}\r\n\r\nexport async function activateObjects(\r\n client: AdtRequestor,\r\n objects: ObjectRef[]\r\n): AsyncResult<ActivationResult[], Error> {\r\n // Handle empty input.\r\n if (objects.length === 0) {\r\n return ok([]);\r\n }\r\n\r\n // Validate object extension is supported.\r\n const extension = objects[0]!.extension;\r\n const config = getConfigByExtension(extension);\r\n if (!config) return err(new Error(`Unsupported extension: ${extension}`));\r\n\r\n // Verify all objects have same extension for batch activation.\r\n for (const obj of objects) {\r\n if (obj.extension !== extension) {\r\n return err(new Error('All objects must have the same extension for batch activation'));\r\n }\r\n }\r\n\r\n // Build XML request body with object references.\r\n const objectRefs = objects.map(obj => `<adtcore:objectReference\r\n adtcore:uri=\"/sap/bc/adt/${config.endpoint}/${obj.name.toLowerCase()}\"\r\n adtcore:type=\"${config.type}\"\r\n adtcore:name=\"${obj.name}\"\r\n adtcore:description=\"*\"/>`).join('\\n ');\r\n\r\n const body = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n <adtcore:objectReferences xmlns:adtcore=\"http://www.sap.com/adt/core\">\r\n ${objectRefs}\r\n </adtcore:objectReferences>`;\r\n\r\n // Execute activation request.\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: '/sap/bc/adt/activation',\r\n params: {\r\n 'method': 'activate',\r\n 'preAuditRequested': 'true',\r\n },\r\n headers: {\r\n 'Content-Type': 'application/xml',\r\n 'Accept': 'application/xml',\r\n },\r\n body,\r\n });\r\n\r\n // Validate successful response.\r\n if (requestErr) { return err(requestErr); }\r\n const text = await response.text();\r\n debug(`Activation response status: ${response.status}`);\r\n debug(`Activation response: ${text.substring(0, 500)}`);\r\n if (!response.ok) {\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Activation failed: ${errorMsg}`));\r\n }\r\n\r\n // Parse activation results from response.\r\n const [results, parseErr] = extractActivationErrors(objects, text, extension);\r\n if (parseErr) { return err(parseErr); }\r\n return ok(results);\r\n}\r\n\r\n// Parse activation response XML for errors\r\nfunction extractActivationErrors(\r\n objects: ObjectRef[],\r\n xml: string,\r\n _extension: string\r\n): Result<ActivationResult[], Error> {\r\n // Parse XML response.\r\n const [doc, parseErr] = safeParseXml(xml);\r\n if (parseErr) { return err(parseErr); }\r\n\r\n // Initialize error map with empty arrays for each object.\r\n const errorMap: Map<string, ActivationMessage[]> = new Map();\r\n objects.forEach(obj => errorMap.set(obj.name.toLowerCase(), []));\r\n\r\n // Extract message elements and prepare regex for position parsing.\r\n const msgElements = doc.getElementsByTagName('msg');\r\n const startRegex = /#start=(\\d+),(\\d+)/;\r\n\r\n // Process each message element.\r\n for (let i = 0; i < msgElements.length; i++) {\r\n const msg = msgElements[i];\r\n if (!msg) continue;\r\n\r\n // Skip warning messages (type 'W').\r\n const type = msg.getAttribute('type');\r\n if (type === 'W') continue;\r\n\r\n // Extract object description and href for position info.\r\n const objDescr = msg.getAttribute('objDescr');\r\n const href = msg.getAttribute('href');\r\n if (!objDescr || !href) continue;\r\n\r\n // Parse line and column from href.\r\n let line: number | undefined;\r\n let column: number | undefined;\r\n const match = startRegex.exec(href);\r\n if (match && match[1] && match[2]) {\r\n line = parseInt(match[1], 10);\r\n column = parseInt(match[2], 10);\r\n }\r\n if (!line || !column) continue;\r\n\r\n // Find matching object by name.\r\n const matchingObj = objects.find(obj =>\r\n objDescr.toLowerCase().includes(obj.name.toLowerCase())\r\n );\r\n if (!matchingObj) continue;\r\n\r\n // Extract message text elements.\r\n const shortTextElements = msg.getElementsByTagName('txt');\r\n for (let j = 0; j < shortTextElements.length; j++) {\r\n const txt = shortTextElements[j];\r\n if (!txt) continue;\r\n\r\n const text = txt.textContent;\r\n if (!text) continue;\r\n\r\n // Build activation message with severity and position.\r\n const message: ActivationMessage = {\r\n severity: type === 'E' ? 'error' : 'warning',\r\n text,\r\n line,\r\n column,\r\n };\r\n\r\n // Add message to object's error list.\r\n const messages = errorMap.get(matchingObj.name.toLowerCase()) || [];\r\n messages.push(message);\r\n errorMap.set(matchingObj.name.toLowerCase(), messages);\r\n }\r\n }\r\n\r\n // Build final results with status based on message severity.\r\n const results: ActivationResult[] = objects.map(obj => {\r\n const messages = errorMap.get(obj.name.toLowerCase()) || [];\r\n const hasErrors = messages.some(m => m.severity === 'error');\r\n\r\n return {\r\n name: obj.name,\r\n extension: obj.extension,\r\n status: hasErrors ? 'error' : messages.length > 0 ? 'warning' : 'success',\r\n messages,\r\n };\r\n });\r\n\r\n return ok(results);\r\n}\r\n","// ADT Syntax Check — check objects for errors and warnings without activation\r\n\r\nimport type { Result, AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { ObjectRef } from '../../../types/requests';\r\nimport type { AdtRequestor } from '../types';\r\nimport { getConfigByExtension } from '../types';\r\nimport type { ActivationMessage } from './activation';\r\nimport { readObject } from './read';\r\nimport { extractError, safeParseXml } from '../../utils/xml';\r\nimport { debug } from '../../utils/logging';\r\n\r\n// Result of syntax check operation\r\nexport interface CheckResult {\r\n name: string;\r\n extension: string;\r\n status: 'success' | 'warning' | 'error';\r\n messages: ActivationMessage[];\r\n}\r\n\r\nexport async function checkSyntax(\r\n client: AdtRequestor,\r\n objects: ObjectRef[]\r\n): AsyncResult<CheckResult[], Error> {\r\n // Handle empty input.\r\n if (objects.length === 0) {\r\n return ok([]);\r\n }\r\n\r\n // Validate object extension is supported.\r\n const extension = objects[0]!.extension;\r\n const config = getConfigByExtension(extension);\r\n if (!config) return err(new Error(`Unsupported extension: ${extension}`));\r\n\r\n // Verify all objects have same extension for batch check.\r\n for (const obj of objects) {\r\n if (obj.extension !== extension) {\r\n return err(new Error('All objects must have the same extension for batch syntax check'));\r\n }\r\n }\r\n\r\n // Read source code for each object.\r\n const sources: Map<string, string> = new Map();\r\n for (const obj of objects) {\r\n const [result, readErr] = await readObject(client, obj);\r\n if (readErr) return err(new Error(`Failed to read ${obj.name}: ${readErr.message}`));\r\n sources.set(obj.name.toLowerCase(), result.content);\r\n }\r\n\r\n // Build XML request body with inline source code.\r\n const objectRefs = objects.map(obj => {\r\n const uri = `/sap/bc/adt/${config.endpoint}/${obj.name.toLowerCase()}`;\r\n const sourceUri = `${uri}/source/main`;\r\n const content = sources.get(obj.name.toLowerCase()) ?? '';\r\n const encoded = Buffer.from(content).toString('base64');\r\n\r\n return `<chkrun:checkObject adtcore:uri=\"${uri}\" chkrun:version=\"active\">\r\n <chkrun:artifacts>\r\n <chkrun:artifact chkrun:contentType=\"text/plain; charset=utf-8\" chkrun:uri=\"${sourceUri}\">\r\n <chkrun:content>${encoded}</chkrun:content>\r\n </chkrun:artifact>\r\n </chkrun:artifacts>\r\n </chkrun:checkObject>`;\r\n }).join('\\n ');\r\n\r\n const body = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<chkrun:checkObjectList xmlns:chkrun=\"http://www.sap.com/adt/checkrun\"\r\n xmlns:adtcore=\"http://www.sap.com/adt/core\">\r\n ${objectRefs}\r\n</chkrun:checkObjectList>`;\r\n\r\n // Execute syntax check request.\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: '/sap/bc/adt/checkruns',\r\n params: {\r\n 'reporters': 'abapCheckRun',\r\n },\r\n headers: {\r\n 'Content-Type': 'application/vnd.sap.adt.checkobjects+xml',\r\n 'Accept': 'application/vnd.sap.adt.checkmessages+xml',\r\n },\r\n body,\r\n });\r\n\r\n // Validate successful response.\r\n if (requestErr) { return err(requestErr); }\r\n const text = await response.text();\r\n debug(`Syntax check response status: ${response.status}`);\r\n debug(`Syntax check response: ${text.substring(0, 500)}`);\r\n if (!response.ok) {\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Syntax check failed: ${errorMsg}`));\r\n }\r\n\r\n // Parse check results from response.\r\n const [results, parseErr] = extractCheckMessages(objects, text);\r\n if (parseErr) { return err(parseErr); }\r\n return ok(results);\r\n}\r\n\r\n// Parse check run response XML for messages\r\nfunction extractCheckMessages(\r\n objects: ObjectRef[],\r\n xml: string\r\n): Result<CheckResult[], Error> {\r\n // Parse XML response.\r\n const [doc, parseErr] = safeParseXml(xml);\r\n if (parseErr) { return err(parseErr); }\r\n\r\n // Initialize message map with empty arrays for each object.\r\n const messageMap: Map<string, ActivationMessage[]> = new Map();\r\n objects.forEach(obj => messageMap.set(obj.name.toLowerCase(), []));\r\n\r\n // Try both namespaced and non-namespaced tag names.\r\n let msgElements = doc.getElementsByTagName('chkrun:checkMessage');\r\n if (msgElements.length === 0) {\r\n msgElements = doc.getElementsByTagName('checkMessage');\r\n }\r\n\r\n const startRegex = /#start=(\\d+),(\\d+)/;\r\n\r\n // Process each message element.\r\n for (let i = 0; i < msgElements.length; i++) {\r\n const msg = msgElements[i];\r\n if (!msg) continue;\r\n\r\n // Extract severity from type attribute.\r\n const type = msg.getAttribute('chkrun:type') ?? msg.getAttribute('type');\r\n if (!type) continue;\r\n\r\n // Extract URI for position info and object matching.\r\n const uri = msg.getAttribute('chkrun:uri') ?? msg.getAttribute('uri') ?? '';\r\n\r\n // Parse line and column from URI fragment.\r\n let line: number | undefined;\r\n let column: number | undefined;\r\n const match = startRegex.exec(uri);\r\n if (match && match[1] && match[2]) {\r\n line = parseInt(match[1], 10);\r\n column = parseInt(match[2], 10);\r\n }\r\n\r\n // Find matching object by name in URI.\r\n const matchingObj = objects.find(obj =>\r\n uri.toLowerCase().includes(obj.name.toLowerCase())\r\n );\r\n if (!matchingObj) continue;\r\n\r\n // Extract message text from shortText attribute.\r\n const text = msg.getAttribute('chkrun:shortText') ?? msg.getAttribute('shortText');\r\n if (!text) continue;\r\n\r\n // Build check message with severity and position.\r\n const message: ActivationMessage = {\r\n severity: type === 'E' ? 'error' : type === 'W' ? 'warning' : 'info',\r\n text,\r\n ...(line !== undefined && { line }),\r\n ...(column !== undefined && { column }),\r\n };\r\n\r\n // Add message to object's list.\r\n const messages = messageMap.get(matchingObj.name.toLowerCase()) || [];\r\n messages.push(message);\r\n messageMap.set(matchingObj.name.toLowerCase(), messages);\r\n }\r\n\r\n // Build final results with status based on message severity.\r\n const results: CheckResult[] = objects.map(obj => {\r\n const messages = messageMap.get(obj.name.toLowerCase()) || [];\r\n const hasErrors = messages.some(m => m.severity === 'error');\r\n\r\n return {\r\n name: obj.name,\r\n extension: obj.extension,\r\n status: hasErrors ? 'error' : messages.length > 0 ? 'warning' : 'success',\r\n messages,\r\n };\r\n });\r\n\r\n return ok(results);\r\n}\r\n","/**\r\n * PackageStats — Get stats for specific packages\r\n *\r\n * Uses virtualfolders/contents endpoint with package names in preselection:\r\n * - counter attribute = recursive object count (includes subpackages)\r\n * - text attribute = package description\r\n */\r\n\r\nimport type { AsyncResult } from '../../../../types/result';\r\nimport { ok, err } from '../../../../types/result';\r\nimport type { AdtRequestor } from '../../types';\r\nimport type { PackageNode } from './types';\r\nimport { extractError, safeParseXml } from '../../../utils/xml';\r\n\r\n/**\r\n * Construct request body for fetching specific packages by name.\r\n *\r\n * SAP quirk: With only 1 package in preselection, SAP drills INTO that package.\r\n * With 2+ packages, it returns those packages as top-level results.\r\n * We add an empty value when only 1 package is requested to get the correct behavior.\r\n */\r\nfunction constructPackageStatsBody(packageNames: string[]): string {\r\n // Ensure at least 2 values - SAP needs 2+ to return packages as results\r\n // SRIS_TEST_DATA_VFS_EMPTY is a known empty SAP package that won't add noise\r\n const names = packageNames.length === 1\r\n ? [...packageNames, 'SRIS_TEST_DATA_VFS_EMPTY']\r\n : packageNames;\r\n\r\n const values = names\r\n .map(name => ` <vfs:value>${name}</vfs:value>`)\r\n .join('\\n');\r\n\r\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<vfs:virtualFoldersRequest xmlns:vfs=\"http://www.sap.com/adt/ris/virtualFolders\" objectSearchPattern=\"*\">\r\n <vfs:preselection facet=\"package\">\r\n${values}\r\n </vfs:preselection>\r\n <vfs:facetorder>\r\n <vfs:facet>package</vfs:facet>\r\n <vfs:facet>group</vfs:facet>\r\n <vfs:facet>type</vfs:facet>\r\n </vfs:facetorder>\r\n</vfs:virtualFoldersRequest>`;\r\n}\r\n\r\n/**\r\n * Parse package stats from virtualfolders response.\r\n */\r\nfunction parsePackageStats(xml: string): PackageNode[] {\r\n const [doc, parseErr] = safeParseXml(xml);\r\n if (parseErr) return [];\r\n\r\n const packages: PackageNode[] = [];\r\n const virtualFolders = doc.getElementsByTagName('vfs:virtualFolder');\r\n\r\n for (let i = 0; i < virtualFolders.length; i++) {\r\n const vf = virtualFolders[i];\r\n if (!vf) continue;\r\n\r\n const facet = vf.getAttribute('facet')?.toUpperCase();\r\n if (facet !== 'PACKAGE') continue;\r\n\r\n const name = vf.getAttribute('name');\r\n if (!name) continue;\r\n\r\n const countAttr = vf.getAttribute('counter');\r\n const count = countAttr ? parseInt(countAttr, 10) : 0;\r\n const description = vf.getAttribute('text');\r\n\r\n const pkg: PackageNode = {\r\n name,\r\n numContents: count,\r\n };\r\n if (description) pkg.description = description;\r\n packages.push(pkg);\r\n }\r\n\r\n return packages;\r\n}\r\n\r\n/**\r\n * Get stats for a single package.\r\n */\r\nexport async function getPackageStats(\r\n client: AdtRequestor,\r\n packageName: string\r\n): AsyncResult<PackageNode, Error>;\r\n\r\n/**\r\n * Get stats for multiple packages.\r\n */\r\nexport async function getPackageStats(\r\n client: AdtRequestor,\r\n packageNames: string[]\r\n): AsyncResult<PackageNode[], Error>;\r\n\r\n/**\r\n * Get stats for one or more packages (name, description, numContents).\r\n *\r\n * Efficiently fetches only the requested packages by putting their names\r\n * in the preselection, rather than fetching all packages.\r\n */\r\nexport async function getPackageStats(\r\n client: AdtRequestor,\r\n packageNames: string | string[]\r\n): AsyncResult<PackageNode | PackageNode[], Error> {\r\n const isSingle = typeof packageNames === 'string';\r\n const names = isSingle ? [packageNames] : packageNames;\r\n if (names.length === 0) {\r\n return ok([]);\r\n }\r\n\r\n const body = constructPackageStatsBody(names);\r\n\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: '/sap/bc/adt/repository/informationsystem/virtualfolders/contents',\r\n headers: {\r\n 'Content-Type': 'application/vnd.sap.adt.repository.virtualfolders.request.v1+xml',\r\n 'Accept': 'application/vnd.sap.adt.repository.virtualfolders.result.v1+xml',\r\n },\r\n body,\r\n });\r\n\r\n if (requestErr) return err(requestErr);\r\n if (!response.ok) {\r\n const text = await response.text();\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Package stats fetch failed: ${errorMsg}`));\r\n }\r\n\r\n const xml = await response.text();\r\n const packages = parsePackageStats(xml)\r\n .filter(pkg => pkg.name !== 'SRIS_TEST_DATA_VFS_EMPTY');\r\n\r\n // Match the return type to the input type.\r\n if (isSingle) {\r\n if (packages.length === 0) {\r\n return err(new Error(`Package ${packageNames} not found`));\r\n }\r\n return ok(packages[0]!);\r\n }\r\n return ok(packages);\r\n}\r\n","/**\r\n * Packages — List available packages\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { AdtRequestor } from '../types';\r\nimport { extractError, safeParseXml } from '../../utils/xml';\r\nimport { getPackageStats } from './tree/packageStats';\r\n\r\nexport interface Package {\r\n name: string;\r\n description?: string;\r\n}\r\n\r\n/**\r\n * Get list of available packages\r\n *\r\n * Uses the ADT search API with DEVC/K object type to search for packages,\r\n * then enriches results with descriptions from the virtualfolders API.\r\n *\r\n * @param client - ADT client\r\n * @param filter - Package name filter pattern (default: '*' for all packages)\r\n * Examples: 'Z*' for custom packages, '$TMP' for local, 'ZSNAP*' for specific prefix\r\n * @returns Array of packages or error\r\n */\r\nexport interface GetPackagesOptions {\r\n filter?: string;\r\n includeDescriptions?: boolean;\r\n}\r\n\r\nexport async function getPackages(\r\n client: AdtRequestor,\r\n options: GetPackagesOptions = {}\r\n): AsyncResult<Package[], Error> {\r\n const { filter = '*', includeDescriptions = false } = options;\r\n\r\n // Build search parameters for package search.\r\n const params = new URLSearchParams([\r\n ['operation', 'quickSearch'],\r\n ['query', filter],\r\n ['maxResults', '10001'],\r\n ['objectType', 'DEVC/K'],\r\n ]);\r\n\r\n // Execute search request.\r\n const [response, requestErr] = await client.request({\r\n method: 'GET',\r\n path: `/sap/bc/adt/repository/informationsystem/search?${params.toString()}`,\r\n });\r\n\r\n // Validate successful response.\r\n if (requestErr) { return err(requestErr); }\r\n if (!response.ok) {\r\n const text = await response.text();\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Package search failed: ${errorMsg}`));\r\n }\r\n\r\n // Parse search results.\r\n const text = await response.text();\r\n const [doc, parseErr] = safeParseXml(text);\r\n if (parseErr) { return err(parseErr); }\r\n\r\n // Extract package names from object references.\r\n const packageNames: string[] = [];\r\n const objectRefs = doc.getElementsByTagNameNS('http://www.sap.com/adt/core', 'objectReference');\r\n\r\n for (let i = 0; i < objectRefs.length; i++) {\r\n const obj = objectRefs[i];\r\n if (!obj) return err(new Error('Invalid object reference in package search results'));\r\n\r\n const name = obj.getAttributeNS('http://www.sap.com/adt/core', 'name') || obj.getAttribute('adtcore:name');\r\n if (!name) return err(new Error('Package name missing in object reference'));\r\n packageNames.push(name);\r\n }\r\n\r\n if (packageNames.length === 0) return ok([]);\r\n if (!includeDescriptions) return ok(packageNames.map(name => ({ name })));\r\n\r\n // Enrich with descriptions from virtualfolders API (quickSearch doesn't return them).\r\n const [stats, statsErr] = await getPackageStats(client, packageNames);\r\n if (statsErr) {\r\n return ok(packageNames.map(name => ({ name })));\r\n }\r\n\r\n // Build lookup for descriptions.\r\n const descriptionMap = new Map<string, string>();\r\n for (const stat of stats) {\r\n if (stat.description) descriptionMap.set(stat.name, stat.description);\r\n }\r\n\r\n // Merge descriptions into results.\r\n const packages: Package[] = packageNames.map(name => {\r\n const pkg: Package = { name };\r\n const description = descriptionMap.get(name);\r\n if (description) pkg.description = description;\r\n return pkg;\r\n });\r\n\r\n return ok(packages);\r\n}\r\n","/**\r\n * Parsers — XML parsing and response transformation\r\n */\r\n\r\nimport type { Result } from '../../../../types/result';\r\nimport { ok, err } from '../../../../types/result';\r\nimport { getConfigByType } from '../../types';\r\nimport { safeParseXml } from '../../../utils/xml';\r\nimport type {\r\n TreeResponse,\r\n PackageNode,\r\n FolderNode,\r\n ObjectNode,\r\n TreeDiscoveryQuery,\r\n ParseResult,\r\n ParsedFolder,\r\n ParsedObject,\r\n} from './types';\r\n\r\n/**\r\n * Build query from package and path\r\n */\r\nexport function buildQueryFromPath(packageName: string, path?: string): TreeDiscoveryQuery {\r\n const query: TreeDiscoveryQuery = {\r\n PACKAGE: {\r\n name: packageName.startsWith('..') ? packageName : `..${packageName}`,\r\n hasChildrenOfSameFacet: false,\r\n },\r\n };\r\n\r\n if (!path) return query;\r\n\r\n const segments = path.split('/').filter(s => s.length > 0);\r\n\r\n // First segment = GROUP\r\n if (segments[0]) {\r\n query.GROUP = {\r\n name: segments[0],\r\n hasChildrenOfSameFacet: false,\r\n };\r\n }\r\n\r\n // Second segment = TYPE\r\n if (segments[1]) {\r\n query.TYPE = {\r\n name: segments[1],\r\n hasChildrenOfSameFacet: false,\r\n };\r\n }\r\n\r\n return query;\r\n}\r\n\r\n/**\r\n * Construct tree discovery request body\r\n */\r\nexport function constructTreeBody(\r\n query: TreeDiscoveryQuery,\r\n searchPattern: string,\r\n owner?: string\r\n): string {\r\n const facets: string[] = [];\r\n const specified: Record<string, string> = {};\r\n const sortedFacets = ['PACKAGE', 'GROUP', 'TYPE', 'API'];\r\n\r\n for (const facet of sortedFacets) {\r\n const value = query[facet as keyof TreeDiscoveryQuery];\r\n if (value) {\r\n specified[facet] = value.name;\r\n if (value.hasChildrenOfSameFacet) {\r\n facets.push(facet);\r\n }\r\n } else {\r\n facets.push(facet);\r\n }\r\n }\r\n\r\n // Build preselection XML for facets\r\n const preselections: string[] = [];\r\n\r\n // Add owner preselection first if specified\r\n if (owner) {\r\n preselections.push(` <vfs:preselection facet=\"owner\">\r\n <vfs:value>${owner}</vfs:value>\r\n </vfs:preselection>`);\r\n }\r\n\r\n // Add facet preselections\r\n for (const [facet, name] of Object.entries(specified)) {\r\n preselections.push(` <vfs:preselection facet=\"${facet.toLowerCase()}\">\r\n <vfs:value>${name}</vfs:value>\r\n </vfs:preselection>`);\r\n }\r\n\r\n const specifiedXml = preselections.join('\\n');\r\n\r\n // At object level (PACKAGE, GROUP, TYPE all specified), use empty facetorder\r\n // This returns objects with descriptions in the text attribute\r\n const atObjectLevel = query.PACKAGE && query.GROUP && query.TYPE;\r\n const facetorderXml = atObjectLevel || facets.length === 0\r\n ? ' <vfs:facetorder/>'\r\n : ` <vfs:facetorder>\\n${facets.map(f => ` <vfs:facet>${f.toLowerCase()}</vfs:facet>`).join('\\n')}\\n </vfs:facetorder>`;\r\n\r\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<vfs:virtualFoldersRequest xmlns:vfs=\"http://www.sap.com/adt/ris/virtualFolders\" objectSearchPattern=\"${searchPattern}\">\r\n${specifiedXml}\r\n${facetorderXml}\r\n</vfs:virtualFoldersRequest>`;\r\n}\r\n\r\n/**\r\n * Parse tree XML into structured data\r\n */\r\nexport function parseTreeXml(xml: string): Result<ParseResult, Error> {\r\n const [doc, parseErr] = safeParseXml(xml);\r\n if (parseErr) return err(parseErr);\r\n\r\n const folders: ParsedFolder[] = [];\r\n const objects: ParsedObject[] = [];\r\n\r\n // Process virtual folder elements\r\n const virtualFolders = doc.getElementsByTagName('vfs:virtualFolder');\r\n for (let i = 0; i < virtualFolders.length; i++) {\r\n const vf = virtualFolders[i];\r\n if (!vf) continue;\r\n\r\n const facet = vf.getAttribute('facet')?.toUpperCase();\r\n const name = vf.getAttribute('name');\r\n if (!name || !facet) continue;\r\n\r\n const validFacets = ['PACKAGE', 'GROUP', 'TYPE', 'API'] as const;\r\n if (!validFacets.includes(facet as typeof validFacets[number])) continue;\r\n\r\n const countAttr = vf.getAttribute('counter');\r\n const count = countAttr ? parseInt(countAttr, 10) : 0;\r\n const desc = vf.getAttribute('text');\r\n const displayNameAttr = vf.getAttribute('displayName');\r\n\r\n const technicalName = name.startsWith('..') ? name.substring(2) : name;\r\n const displayName = displayNameAttr || technicalName;\r\n\r\n const parsedFolder: ParsedFolder = {\r\n facet: facet as 'PACKAGE' | 'GROUP' | 'TYPE' | 'API',\r\n name: technicalName,\r\n displayName,\r\n count,\r\n };\r\n if (desc) parsedFolder.description = desc;\r\n folders.push(parsedFolder);\r\n }\r\n\r\n // Process object elements\r\n const objectElements = doc.getElementsByTagName('vfs:object');\r\n for (let i = 0; i < objectElements.length; i++) {\r\n const obj = objectElements[i];\r\n if (!obj) continue;\r\n\r\n const name = obj.getAttribute('name');\r\n const type = obj.getAttribute('type');\r\n if (!name || !type) continue;\r\n\r\n const config = getConfigByType(type);\r\n if (!config) continue;\r\n\r\n const text = obj.getAttribute('text');\r\n const parsedObj: ParsedObject = {\r\n name,\r\n objectType: config.label,\r\n extension: config.extension,\r\n };\r\n if (text) parsedObj.description = text;\r\n objects.push(parsedObj);\r\n }\r\n\r\n return ok({ folders, objects });\r\n}\r\n\r\n/**\r\n * Transform parsed data to TreeResponse\r\n */\r\nexport function transformToTreeResponse(parsed: ParseResult, queryPackage: string): TreeResponse {\r\n const packages: PackageNode[] = [];\r\n const folders: FolderNode[] = [];\r\n\r\n for (const folder of parsed.folders) {\r\n if (folder.facet === 'PACKAGE' && folder.name === queryPackage) continue;\r\n\r\n if (folder.facet === 'PACKAGE') {\r\n const pkg: PackageNode = {\r\n name: folder.name,\r\n numContents: folder.count,\r\n };\r\n if (folder.description) pkg.description = folder.description;\r\n packages.push(pkg);\r\n } else {\r\n folders.push({\r\n name: folder.name,\r\n displayName: folder.displayName,\r\n numContents: folder.count,\r\n });\r\n }\r\n }\r\n\r\n const objects: ObjectNode[] = parsed.objects.map(obj => {\r\n const node: ObjectNode = {\r\n name: obj.name,\r\n objectType: obj.objectType,\r\n extension: obj.extension,\r\n };\r\n if (obj.description) node.description = obj.description;\r\n return node;\r\n });\r\n\r\n return { packages, folders, objects };\r\n}\r\n","/**\r\n * ChildPackages — Fetch child packages via virtualfolders endpoint\r\n *\r\n * Unlike getSubpackages (nodestructure), this returns packages WITH counts and descriptions.\r\n *\r\n * Key difference from directly-assigned objects:\r\n * - Package preselection WITHOUT `..` prefix = child packages\r\n * - Package preselection WITH `..` prefix = directly assigned objects\r\n * - hasChildrenOfSameFacet: true = include package facet in facetorder\r\n */\r\n\r\nimport type { AsyncResult } from '../../../../types/result';\r\nimport { ok, err } from '../../../../types/result';\r\nimport type { AdtRequestor } from '../../types';\r\nimport { extractError } from '../../../utils/xml';\r\nimport type { PackageNode, TreeDiscoveryQuery } from './types';\r\nimport { constructTreeBody, parseTreeXml } from './parsers';\r\n\r\n/**\r\n * Fetch child packages for a given package using virtualfolders endpoint.\r\n *\r\n * Request format (no .. prefix = child packages):\r\n * <vfs:preselection facet=\"package\">\r\n * <vfs:value>BASIS</vfs:value>\r\n * </vfs:preselection>\r\n * <vfs:facetorder>\r\n * <vfs:facet>package</vfs:facet>\r\n * <vfs:facet>group</vfs:facet>\r\n * <vfs:facet>type</vfs:facet>\r\n * </vfs:facetorder>\r\n */\r\nexport async function fetchChildPackages(\r\n client: AdtRequestor,\r\n parentPackage: string\r\n): AsyncResult<PackageNode[], Error> {\r\n // Build query WITHOUT .. prefix and WITH hasChildrenOfSameFacet: true\r\n const query: TreeDiscoveryQuery = {\r\n PACKAGE: {\r\n name: parentPackage,\r\n hasChildrenOfSameFacet: true,\r\n },\r\n };\r\n\r\n const body = constructTreeBody(query, '*');\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: '/sap/bc/adt/repository/informationsystem/virtualfolders/contents',\r\n headers: {\r\n 'Content-Type': 'application/vnd.sap.adt.repository.virtualfolders.request.v1+xml',\r\n 'Accept': 'application/vnd.sap.adt.repository.virtualfolders.result.v1+xml',\r\n },\r\n body,\r\n });\r\n\r\n if (requestErr) return err(requestErr);\r\n if (!response.ok) {\r\n const text = await response.text();\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Failed to fetch child packages: ${errorMsg}`));\r\n }\r\n\r\n const text = await response.text();\r\n const [parsed, parseErr] = parseTreeXml(text);\r\n if (parseErr) return err(parseErr);\r\n\r\n // Filter to PACKAGE facet folders, excluding the parent package itself\r\n // The response includes a `..{parentPackage}` entry (directly assigned objects)\r\n // which, after the `..` prefix is stripped, becomes just `{parentPackage}`\r\n const parentUpper = parentPackage.toUpperCase();\r\n const packages: PackageNode[] = parsed.folders\r\n .filter(f => f.facet === 'PACKAGE' && f.name.toUpperCase() !== parentUpper)\r\n .map(f => {\r\n const pkg: PackageNode = {\r\n name: f.name,\r\n numContents: f.count,\r\n };\r\n if (f.description) pkg.description = f.description;\r\n return pkg;\r\n });\r\n\r\n return ok(packages);\r\n}\r\n","/**\r\n * VirtualFolders — Fetch folder contents\r\n */\r\n\r\nimport type { AsyncResult } from '../../../../types/result';\r\nimport { err } from '../../../../types/result';\r\nimport type { AdtRequestor } from '../../types';\r\nimport { extractError } from '../../../utils/xml';\r\nimport type { TreeDiscoveryQuery, ParseResult } from './types';\r\nimport { constructTreeBody, parseTreeXml } from './parsers';\r\n\r\n/**\r\n * Fetch virtualfolders contents\r\n */\r\nexport async function fetchVirtualFolders(\r\n client: AdtRequestor,\r\n query: TreeDiscoveryQuery,\r\n owner?: string\r\n): AsyncResult<ParseResult, Error> {\r\n const body = constructTreeBody(query, '*', owner);\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: '/sap/bc/adt/repository/informationsystem/virtualfolders/contents',\r\n headers: {\r\n 'Content-Type': 'application/vnd.sap.adt.repository.virtualfolders.request.v1+xml',\r\n 'Accept': 'application/vnd.sap.adt.repository.virtualfolders.result.v1+xml',\r\n },\r\n body,\r\n });\r\n\r\n if (requestErr) return err(requestErr);\r\n if (!response.ok) {\r\n const text = await response.text();\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Tree discovery failed: ${errorMsg}`));\r\n }\r\n\r\n const text = await response.text();\r\n return parseTreeXml(text);\r\n}\r\n","/**\r\n * Tree — Hierarchical tree browsing for packages\r\n */\r\n\r\nimport type { AsyncResult } from '../../../../types/result';\r\nimport { ok, err } from '../../../../types/result';\r\nimport type { TreeQuery } from '../../../../types/requests';\r\nimport type { AdtRequestor } from '../../types';\r\nimport type { TreeResponse, PackageNode } from './types';\r\nimport { fetchChildPackages } from './childPackages';\r\nimport { buildQueryFromPath, transformToTreeResponse } from './parsers';\r\nimport { fetchVirtualFolders } from './virtualFolders';\r\n\r\n// Re-export types\r\nexport type {\r\n TreeResponse,\r\n PackageNode,\r\n FolderNode,\r\n ObjectNode,\r\n} from './types';\r\n\r\n/**\r\n * Get hierarchical tree contents for a package.\r\n * If package is omitted, returns top-level packages only.\r\n */\r\nexport async function getTree(\r\n client: AdtRequestor,\r\n query: TreeQuery = {}\r\n): AsyncResult<TreeResponse, Error> {\r\n // If no package specified, return only top-level packages using virtualfolders\r\n // (nodestructure endpoint doesn't return object counts)\r\n if (!query.package) {\r\n const [parsed, parseErr] = await fetchVirtualFolders(client, {}, query.owner);\r\n if (parseErr) return err(parseErr);\r\n\r\n // Filter to only PACKAGE facet folders and transform to PackageNode[]\r\n const packages: PackageNode[] = parsed.folders\r\n .filter(f => f.facet === 'PACKAGE')\r\n .map(f => {\r\n const pkg: PackageNode = {\r\n name: f.name,\r\n numContents: f.count,\r\n };\r\n if (f.description) pkg.description = f.description;\r\n return pkg;\r\n });\r\n\r\n return ok({\r\n packages,\r\n folders: [],\r\n objects: [],\r\n });\r\n }\r\n\r\n // If no path specified, fetch child packages via virtualfolders\r\n let packages: PackageNode[] = [];\r\n\r\n if (!query.path) {\r\n const [childPkgs, childErr] = await fetchChildPackages(client, query.package);\r\n if (childErr) return err(childErr);\r\n packages = childPkgs;\r\n }\r\n\r\n // Build internal query from path segments\r\n const internalQuery = buildQueryFromPath(query.package, query.path);\r\n\r\n // Execute virtualfolders for folders/objects\r\n const [parsed, parseErr] = await fetchVirtualFolders(client, internalQuery, query.owner);\r\n if (parseErr) return err(parseErr);\r\n\r\n const result = transformToTreeResponse(parsed, query.package);\r\n result.packages = packages;\r\n\r\n return ok(result);\r\n}\r\n","/**\r\n * Transports — List transport requests for a package\r\n */\r\n\r\nimport type { Result, AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { AdtRequestor } from '../types';\r\n\r\n/**\r\n * Transport request\r\n */\r\nexport interface Transport {\r\n id: string;\r\n description: string;\r\n owner: string;\r\n}\r\n\r\nimport { extractError, safeParseXml } from '../../utils/xml';\r\n\r\n/**\r\n * Get transports for a package\r\n *\r\n * Uses the transportchecks endpoint to query available transports\r\n * for a given package.\r\n *\r\n * @param client - ADT client\r\n * @param packageName - Package name to query transports for\r\n * @returns Array of transports or error\r\n */\r\nexport async function getTransports(\r\n client: AdtRequestor,\r\n packageName: string\r\n): AsyncResult<Transport[], Error> {\r\n const contentType = 'application/vnd.sap.as+xml; charset=UTF-8; dataname=com.sap.adt.transport.service.checkData';\r\n\r\n // Build XML request body (same format as original SNAP-Relay-API)\r\n const body = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<asx:abap version=\"1.0\" xmlns:asx=\"http://www.sap.com/abapxml\">\r\n <asx:values>\r\n <DATA>\r\n <PGMID></PGMID>\r\n <OBJECT></OBJECT>\r\n <OBJECTNAME></OBJECTNAME>\r\n <DEVCLASS>${packageName}</DEVCLASS>\r\n <SUPER_PACKAGE></SUPER_PACKAGE>\r\n <OPERATION>I</OPERATION>\r\n <URI>/sap/bc/adt/ddic/ddl/sources/zsnap_test4transports</URI>\r\n </DATA>\r\n </asx:values>\r\n</asx:abap>`;\r\n\r\n // Execute transport check request\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: '/sap/bc/adt/cts/transportchecks',\r\n headers: {\r\n 'Accept': contentType,\r\n 'Content-Type': contentType,\r\n },\r\n body,\r\n });\r\n\r\n // Validate successful response\r\n if (requestErr) return err(requestErr);\r\n if (!response.ok) {\r\n const text = await response.text();\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Failed to fetch transports for package ${packageName}: ${errorMsg}`));\r\n }\r\n\r\n // Parse transports from response\r\n const text = await response.text();\r\n\r\n const [transports, parseErr] = extractTransports(text);\r\n if (parseErr) return err(parseErr);\r\n return ok(transports);\r\n}\r\n\r\n/**\r\n * Extract transports from XML response.\r\n *\r\n * Response contains REQ_HEADER elements with:\r\n * - TRKORR: Transport ID\r\n * - AS4USER: Owner username\r\n * - AS4TEXT: Description\r\n */\r\nfunction extractTransports(xml: string): Result<Transport[], Error> {\r\n const [doc, parseErr] = safeParseXml(xml);\r\n if (parseErr) return err(parseErr);\r\n\r\n const transports: Transport[] = [];\r\n const reqHeaders = doc.getElementsByTagName('REQ_HEADER');\r\n\r\n for (let i = 0; i < reqHeaders.length; i++) {\r\n const header = reqHeaders[i];\r\n if (!header) continue;\r\n\r\n const id = header.getElementsByTagName('TRKORR')[0]?.textContent;\r\n const owner = header.getElementsByTagName('AS4USER')[0]?.textContent;\r\n const description = header.getElementsByTagName('AS4TEXT')[0]?.textContent;\r\n if (!id) continue;\r\n\r\n transports.push({\r\n id,\r\n description: description || '',\r\n owner: owner || '',\r\n });\r\n }\r\n\r\n return ok(transports);\r\n}\r\n","/**\r\n * Preview Parser — Parse data preview XML responses\r\n *\r\n * Internal helper used by data.ts, distinct.ts, and count.ts\r\n */\r\n\r\nimport type { Result } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport { safeParseXml } from '../../utils/xml';\r\n\r\n/**\r\n * Data preview result (columnar format)\r\n */\r\nexport interface DataFrame {\r\n columns: ColumnInfo[];\r\n rows: unknown[][];\r\n totalRows?: number;\r\n}\r\n\r\nexport interface ColumnInfo {\r\n name: string;\r\n dataType: string;\r\n label?: string;\r\n}\r\n\r\n/**\r\n * Parse data preview XML response\r\n *\r\n * Handles two XML formats:\r\n * 1. Regular queries: Have <metadata> elements with column definitions\r\n * 2. Aggregate queries (COUNT, GROUP BY): No metadata, infer columns from <dataSet> elements\r\n *\r\n * @param xml - XML response from SAP\r\n * @param maxRows - Maximum rows to parse\r\n * @param isTable - Whether source is a table (affects column name attribute)\r\n * @returns DataFrame or error\r\n */\r\nexport function parseDataPreview(\r\n xml: string,\r\n maxRows: number,\r\n isTable: boolean\r\n): Result<DataFrame, Error> {\r\n // Parse XML response.\r\n const [doc, parseErr] = safeParseXml(xml);\r\n if (parseErr) { return err(parseErr); }\r\n\r\n const namespace = 'http://www.sap.com/adt/dataPreview';\r\n\r\n // Extract column metadata from response (if present).\r\n const metadataElements = doc.getElementsByTagNameNS(namespace, 'metadata');\r\n const columns: ColumnInfo[] = [];\r\n\r\n for (let i = 0; i < metadataElements.length; i++) {\r\n const meta = metadataElements[i];\r\n if (!meta) continue;\r\n\r\n // Tables use 'name', views use 'camelCaseName'.\r\n const nameAttr = isTable ? 'name' : 'camelCaseName';\r\n const name = meta.getAttributeNS(namespace, nameAttr) || meta.getAttribute('name');\r\n const dataType = meta.getAttributeNS(namespace, 'colType') || meta.getAttribute('colType');\r\n if (!name || !dataType) continue;\r\n\r\n columns.push({ name, dataType });\r\n }\r\n\r\n // Extract data values organized by column.\r\n const dataSetElements = doc.getElementsByTagNameNS(namespace, 'dataSet');\r\n\r\n // If no metadata, infer columns from dataSet elements (aggregate queries).\r\n if (columns.length === 0 && dataSetElements.length > 0) {\r\n for (let i = 0; i < dataSetElements.length; i++) {\r\n const dataSet = dataSetElements[i];\r\n if (!dataSet) continue;\r\n // Use column index as name for aggregate results.\r\n const name = dataSet.getAttributeNS(namespace, 'columnName')\r\n || dataSet.getAttribute('columnName')\r\n || `column${i}`;\r\n columns.push({ name, dataType: 'unknown' });\r\n }\r\n }\r\n\r\n // Still no columns - return empty DataFrame.\r\n if (columns.length === 0) {\r\n return ok({ columns: [], rows: [], totalRows: 0 });\r\n }\r\n\r\n const columnData: string[][] = Array.from({ length: columns.length }, () => []);\r\n\r\n for (let i = 0; i < dataSetElements.length; i++) {\r\n const dataSet = dataSetElements[i];\r\n if (!dataSet) continue;\r\n\r\n const dataElements = dataSet.getElementsByTagNameNS(namespace, 'data');\r\n for (let j = 0; j < dataElements.length; j++) {\r\n const data = dataElements[j];\r\n if (!data) continue;\r\n\r\n const value = data.textContent?.trim() || '';\r\n columnData[i]!.push(value);\r\n }\r\n }\r\n\r\n // Transform column-oriented data into row-oriented format.\r\n const rows: unknown[][] = [];\r\n const rowCount = columnData[0]?.length || 0;\r\n for (let i = 0; i < Math.min(rowCount, maxRows); i++) {\r\n const row: unknown[] = [];\r\n for (let j = 0; j < columns.length; j++) {\r\n row.push(columnData[j]![i]);\r\n }\r\n rows.push(row);\r\n }\r\n\r\n // Build final DataFrame result.\r\n const dataFrame: DataFrame = {\r\n columns,\r\n rows,\r\n totalRows: rowCount,\r\n };\r\n\r\n return ok(dataFrame);\r\n}\r\n","/**\r\n * Data Preview — Execute SQL queries against table/view data\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { PreviewSQL } from '../../../types/requests';\r\nimport type { AdtRequestor } from '../types';\r\nimport type { DataFrame } from './previewParser';\r\nimport { getConfigByExtension } from '../types';\r\nimport { extractError } from '../../utils/xml';\r\nimport { debug } from '../../utils/logging';\r\nimport { parseDataPreview } from './previewParser';\r\n\r\n/**\r\n * Execute SQL query against table/view data\r\n *\r\n * @param client - ADT client\r\n * @param query - Preview query with SQL\r\n * @returns DataFrame or error\r\n */\r\nexport async function previewData(\r\n client: AdtRequestor,\r\n query: PreviewSQL\r\n): AsyncResult<DataFrame, Error> {\r\n // Get config by objectType.\r\n const extension = query.objectType === 'table' ? 'astabldt' : 'asddls';\r\n const config = getConfigByExtension(extension);\r\n if (!config?.dpEndpoint || !config?.dpParam) {\r\n return err(new Error(`Data preview not supported for object type: ${query.objectType}`));\r\n }\r\n\r\n // Execute request with caller-provided SQL.\r\n const limit = query.limit ?? 100;\r\n debug(`Data preview: endpoint=${config.dpEndpoint}, param=${config.dpParam}=${query.objectName}`);\r\n debug(`SQL: ${query.sqlQuery}`);\r\n\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: `/sap/bc/adt/datapreview/${config.dpEndpoint}`,\r\n params: {\r\n 'rowNumber': limit,\r\n [config.dpParam]: query.objectName,\r\n },\r\n headers: {\r\n 'Accept': 'application/vnd.sap.adt.datapreview.table.v1+xml',\r\n 'Content-Type': 'text/plain',\r\n },\r\n body: query.sqlQuery,\r\n });\r\n\r\n // Handle errors.\r\n if (requestErr) { return err(requestErr); }\r\n if (!response.ok) {\r\n const text = await response.text();\r\n debug(`Data preview error response: ${text.substring(0, 500)}`);\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Data preview failed: ${errorMsg}`));\r\n }\r\n\r\n // Parse response.\r\n const text = await response.text();\r\n const [dataFrame, parseErr] = parseDataPreview(text, limit, query.objectType === 'table');\r\n if (parseErr) { return err(parseErr); }\r\n return ok(dataFrame);\r\n}\r\n","/**\r\n * Freestyle SQL Query — Execute arbitrary OpenSQL via the freestyle endpoint\r\n *\r\n * The freestyle endpoint supports full OpenSQL including COUNT(*), GROUP BY, JOINs, etc.\r\n * Use this for aggregate queries; use dataPreview.ts for simple table/view previews.\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { AdtRequestor } from '../types';\r\nimport type { DataFrame } from './previewParser';\r\nimport { extractError } from '../../utils/xml';\r\nimport { debug } from '../../utils/logging';\r\nimport { parseDataPreview } from './previewParser';\r\n\r\nconst DEFAULT_ROW_LIMIT = 100;\r\n\r\n/**\r\n * Execute arbitrary OpenSQL query via the freestyle endpoint\r\n *\r\n * @param client - ADT client\r\n * @param sqlQuery - OpenSQL SELECT statement\r\n * @param limit - Max rows to return (default 100)\r\n * @returns DataFrame or error\r\n */\r\nexport async function freestyleQuery(\r\n client: AdtRequestor,\r\n sqlQuery: string,\r\n limit = DEFAULT_ROW_LIMIT\r\n): AsyncResult<DataFrame, Error> {\r\n debug(`Freestyle query: ${sqlQuery}`);\r\n\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: '/sap/bc/adt/datapreview/freestyle',\r\n params: {\r\n 'rowNumber': limit,\r\n },\r\n headers: {\r\n 'Accept': 'application/xml, application/vnd.sap.adt.datapreview.table.v1+xml',\r\n 'Content-Type': 'text/plain',\r\n },\r\n body: sqlQuery,\r\n });\r\n\r\n if (requestErr) return err(requestErr);\r\n\r\n if (!response.ok) {\r\n const text = await response.text();\r\n debug(`Freestyle query error response: ${text.substring(0, 500)}`);\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Freestyle query failed: ${errorMsg}`));\r\n }\r\n\r\n const text = await response.text();\r\n const [dataFrame, parseErr] = parseDataPreview(text, limit, true);\r\n if (parseErr) return err(parseErr);\r\n\r\n return ok(dataFrame);\r\n}\r\n","/**\r\n * Query Builder — Optional helper for building SQL queries for data preview\r\n */\r\n\r\nimport { type Result, ok, err } from '../../../types/result';\r\nimport type { PreviewSQL } from '../../../types/requests';\r\n\r\nexport function quoteString(value: string | number): string {\r\n return typeof value == \"string\" ? \"'\" + value + \"'\" : \"\" + value;\r\n}\r\n\r\n// Where Clause Types and Converters\r\nexport type BasicFilter = {\r\n type: \"basic\";\r\n field: string;\r\n value: string | number;\r\n operator: \"=\" | \"<>\" | \"<\" | \"<=\" | \">\" | \">=\" | \"like\" | \"not like\";\r\n}\r\n\r\nexport function basicFilterToWhere(filter: BasicFilter): string {\r\n return `${filter.field} ${filter.operator} ${quoteString(filter.value)}`;\r\n}\r\n\r\nexport type BetweenFilter = {\r\n type: \"between\";\r\n field: string;\r\n minimum: string | number;\r\n maximum: string | number;\r\n}\r\n\r\nexport function betweenFilterToWhere(filter: BetweenFilter): string {\r\n return `${filter.field} between ${quoteString(filter.minimum)} and ${quoteString(filter.maximum)}`;\r\n}\r\n\r\nexport type ListFilter = {\r\n type: \"list\";\r\n field: string;\r\n values: (string | number)[];\r\n include: boolean;\r\n}\r\n\r\nexport function listFilterToWhere(filter: ListFilter): string {\r\n return `${filter.field} ${filter.include ? \"\" : \"not \"}in ( ${filter.values.map(quoteString).join(\", \")} )`;\r\n}\r\n\r\nexport type QueryFilter = BasicFilter | BetweenFilter | ListFilter;\r\n\r\nfunction queryFilterToWhere(filter: QueryFilter): string {\r\n if (filter.type === \"list\") return listFilterToWhere(filter);\r\n if (filter.type === \"between\") return betweenFilterToWhere(filter);\r\n return basicFilterToWhere(filter);\r\n}\r\n\r\nexport function queryFiltersToWhere(filters: QueryFilter[]): string {\r\n if (filters.length === 0) return \"\";\r\n return `\\nwhere ${filters.map(queryFilterToWhere).join(\" and \")}`;\r\n}\r\n\r\n// Order By Types and Converters\r\nexport type Sorting = {\r\n field: string;\r\n direction: \"ascending\" | \"descending\";\r\n}\r\n\r\nexport function sortingsToOrderBy(sortings: Sorting[]): string {\r\n if (sortings.length === 0) return \"\";\r\n return `\\norder by ${sortings.map(s => `${s.field} ${s.direction}`).join(\", \")}`;\r\n}\r\n\r\n// Aggregation Types\r\nexport type Aggregation = {\r\n field: string;\r\n function: \"count\" | \"sum\" | \"avg\" | \"min\" | \"max\";\r\n}\r\n\r\nexport function fieldsToGroupbyClause(fields: string[]): string {\r\n if (fields.length === 0) return \"\";\r\n return `\\ngroup by ${fields.join(\", \")}`;\r\n}\r\n\r\nexport function aggregationToFieldDefinition(aggregation: Aggregation): string {\r\n if (aggregation.function === \"count\") {\r\n return `count( distinct main~${aggregation.field} ) as ${aggregation.field}`;\r\n }\r\n return `${aggregation.function}( main~${aggregation.field} ) as ${aggregation.field}`;\r\n}\r\n\r\n// Parameter Types\r\nexport type Parameter = {\r\n name: string;\r\n value: string | number;\r\n}\r\n\r\nexport function parametersToSQLParams(params: Parameter[]): string {\r\n if (params.length === 0) return \"\";\r\n return `( ${params.map(p => `${p.name} = ${quoteString(p.value)}`).join(\", \")})`;\r\n}\r\n\r\n// Query Type\r\nexport type DataPreviewQuery = {\r\n objectName: string;\r\n objectType: 'table' | 'view';\r\n limit?: number;\r\n\r\n fields: string[];\r\n parameters?: Parameter[];\r\n filters?: QueryFilter[];\r\n sortings?: Sorting[];\r\n aggregations?: Aggregation[];\r\n}\r\n\r\nexport function buildSQLQuery(query: DataPreviewQuery): Result<PreviewSQL> {\r\n // Isolate filters, sortings, and aggregations with defaults.\r\n const [parameters, filters, sortings, aggregations] = [query.parameters ?? [], query.filters ?? [], query.sortings ?? [], query.aggregations ?? []];\r\n const groupingFields = query.fields.filter(f => !aggregations.find(a => a.field === f));\r\n\r\n // Do some validation.\r\n if (sortings.filter(s => !query.fields.includes(s.field)).length > 0) {\r\n return err(new Error(\"Sorting fields must be included in the selected fields.\"));\r\n }\r\n\r\n // Build main field selection.\r\n let selectClause = \"select\\n\";\r\n\r\n const fieldSelections: string[] = [];\r\n for (const field of query.fields) {\r\n const aggregation = aggregations.find(a => a.field === field);\r\n if (aggregation) {\r\n fieldSelections.push(`\\t${aggregationToFieldDefinition(aggregation)}`);\r\n continue;\r\n }\r\n fieldSelections.push(`\\tmain~${field}`);\r\n }\r\n selectClause += fieldSelections.join(\",\\n\") + `\\nfrom ${query.objectName}${parametersToSQLParams(parameters)} as main\\n`;\r\n\r\n // Build the rest of the clauses.\r\n const [whereClause, groupbyClause, orderbyClause] = [queryFiltersToWhere(filters), aggregations.length ? fieldsToGroupbyClause(groupingFields) : \"\", sortingsToOrderBy(sortings)];\r\n\r\n const result: PreviewSQL = {\r\n objectName: query.objectName,\r\n objectType: query.objectType,\r\n sqlQuery: `${selectClause}${whereClause}${groupbyClause}${orderbyClause}`,\r\n };\r\n if (query.limit !== undefined) result.limit = query.limit;\r\n return ok(result);\r\n}\r\n","/**\r\n * Distinct Values — Get distinct column values with counts\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { AdtRequestor } from '../types';\r\nimport { freestyleQuery } from './freestyle';\r\nimport { type Parameter, parametersToSQLParams } from './queryBuilder';\r\n\r\n/**\r\n * Distinct values result\r\n */\r\nexport interface DistinctResult {\r\n column: string;\r\n values: Array<{\r\n value: unknown;\r\n count: number;\r\n }>;\r\n}\r\n\r\nconst MAX_ROW_COUNT = 50000;\r\n\r\n/**\r\n * Get distinct values for a column with counts, ordered by count descending\r\n *\r\n * Uses the freestyle endpoint which supports COUNT(*) and GROUP BY.\r\n */\r\nexport async function getDistinctValues(\r\n client: AdtRequestor,\r\n objectName: string,\r\n parameters: Parameter[],\r\n column: string,\r\n _objectType: 'table' | 'view' = 'view'\r\n): AsyncResult<DistinctResult, Error> {\r\n const columnName = column.toUpperCase();\r\n const sqlQuery = `SELECT ${columnName} AS value, COUNT(*) AS value_count FROM ${objectName}${parametersToSQLParams(parameters)} GROUP BY ${columnName} ORDER BY value_count DESCENDING`;\r\n\r\n const [dataFrame, error] = await freestyleQuery(client, sqlQuery, MAX_ROW_COUNT);\r\n\r\n if (error) {\r\n return err(new Error(`Distinct values query failed: ${error.message}`));\r\n }\r\n\r\n // Transform DataFrame to DistinctResult.\r\n const values = dataFrame.rows.map(row => ({\r\n value: row[0],\r\n count: parseInt(String(row[1]), 10),\r\n }));\r\n\r\n return ok({ column, values });\r\n}\r\n","/**\r\n * Count Rows — Get total row count for table/view\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { AdtRequestor } from '../types';\r\nimport { freestyleQuery } from './freestyle';\r\nimport { type Parameter, parametersToSQLParams } from './queryBuilder';\r\n\r\n/**\r\n * Count total rows in a table or view\r\n *\r\n * Uses the freestyle endpoint which supports COUNT(*) aggregation.\r\n */\r\nexport async function countRows(\r\n client: AdtRequestor,\r\n objectName: string,\r\n _objectType: 'table' | 'view',\r\n parameters: Parameter[] = []\r\n): AsyncResult<number, Error> {\r\n const sqlQuery = `SELECT COUNT(*) AS row_count FROM ${objectName}${parametersToSQLParams(parameters)}`;\r\n\r\n const [dataFrame, error] = await freestyleQuery(client, sqlQuery, 1);\r\n\r\n if (error) {\r\n return err(new Error(`Row count query failed: ${error.message}`));\r\n }\r\n\r\n // Extract count from first row, first column.\r\n const countValue = dataFrame.rows[0]?.[0];\r\n if (countValue === undefined) {\r\n return err(new Error('No count value returned'));\r\n }\r\n\r\n const count = parseInt(String(countValue), 10);\r\n if (isNaN(count)) {\r\n return err(new Error('Invalid count value returned'));\r\n }\r\n\r\n return ok(count);\r\n}\r\n","/**\r\n * Search Objects — Quick search by name pattern\r\n */\r\n\r\nimport type { Result, AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { AdtRequestor } from '../types';\r\n\r\n/**\r\n * Search result\r\n */\r\nexport interface SearchResult {\r\n name: string;\r\n uri: string;\r\n extension: string;\r\n package: string;\r\n description?: string;\r\n objectType: string;\r\n}\r\n\r\nimport { getConfigByType, getAllTypes } from '../types';\r\nimport { extractError, safeParseXml } from '../../utils/xml';\r\n\r\n/**\r\n * Search for objects by name pattern\r\n *\r\n * @param client - ADT client\r\n * @param query - Search pattern (supports wildcards)\r\n * @param types - Optional array of object type filters\r\n * @returns Array of matching objects or error\r\n */\r\nexport interface SearchOptions {\r\n types?: string[];\r\n includePackages?: boolean;\r\n}\r\n\r\nexport async function searchObjects(\r\n client: AdtRequestor,\r\n query: string,\r\n options?: SearchOptions\r\n): AsyncResult<SearchResult[], Error> {\r\n const { types, includePackages = true } = options ?? {};\r\n // Build search parameters.\r\n const searchPattern = query || '*';\r\n const objectTypes = types && types.length > 0 ? types : getAllTypes();\r\n\r\n // Construct query parameters (matching Python reference exactly).\r\n const params: Array<[string, string]> = [\r\n ['operation', 'quickSearch'],\r\n ['query', searchPattern],\r\n ['maxResults', '10001'],\r\n ];\r\n for (const type of objectTypes) {\r\n params.push(['objectType', type]);\r\n }\r\n\r\n // Build URL search params.\r\n const urlParams = new URLSearchParams();\r\n for (const [key, value] of params) {\r\n urlParams.append(key, value);\r\n }\r\n\r\n // Execute search request.\r\n const [response, requestErr] = await client.request({\r\n method: 'GET',\r\n path: `/sap/bc/adt/repository/informationsystem/search?${urlParams.toString()}`,\r\n });\r\n\r\n // Validate successful response.\r\n if (requestErr) { return err(requestErr); }\r\n if (!response.ok) {\r\n const text = await response.text();\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Search failed: ${errorMsg}`));\r\n }\r\n\r\n // Parse search results from response.\r\n const text = await response.text();\r\n const [results, parseErr] = parseSearchResults(text);\r\n if (parseErr) { return err(parseErr); }\r\n\r\n // Enrich results with package info from object properties endpoint.\r\n if (includePackages) await enrichWithPackages(client, results);\r\n return ok(results);\r\n}\r\n\r\n// Fetch package info for results that are missing it.\r\nasync function enrichWithPackages(client: AdtRequestor, results: SearchResult[]): Promise<void> {\r\n const needsPackage = results.filter(r => !r.package);\r\n if (needsPackage.length === 0) return;\r\n\r\n // Fetch object properties in parallel.\r\n const promises = needsPackage.map(async (result) => {\r\n const encodedUri = encodeURIComponent(result.uri);\r\n const [response, reqErr] = await client.request({\r\n method: 'GET',\r\n path: `/sap/bc/adt/repository/informationsystem/objectproperties/values?uri=${encodedUri}&facet=package`,\r\n });\r\n if (reqErr || !response.ok) return;\r\n\r\n const text = await response.text();\r\n const [doc, parseErr] = safeParseXml(text);\r\n if (parseErr) return;\r\n\r\n // Package is an attribute on the opr:object element.\r\n const oprNs = 'http://www.sap.com/adt/ris/objectProperties';\r\n const objEl = doc.getElementsByTagNameNS(oprNs, 'object')[0];\r\n if (!objEl) return;\r\n\r\n const pkg = objEl.getAttribute('package');\r\n if (pkg) result.package = pkg;\r\n });\r\n\r\n await Promise.all(promises);\r\n}\r\n\r\n// Parse search results from XML.\r\nfunction parseSearchResults(xml: string): Result<SearchResult[], Error> {\r\n // Parse XML response.\r\n const [doc, parseErr] = safeParseXml(xml);\r\n if (parseErr) { return err(parseErr); }\r\n\r\n // Extract object reference elements.\r\n const results: SearchResult[] = [];\r\n const objectRefs = doc.getElementsByTagNameNS('http://www.sap.com/adt/core', 'objectReference');\r\n\r\n // Process each object reference.\r\n for (let i = 0; i < objectRefs.length; i++) {\r\n const obj = objectRefs[i];\r\n if (!obj) continue;\r\n\r\n // Extract object metadata.\r\n const name = obj.getAttributeNS('http://www.sap.com/adt/core', 'name') || obj.getAttribute('adtcore:name');\r\n const type = obj.getAttributeNS('http://www.sap.com/adt/core', 'type') || obj.getAttribute('adtcore:type');\r\n const uri = obj.getAttributeNS('http://www.sap.com/adt/core', 'uri') || obj.getAttribute('adtcore:uri');\r\n const description = obj.getAttributeNS('http://www.sap.com/adt/core', 'description') || obj.getAttribute('adtcore:description');\r\n if (!name || !type || !uri) continue;\r\n\r\n // Look up object type configuration.\r\n const config = getConfigByType(type);\r\n if (!config) continue;\r\n\r\n // Extract package reference if available.\r\n const packageRef = obj.getElementsByTagNameNS('http://www.sap.com/adt/core', 'packageRef')[0];\r\n const packageName = packageRef\r\n ? (packageRef.getAttributeNS('http://www.sap.com/adt/core', 'name') || packageRef.getAttribute('adtcore:name'))\r\n : '';\r\n\r\n // Build search result object.\r\n const result: SearchResult = {\r\n name,\r\n uri,\r\n extension: config.extension,\r\n package: packageName || '',\r\n objectType: config.label,\r\n };\r\n if (description) {\r\n result.description = description;\r\n }\r\n results.push(result);\r\n }\r\n\r\n return ok(results);\r\n}\r\n","/**\r\n * Where-Used — Find object dependencies\r\n */\r\n\r\nimport type { Result, AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { ObjectRef } from '../../../types/requests';\r\nimport type { AdtRequestor } from '../types';\r\n\r\n/**\r\n * Where-used dependency\r\n */\r\nexport interface Dependency {\r\n name: string;\r\n extension: string;\r\n package: string;\r\n usageType: string;\r\n}\r\n\r\nimport { getConfigByType, getConfigByExtension } from '../types';\r\nimport { extractError, safeParseXml } from '../../utils/xml';\r\n\r\n/**\r\n * Find where an object is used (dependencies)\r\n *\r\n * @param client - ADT client\r\n * @param object - Object to analyze\r\n * @returns Array of dependent objects or error\r\n */\r\nexport async function findWhereUsed(\r\n client: AdtRequestor,\r\n object: ObjectRef\r\n): AsyncResult<Dependency[], Error> {\r\n // Validate object extension is supported.\r\n const config = getConfigByExtension(object.extension);\r\n if (!config) {\r\n return err(new Error(`Unsupported extension: ${object.extension}`));\r\n }\r\n\r\n // Build object URI and request body.\r\n const uri = `/sap/bc/adt/${config.endpoint}/${object.name}`;\r\n const body = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n <usagereferences:usageReferenceRequest xmlns:usagereferences=\"http://www.sap.com/adt/ris/usageReferences\">\r\n <usagereferences:affectedObjects/>\r\n </usagereferences:usageReferenceRequest>`;\r\n\r\n // Execute where-used query.\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: '/sap/bc/adt/repository/informationsystem/usageReferences',\r\n params: {\r\n 'uri': uri,\r\n 'ris_request_type': 'usageReferences',\r\n },\r\n headers: {\r\n 'Content-Type': 'application/vnd.sap.adt.repository.usagereferences.request.v1+xml',\r\n 'Accept': 'application/vnd.sap.adt.repository.usagereferences.result.v1+xml',\r\n },\r\n body,\r\n });\r\n\r\n // Validate successful response.\r\n if (requestErr) { return err(requestErr); }\r\n if (!response.ok) {\r\n const text = await response.text();\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Where-used query failed: ${errorMsg}`));\r\n }\r\n\r\n // Parse dependencies from response.\r\n const text = await response.text();\r\n const [dependencies, parseErr] = parseWhereUsed(text);\r\n if (parseErr) { return err(parseErr); }\r\n return ok(dependencies);\r\n}\r\n\r\n// Parse where-used results from XML.\r\nfunction parseWhereUsed(xml: string): Result<Dependency[], Error> {\r\n // Parse XML response.\r\n const [doc, parseErr] = safeParseXml(xml);\r\n if (parseErr) { return err(parseErr); }\r\n\r\n // Extract referenced object elements.\r\n const dependencies: Dependency[] = [];\r\n const referencedObjects = doc.getElementsByTagNameNS(\r\n 'http://www.sap.com/adt/ris/usageReferences',\r\n 'referencedObject'\r\n );\r\n\r\n // Process each referenced object.\r\n for (let i = 0; i < referencedObjects.length; i++) {\r\n const refObj = referencedObjects[i];\r\n if (!refObj) continue;\r\n\r\n // Extract ADT object element.\r\n const adtObject = refObj.getElementsByTagNameNS(\r\n 'http://www.sap.com/adt/ris/usageReferences',\r\n 'adtObject'\r\n )[0];\r\n if (!adtObject) continue;\r\n\r\n // Extract object name and type.\r\n const name = adtObject.getAttributeNS('http://www.sap.com/adt/core', 'name') || adtObject.getAttribute('adtcore:name');\r\n const type = adtObject.getAttributeNS('http://www.sap.com/adt/core', 'type') || adtObject.getAttribute('adtcore:type');\r\n if (!name || !type) continue;\r\n\r\n // Look up object type configuration.\r\n const config = getConfigByType(type);\r\n if (!config) continue;\r\n\r\n // Extract package reference if available.\r\n const packageRef = adtObject.getElementsByTagNameNS('http://www.sap.com/adt/core', 'packageRef')[0];\r\n const packageName = packageRef\r\n ? (packageRef.getAttributeNS('http://www.sap.com/adt/core', 'name') || packageRef.getAttribute('adtcore:name'))\r\n : '';\r\n\r\n // Build dependency object.\r\n dependencies.push({\r\n name,\r\n extension: config.extension,\r\n package: packageName || '',\r\n usageType: 'reference',\r\n });\r\n }\r\n\r\n return ok(dependencies);\r\n}\r\n","/**\r\n * Create Transport — Create a new transport request for a package\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { AdtRequestor } from '../types';\r\nimport { dictToAbapXml, extractError } from '../../utils/xml';\r\n\r\n/**\r\n * Configuration for creating a transport\r\n */\r\nexport interface TransportConfig {\r\n /** Package name (DEVCLASS) */\r\n package: string;\r\n /** Transport description/text */\r\n description: string;\r\n}\r\n\r\n/**\r\n * Create a new transport request\r\n *\r\n * @param client - ADT client\r\n * @param config - Transport configuration\r\n * @returns Transport ID or error\r\n */\r\nexport async function createTransport(\r\n client: AdtRequestor,\r\n config: TransportConfig\r\n): AsyncResult<string, Error> {\r\n // Build XML request body.\r\n const body = dictToAbapXml({\r\n DEVCLASS: config.package,\r\n REQUEST_TEXT: config.description,\r\n REF: '',\r\n OPERATION: 'I',\r\n });\r\n\r\n // Execute transport creation request.\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: '/sap/bc/adt/cts/transports',\r\n headers: {\r\n 'Content-Type': 'application/vnd.sap.as+xml; charset=UTF-8; dataname=com.sap.adt.CreateCorrectionRequest',\r\n 'Accept': 'text/plain',\r\n },\r\n body,\r\n });\r\n\r\n // Validate response.\r\n if (requestErr) return err(requestErr);\r\n if (!response.ok) {\r\n const text = await response.text();\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Failed to create transport for ${config.package}: ${errorMsg}`));\r\n }\r\n\r\n // Extract transport ID from response.\r\n const text = await response.text();\r\n const transportId = text.trim().split('/').pop();\r\n\r\n if (!transportId) {\r\n return err(new Error('Failed to parse transport ID from response'));\r\n }\r\n\r\n return ok(transportId);\r\n}\r\n","/**\n * Parse Transport Tasks — Extract task IDs and their objects from transport XML\n */\n\nimport type { TransportObject } from './removeFromTransport';\n\nexport interface TaskContents {\n taskId: string;\n objects: TransportObject[];\n}\n\n/**\n * Parse the transport XML to extract task IDs and their objects.\n */\nexport function parseTransportTasks(doc: Document): TaskContents[] {\n const tasks: TaskContents[] = [];\n const taskElements = doc.getElementsByTagName('tm:task');\n\n for (let i = 0; i < taskElements.length; i++) {\n const taskEl = taskElements[i];\n if (!taskEl) continue;\n\n const taskId = taskEl.getAttribute('tm:number');\n if (!taskId) continue;\n\n const objects: TransportObject[] = [];\n const objectElements = taskEl.getElementsByTagName('tm:abap_object');\n\n for (let j = 0; j < objectElements.length; j++) {\n const el = objectElements[j];\n if (!el) continue;\n\n const name = el.getAttribute('tm:name');\n if (!name) continue;\n\n objects.push({\n name,\n description: el.getAttribute('tm:obj_desc') || el.getAttribute('tm:obj_info') || '',\n pgmid: el.getAttribute('tm:pgmid') || '',\n type: el.getAttribute('tm:type') || '',\n position: el.getAttribute('tm:position') || '',\n });\n }\n\n tasks.push({ taskId, objects });\n }\n\n return tasks;\n}\n","/**\r\n * Remove From Transport — Remove an object from a transport request\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { AdtRequestor } from '../types';\r\nimport { extractError, escapeXml, safeParseXml } from '../../utils/xml';\r\nimport { parseTransportTasks } from './parseTransportTasks';\r\n\r\nconst ACCEPT_HEADER = 'application/vnd.sap.adt.transportorganizer.v1+xml';\r\n\r\n/**\r\n * Object entry on a transport\r\n */\r\nexport interface TransportObject {\r\n /** Object name (e.g., 'ZSNAP_F72TG_103') */\r\n name: string;\r\n /** Object description */\r\n description: string;\r\n /** Program ID (e.g., 'R3TR') */\r\n pgmid: string;\r\n /** Object type (e.g., 'DDLS') */\r\n type: string;\r\n /** Position in the transport (e.g., '000002') */\r\n position: string;\r\n}\r\n\r\n/**\r\n * Remove a specific object entry from a transport (internal helper).\r\n * Requires full object details — used by deleteTransport and removeFromTransport.\r\n */\r\nexport async function removeTransportEntry(\r\n client: AdtRequestor,\r\n transportId: string,\r\n object: TransportObject\r\n): AsyncResult<void, Error> {\r\n const body = [\r\n '<?xml version=\"1.0\" encoding=\"ASCII\"?>',\r\n `<tm:root xmlns:tm=\"http://www.sap.com/cts/adt/tm\" tm:number=\"${escapeXml(transportId)}\" tm:useraction=\"removeobject\">`,\r\n ' <tm:request>',\r\n ` <tm:abap_object tm:name=\"${escapeXml(object.name)}\" tm:obj_desc=\"${escapeXml(object.description)}\" tm:pgmid=\"${escapeXml(object.pgmid)}\" tm:type=\"${escapeXml(object.type)}\" tm:position=\"${escapeXml(object.position)}\"/>`,\r\n ' </tm:request>',\r\n '</tm:root>',\r\n ].join('\\n');\r\n\r\n const [response, requestErr] = await client.request({\r\n method: 'PUT',\r\n path: `/sap/bc/adt/cts/transportrequests/${transportId}`,\r\n headers: {\r\n 'Accept': ACCEPT_HEADER,\r\n 'Content-Type': 'text/plain',\r\n },\r\n body,\r\n });\r\n\r\n if (requestErr) return err(requestErr);\r\n if (!response.ok) {\r\n const text = await response.text();\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Failed to remove ${object.name} from transport ${transportId}: ${errorMsg}`));\r\n }\r\n\r\n return ok(undefined);\r\n}\r\n\r\n/**\r\n * Remove an object from a transport by name.\r\n * Reads the transport XML, finds which task the object lives on, and removes it\r\n * using the task ID (not the request ID).\r\n */\r\nexport async function removeFromTransport(\r\n client: AdtRequestor,\r\n transportId: string,\r\n objectName: string\r\n): AsyncResult<void, Error> {\r\n // Fetch transport XML to get the task hierarchy.\r\n const [response, requestErr] = await client.request({\r\n method: 'GET',\r\n path: `/sap/bc/adt/cts/transportrequests/${transportId}`,\r\n headers: { 'Accept': ACCEPT_HEADER },\r\n });\r\n\r\n if (requestErr) return err(requestErr);\r\n if (!response.ok) {\r\n const text = await response.text();\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Failed to read transport ${transportId}: ${errorMsg}`));\r\n }\r\n\r\n const text = await response.text();\r\n const [doc, parseErr] = safeParseXml(text);\r\n if (parseErr) return err(parseErr);\r\n\r\n // Find which task contains the object.\r\n const tasks = parseTransportTasks(doc);\r\n for (const task of tasks) {\r\n const object = task.objects.find(o => o.name === objectName);\r\n if (!object) continue;\r\n\r\n return removeTransportEntry(client, task.taskId, object);\r\n }\r\n\r\n return err(new Error(`Object '${objectName}' not found on transport ${transportId}`));\r\n}\r\n","/**\r\n * Delete Transport — Delete a transport request\r\n *\r\n * SAP transports have a hierarchy: Request → Tasks → Objects.\r\n * To delete a request, all tasks must be deleted first.\r\n * To delete a task, all objects must be removed from it first.\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { AdtRequestor } from '../types';\r\nimport { extractError, safeParseXml } from '../../utils/xml';\r\nimport { removeTransportEntry } from './removeFromTransport';\r\nimport { parseTransportTasks } from './parseTransportTasks';\r\n\r\nconst ACCEPT_HEADER = 'application/vnd.sap.adt.transportorganizer.v1+xml';\r\n\r\n/**\r\n * Sort and compress a task to consolidate duplicate entries.\r\n *\r\n * Deleting tables creates two different entries on a transport that must be merged before removal.\r\n */\r\nasync function sortAndCompress(\r\n client: AdtRequestor,\r\n taskId: string\r\n): AsyncResult<void, Error> {\r\n const [response, requestErr] = await client.request({\r\n method: 'POST',\r\n path: `/sap/bc/adt/cts/transportrequests/${taskId}/sortandcompress`,\r\n headers: { 'Accept': ACCEPT_HEADER },\r\n });\r\n\r\n if (requestErr) return err(requestErr);\r\n if (!response.ok) {\r\n const text = await response.text();\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Failed to sort and compress task ${taskId}: ${errorMsg}`));\r\n }\r\n\r\n return ok(undefined);\r\n}\r\n\r\n/**\r\n * Send a DELETE request for a transport or task.\r\n */\r\nasync function deleteRequest(\r\n client: AdtRequestor,\r\n id: string\r\n): AsyncResult<void, Error> {\r\n const [response, requestErr] = await client.request({\r\n method: 'DELETE',\r\n path: `/sap/bc/adt/cts/transportrequests/${id}`,\r\n headers: { 'Accept': ACCEPT_HEADER },\r\n });\r\n\r\n if (requestErr) return err(requestErr);\r\n if (!response.ok) {\r\n const text = await response.text();\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Failed to delete ${id}: ${errorMsg}`));\r\n }\r\n\r\n return ok(undefined);\r\n}\r\n\r\n/**\r\n * Delete a transport request\r\n *\r\n * @param client - ADT client\r\n * @param transportId - Transport request ID (e.g., 'DS4K904713')\r\n * @param removeObjects - If true, removes all objects from tasks before deleting\r\n * @returns void on success or error\r\n */\r\nexport async function deleteTransport(\r\n client: AdtRequestor,\r\n transportId: string,\r\n removeObjects = false\r\n): AsyncResult<void, Error> {\r\n // Read the transport to discover its task hierarchy.\r\n const [response, requestErr] = await client.request({\r\n method: 'GET',\r\n path: `/sap/bc/adt/cts/transportrequests/${transportId}`,\r\n headers: { 'Accept': ACCEPT_HEADER },\r\n });\r\n\r\n if (requestErr) return err(requestErr);\r\n if (!response.ok) {\r\n const text = await response.text();\r\n const errorMsg = extractError(text);\r\n return err(new Error(`Failed to read transport ${transportId}: ${errorMsg}`));\r\n }\r\n\r\n const text = await response.text();\r\n const [doc, parseErr] = safeParseXml(text);\r\n if (parseErr) return err(parseErr);\r\n\r\n const tasks = parseTransportTasks(doc);\r\n\r\n // Process each task: sort+compress, remove objects, then delete the task.\r\n for (const task of tasks) {\r\n if (removeObjects && task.objects.length > 0) {\r\n // Consolidate duplicate entries before removal.\r\n const [, compressErr] = await sortAndCompress(client, task.taskId);\r\n if (compressErr) return err(compressErr);\r\n\r\n // Re-read the task after compression (entries and positions change).\r\n const [taskResponse, taskReadErr] = await client.request({\r\n method: 'GET',\r\n path: `/sap/bc/adt/cts/transportrequests/${task.taskId}`,\r\n headers: { 'Accept': ACCEPT_HEADER },\r\n });\r\n if (taskReadErr) return err(taskReadErr);\r\n\r\n const taskText = await taskResponse.text();\r\n const [taskDoc, taskParseErr] = safeParseXml(taskText);\r\n if (taskParseErr) return err(taskParseErr);\r\n\r\n // Extract fresh object list from the compressed task.\r\n const elements = taskDoc.getElementsByTagName('tm:abap_object');\r\n for (let i = 0; i < elements.length; i++) {\r\n const el = elements[i];\r\n if (!el) continue;\r\n const name = el.getAttribute('tm:name');\r\n if (!name) continue;\r\n\r\n const [, removeErr] = await removeTransportEntry(client, task.taskId, {\r\n name,\r\n description: el.getAttribute('tm:obj_desc') || el.getAttribute('tm:obj_info') || '',\r\n pgmid: el.getAttribute('tm:pgmid') || '',\r\n type: el.getAttribute('tm:type') || '',\r\n position: el.getAttribute('tm:position') || '',\r\n });\r\n if (removeErr) return err(removeErr);\r\n }\r\n }\r\n\r\n const [, taskErr] = await deleteRequest(client, task.taskId);\r\n if (taskErr) return err(taskErr);\r\n }\r\n\r\n // Delete the parent request.\r\n return deleteRequest(client, transportId);\r\n}\r\n","/**\n * View Transport Objects — List all tasks and their objects on a transport\n */\n\nimport type { AsyncResult } from '../../../types/result';\nimport { ok, err } from '../../../types/result';\nimport type { AdtRequestor } from '../types';\nimport { extractError, safeParseXml } from '../../utils/xml';\nimport { parseTransportTasks } from './parseTransportTasks';\nimport type { TaskContents } from './parseTransportTasks';\n\nconst ACCEPT_HEADER = 'application/vnd.sap.adt.transportorganizer.v1+xml';\n\nexport async function viewTransportObjects(\n client: AdtRequestor,\n transportId: string\n): AsyncResult<TaskContents[], Error> {\n const [response, requestErr] = await client.request({\n method: 'GET',\n path: `/sap/bc/adt/cts/transportrequests/${transportId}`,\n headers: { 'Accept': ACCEPT_HEADER },\n });\n\n if (requestErr) return err(requestErr);\n if (!response.ok) {\n const text = await response.text();\n const errorMsg = extractError(text);\n return err(new Error(`Failed to read transport ${transportId}: ${errorMsg}`));\n }\n\n const text = await response.text();\n const [doc, parseErr] = safeParseXml(text);\n if (parseErr) return err(parseErr);\n\n return ok(parseTransportTasks(doc));\n}\n","/**\r\n * Git Diff — Compare local content with server content\r\n *\r\n * Uses Myers diff algorithm to compute line-by-line differences.\r\n */\r\n\r\nimport { diffArrays, type ChangeObject } from 'diff';\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { ok, err } from '../../../types/result';\r\nimport type { AdtRequestor } from '../types';\r\nimport type { ObjectContent } from '../../../types/requests';\r\nimport { readObject } from './read';\r\nimport { getConfigByExtension } from '../types';\r\n\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n// Types (colocated - only used by this function)\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\n/** Base fields for all diff hunks */\r\ninterface BaseDiffHunk {\r\n /** Total number of lines in the hunk */\r\n length: number;\r\n /** Starting line in the diff output (0-indexed) */\r\n diffStart: number;\r\n /** Starting line in the local file (0-indexed) */\r\n localStart: number;\r\n}\r\n\r\n/** Addition or deletion hunk */\r\nexport interface SimpleDiffHunk extends BaseDiffHunk {\r\n type: 'addition' | 'deletion';\r\n /** Lines added or removed */\r\n changes: string[];\r\n}\r\n\r\n/** Modification hunk (deletion immediately followed by addition) */\r\nexport interface ModifiedDiffHunk extends BaseDiffHunk {\r\n type: 'modification';\r\n /** Tuple of [server_lines, local_lines] */\r\n changes: [string[], string[]];\r\n}\r\n\r\n/** Any diff hunk */\r\nexport type DiffHunk = SimpleDiffHunk | ModifiedDiffHunk;\r\n\r\n/** Result of comparing a single object */\r\nexport interface DiffResult {\r\n name: string;\r\n extension: string;\r\n label: string;\r\n diffs: DiffHunk[];\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n// Implementation\r\n// ─────────────────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Compute diff between server and local content\r\n *\r\n * Converts jsdiff ChangeObject[] output to the hunk format matching Python behavior.\r\n */\r\nfunction computeDiff(serverLines: string[], localLines: string[]): DiffHunk[] {\r\n const changes = diffArrays(serverLines, localLines);\r\n const hunks: DiffHunk[] = [];\r\n\r\n let diffIndex = 0;\r\n let localIndex = 0;\r\n\r\n for (let i = 0; i < changes.length; i++) {\r\n const change = changes[i] as ChangeObject<string[]>;\r\n if (!change) continue;\r\n\r\n if (!change.added && !change.removed) {\r\n // Unchanged lines - advance both indices\r\n const count = change.count ?? change.value.length;\r\n diffIndex += count;\r\n localIndex += count;\r\n continue;\r\n }\r\n\r\n if (change.removed) {\r\n // Check if next change is an addition (making this a modification)\r\n const nextChange = changes[i + 1] as ChangeObject<string[]> | undefined;\r\n\r\n if (nextChange?.added) {\r\n // Modification: deletion followed by addition\r\n const serverChanges = change.value;\r\n const localChanges = nextChange.value;\r\n const modHunk: ModifiedDiffHunk = {\r\n type: 'modification',\r\n length: serverChanges.length + localChanges.length,\r\n diffStart: diffIndex,\r\n localStart: localIndex,\r\n changes: [serverChanges, localChanges],\r\n };\r\n hunks.push(modHunk);\r\n\r\n // Advance indices and skip the next addition\r\n diffIndex += serverChanges.length + localChanges.length;\r\n localIndex += localChanges.length;\r\n i++; // Skip the addition we just processed\r\n continue;\r\n }\r\n\r\n // Pure deletion\r\n const deletionHunk: SimpleDiffHunk = {\r\n type: 'deletion',\r\n length: change.value.length,\r\n diffStart: diffIndex,\r\n localStart: localIndex,\r\n changes: change.value,\r\n };\r\n hunks.push(deletionHunk);\r\n diffIndex += change.value.length;\r\n continue;\r\n }\r\n\r\n if (!change.added) continue;\r\n\r\n // Pure addition (not preceded by deletion - handled above)\r\n const additionHunk: SimpleDiffHunk = {\r\n type: 'addition',\r\n length: change.value.length,\r\n diffStart: diffIndex,\r\n localStart: localIndex,\r\n changes: change.value,\r\n };\r\n hunks.push(additionHunk);\r\n diffIndex += change.value.length;\r\n localIndex += change.value.length;\r\n }\r\n\r\n return hunks;\r\n}\r\n\r\n/**\r\n * Compare local object content with server content\r\n *\r\n * @param client - ADT client\r\n * @param object - Object with local content to compare\r\n * @returns Diff result or error\r\n */\r\nexport async function gitDiff(\r\n client: AdtRequestor,\r\n object: ObjectContent\r\n): AsyncResult<DiffResult, Error> {\r\n // Read current server content.\r\n const [serverObj, readErr] = await readObject(client, {\r\n name: object.name,\r\n extension: object.extension,\r\n });\r\n\r\n if (readErr) {\r\n return err(new Error(`${object.name} does not exist on server`));\r\n }\r\n\r\n // Get label from config.\r\n const config = getConfigByExtension(object.extension);\r\n const label = config?.label ?? object.extension;\r\n\r\n // Split content into lines for comparison.\r\n const serverLines = serverObj.content.split('\\n');\r\n const localLines = object.content.split('\\n');\r\n\r\n // Compute diff.\r\n const diffs = computeDiff(serverLines, localLines);\r\n\r\n return ok({\r\n name: serverObj.name,\r\n extension: serverObj.extension,\r\n label,\r\n diffs,\r\n });\r\n}\r\n","/**\r\n * Read objects method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { ObjectRef } from '../../../types/requests';\r\nimport type { ObjectWithContent, AdtRequestor } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { ok, err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function read(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n objects: ObjectRef[]\r\n): AsyncResult<ObjectWithContent[]> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n\r\n const results: ObjectWithContent[] = [];\r\n for (const obj of objects) {\r\n const [result, readErr] = await adt.readObject(requestor, obj);\r\n if (readErr) return err(readErr);\r\n results.push(result);\r\n }\r\n return ok(results);\r\n}\r\n","/**\r\n * Create object method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { ObjectRef, ObjectContent } from '../../../types/requests';\r\nimport type { AdtRequestor } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { ok, err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function create(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n object: ObjectContent,\r\n packageName: string,\r\n transport?: string\r\n): AsyncResult<void> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n\r\n // Step 1: Create empty object shell\r\n const [, createErr] = await adt.createObject(requestor, object, packageName, transport, state.session.username);\r\n if (createErr) return err(createErr);\r\n\r\n // Step 2: Populate content via lock → update → unlock\r\n const objRef: ObjectRef = { name: object.name, extension: object.extension };\r\n\r\n const [lockHandle, lockErr] = await adt.lockObject(requestor, objRef);\r\n if (lockErr) return err(lockErr);\r\n\r\n const [, updateErr] = await adt.updateObject(requestor, object, lockHandle, transport);\r\n\r\n // Always unlock after update attempt\r\n const [, unlockErr] = await adt.unlockObject(requestor, objRef, lockHandle);\r\n\r\n if (updateErr) return err(updateErr);\r\n if (unlockErr) return err(unlockErr);\r\n\r\n return ok(undefined);\r\n}\r\n","/**\r\n * Update object method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { ObjectRef, ObjectContent } from '../../../types/requests';\r\nimport type { AdtRequestor } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { ok, err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function update(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n object: ObjectContent,\r\n transport?: string\r\n): AsyncResult<void> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n\r\n const objRef: ObjectRef = { name: object.name, extension: object.extension };\r\n\r\n // Lock object before update\r\n const [lockHandle, lockErr] = await adt.lockObject(requestor, objRef);\r\n if (lockErr) return err(lockErr);\r\n\r\n // Update object content\r\n const [, updateErr] = await adt.updateObject(requestor, object, lockHandle, transport);\r\n\r\n // Always unlock after update attempt\r\n const [, unlockErr] = await adt.unlockObject(requestor, objRef, lockHandle);\r\n\r\n // Return first error encountered\r\n if (updateErr) return err(updateErr);\r\n if (unlockErr) return err(unlockErr);\r\n\r\n return ok(undefined);\r\n}\r\n","/**\r\n * Upsert methods (create or update)\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { ObjectRef, ObjectContent } from '../../../types/requests';\r\nimport type { AdtRequestor, UpsertResult } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { ok, err, resolveAllAsync } from '../../../types/result';\r\nimport { normalizeContent } from '../../../core/utils';\r\nimport * as adt from '../../../core/adt';\r\nimport { create } from './create';\r\nimport { update } from './update';\r\n\r\nexport async function upsertSingle(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n object: ObjectContent,\r\n packageName: string,\r\n transport?: string\r\n): AsyncResult<UpsertResult> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n\r\n // Try to read existing object\r\n const objRef: ObjectRef = { name: object.name, extension: object.extension };\r\n const [existing] = await adt.readObject(requestor, objRef);\r\n\r\n // Object doesn't exist - create it\r\n if (!existing) {\r\n const [, createErr] = await create(state, requestor, object, packageName, transport);\r\n if (createErr) return err(createErr);\r\n\r\n const result: UpsertResult = {\r\n name: object.name,\r\n extension: object.extension,\r\n status: 'created',\r\n };\r\n if (transport) result.transport = transport;\r\n return ok(result);\r\n }\r\n\r\n // Compare normalized content to avoid unnecessary updates\r\n const serverContent = normalizeContent(existing.content);\r\n const localContent = normalizeContent(object.content);\r\n\r\n if (serverContent === localContent) {\r\n const result: UpsertResult = {\r\n name: object.name,\r\n extension: object.extension,\r\n status: 'unchanged',\r\n };\r\n if (transport) result.transport = transport;\r\n return ok(result);\r\n }\r\n\r\n // Content differs - update it\r\n const [, updateErr] = await update(state, requestor, object, transport);\r\n if (updateErr) return err(updateErr);\r\n\r\n const result: UpsertResult = {\r\n name: object.name,\r\n extension: object.extension,\r\n status: 'updated',\r\n };\r\n if (transport) result.transport = transport;\r\n return ok(result);\r\n}\r\n\r\nexport async function upsert(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n objects: ObjectContent[],\r\n packageName: string,\r\n transport?: string\r\n): AsyncResult<UpsertResult[]> {\r\n // Confirm we can execute this request.\r\n if (!state.session) return err(new Error('Not logged in'));\r\n if (objects.length === 0) return ok([]);\r\n\r\n // Dispatch all upserts in sync.\r\n const asyncResults: AsyncResult<UpsertResult>[] = [];\r\n for (const obj of objects) {\r\n if (!obj.name || !obj.extension) continue;\r\n asyncResults.push(upsertSingle(state, requestor, obj, packageName, transport));\r\n }\r\n\r\n // Await all responses.\r\n const [results, error] = await resolveAllAsync(asyncResults);\r\n if (error) return err(error);\r\n return ok(results);\r\n}\r\n","/**\r\n * Activate objects method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { ObjectRef } from '../../../types/requests';\r\nimport type { AdtRequestor, ActivationResult } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function activate(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n objects: ObjectRef[]\r\n): AsyncResult<ActivationResult[]> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n return adt.activateObjects(requestor, objects);\r\n}\r\n","/**\r\n * Delete objects method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { ObjectRef } from '../../../types/requests';\r\nimport type { AdtRequestor } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { ok, err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function deleteObjects(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n objects: ObjectRef[],\r\n transport?: string\r\n): AsyncResult<void> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n\r\n for (const obj of objects) {\r\n // Lock object before deletion\r\n const [lockHandle, lockErr] = await adt.lockObject(requestor, obj);\r\n if (lockErr) return err(lockErr);\r\n\r\n // Delete object\r\n const [, deleteErr] = await adt.deleteObject(requestor, obj, lockHandle, transport);\r\n if (deleteErr) {\r\n // Attempt to unlock on failure\r\n await adt.unlockObject(requestor, obj, lockHandle);\r\n return err(deleteErr);\r\n }\r\n }\r\n return ok(undefined);\r\n}\r\n","// Syntax check method\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { ObjectRef } from '../../../types/requests';\r\nimport type { AdtRequestor, CheckResult } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function checkSyntax(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n objects: ObjectRef[]\r\n): AsyncResult<CheckResult[]> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n return adt.checkSyntax(requestor, objects);\r\n}\r\n","/**\r\n * Get packages method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { AdtRequestor, Package, GetPackagesOptions } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function getPackages(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n options?: GetPackagesOptions\r\n): AsyncResult<Package[]> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n return adt.getPackages(requestor, options);\r\n}\r\n","/**\r\n * Get tree method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { TreeQuery } from '../../../types/requests';\r\nimport type { AdtRequestor, TreeResponse } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function getTree(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n query: TreeQuery\r\n): AsyncResult<TreeResponse> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n return adt.getTree(requestor, query);\r\n}\r\n","/**\r\n * Get package stats method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { AdtRequestor, PackageNode } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\n// Single package overload\r\nexport async function getPackageStats(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n packageName: string\r\n): AsyncResult<PackageNode>;\r\n\r\n// Multiple packages overload\r\nexport async function getPackageStats(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n packageNames: string[]\r\n): AsyncResult<PackageNode[]>;\r\n\r\n// Implementation\r\nexport async function getPackageStats(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n packageNames: string | string[]\r\n): AsyncResult<PackageNode | PackageNode[]> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n // Type assertion needed because TS can't infer overload from union\r\n return adt.getPackageStats(requestor, packageNames as string & string[]);\r\n}\r\n","/**\r\n * Get transports method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { AdtRequestor, Transport } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function getTransports(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n packageName: string\r\n): AsyncResult<Transport[]> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n return adt.getTransports(requestor, packageName);\r\n}\r\n","/**\r\n * Preview data method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { PreviewSQL } from '../../../types/requests';\r\nimport type { AdtRequestor, DataFrame } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function previewData(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n query: PreviewSQL\r\n): AsyncResult<DataFrame> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n return adt.previewData(requestor, query);\r\n}\r\n","/**\r\n * Get distinct values method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { AdtRequestor, DistinctResult, Parameter } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function getDistinctValues(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n objectName: string,\r\n parameters: Parameter[],\r\n column: string,\r\n objectType: 'table' | 'view' = 'view'\r\n): AsyncResult<DistinctResult> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n return adt.getDistinctValues(requestor, objectName, parameters, column, objectType);\r\n}\r\n","/**\r\n * Count rows method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { AdtRequestor, Parameter } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function countRows(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n objectName: string,\r\n objectType: 'table' | 'view',\r\n parameters: Parameter[] = []\r\n): AsyncResult<number> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n return adt.countRows(requestor, objectName, objectType, parameters);\r\n}\r\n","/**\r\n * Search objects method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { AdtRequestor, SearchResult, SearchOptions } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function search(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n query: string,\r\n options?: SearchOptions\r\n): AsyncResult<SearchResult[]> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n return adt.searchObjects(requestor, query, options);\r\n}\r\n","/**\r\n * Where-used analysis method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { ObjectRef } from '../../../types/requests';\r\nimport type { AdtRequestor, Dependency } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function whereUsed(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n object: ObjectRef\r\n): AsyncResult<Dependency[]> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n return adt.findWhereUsed(requestor, object);\r\n}\r\n","/**\r\n * Create transport method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { AdtRequestor, TransportConfig } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function createTransport(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n transportConfig: TransportConfig\r\n): AsyncResult<string> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n return adt.createTransport(requestor, transportConfig);\r\n}\r\n","/**\r\n * Delete transport method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { AdtRequestor } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function deleteTransport(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n transportId: string,\r\n removeObjects = false\r\n): AsyncResult<void> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n return adt.deleteTransport(requestor, transportId, removeObjects);\r\n}\r\n","/**\r\n * Remove object from transport method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { AdtRequestor } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function removeFromTransport(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n transportId: string,\r\n objectName: string\r\n): AsyncResult<void> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n return adt.removeFromTransport(requestor, transportId, objectName);\r\n}\r\n","/**\n * View transport objects method\n */\n\nimport type { AsyncResult } from '../../../types/result';\nimport type { AdtRequestor } from '../../../core/adt';\nimport type { TaskContents } from '../../../core/adt';\nimport type { ClientState } from '../../types';\nimport { err } from '../../../types/result';\nimport * as adt from '../../../core/adt';\n\nexport async function viewTransportObjects(\n state: ClientState,\n requestor: AdtRequestor,\n transportId: string\n): AsyncResult<TaskContents[]> {\n if (!state.session) return err(new Error('Not logged in'));\n return adt.viewTransportObjects(requestor, transportId);\n}\n","/**\r\n * Git diff method\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { ObjectContent } from '../../../types/requests';\r\nimport type { AdtRequestor, DiffResult } from '../../../core/adt';\r\nimport type { ClientState } from '../../types';\r\nimport { ok, err } from '../../../types/result';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport async function gitDiff(\r\n state: ClientState,\r\n requestor: AdtRequestor,\r\n objects: ObjectContent[]\r\n): AsyncResult<DiffResult[]> {\r\n if (!state.session) return err(new Error('Not logged in'));\r\n if (objects.length === 0) return ok([]);\r\n\r\n const results: DiffResult[] = [];\r\n for (const obj of objects) {\r\n const [result, diffErr] = await adt.gitDiff(requestor, obj);\r\n if (diffErr) return err(diffErr);\r\n results.push(result);\r\n }\r\n return ok(results);\r\n}\r\n","/**\r\n * Get object configuration method\r\n */\r\n\r\nimport type { ObjectConfig } from '../../../core/adt';\r\nimport * as adt from '../../../core/adt';\r\n\r\nexport function getObjectConfig(): ObjectConfig[] {\r\n return Object.values(adt.OBJECT_CONFIG_MAP);\r\n}\r\n","/**\r\n * Cookie management helpers\r\n */\r\n\r\nexport function storeCookies(cookies: Map<string, string>, response: Response): void {\r\n const setCookieHeader = response.headers.get('set-cookie');\r\n if (!setCookieHeader) return;\r\n\r\n // Parse Set-Cookie header(s) - may be multiple cookies\r\n // Format: \"name=value; Path=/; HttpOnly\" or multiple separated\r\n const cookieStrings = setCookieHeader.split(/,(?=\\s*\\w+=)/);\r\n for (const cookieStr of cookieStrings) {\r\n const match = cookieStr.match(/^([^=]+)=([^;]*)/);\r\n if (match && match[1] && match[2]) {\r\n cookies.set(match[1].trim(), match[2].trim());\r\n }\r\n }\r\n}\r\n\r\nexport function buildCookieHeader(cookies: Map<string, string>): string | null {\r\n if (cookies.size === 0) return null;\r\n return Array.from(cookies.entries())\r\n .map(([name, value]) => `${name}=${value}`)\r\n .join('; ');\r\n}\r\n","/**\r\n * Auto-refresh timer management\r\n */\r\n\r\nimport type { Session } from '../../../core/session/types';\r\nimport type { RefreshResult } from '../../../core/session/refresh';\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport { debug } from '../../../core/utils';\r\n\r\nexport interface AutoRefreshManager {\r\n start: (intervalMs: number) => void;\r\n stop: () => void;\r\n}\r\n\r\nexport function createAutoRefresh(\r\n getSession: () => Session | null,\r\n refreshSession: () => AsyncResult<RefreshResult>\r\n): AutoRefreshManager {\r\n let timer: ReturnType<typeof setInterval> | null = null;\r\n\r\n return {\r\n start(intervalMs: number) {\r\n this.stop();\r\n timer = setInterval(async () => {\r\n if (!getSession()) return;\r\n const [, refreshErr] = await refreshSession();\r\n if (refreshErr) {\r\n debug(`Auto-refresh failed: ${refreshErr.message}`);\r\n }\r\n }, intervalMs);\r\n // Don't keep the process alive just for auto-refresh\r\n // This allows CLI commands to exit naturally after completing their work\r\n timer.unref();\r\n },\r\n stop() {\r\n if (timer) {\r\n clearInterval(timer);\r\n timer = null;\r\n }\r\n }\r\n };\r\n}\r\n","/**\r\n * HTTP utilities for ADT client\r\n */\r\n\r\nimport * as http from 'http';\r\nimport * as https from 'https';\r\nimport type { HttpRequestOptions } from './types';\r\n\r\nexport const MAX_REDIRECTS = 5;\r\nexport const REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);\r\n\r\n/**\r\n * Make HTTP request using Node.js http/https modules.\r\n *\r\n * Why http/https modules instead of undici/fetch:\r\n * - Undici doesn't work with mTLS client certificates (tested, fails with \"unable to get local issuer certificate\")\r\n * - Node.js https module works reliably with mTLS in all environments (Node.js, Electron, Bun)\r\n * - Simpler to maintain one implementation that works everywhere\r\n */\r\nexport async function httpRequest(\r\n url: string,\r\n options: HttpRequestOptions,\r\n redirectCount = 0\r\n): Promise<Response> {\r\n if (redirectCount > MAX_REDIRECTS) {\r\n throw new Error(`Too many redirects (max ${MAX_REDIRECTS})`);\r\n }\r\n\r\n const urlObj = new URL(url);\r\n const isHttps = urlObj.protocol === 'https:';\r\n const requestFn = isHttps ? https.request : http.request;\r\n const defaultPort = isHttps ? 443 : 80;\r\n\r\n return new Promise((resolve, reject) => {\r\n const req = requestFn({\r\n hostname: urlObj.hostname,\r\n port: urlObj.port || defaultPort,\r\n path: urlObj.pathname + urlObj.search,\r\n method: options.method,\r\n headers: options.headers,\r\n cert: options.cert,\r\n key: options.key,\r\n rejectUnauthorized: options.rejectUnauthorized ?? true,\r\n timeout: options.timeout,\r\n }, (res) => {\r\n const statusCode = res.statusCode || 0;\r\n\r\n // Handle redirects\r\n if (REDIRECT_STATUSES.has(statusCode) && res.headers.location) {\r\n const redirectUrl = new URL(res.headers.location, url).toString();\r\n // For 303, always use GET; for 307/308, preserve method\r\n const redirectMethod = statusCode === 303 ? 'GET' : options.method;\r\n const redirectBody = statusCode === 303 ? undefined : options.body;\r\n\r\n httpRequest(redirectUrl, { ...options, method: redirectMethod, body: redirectBody }, redirectCount + 1)\r\n .then(resolve)\r\n .catch(reject);\r\n return;\r\n }\r\n\r\n const chunks: Buffer[] = [];\r\n res.on('data', chunk => chunks.push(chunk));\r\n res.on('end', () => {\r\n const body = Buffer.concat(chunks).toString('utf-8');\r\n // Convert to web Response\r\n const headers = new Headers();\r\n for (const [key, value] of Object.entries(res.headers)) {\r\n if (value) {\r\n if (Array.isArray(value)) {\r\n value.forEach(v => headers.append(key, v));\r\n } else {\r\n headers.set(key, value);\r\n }\r\n }\r\n }\r\n resolve(new Response(body, {\r\n status: statusCode,\r\n statusText: res.statusMessage || '',\r\n headers,\r\n }));\r\n });\r\n });\r\n\r\n req.on('error', reject);\r\n req.on('timeout', () => {\r\n req.destroy();\r\n reject(new Error('Request timeout'));\r\n });\r\n\r\n if (options.body) {\r\n req.write(options.body);\r\n }\r\n req.end();\r\n });\r\n}\r\n\r\n// Build URL search parameters with sap-client\r\nexport function buildParams(\r\n baseParams: Record<string, string | number> | undefined,\r\n clientNum: string\r\n): URLSearchParams {\r\n const params = new URLSearchParams();\r\n\r\n // Add any custom parameters from the request.\r\n if (baseParams) {\r\n for (const [key, value] of Object.entries(baseParams)) {\r\n params.append(key, String(value));\r\n }\r\n }\r\n\r\n // Always append sap-client parameter.\r\n params.append('sap-client', clientNum);\r\n\r\n return params;\r\n}\r\n\r\n// Build full URL from base URL and path\r\nexport function buildUrl(baseUrl: string, path: string, params?: URLSearchParams): string {\r\n // Construct URL from base and path.\r\n const url = new URL(path, baseUrl);\r\n\r\n // Merge query parameters: preserve existing ones from path, add new ones.\r\n if (params) {\r\n for (const [key, value] of params.entries()) {\r\n url.searchParams.append(key, value);\r\n }\r\n }\r\n\r\n return url.toString();\r\n}\r\n","/**\r\n * Core HTTP request with CSRF handling\r\n */\r\n\r\nimport type { AsyncResult } from '../../../types/result';\r\nimport type { ClientState, RequestOptions, SsoCerts } from '../../types';\r\nimport { ok, err } from '../../../types/result';\r\nimport {\r\n CSRF_TOKEN_HEADER,\r\n BASE_HEADERS,\r\n DEFAULT_TIMEOUT,\r\n buildRequestHeaders,\r\n debug,\r\n debugError,\r\n} from '../../../core/utils';\r\nimport * as sessionOps from '../../../core/session';\r\nimport { httpRequest, buildParams, buildUrl } from '../../helpers';\r\n\r\nexport interface RequestDependencies {\r\n state: ClientState;\r\n ssoCerts: SsoCerts | undefined;\r\n getCookieHeader: () => string | null;\r\n storeCookies: (response: Response) => void;\r\n}\r\n\r\n/**\r\n * Execute HTTP request with CSRF token injection and automatic retry on 403 errors\r\n */\r\nexport async function executeRequest(\r\n deps: RequestDependencies,\r\n options: RequestOptions,\r\n selfRequest: (options: RequestOptions) => AsyncResult<Response, Error>\r\n): AsyncResult<Response, Error> {\r\n const { state, ssoCerts, getCookieHeader, storeCookies } = deps;\r\n const { method, path, params, headers: customHeaders, body } = options;\r\n const { config } = state;\r\n\r\n // Build headers with auth and CSRF token\r\n debug(`Request ${method} ${path} - CSRF token in state: ${state.csrfToken?.substring(0, 20) || 'null'}...`);\r\n const headers = buildRequestHeaders(\r\n BASE_HEADERS,\r\n customHeaders,\r\n config.auth,\r\n state.csrfToken\r\n );\r\n debug(`CSRF header being sent: ${headers['x-csrf-token']?.substring(0, 20) || 'none'}...`);\r\n\r\n // Add stored cookies to request\r\n const cookieHeader = getCookieHeader();\r\n if (cookieHeader) {\r\n headers['Cookie'] = cookieHeader;\r\n debug(`Cookies being sent: ${cookieHeader.substring(0, 50)}...`);\r\n }\r\n\r\n // Build URL with parameters\r\n const urlParams = buildParams(params, config.client);\r\n const url = buildUrl(config.url, path, urlParams);\r\n\r\n try {\r\n // Execute HTTP request using Node.js https module\r\n debug(`Fetching URL: ${url}`);\r\n debug(`mTLS: ${!!ssoCerts}, insecure: ${config.insecure}`);\r\n\r\n const response = await httpRequest(url, {\r\n method,\r\n headers,\r\n body,\r\n cert: ssoCerts?.cert,\r\n key: ssoCerts?.key,\r\n rejectUnauthorized: !config.insecure,\r\n timeout: config.timeout ?? DEFAULT_TIMEOUT,\r\n });\r\n\r\n // Store any cookies from response\r\n storeCookies(response);\r\n\r\n // Handle CSRF token validation failure with automatic refresh\r\n if (response.status === 403) {\r\n const text = await response.text();\r\n if (text.includes('CSRF token validation failed')) {\r\n // Fetch new CSRF token\r\n const [newToken, tokenErr] = await sessionOps.fetchCsrfToken(state, selfRequest);\r\n if (tokenErr) {\r\n return err(new Error(`CSRF token refresh failed: ${tokenErr.message}`));\r\n }\r\n\r\n // Retry request with new token and cookies\r\n headers[CSRF_TOKEN_HEADER] = newToken;\r\n const retryCookieHeader = getCookieHeader();\r\n if (retryCookieHeader) {\r\n headers['Cookie'] = retryCookieHeader;\r\n }\r\n debug(`Retrying with new CSRF token: ${newToken.substring(0, 20)}...`);\r\n\r\n const retryResponse = await httpRequest(url, {\r\n method,\r\n headers,\r\n body,\r\n cert: ssoCerts?.cert,\r\n key: ssoCerts?.key,\r\n rejectUnauthorized: !config.insecure,\r\n timeout: config.timeout ?? DEFAULT_TIMEOUT,\r\n });\r\n storeCookies(retryResponse);\r\n return ok(retryResponse);\r\n }\r\n\r\n // Return 403 response if not CSRF-related\r\n return ok(new Response(text, {\r\n status: response.status,\r\n statusText: response.statusText,\r\n headers: response.headers,\r\n }));\r\n }\r\n\r\n // Handle session expiration with automatic reset\r\n if (response.status === 500) {\r\n const text = await response.text();\r\n\r\n // Attempt session reset\r\n const [, resetErr] = await sessionOps.sessionReset(state, selfRequest);\r\n if (resetErr) {\r\n return err(new Error(`Session reset failed: ${resetErr.message}`));\r\n }\r\n\r\n // Return original 500 response\r\n return ok(new Response(text, {\r\n status: response.status,\r\n statusText: response.statusText,\r\n headers: response.headers,\r\n }));\r\n }\r\n\r\n return ok(response);\r\n } catch (error) {\r\n // Log detailed error info for debugging\r\n if (error instanceof Error) {\r\n debugError(`Fetch error: ${error.name}: ${error.message}`, error.cause);\r\n if ('code' in error) {\r\n debugError(`Error code: ${(error as NodeJS.ErrnoException).code}`);\r\n }\r\n return err(error);\r\n }\r\n return err(new Error(`Network error: ${String(error)}`));\r\n }\r\n}\r\n","/**\r\n * ADT Client Core Implementation\r\n *\r\n * HTTP client for SAP ADT (ABAP Development Tools) with:\r\n * - Session management (login/logout)\r\n * - CSRF token fetching and automatic refresh\r\n * - Basic, SAML, and SSO (Kerberos + mTLS) authentication\r\n * - Automatic retry on 403 CSRF errors\r\n * - Session reset on 500 errors\r\n *\r\n * Uses Node.js https module for all HTTP requests (works reliably with mTLS).\r\n */\r\n\r\nimport type { ClientConfig } from '../types/config';\r\nimport type {\r\n ObjectRef,\r\n ObjectContent,\r\n TreeQuery,\r\n PreviewSQL,\r\n} from '../types/requests';\r\nimport type { Session, ExportableSessionState } from '../core/session/types';\r\nimport type { RefreshResult } from '../core/session/refresh';\r\nimport type {\r\n ObjectWithContent,\r\n UpsertResult,\r\n ActivationResult,\r\n CheckResult,\r\n TreeResponse,\r\n PackageNode,\r\n Transport,\r\n Package,\r\n GetPackagesOptions,\r\n DataFrame,\r\n DistinctResult,\r\n SearchResult,\r\n SearchOptions,\r\n Dependency,\r\n TransportConfig,\r\n TaskContents,\r\n DiffResult,\r\n ObjectConfig,\r\n Parameter,\r\n AdtRequestor,\r\n} from '../core/adt';\r\nimport type { AsyncResult } from '../types/result';\r\nimport { createAuthStrategy } from '../core/auth/factory';\r\nimport type { ClientState, ClientContext, RequestOptions, SsoCerts } from './types';\r\n\r\n// Import extracted methods\r\nimport * as lifecycleMethods from './methods/lifecycle';\r\nimport * as sessionMethods from './methods/session';\r\nimport * as craudMethods from './methods/craud';\r\nimport * as discoveryMethods from './methods/discovery';\r\nimport * as previewMethods from './methods/preview';\r\nimport * as searchMethods from './methods/search';\r\nimport * as transportMethods from './methods/transport';\r\nimport * as diffMethods from './methods/diff';\r\nimport * as configMethods from './methods/config';\r\nimport {\r\n storeCookies,\r\n buildCookieHeader,\r\n createAutoRefresh,\r\n executeRequest,\r\n} from './methods/internal';\r\nimport type { AutoRefreshManager } from './methods/internal';\r\n\r\n// ADT Client interface - provides all operations for interacting with SAP ADT servers\r\nexport interface ADTClient {\r\n /** Current session info (null if not logged in) */\r\n readonly session: Session | null;\r\n\r\n // Lifecycle\r\n login(): AsyncResult<Session>;\r\n logout(): AsyncResult<void>;\r\n refreshSession(): AsyncResult<RefreshResult>;\r\n\r\n // Session state export/import (for session caching across processes)\r\n exportSessionState(): ExportableSessionState | null;\r\n importSessionState(state: ExportableSessionState): AsyncResult<boolean>;\r\n\r\n // CRAUD Operations\r\n read(objects: ObjectRef[]): AsyncResult<ObjectWithContent[]>;\r\n create(object: ObjectContent, packageName: string, transport?: string): AsyncResult<void>;\r\n update(object: ObjectContent, transport?: string): AsyncResult<void>;\r\n upsert(objects: ObjectContent[], packageName: string, transport?: string): AsyncResult<UpsertResult[]>;\r\n activate(objects: ObjectRef[]): AsyncResult<ActivationResult[]>;\r\n checkSyntax(objects: ObjectRef[]): AsyncResult<CheckResult[]>;\r\n delete(objects: ObjectRef[], transport?: string): AsyncResult<void>;\r\n\r\n // Discovery\r\n getPackages(options?: GetPackagesOptions): AsyncResult<Package[]>;\r\n getTree(query: TreeQuery): AsyncResult<TreeResponse>;\r\n getPackageStats(packageName: string): AsyncResult<PackageNode>;\r\n getPackageStats(packageNames: string[]): AsyncResult<PackageNode[]>;\r\n getTransports(packageName: string): AsyncResult<Transport[]>;\r\n\r\n // Data Preview\r\n previewData(query: PreviewSQL): AsyncResult<DataFrame>;\r\n getDistinctValues(objectName: string, parameters: Parameter[], column: string, objectType?: 'table' | 'view'): AsyncResult<DistinctResult>;\r\n countRows(objectName: string, objectType: 'table' | 'view', parameters?: Parameter[]): AsyncResult<number>;\r\n\r\n // Search\r\n search(query: string, options?: SearchOptions): AsyncResult<SearchResult[]>;\r\n whereUsed(object: ObjectRef): AsyncResult<Dependency[]>;\r\n\r\n // Transport Management\r\n createTransport(config: TransportConfig): AsyncResult<string>;\r\n deleteTransport(transportId: string, removeObjects?: boolean): AsyncResult<void>;\r\n removeFromTransport(transportId: string, objectName: string): AsyncResult<void>;\r\n viewTransportObjects(transportId: string): AsyncResult<TaskContents[]>;\r\n\r\n // Diff Operations\r\n gitDiff(objects: ObjectContent[]): AsyncResult<DiffResult[]>;\r\n\r\n // Configuration\r\n getObjectConfig(): ObjectConfig[];\r\n}\r\n\r\n/**\r\n * ADT Client implementation class.\r\n * Methods delegate to extracted functions in methods/ folder.\r\n */\r\nexport class ADTClientImpl implements ADTClient {\r\n private state: ClientState;\r\n private requestor: AdtRequestor;\r\n private ssoCerts: SsoCerts | undefined;\r\n private autoRefresh: AutoRefreshManager;\r\n\r\n constructor(config: ClientConfig) {\r\n // Create auth strategy from config\r\n const authOptions: Parameters<typeof createAuthStrategy>[0] = {\r\n config: config.auth,\r\n baseUrl: config.url,\r\n };\r\n if (config.insecure) {\r\n authOptions.insecure = config.insecure;\r\n }\r\n const authStrategy = createAuthStrategy(authOptions);\r\n\r\n this.state = {\r\n config,\r\n session: null,\r\n csrfToken: null,\r\n cookies: new Map(),\r\n authStrategy,\r\n };\r\n\r\n // Bind request method for use as requestor\r\n this.requestor = { request: this.request.bind(this) };\r\n\r\n // Initialize auto-refresh manager\r\n this.autoRefresh = createAutoRefresh(\r\n () => this.state.session,\r\n () => this.refreshSession()\r\n );\r\n }\r\n\r\n get session(): Session | null {\r\n return this.state.session;\r\n }\r\n\r\n // --- Private helpers (one-line delegations) ---\r\n\r\n private storeCookies(response: Response): void {\r\n storeCookies(this.state.cookies, response);\r\n }\r\n\r\n private buildCookieHeader(): string | null {\r\n return buildCookieHeader(this.state.cookies);\r\n }\r\n\r\n private startAutoRefresh(intervalMs: number): void {\r\n this.autoRefresh.start(intervalMs);\r\n }\r\n\r\n private stopAutoRefresh(): void {\r\n this.autoRefresh.stop();\r\n }\r\n\r\n private getContext(): ClientContext {\r\n return {\r\n state: this.state,\r\n ssoCerts: this.ssoCerts,\r\n request: this.request.bind(this),\r\n buildCookieHeader: this.buildCookieHeader.bind(this),\r\n storeCookies: this.storeCookies.bind(this),\r\n startAutoRefresh: this.startAutoRefresh.bind(this),\r\n stopAutoRefresh: this.stopAutoRefresh.bind(this),\r\n };\r\n }\r\n\r\n private setSsoCerts(certs: SsoCerts): void {\r\n this.ssoCerts = certs;\r\n }\r\n\r\n private async request(options: RequestOptions): AsyncResult<Response, Error> {\r\n return executeRequest(\r\n {\r\n state: this.state,\r\n ssoCerts: this.ssoCerts,\r\n getCookieHeader: this.buildCookieHeader.bind(this),\r\n storeCookies: this.storeCookies.bind(this),\r\n },\r\n options,\r\n this.request.bind(this)\r\n );\r\n }\r\n\r\n // --- Lifecycle ---\r\n\r\n async login(): AsyncResult<Session> {\r\n return lifecycleMethods.login(this.getContext(), this.setSsoCerts.bind(this));\r\n }\r\n\r\n async logout(): AsyncResult<void> {\r\n return lifecycleMethods.logout(this.getContext());\r\n }\r\n\r\n async refreshSession(): AsyncResult<RefreshResult> {\r\n return lifecycleMethods.refreshSession(this.getContext());\r\n }\r\n\r\n // --- Session State Export/Import ---\r\n\r\n exportSessionState(): ExportableSessionState | null {\r\n return sessionMethods.exportSessionState(this.getContext(), this.ssoCerts);\r\n }\r\n\r\n async importSessionState(state: ExportableSessionState): AsyncResult<boolean> {\r\n return sessionMethods.importSessionState(this.getContext(), state, this.setSsoCerts.bind(this));\r\n }\r\n\r\n // --- CRAUD Operations ---\r\n\r\n async read(objects: ObjectRef[]): AsyncResult<ObjectWithContent[]> {\r\n return craudMethods.read(this.state, this.requestor, objects);\r\n }\r\n\r\n async create(object: ObjectContent, packageName: string, transport?: string): AsyncResult<void> {\r\n return craudMethods.create(this.state, this.requestor, object, packageName, transport);\r\n }\r\n\r\n async update(object: ObjectContent, transport?: string): AsyncResult<void> {\r\n return craudMethods.update(this.state, this.requestor, object, transport);\r\n }\r\n\r\n async upsert(objects: ObjectContent[], packageName: string, transport?: string): AsyncResult<UpsertResult[]> {\r\n return craudMethods.upsert(this.state, this.requestor, objects, packageName, transport);\r\n }\r\n\r\n async activate(objects: ObjectRef[]): AsyncResult<ActivationResult[]> {\r\n return craudMethods.activate(this.state, this.requestor, objects);\r\n }\r\n\r\n async checkSyntax(objects: ObjectRef[]): AsyncResult<CheckResult[]> {\r\n return craudMethods.checkSyntax(this.state, this.requestor, objects);\r\n }\r\n\r\n async delete(objects: ObjectRef[], transport?: string): AsyncResult<void> {\r\n return craudMethods.deleteObjects(this.state, this.requestor, objects, transport);\r\n }\r\n\r\n // --- Discovery ---\r\n\r\n async getPackages(options?: GetPackagesOptions): AsyncResult<Package[]> {\r\n return discoveryMethods.getPackages(this.state, this.requestor, options);\r\n }\r\n\r\n async getTree(query: TreeQuery): AsyncResult<TreeResponse> {\r\n return discoveryMethods.getTree(this.state, this.requestor, query);\r\n }\r\n\r\n async getPackageStats(packageName: string): AsyncResult<PackageNode>;\r\n async getPackageStats(packageNames: string[]): AsyncResult<PackageNode[]>;\r\n async getPackageStats(packageNames: string | string[]): AsyncResult<PackageNode | PackageNode[]> {\r\n return discoveryMethods.getPackageStats(this.state, this.requestor, packageNames as string & string[]);\r\n }\r\n\r\n async getTransports(packageName: string): AsyncResult<Transport[]> {\r\n return discoveryMethods.getTransports(this.state, this.requestor, packageName);\r\n }\r\n\r\n // --- Data Preview ---\r\n\r\n async previewData(query: PreviewSQL): AsyncResult<DataFrame> {\r\n return previewMethods.previewData(this.state, this.requestor, query);\r\n }\r\n\r\n async getDistinctValues(objectName: string, parameters: Parameter[], column: string, objectType: 'table' | 'view' = 'view'): AsyncResult<DistinctResult> {\r\n return previewMethods.getDistinctValues(this.state, this.requestor, objectName, parameters, column, objectType);\r\n }\r\n\r\n async countRows(objectName: string, objectType: 'table' | 'view', parameters: Parameter[] = []): AsyncResult<number> {\r\n return previewMethods.countRows(this.state, this.requestor, objectName, objectType, parameters);\r\n }\r\n\r\n // --- Search ---\r\n\r\n async search(query: string, options?: SearchOptions): AsyncResult<SearchResult[]> {\r\n return searchMethods.search(this.state, this.requestor, query, options);\r\n }\r\n\r\n async whereUsed(object: ObjectRef): AsyncResult<Dependency[]> {\r\n return searchMethods.whereUsed(this.state, this.requestor, object);\r\n }\r\n\r\n // --- Transport Management ---\r\n\r\n async createTransport(transportConfig: TransportConfig): AsyncResult<string> {\r\n return transportMethods.createTransport(this.state, this.requestor, transportConfig);\r\n }\r\n\r\n async deleteTransport(transportId: string, removeObjects = false): AsyncResult<void> {\r\n return transportMethods.deleteTransport(this.state, this.requestor, transportId, removeObjects);\r\n }\r\n\r\n async removeFromTransport(transportId: string, objectName: string): AsyncResult<void> {\r\n return transportMethods.removeFromTransport(this.state, this.requestor, transportId, objectName);\r\n }\r\n\r\n async viewTransportObjects(transportId: string): AsyncResult<TaskContents[]> {\r\n return transportMethods.viewTransportObjects(this.state, this.requestor, transportId);\r\n }\r\n\r\n // --- Diff Operations ---\r\n\r\n async gitDiff(objects: ObjectContent[]): AsyncResult<DiffResult[]> {\r\n return diffMethods.gitDiff(this.state, this.requestor, objects);\r\n }\r\n\r\n // --- Configuration ---\r\n\r\n getObjectConfig(): ObjectConfig[] {\r\n return configMethods.getObjectConfig();\r\n }\r\n}\r\n","/**\r\n * ADT Client Module\r\n *\r\n * Exports the ADTClient interface and createClient factory function.\r\n */\r\n\r\nimport type { ClientConfig } from '../types/config';\r\nimport type { Result } from '../types/result';\r\nimport { ok, err } from '../types/result';\r\nimport { clientConfigSchema } from '../types/config';\r\nimport { ADTClientImpl } from './client';\r\nimport type { ADTClient } from './client';\r\n\r\nexport type { ADTClient };\r\n\r\n// Create a new ADT client - validates config and returns client instance\r\nexport function createClient(config: ClientConfig): Result<ADTClient, Error> {\r\n // Validate config using Zod schema.\r\n const validation = clientConfigSchema.safeParse(config);\r\n if (!validation.success) {\r\n const issues = validation.error.issues.map(i => `${i.path.join('.')}: ${i.message}`).join(', ');\r\n return err(new Error(`Invalid client configuration: ${issues}`));\r\n }\r\n\r\n return ok(new ADTClientImpl(config));\r\n}\r\n"],"mappings":"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","names":["err","forge","import_node_forge","forge","forge","request","request","login","loginErr","logout","refreshSession","DEFAULT_REFRESH_INTERVAL","text","stat","text","text","parsed","parseErr","packages","text","text","text","text","text","text","text","ACCEPT_HEADER","text","ACCEPT_HEADER","text","result","checkSyntax","getPackages","getTree","getPackageStats","getTransports","previewData","getDistinctValues","countRows","createTransport","deleteTransport","removeFromTransport","viewTransportObjects","gitDiff","refreshSession","https","buildUrl","storeCookies","buildUrl","login","logout","refreshSession","checkSyntax","getPackages","getTree","getPackageStats","getTransports","previewData","getDistinctValues","countRows","createTransport","deleteTransport","removeFromTransport","viewTransportObjects","gitDiff"]}