import type { FetchEngineCore } from '../engine/types.ts'; import type { PropertyEventData } from '../engine/events.ts'; import type { HttpMethods, DictAndT } from '../types.ts'; import { PropertyStore, type PropertyStoreOptions } from './store.ts'; /** * Manages URL parameters for FetchEngine with event emission. * * Wraps PropertyStore with FetchEngine-specific event emission. * Pulls initial params and validation from engine options. * * @template P - Params type * * @example * ```typescript * // Access via engine.params * engine.params.set('apiKey', 'abc123'); * engine.params.set({ page: '1', limit: '10' }); * * // Method-specific params * engine.params.set('format', 'json', 'GET'); * * // Remove params * engine.params.remove('apiKey'); * engine.params.remove(['page', 'limit']); * * // Check if param exists * if (engine.params.has('apiKey')) { ... } * * // Get resolved params for a request * const params = engine.params.resolve('GET', { extra: 'value' }); * ``` */ export class ParamsManager

{ #engine: FetchEngineCore; #store: PropertyStore>; constructor(engine: FetchEngineCore) { this.#engine = engine; const defaults = engine.config.get('params') ?? {} as DictAndT

; const methodOverrides = engine.config.get('methodParams'); const validate = engine.config.get('validate.params'); const storeOptions: PropertyStoreOptions> = { defaults }; if (methodOverrides !== undefined) { storeOptions.methodOverrides = methodOverrides; } if (validate !== undefined) { storeOptions.validate = validate; } this.#store = new PropertyStore>(storeOptions); } /** * Set a param value globally or for a specific method. * * @example * ```typescript * engine.params.set('apiKey', 'abc123'); * engine.params.set('format', 'json', 'GET'); * ``` */ set(key: string, value: string, method?: HttpMethods): void; /** * Set multiple param values globally or for a specific method. * * @example * ```typescript * engine.params.set({ page: '1', limit: '10' }); * engine.params.set({ format: 'json' }, 'GET'); * ``` */ set(params: Partial>, method?: HttpMethods): void; set( keyOrParams: string | Partial>, valueOrMethod?: string | HttpMethods, maybeMethod?: HttpMethods ): void { if (typeof keyOrParams === 'string') { const key = keyOrParams; const value = valueOrMethod as string; const method = maybeMethod; this.#store.set(key, value, method); const eventData = { key, value, method } as PropertyEventData>; this.#engine.emit('param-add', eventData); } else { const params = keyOrParams; const method = valueOrMethod as HttpMethods | undefined; this.#store.set(params, method); const eventData = { value: params as Partial>, method } as PropertyEventData>; this.#engine.emit('param-add', eventData); } } /** * Remove a param globally or for a specific method. * * @example * ```typescript * engine.params.remove('apiKey'); * engine.params.remove('format', 'GET'); * ``` */ remove(key: string, method?: HttpMethods): void; /** * Remove multiple params globally or for a specific method. * * @example * ```typescript * engine.params.remove(['page', 'limit']); * engine.params.remove(['format'], 'GET'); * ``` */ remove(keys: string[], method?: HttpMethods): void; remove(keyOrKeys: string | string[], method?: HttpMethods): void { this.#store.remove(keyOrKeys as string, method); const eventData = { key: keyOrKeys, method } as PropertyEventData>; this.#engine.emit('param-remove', eventData); } /** * Check if a param exists globally or for a specific method. * * @example * ```typescript * if (engine.params.has('apiKey')) { * console.log('API key is set'); * } * ``` */ has(key: string, method?: HttpMethods): boolean { return this.#store.has(key, method); } /** * Resolve the final params for a specific method. * * Merges in order: defaults → method overrides → request overrides. * * @example * ```typescript * const params = engine.params.resolve('GET', { extra: 'value' }); * ``` */ resolve(method: HttpMethods, requestOverrides?: Partial>): DictAndT

{ return this.#store.resolve(method, requestOverrides); } /** * Get the default params (without method overrides). */ get defaults(): DictAndT

{ return this.#store.defaults; } /** * Get all params including method overrides. * * @example * ```typescript * const all = engine.params.all; * // { default: { apiKey: '...' }, get: { format: '...' } } * ``` */ get all(): { default: DictAndT

} & Record>> { return this.#store.all; } /** * Get method-specific params only (not merged with defaults). */ forMethod(method: HttpMethods): Partial> { return this.#store.forMethod(method); } /** * Get the underlying PropertyStore for internal use. * * Exposed for FetchEngineCore compliance. Internal components * (executor, policies) access the store directly for resolution. * * @internal */ get $store(): PropertyStore> { return this.#store; } }