@abapify/adt-config 0.4.1 → 0.4.3

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.d.mts CHANGED
@@ -26,9 +26,33 @@ interface AdtConfig {
26
26
  codegen?: Record<string, unknown>;
27
27
  /** Contract generation configuration */
28
28
  contracts?: ContractsConfig;
29
+ /** Incremental transport tree materialization. */
30
+ flow?: FlowConfig;
29
31
  /** Allow arbitrary plugin-specific config sections */
30
32
  [key: string]: unknown;
31
33
  }
34
+ interface FlowFormatConfig {
35
+ id: string;
36
+ options?: Record<string, string | number | boolean>;
37
+ }
38
+ interface FlowSelectorConfig {
39
+ objectTypes?: string[];
40
+ packages?: string[];
41
+ applicationComponents?: string[];
42
+ }
43
+ interface FlowConcurrencyConfig {
44
+ /** Positive integer in [1, 32] */
45
+ metadata?: number;
46
+ /** Positive integer in [1, 32] */
47
+ sources?: number;
48
+ }
49
+ interface FlowConfig {
50
+ format: FlowFormatConfig;
51
+ include?: FlowSelectorConfig;
52
+ concurrency?: FlowConcurrencyConfig;
53
+ /** Positive integer in [1, 64 MiB] */
54
+ maxSourceBytes?: number;
55
+ }
32
56
  /**
33
57
  * Contract generation configuration
34
58
  */
@@ -180,5 +204,5 @@ declare function defineConfig(config: AdtConfig): AdtConfig;
180
204
  */
181
205
  declare function defineAuthPlugin<TOptions = unknown, TCredentials = unknown>(plugin: AuthPlugin<TOptions, TCredentials>): AuthPlugin<TOptions, TCredentials>;
182
206
  //#endregion
183
- export { type AdtConfig, type AuthPlugin, type AuthTestResult, type ContentTypeMapping, type ContractsConfig, type Destination, type DestinationInput, type EnabledEndpoints, type LoadConfigOptions, type LoadedConfig, defineAuthPlugin, defineConfig, loadConfig };
207
+ export { type AdtConfig, type AuthPlugin, type AuthTestResult, type ContentTypeMapping, type ContractsConfig, type Destination, type DestinationInput, type EnabledEndpoints, type FlowConcurrencyConfig, type FlowConfig, type FlowFormatConfig, type FlowSelectorConfig, type LoadConfigOptions, type LoadedConfig, defineAuthPlugin, defineConfig, loadConfig };
184
208
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/config-loader.ts","../src/plugin.ts"],"mappings":";;AAWA;;;;;UAAiB,WAAA;EAIf;EAFA,IAAA;EAEiB;EAAjB,OAAA,EAAS,QAAA;AAAA;;;;;AAcX;KAFY,gBAAA,GAAmB,WAAA;AAAA,UAEd,SAAA;EAEe;EAA9B,YAAA,GAAe,MAAA,SAAe,gBAAA;EAMpB;EAHV,QAAA;EAM2B;EAH3B,OAAA,GAAU,MAAA;EANV;EASA,SAAA,GAAY,eAAA;EATkB;EAAA,CAY7B,GAAA;AAAA;;;;UAMc,eAAA;EANH;;AAMd;;;;;EAQE,SAAA;EAGqB;EAArB,kBAAA,GAAqB,kBAAA;EAEF;EAAnB,gBAAA,GAAmB,gBAAA;EAInB;EAFA,MAAA;EAIyB;EAFzB,IAAA;EAQA;EANA,cAAA;IAAyB,IAAA;IAAc,OAAA;EAAA;;;;;;EAMvC,KAAA;AAAA;AAAA,UAGe,kBAAA;EACf,OAAA,EAAS,MAAA;EACT,SAAA,EAAW,MAAA;AAAA;AAAA,UAGI,gBAAA;EACf,OAAA;EACA,KAAA,GAAQ,MAAA;AAAA;;;AAUV;UAAiB,cAAA;EACf,OAAA;EACA,KAAA;EACA,UAAA;EACA,YAAA;AAAA;;;;AASF;;;UAAiB,UAAA;EAW0B;EAAA,SAThC,IAAA;EAeS;EAAA,SAZT,WAAA;EAYwB;;;;EANjC,YAAA,CAAa,OAAA,EAAS,QAAA,GAAW,OAAA,CAAQ,YAAA;EAaG;;;;EAP5C,IAAA,CAAK,WAAA,EAAa,YAAA,GAAe,OAAA,CAAQ,cAAA;EANzC;;;;;EAaA,OAAA,EAAS,WAAA,EAAa,YAAA,GAAe,OAAA,CAAQ,YAAA;AAAA;;;UCxG9B,YAAA;EDZE;EAAA,SCcR,GAAA,EAAK,SAAA;EDFY;ECK1B,cAAA,CAAe,IAAA,WAAe,WAAA;EDLD;ECQ7B,gBAAA;EDNe;ECSf,cAAA,CAAe,IAAA;AAAA;AAAA,UAuLA,iBAAA;ED9LA;ECgMf,UAAA;EDvLY;ECyLZ,GAAA;AAAA;;;;;;;;;;iBAyCoB,UAAA,CACpB,OAAA,GAAS,iBAAA,YACR,OAAA,CAAQ,YAAA;;AD3NX;;;;;;;;;;;;;;iBCmSgB,YAAA,CAAa,MAAA,EAAQ,SAAA,GAAY,SAAA;;;;;;;;ADzTjD;;;;;AAEA;;;;;;;;;;;;;;;;iBEKgB,gBAAA,4CAAA,CACd,MAAA,EAAQ,UAAA,CAAW,QAAA,EAAU,YAAA,IAC5B,UAAA,CAAW,QAAA,EAAU,YAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/config-loader.ts","../src/plugin.ts"],"mappings":";;;;;;;UAWiB,YAAY;;EAE3B;;EAEA,SAAS;;;;;;;KAYC,mBAAmB;UAEd;;EAEf,eAAe,eAAe;;EAG9B;;EAGA,UAAU;;EAGV,YAAY;;EAGZ,OAAO;;GAGN;;UAGc;EACf;EACA,UAAU;;UAGK;EACf;EACA;EACA;;UAGe;;EAEf;;EAEA;;UAGe;EACf,QAAQ;EACR,UAAU;EACV,cAAc;;EAEd;;;;;UAMe;;;;;;;;EAQf;;EAGA,qBAAqB;;EAErB,mBAAmB;;EAEnB;;EAEA;;EAEA;IAAyB;IAAc;;;;;;;EAMvC;;UAGe;EACf,SAAS;EACT,WAAW;;UAGI;EACf;EACA,QAAQ;;;;;UAUO;EACf;EACA;EACA;EACA;;;;;;;;UASe,WAAW,oBAAoB;;WAErC;;WAGA;;;;;EAMT,aAAa,SAAS,WAAW,QAAQ;;;;;EAMzC,KAAK,aAAa,eAAe,QAAQ;;;;;;EAOzC,SAAS,aAAa,eAAe,QAAQ;;;;UCrI9B;;WAEN,KAAK;;EAGd,eAAe,eAAe;;EAG9B;;EAGA,eAAe;;UAuLA;;EAEf;;EAEA;;;;;;;;;;;iBAyCoB,WACpB,UAAS,6BACR,QAAQ;;;;;;;;;;;;;;;;iBAwEK,aAAa,QAAQ,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBClTjC,iBAAiB,oBAAoB,wBACnD,QAAQ,WAAW,UAAU,gBAC5B,WAAW,UAAU"}
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { existsSync, readFileSync, readdirSync } from "fs";
2
- import { join, resolve } from "path";
1
+ import { existsSync, readFileSync, readdirSync } from "node:fs";
2
+ import { join, resolve } from "node:path";
3
3
 
4
4
  //#region src/config-loader.ts
5
5
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/config-loader.ts","../src/plugin.ts"],"sourcesContent":["/**\n * Config Loader\n *\n * Loads ADT configuration from:\n * 1. adt.config.ts (TypeScript config - takes precedence)\n * 2. adt.config.json (JSON config)\n * 3. ~/.adt/config.json (global defaults)\n */\n\nimport { existsSync, readFileSync, readdirSync } from 'fs';\nimport { resolve, join } from 'path';\nimport type { AdtConfig, Destination } from './types';\n\n// =============================================================================\n// Configuration Paths\n// =============================================================================\n\nconst GLOBAL_CONFIG_PATH = resolve(\n process.env.HOME || process.env.USERPROFILE || '.',\n '.adt',\n 'config.json',\n);\n\n// =============================================================================\n// Loaded Config Interface\n// =============================================================================\n\nexport interface LoadedConfig {\n /** Raw config data */\n readonly raw: AdtConfig;\n\n /** Get a destination by name (SID) */\n getDestination(name: string): Destination | undefined;\n\n /** List all destination names */\n listDestinations(): string[];\n\n /** Check if destination exists */\n hasDestination(name: string): boolean;\n}\n\n// =============================================================================\n// Config Loading\n// =============================================================================\n\n/**\n * Load JSON config from a file path\n */\nfunction loadJsonConfig(filePath: string): AdtConfig | null {\n if (!existsSync(filePath)) {\n return null;\n }\n\n try {\n return JSON.parse(readFileSync(filePath, 'utf8'));\n } catch {\n return null;\n }\n}\n\nfunction normalizeDestinationEntry(raw: unknown): Destination | string | null {\n if (!raw || typeof raw !== 'object') {\n return null;\n }\n\n const candidate = raw as Record<string, unknown>;\n\n // Already in destination format\n if (\n typeof candidate.type === 'string' &&\n 'options' in candidate &&\n candidate.options != null &&\n typeof candidate.options === 'object'\n ) {\n return candidate as unknown as Destination;\n }\n\n // Service key JSON format\n if (\n typeof candidate.url === 'string' &&\n candidate.uaa != null &&\n typeof candidate.uaa === 'object'\n ) {\n return {\n type: '@abapify/adt-auth/plugins/service-key',\n options: {\n url: candidate.url,\n serviceKey: candidate,\n },\n };\n }\n\n // URL-only shorthand\n if (typeof candidate.url === 'string') {\n return candidate.url;\n }\n\n return null;\n}\n\nfunction loadDestinationsDirectory(cwd: string): AdtConfig | null {\n const destinationsDir = join(cwd, '.adt', 'destinations');\n if (!existsSync(destinationsDir)) {\n return null;\n }\n\n const destinations: Record<string, Destination | string> = {};\n\n for (const fileName of readdirSync(destinationsDir)) {\n if (!fileName.toLowerCase().endsWith('.json')) {\n continue;\n }\n\n const sid = fileName.slice(0, -5).toUpperCase();\n const filePath = join(destinationsDir, fileName);\n\n try {\n const raw = JSON.parse(readFileSync(filePath, 'utf8')) as unknown;\n const normalized = normalizeDestinationEntry(raw);\n if (normalized) {\n destinations[sid] = normalized;\n }\n } catch {\n // Ignore invalid destination files and continue loading others.\n }\n }\n\n if (Object.keys(destinations).length === 0) {\n return null;\n }\n\n return { destinations };\n}\n\n/**\n * Load TypeScript config (requires dynamic import)\n * The TS config is expected to export a default config object\n */\nasync function loadTsConfig(filePath: string): Promise<AdtConfig | null> {\n if (!existsSync(filePath)) {\n return null;\n }\n\n try {\n // Dynamic import for TS/JS config files\n const module = await import(filePath);\n return module.default || module;\n } catch {\n return null;\n }\n}\n\n/**\n * Merge local config with global config\n * Local destinations override global ones with the same name\n */\nfunction mergeWithGlobal(localConfig: AdtConfig): AdtConfig {\n const globalConfig = loadJsonConfig(GLOBAL_CONFIG_PATH);\n\n if (!globalConfig) {\n return localConfig;\n }\n\n return {\n ...globalConfig,\n ...localConfig,\n destinations: {\n ...globalConfig.destinations,\n ...localConfig.destinations,\n },\n };\n}\n\n/**\n * Merge two local configs where overlay values win, and destinations are merged by key.\n */\nfunction mergeLocalConfig(\n baseConfig: AdtConfig,\n overlayConfig: AdtConfig,\n): AdtConfig {\n return {\n ...baseConfig,\n ...overlayConfig,\n destinations: {\n ...baseConfig.destinations,\n ...overlayConfig.destinations,\n },\n };\n}\n\n/**\n * Create LoadedConfig wrapper\n */\nfunction createLoadedConfig(config: AdtConfig): LoadedConfig {\n return {\n raw: config,\n\n getDestination(name: string): Destination | undefined {\n const dest = config.destinations?.[name];\n if (!dest) return undefined;\n // Handle string shorthand (URL) by converting to Destination object\n // Uses built-in basic auth plugin as the default\n if (typeof dest === 'string') {\n return {\n type: '@abapify/adt-auth/plugins/basic',\n options: { url: dest },\n };\n }\n return dest;\n },\n\n listDestinations(): string[] {\n return Object.keys(config.destinations || {});\n },\n\n hasDestination(name: string): boolean {\n return name in (config.destinations || {});\n },\n };\n}\n\nexport interface LoadConfigOptions {\n /** Explicit config file path (overrides auto-discovery) */\n configPath?: string;\n /** Current working directory for auto-discovery (defaults to process.cwd()) */\n cwd?: string;\n}\n\n/**\n * Try loading a config file from an explicit path (JSON or TS/JS).\n */\nasync function loadExplicitConfig(\n configPath: string,\n): Promise<AdtConfig | null> {\n if (configPath.endsWith('.json')) {\n return loadJsonConfig(configPath);\n }\n return loadTsConfig(configPath);\n}\n\n/**\n * Discover a config file by trying multiple extensions in priority order:\n * .ts → .js → .json\n */\nasync function discoverConfig(\n basePath: string,\n baseName: string,\n): Promise<AdtConfig | null> {\n const tsConfig = await loadTsConfig(join(basePath, `${baseName}.ts`));\n if (tsConfig) return tsConfig;\n\n const jsConfig = await loadTsConfig(join(basePath, `${baseName}.js`));\n if (jsConfig) return jsConfig;\n\n return loadJsonConfig(join(basePath, `${baseName}.json`));\n}\n\n/**\n * Load configuration with precedence:\n * 1. Explicit configPath (if provided via --config flag)\n * 2. adt.config.ts in cwd\n * 3. adt.config.json in cwd\n * 4. ~/.adt/config.json (global)\n *\n * @param options Load config options or cwd string for backwards compatibility\n */\nexport async function loadConfig(\n options: LoadConfigOptions | string = {},\n): Promise<LoadedConfig> {\n // Support legacy string parameter (cwd)\n const opts: LoadConfigOptions =\n typeof options === 'string' ? { cwd: options } : options;\n const cwd = opts.cwd ?? process.cwd();\n\n // If explicit config path provided, use it directly\n if (opts.configPath) {\n const configPath = resolve(cwd, opts.configPath);\n const config = await loadExplicitConfig(configPath);\n if (config) {\n return createLoadedConfig(mergeWithGlobal(config));\n }\n // Config path specified but file not found/loadable - continue with auto-discovery\n console.warn(\n `Warning: Config file not found at ${configPath}, using auto-discovery`,\n );\n }\n\n // Discover base local config (adt.config.*)\n const baseLocalConfig = await discoverConfig(cwd, 'adt.config');\n\n // Discover optional local override (.adt/config.*)\n const localOverrideConfig = await discoverConfig(join(cwd, '.adt'), 'config');\n\n // Discover optional destinations directory (.adt/destinations/*.json)\n const destinationsDirConfig = loadDestinationsDirectory(cwd);\n\n if (baseLocalConfig || localOverrideConfig || destinationsDirConfig) {\n let mergedLocalConfig = baseLocalConfig || {};\n\n if (destinationsDirConfig) {\n mergedLocalConfig = mergeLocalConfig(\n mergedLocalConfig,\n destinationsDirConfig,\n );\n }\n\n if (localOverrideConfig) {\n mergedLocalConfig = mergeLocalConfig(\n mergedLocalConfig,\n localOverrideConfig,\n );\n }\n\n return createLoadedConfig(mergeWithGlobal(mergedLocalConfig));\n }\n\n // Fall back to global config\n const globalConfig = loadJsonConfig(GLOBAL_CONFIG_PATH);\n return createLoadedConfig(globalConfig || { destinations: {} });\n}\n\n// =============================================================================\n// Config Helper - defineConfig\n// =============================================================================\n\n/**\n * Helper function for TypeScript config files.\n * Provides type checking and autocomplete.\n *\n * Usage in adt.config.ts:\n * ```ts\n * import { defineConfig } from '@abapify/adt-config';\n *\n * export default defineConfig({\n * destinations: {\n * DEV: { type: 'basic', options: { url: '...' } },\n * }\n * });\n * ```\n */\nexport function defineConfig(config: AdtConfig): AdtConfig {\n return config;\n}\n","/**\n * Auth Plugin Helpers\n *\n * Provides type-safe helpers for defining auth plugins.\n */\n\nimport type { AuthPlugin } from './types';\n\n/**\n * Define an auth plugin with full type inference.\n *\n * Usage:\n * ```ts\n * import { defineAuthPlugin } from '@abapify/adt-config';\n *\n * interface MyOptions { url: string; }\n * interface MyCredentials { token: string; }\n *\n * export const myPlugin = defineAuthPlugin<MyOptions, MyCredentials>({\n * name: 'my-auth',\n * displayName: 'My Auth Method',\n *\n * async authenticate(options) {\n * // options is typed as MyOptions\n * return { token: '...' };\n * },\n *\n * async test(credentials) {\n * // credentials is typed as MyCredentials\n * return { success: true };\n * },\n * });\n * ```\n */\nexport function defineAuthPlugin<TOptions = unknown, TCredentials = unknown>(\n plugin: AuthPlugin<TOptions, TCredentials>,\n): AuthPlugin<TOptions, TCredentials> {\n return plugin;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/config-loader.ts","../src/plugin.ts"],"sourcesContent":["/**\n * Config Loader\n *\n * Loads ADT configuration from:\n * 1. adt.config.ts (TypeScript config - takes precedence)\n * 2. adt.config.json (JSON config)\n * 3. ~/.adt/config.json (global defaults)\n */\n\nimport { existsSync, readFileSync, readdirSync } from 'node:fs';\nimport { resolve, join } from 'node:path';\nimport type { AdtConfig, Destination } from './types';\n\n// =============================================================================\n// Configuration Paths\n// =============================================================================\n\nconst GLOBAL_CONFIG_PATH = resolve(\n process.env.HOME || process.env.USERPROFILE || '.',\n '.adt',\n 'config.json',\n);\n\n// =============================================================================\n// Loaded Config Interface\n// =============================================================================\n\nexport interface LoadedConfig {\n /** Raw config data */\n readonly raw: AdtConfig;\n\n /** Get a destination by name (SID) */\n getDestination(name: string): Destination | undefined;\n\n /** List all destination names */\n listDestinations(): string[];\n\n /** Check if destination exists */\n hasDestination(name: string): boolean;\n}\n\n// =============================================================================\n// Config Loading\n// =============================================================================\n\n/**\n * Load JSON config from a file path\n */\nfunction loadJsonConfig(filePath: string): AdtConfig | null {\n if (!existsSync(filePath)) {\n return null;\n }\n\n try {\n return JSON.parse(readFileSync(filePath, 'utf8'));\n } catch {\n return null;\n }\n}\n\nfunction normalizeDestinationEntry(raw: unknown): Destination | string | null {\n if (!raw || typeof raw !== 'object') {\n return null;\n }\n\n const candidate = raw as Record<string, unknown>;\n\n // Already in destination format\n if (\n typeof candidate.type === 'string' &&\n 'options' in candidate &&\n candidate.options != null &&\n typeof candidate.options === 'object'\n ) {\n return candidate as unknown as Destination;\n }\n\n // Service key JSON format\n if (\n typeof candidate.url === 'string' &&\n candidate.uaa != null &&\n typeof candidate.uaa === 'object'\n ) {\n return {\n type: '@abapify/adt-auth/plugins/service-key',\n options: {\n url: candidate.url,\n serviceKey: candidate,\n },\n };\n }\n\n // URL-only shorthand\n if (typeof candidate.url === 'string') {\n return candidate.url;\n }\n\n return null;\n}\n\nfunction loadDestinationsDirectory(cwd: string): AdtConfig | null {\n const destinationsDir = join(cwd, '.adt', 'destinations');\n if (!existsSync(destinationsDir)) {\n return null;\n }\n\n const destinations: Record<string, Destination | string> = {};\n\n for (const fileName of readdirSync(destinationsDir)) {\n if (!fileName.toLowerCase().endsWith('.json')) {\n continue;\n }\n\n const sid = fileName.slice(0, -5).toUpperCase();\n const filePath = join(destinationsDir, fileName);\n\n try {\n const raw = JSON.parse(readFileSync(filePath, 'utf8')) as unknown;\n const normalized = normalizeDestinationEntry(raw);\n if (normalized) {\n destinations[sid] = normalized;\n }\n } catch {\n // Ignore invalid destination files and continue loading others.\n }\n }\n\n if (Object.keys(destinations).length === 0) {\n return null;\n }\n\n return { destinations };\n}\n\n/**\n * Load TypeScript config (requires dynamic import)\n * The TS config is expected to export a default config object\n */\nasync function loadTsConfig(filePath: string): Promise<AdtConfig | null> {\n if (!existsSync(filePath)) {\n return null;\n }\n\n try {\n // Dynamic import for TS/JS config files\n const module = await import(filePath);\n return module.default || module;\n } catch {\n return null;\n }\n}\n\n/**\n * Merge local config with global config\n * Local destinations override global ones with the same name\n */\nfunction mergeWithGlobal(localConfig: AdtConfig): AdtConfig {\n const globalConfig = loadJsonConfig(GLOBAL_CONFIG_PATH);\n\n if (!globalConfig) {\n return localConfig;\n }\n\n return {\n ...globalConfig,\n ...localConfig,\n destinations: {\n ...globalConfig.destinations,\n ...localConfig.destinations,\n },\n };\n}\n\n/**\n * Merge two local configs where overlay values win, and destinations are merged by key.\n */\nfunction mergeLocalConfig(\n baseConfig: AdtConfig,\n overlayConfig: AdtConfig,\n): AdtConfig {\n return {\n ...baseConfig,\n ...overlayConfig,\n destinations: {\n ...baseConfig.destinations,\n ...overlayConfig.destinations,\n },\n };\n}\n\n/**\n * Create LoadedConfig wrapper\n */\nfunction createLoadedConfig(config: AdtConfig): LoadedConfig {\n return {\n raw: config,\n\n getDestination(name: string): Destination | undefined {\n const dest = config.destinations?.[name];\n if (!dest) return undefined;\n // Handle string shorthand (URL) by converting to Destination object\n // Uses built-in basic auth plugin as the default\n if (typeof dest === 'string') {\n return {\n type: '@abapify/adt-auth/plugins/basic',\n options: { url: dest },\n };\n }\n return dest;\n },\n\n listDestinations(): string[] {\n return Object.keys(config.destinations || {});\n },\n\n hasDestination(name: string): boolean {\n return name in (config.destinations || {});\n },\n };\n}\n\nexport interface LoadConfigOptions {\n /** Explicit config file path (overrides auto-discovery) */\n configPath?: string;\n /** Current working directory for auto-discovery (defaults to process.cwd()) */\n cwd?: string;\n}\n\n/**\n * Try loading a config file from an explicit path (JSON or TS/JS).\n */\nasync function loadExplicitConfig(\n configPath: string,\n): Promise<AdtConfig | null> {\n if (configPath.endsWith('.json')) {\n return loadJsonConfig(configPath);\n }\n return loadTsConfig(configPath);\n}\n\n/**\n * Discover a config file by trying multiple extensions in priority order:\n * .ts → .js → .json\n */\nasync function discoverConfig(\n basePath: string,\n baseName: string,\n): Promise<AdtConfig | null> {\n const tsConfig = await loadTsConfig(join(basePath, `${baseName}.ts`));\n if (tsConfig) return tsConfig;\n\n const jsConfig = await loadTsConfig(join(basePath, `${baseName}.js`));\n if (jsConfig) return jsConfig;\n\n return loadJsonConfig(join(basePath, `${baseName}.json`));\n}\n\n/**\n * Load configuration with precedence:\n * 1. Explicit configPath (if provided via --config flag)\n * 2. adt.config.ts in cwd\n * 3. adt.config.json in cwd\n * 4. ~/.adt/config.json (global)\n *\n * @param options Load config options or cwd string for backwards compatibility\n */\nexport async function loadConfig(\n options: LoadConfigOptions | string = {},\n): Promise<LoadedConfig> {\n // Support legacy string parameter (cwd)\n const opts: LoadConfigOptions =\n typeof options === 'string' ? { cwd: options } : options;\n const cwd = opts.cwd ?? process.cwd();\n\n // If explicit config path provided, use it directly\n if (opts.configPath) {\n const configPath = resolve(cwd, opts.configPath);\n const config = await loadExplicitConfig(configPath);\n if (config) {\n return createLoadedConfig(mergeWithGlobal(config));\n }\n // Config path specified but file not found/loadable - continue with auto-discovery\n console.warn(\n `Warning: Config file not found at ${configPath}, using auto-discovery`,\n );\n }\n\n // Discover base local config (adt.config.*)\n const baseLocalConfig = await discoverConfig(cwd, 'adt.config');\n\n // Discover optional local override (.adt/config.*)\n const localOverrideConfig = await discoverConfig(join(cwd, '.adt'), 'config');\n\n // Discover optional destinations directory (.adt/destinations/*.json)\n const destinationsDirConfig = loadDestinationsDirectory(cwd);\n\n if (baseLocalConfig || localOverrideConfig || destinationsDirConfig) {\n let mergedLocalConfig = baseLocalConfig || {};\n\n if (destinationsDirConfig) {\n mergedLocalConfig = mergeLocalConfig(\n mergedLocalConfig,\n destinationsDirConfig,\n );\n }\n\n if (localOverrideConfig) {\n mergedLocalConfig = mergeLocalConfig(\n mergedLocalConfig,\n localOverrideConfig,\n );\n }\n\n return createLoadedConfig(mergeWithGlobal(mergedLocalConfig));\n }\n\n // Fall back to global config\n const globalConfig = loadJsonConfig(GLOBAL_CONFIG_PATH);\n return createLoadedConfig(globalConfig || { destinations: {} });\n}\n\n// =============================================================================\n// Config Helper - defineConfig\n// =============================================================================\n\n/**\n * Helper function for TypeScript config files.\n * Provides type checking and autocomplete.\n *\n * Usage in adt.config.ts:\n * ```ts\n * import { defineConfig } from '@abapify/adt-config';\n *\n * export default defineConfig({\n * destinations: {\n * DEV: { type: 'basic', options: { url: '...' } },\n * }\n * });\n * ```\n */\nexport function defineConfig(config: AdtConfig): AdtConfig {\n return config;\n}\n","/**\n * Auth Plugin Helpers\n *\n * Provides type-safe helpers for defining auth plugins.\n */\n\nimport type { AuthPlugin } from './types';\n\n/**\n * Define an auth plugin with full type inference.\n *\n * Usage:\n * ```ts\n * import { defineAuthPlugin } from '@abapify/adt-config';\n *\n * interface MyOptions { url: string; }\n * interface MyCredentials { token: string; }\n *\n * export const myPlugin = defineAuthPlugin<MyOptions, MyCredentials>({\n * name: 'my-auth',\n * displayName: 'My Auth Method',\n *\n * async authenticate(options) {\n * // options is typed as MyOptions\n * return { token: '...' };\n * },\n *\n * async test(credentials) {\n * // credentials is typed as MyCredentials\n * return { success: true };\n * },\n * });\n * ```\n */\nexport function defineAuthPlugin<TOptions = unknown, TCredentials = unknown>(\n plugin: AuthPlugin<TOptions, TCredentials>,\n): AuthPlugin<TOptions, TCredentials> {\n return plugin;\n}\n"],"mappings":";;;;;;;;;;;;AAiBA,MAAM,qBAAqB,QACzB,QAAQ,IAAI,QAAQ,QAAQ,IAAI,eAAe,KAC/C,QACA,aACF;;;;AA2BA,SAAS,eAAe,UAAoC;CAC1D,IAAI,CAAC,WAAW,QAAQ,GACtB,OAAO;CAGT,IAAI;EACF,OAAO,KAAK,MAAM,aAAa,UAAU,MAAM,CAAC;CAClD,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,0BAA0B,KAA2C;CAC5E,IAAI,CAAC,OAAO,OAAO,QAAQ,UACzB,OAAO;CAGT,MAAM,YAAY;CAGlB,IACE,OAAO,UAAU,SAAS,YAC1B,aAAa,aACb,UAAU,WAAW,QACrB,OAAO,UAAU,YAAY,UAE7B,OAAO;CAIT,IACE,OAAO,UAAU,QAAQ,YACzB,UAAU,OAAO,QACjB,OAAO,UAAU,QAAQ,UAEzB,OAAO;EACL,MAAM;EACN,SAAS;GACP,KAAK,UAAU;GACf,YAAY;EACd;CACF;CAIF,IAAI,OAAO,UAAU,QAAQ,UAC3B,OAAO,UAAU;CAGnB,OAAO;AACT;AAEA,SAAS,0BAA0B,KAA+B;CAChE,MAAM,kBAAkB,KAAK,KAAK,QAAQ,cAAc;CACxD,IAAI,CAAC,WAAW,eAAe,GAC7B,OAAO;CAGT,MAAM,eAAqD,CAAC;CAE5D,KAAK,MAAM,YAAY,YAAY,eAAe,GAAG;EACnD,IAAI,CAAC,SAAS,YAAY,CAAC,CAAC,SAAS,OAAO,GAC1C;EAGF,MAAM,MAAM,SAAS,MAAM,GAAG,EAAE,CAAC,CAAC,YAAY;EAC9C,MAAM,WAAW,KAAK,iBAAiB,QAAQ;EAE/C,IAAI;GAEF,MAAM,aAAa,0BADP,KAAK,MAAM,aAAa,UAAU,MAAM,CACL,CAAC;GAChD,IAAI,YACF,aAAa,OAAO;EAExB,QAAQ,CAER;CACF;CAEA,IAAI,OAAO,KAAK,YAAY,CAAC,CAAC,WAAW,GACvC,OAAO;CAGT,OAAO,EAAE,aAAa;AACxB;;;;;AAMA,eAAe,aAAa,UAA6C;CACvE,IAAI,CAAC,WAAW,QAAQ,GACtB,OAAO;CAGT,IAAI;EAEF,MAAM,SAAS,MAAM,OAAO;EAC5B,OAAO,OAAO,WAAW;CAC3B,QAAQ;EACN,OAAO;CACT;AACF;;;;;AAMA,SAAS,gBAAgB,aAAmC;CAC1D,MAAM,eAAe,eAAe,kBAAkB;CAEtD,IAAI,CAAC,cACH,OAAO;CAGT,OAAO;EACL,GAAG;EACH,GAAG;EACH,cAAc;GACZ,GAAG,aAAa;GAChB,GAAG,YAAY;EACjB;CACF;AACF;;;;AAKA,SAAS,iBACP,YACA,eACW;CACX,OAAO;EACL,GAAG;EACH,GAAG;EACH,cAAc;GACZ,GAAG,WAAW;GACd,GAAG,cAAc;EACnB;CACF;AACF;;;;AAKA,SAAS,mBAAmB,QAAiC;CAC3D,OAAO;EACL,KAAK;EAEL,eAAe,MAAuC;GACpD,MAAM,OAAO,OAAO,eAAe;GACnC,IAAI,CAAC,MAAM,OAAO;GAGlB,IAAI,OAAO,SAAS,UAClB,OAAO;IACL,MAAM;IACN,SAAS,EAAE,KAAK,KAAK;GACvB;GAEF,OAAO;EACT;EAEA,mBAA6B;GAC3B,OAAO,OAAO,KAAK,OAAO,gBAAgB,CAAC,CAAC;EAC9C;EAEA,eAAe,MAAuB;GACpC,OAAO,SAAS,OAAO,gBAAgB,CAAC;EAC1C;CACF;AACF;;;;AAYA,eAAe,mBACb,YAC2B;CAC3B,IAAI,WAAW,SAAS,OAAO,GAC7B,OAAO,eAAe,UAAU;CAElC,OAAO,aAAa,UAAU;AAChC;;;;;AAMA,eAAe,eACb,UACA,UAC2B;CAC3B,MAAM,WAAW,MAAM,aAAa,KAAK,UAAU,GAAG,SAAS,IAAI,CAAC;CACpE,IAAI,UAAU,OAAO;CAErB,MAAM,WAAW,MAAM,aAAa,KAAK,UAAU,GAAG,SAAS,IAAI,CAAC;CACpE,IAAI,UAAU,OAAO;CAErB,OAAO,eAAe,KAAK,UAAU,GAAG,SAAS,MAAM,CAAC;AAC1D;;;;;;;;;;AAWA,eAAsB,WACpB,UAAsC,CAAC,GAChB;CAEvB,MAAM,OACJ,OAAO,YAAY,WAAW,EAAE,KAAK,QAAQ,IAAI;CACnD,MAAM,MAAM,KAAK,OAAO,QAAQ,IAAI;CAGpC,IAAI,KAAK,YAAY;EACnB,MAAM,aAAa,QAAQ,KAAK,KAAK,UAAU;EAC/C,MAAM,SAAS,MAAM,mBAAmB,UAAU;EAClD,IAAI,QACF,OAAO,mBAAmB,gBAAgB,MAAM,CAAC;EAGnD,QAAQ,KACN,qCAAqC,WAAW,uBAClD;CACF;CAGA,MAAM,kBAAkB,MAAM,eAAe,KAAK,YAAY;CAG9D,MAAM,sBAAsB,MAAM,eAAe,KAAK,KAAK,MAAM,GAAG,QAAQ;CAG5E,MAAM,wBAAwB,0BAA0B,GAAG;CAE3D,IAAI,mBAAmB,uBAAuB,uBAAuB;EACnE,IAAI,oBAAoB,mBAAmB,CAAC;EAE5C,IAAI,uBACF,oBAAoB,iBAClB,mBACA,qBACF;EAGF,IAAI,qBACF,oBAAoB,iBAClB,mBACA,mBACF;EAGF,OAAO,mBAAmB,gBAAgB,iBAAiB,CAAC;CAC9D;CAIA,OAAO,mBADc,eAAe,kBACC,KAAK,EAAE,cAAc,CAAC,EAAE,CAAC;AAChE;;;;;;;;;;;;;;;;AAqBA,SAAgB,aAAa,QAA8B;CACzD,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACpTA,SAAgB,iBACd,QACoC;CACpC,OAAO;AACT"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abapify/adt-config",
3
- "version": "0.4.1",
3
+ "version": "0.4.3",
4
4
  "description": "Configuration loader for ADT CLI",
5
5
  "license": "MIT",
6
6
  "publishConfig": {