/** * MediaResolverAdapter (Composite) * * Composite adapter that delegates resolution to type-specific adapters. * This is the main entry point for media resolution. */ import { MediaResolverPort } from '@core/ports/media/MediaResolverPort'; import { MediaReference } from '@core/domain/media/MediaReference'; import { DefaultMediaResolverAdapter } from './resolvers/DefaultMediaResolverAdapter'; import { GeneratedMediaResolverAdapter } from './resolvers/GeneratedMediaResolverAdapter'; import { UploadedMediaResolverAdapter } from './resolvers/UploadedMediaResolverAdapter'; /** * Configuration for the composite MediaResolverAdapter */ export interface MediaResolverAdapterConfig { /** * Base path for default assets (defaults to '/media/default') */ defaultPath?: string; /** * Base path for generated assets (defaults to '/media/generated') */ generatedPath?: string; /** * Base path for uploaded assets (defaults to '/media/uploaded') */ uploadedPath?: string; } /** * MediaResolverAdapter * * Composite adapter that delegates to type-specific resolvers. * Implements the MediaResolverPort interface. * * Returns path-only URLs (e.g., /media/teams/123/logo) without baseUrl. * * Usage: * ```typescript * const resolver = new MediaResolverAdapter({ * defaultPath: '/media/default', * generatedPath: '/media/generated', * uploadedPath: '/media/uploaded' * }); * * const path = await resolver.resolve(mediaReference); * ``` */ export class MediaResolverAdapter implements MediaResolverPort { private readonly defaultResolver: DefaultMediaResolverAdapter; private readonly generatedResolver: GeneratedMediaResolverAdapter; private readonly uploadedResolver: UploadedMediaResolverAdapter; constructor(config: MediaResolverAdapterConfig = {}) { // Initialize type-specific resolvers this.defaultResolver = new DefaultMediaResolverAdapter({ basePath: config.defaultPath }); this.generatedResolver = new GeneratedMediaResolverAdapter({ basePath: config.generatedPath }); this.uploadedResolver = new UploadedMediaResolverAdapter({ basePath: config.uploadedPath }); } /** * Resolve a media reference to a path-only URL * * Delegates to the appropriate type-specific resolver based on the reference type. * Returns paths like /media/... (no baseUrl). */ async resolve(ref: MediaReference): Promise { if (!ref) { return null; } // Delegate to the appropriate resolver based on type switch (ref.type) { case 'system-default': return this.defaultResolver.resolve(ref); case 'generated': return this.generatedResolver.resolve(ref); case 'uploaded': return this.uploadedResolver.resolve(ref); case 'none': return null; default: // Unknown type return null; } } } /** * Factory function for creating MediaResolverAdapter instances */ export function createMediaResolver( config: MediaResolverAdapterConfig = {} ): MediaResolverAdapter { return new MediaResolverAdapter(config); } /** * Default configuration for development/testing */ export const DefaultResolvers = { /** * Creates a resolver for local development */ local: () => createMediaResolver({}), /** * Creates a resolver for production */ production: () => createMediaResolver({}) };