/** * Configuration mapping utilities. * * This module provides the single source of truth for mapping between * different configuration formats (dw.json, normalized config, etc.). * * @module config/mapping */ import type { AuthConfig } from '../auth/types.js'; import { B2CInstance } from '../instance/index.js'; import type { DwJsonConfig } from './dw-json.js'; import type { LibraryEntry, NormalizedConfig, ConfigWarning } from './types.js'; /** * Normalizes a URL origin string by ensuring it has an `https://` protocol prefix. * Accepts both bare hostnames (`cloud.mobify.com`) and full URLs (`https://cloud.mobify.com`). * Strips trailing slashes for consistency. * * @param origin - A hostname or URL origin string * @returns The origin with `https://` protocol, or undefined if input is undefined */ export declare function normalizeOriginUrl(origin: string | undefined): string | undefined; /** * Normalizes a {@link NormalizedConfig.libraries} value to an array of * {@link LibraryEntry} objects. Bare strings are treated as * `{id, siteLibrary: false}`. Returns an empty array when input is undefined. */ export declare function resolveLibraryEntries(libraries: (string | LibraryEntry)[] | undefined): LibraryEntry[]; /** * Converts a kebab-case string to camelCase. * * @param str - The kebab-case string to convert * @returns The camelCase equivalent * * @example * ```typescript * kebabToCamelCase('code-version'); // 'codeVersion' * kebabToCamelCase('client-id'); // 'clientId' * kebabToCamelCase('hostname'); // 'hostname' (no change) * ``` */ export declare function kebabToCamelCase(str: string): string; /** * Legacy/non-standard aliases that cannot be derived by kebab→camel conversion. * Maps alias → canonical camelCase field name. */ export declare const CONFIG_KEY_ALIASES: Record; /** * Normalizes config keys to canonical camelCase form. * * Resolution order for each key: * 1. Check CONFIG_KEY_ALIASES for legacy/non-standard names * 2. Fall back to kebab→camelCase conversion * 3. First value wins when multiple keys resolve to the same canonical name * * @param raw - The raw config object with potentially mixed key formats * @returns A new object with all keys in canonical camelCase * * @example * ```typescript * normalizeConfigKeys({ 'client-id': 'abc', 'code-version': 'v1' }); * // { clientId: 'abc', codeVersion: 'v1' } * * normalizeConfigKeys({ server: 'example.com', hostname: 'other.com' }); * // { hostname: 'example.com' } (first value wins) * ``` */ export declare function normalizeConfigKeys(raw: Record): Record; /** * Maps dw.json fields to normalized config format. * * This is the SINGLE place where dw.json field mapping happens. * Keys are already normalized to camelCase by normalizeConfigKeys() in loadDwJson(), * so this function only handles genuine renames (e.g., `name` → `instanceName`, * `oauthScopes` → `scopes`). * * @param json - The normalized dw.json config (camelCase keys) * @returns Normalized configuration * * @example * ```typescript * import { mapDwJsonToNormalizedConfig } from '@salesforce/b2c-tooling-sdk/config'; * * const dwJson = { hostname: 'example.com', codeVersion: 'v1' }; * const config = mapDwJsonToNormalizedConfig(dwJson); * // { hostname: 'example.com', codeVersion: 'v1' } * ``` */ export declare function mapDwJsonToNormalizedConfig(json: DwJsonConfig): NormalizedConfig; /** * Maps normalized config to dw.json format. * * This is the reverse of mapDwJsonToNormalizedConfig. It converts normalized * config (camelCase) back to dw.json format (kebab-case). * * @param config - The normalized configuration * @param name - Optional instance name to include * @returns DwJsonConfig structure * * @example * ```typescript * const config = { hostname: 'example.com', codeVersion: 'v1', clientId: 'abc' }; * const dwJson = mapNormalizedConfigToDwJson(config, 'staging'); * // { name: 'staging', hostname: 'example.com', 'code-version': 'v1', 'client-id': 'abc' } * ``` */ export declare function mapNormalizedConfigToDwJson(config: Partial, name?: string): DwJsonConfig; /** * Options for merging configurations. */ export interface MergeConfigOptions { /** * Whether to apply hostname mismatch protection. * When true, if overrides.hostname differs from base.hostname, * the entire base config is ignored. * @default true */ hostnameProtection?: boolean; } /** * Result of merging configurations. */ export interface MergeConfigResult { /** The merged configuration */ config: NormalizedConfig; /** Warnings generated during merge (e.g., hostname mismatch) */ warnings: ConfigWarning[]; /** Whether a hostname mismatch was detected and base was ignored */ hostnameMismatch: boolean; } /** * Merges configurations with hostname mismatch protection. * * Applies the precedence rule: overrides > base. * If hostname protection is enabled and the override hostname differs from * the base hostname, the entire base config is ignored to prevent * credential leakage between different instances. * * @param overrides - Higher-priority config values (e.g., from CLI flags/env) * @param base - Lower-priority config values (e.g., from dw.json) * @param options - Merge options * @returns Merged config with warnings * * @example * ```typescript * import { mergeConfigsWithProtection } from '@salesforce/b2c-tooling-sdk/config'; * * const { config, warnings } = mergeConfigsWithProtection( * { hostname: 'staging.example.com' }, * { hostname: 'prod.example.com', clientId: 'abc' }, * { hostnameProtection: true } * ); * // config = { hostname: 'staging.example.com' } * // warnings = [{ code: 'HOSTNAME_MISMATCH', ... }] * ``` */ export declare function mergeConfigsWithProtection(overrides: Partial, base: NormalizedConfig, options?: MergeConfigOptions): MergeConfigResult; /** * Gets the list of fields that have values in a config. * * Used for tracking which sources contributed which fields during * configuration resolution. * * @param config - The configuration to inspect * @returns Array of field names that have non-empty values * * @example * ```typescript * const config = { hostname: 'example.com', clientId: 'abc' }; * const fields = getPopulatedFields(config); * // ['hostname', 'clientId'] * ``` */ export declare function getPopulatedFields(config: NormalizedConfig): (keyof NormalizedConfig)[]; /** * Builds an AuthConfig from a NormalizedConfig. * * This is the single source of truth for converting normalized config * to the AuthConfig format expected by B2CInstance. * * @param config - The normalized configuration * @returns AuthConfig for B2CInstance * * @example * ```typescript * const config = { * clientId: 'my-client-id', * clientSecret: 'my-secret', * username: 'admin', * password: 'pass', * }; * const authConfig = buildAuthConfigFromNormalized(config); * // { oauth: { clientId: '...', clientSecret: '...' }, basic: { username: '...', password: '...' } } * ``` */ export declare function buildAuthConfigFromNormalized(config: NormalizedConfig): AuthConfig; /** * Creates a B2CInstance from a NormalizedConfig. * * This utility provides a single source of truth for instance creation * from resolved configuration. It is used by both ConfigResolver.createInstance() * and CLI commands (e.g., InstanceCommand). * * @param config - The normalized configuration (must include hostname) * @returns Configured B2CInstance * @throws Error if hostname is not available in config * * @example * ```typescript * import { createInstanceFromConfig } from '@salesforce/b2c-tooling-sdk/config'; * * const config = { hostname: 'example.demandware.net', clientId: 'abc' }; * const instance = createInstanceFromConfig(config); * await instance.webdav.mkcol('Cartridges/v1'); * ``` */ export declare function createInstanceFromConfig(config: NormalizedConfig, options?: { redirectUri?: string; openBrowser?: (url: string) => Promise; }): B2CInstance;