Files
gridpilot.gg/adapters/media/MediaResolverAdapter.ts
2025-12-31 15:39:28 +01:00

127 lines
3.4 KiB
TypeScript

/**
* 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<string | null> {
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({})
};