Factory, strategy, and registry patterns for swappable provider implementations. Use these patterns to abstract external services (email, storage, payments) behind a consistent interface.
Create provider instances from a registry of implementations
import { createProviderFactory } from '@infra/provider-factory';
const emailFactory = createProviderFactory({
sendgrid: () => new SendGridProvider(config),
ses: () => new SESProvider(config),
resend: () => new ResendProvider(config),
});
// Runtime selection
const emailProvider = emailFactory.create('sendgrid');
await emailProvider.send({ to, subject, body });Swap implementations at runtime based on context
import { createStrategy } from '@infra/provider-factory';
const storageStrategy = createStrategy<StorageProvider>({
local: new LocalStorage(),
s3: new S3Storage(),
gcs: new GCSStorage(),
});
// Use based on environment
const storage = storageStrategy.resolve(
getEnv('STORAGE_PROVIDER', 'local')
);
await storage.upload(file);Register and discover providers dynamically
import { ProviderRegistry } from '@infra/provider-factory';
const registry = new ProviderRegistry<PaymentProvider>();
registry.register('stripe', new StripeProvider());
registry.register('paddle', new PaddleProvider());
// Discover at runtime
const providers = registry.list();
const provider = registry.get('stripe');