shyun_link 1.0.0
shyun_link: ^1.0.0 copied to clipboard
A comprehensive deeplink and short URL management system built with Clean Architecture principles. Supports strategy patterns, dependency injection, and enterprise-grade error handling.
shyun_link 🚀 #
A comprehensive, enterprise-grade deeplink and short URL management system built with Clean Architecture principles. Perfect for complex Flutter applications that need robust, scalable, and testable deeplink handling.
✨ Features #
🔗 Deeplink Management #
- Universal Link Support - Handle both app schemes and web URLs
- Parametrized Links - Extract parameters from complex URLs
- Fallback Strategies - Graceful handling of unknown links
- Route Validation - Ensure links point to valid destinations
- Preview Mode - Debug and test deeplinks before deployment
📎 Short URL System #
- Multiple Providers - HTTP-based or custom implementations
- Analytics Tracking - Click counts, geographic data, device stats
- Expiration Management - Time-based link expiration
- Custom Aliases - Branded short links
- Batch Operations - Create multiple links efficiently
⚙️ Configuration & DI #
- Framework Agnostic - Works with GetX, get_it, Provider, or built-in DI
- Environment-Based Config - Development, staging, production presets
- Runtime Configuration - Modify behavior without rebuilding
- Security Controls - Domain whitelisting, rate limiting, validation
🛡️ Enterprise Ready #
- Functional Error Handling - Result
- Comprehensive Logging - Debug, performance, and error tracking
- Type Safety - Full Dart null safety and strong typing
- Testing Support - Built-in mocks and test utilities
- Performance Optimized - Caching, request coalescing, concurrent processing
🚀 Quick Start #
Installation #
Add to your pubspec.yaml
:
dependencies:
shyun_link: ^1.0.0
# Optional: Choose your preferred DI framework
get: ^4.6.0 # For GetX
# OR
get_it: ^7.0.0 # For get_it
# OR use built-in DI (no additional dependencies)
Basic Setup #
import 'package:shyun_link/shyun_link.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// 1. Configure the system
final config = DeepLinkConfig.defaults(
appScheme: 'myapp',
baseUrl: 'https://myapp.com',
);
// 2. Initialize the dependency injection
await DeepLinkArchitect.initialize(config);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My App',
home: HomePage(),
// 3. Handle deeplinks
onGenerateRoute: (settings) {
return DeepLinkArchitect.handleRoute(settings);
},
);
}
}
Handle Incoming Deeplinks #
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
late final DeepLinkFacade _deepLinkFacade;
@override
void initState() {
super.initState();
_deepLinkFacade = DIContainer.get<DeepLinkFacade>();
_setupDeepLinkListener();
}
void _setupDeepLinkListener() {
// Handle incoming deeplinks
DeepLinkArchitect.onDeepLink.listen((deepLink) async {
final success = await _deepLinkFacade.handleDeepLink(deepLink);
if (!success) {
// Handle fallback
Navigator.of(context).pushReplacementNamed('/');
}
});
}
}
Create and Share Short Links #
class ProductPage extends StatelessWidget {
final int productId;
const ProductPage({required this.productId});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Product $productId'),
actions: [
IconButton(
icon: Icon(Icons.share),
onPressed: () => _shareProduct(context),
),
],
),
body: ProductDetails(productId: productId),
);
}
Future<void> _shareProduct(BuildContext context) async {
final facade = DIContainer.get<DeepLinkFacade>();
// Create short link for this product
final shortUrl = await facade.createPageLink(
pageType: 'product',
pageId: productId,
originalUrl: 'https://myapp.com/product/$productId',
);
// Share the short link
await facade.shareApp(shareText: 'Check out this product: $shortUrl');
}
}
📋 Advanced Usage #
Custom Configuration #
// Development environment
final devConfig = DeepLinkConfig.development(
appScheme: 'myapp',
baseUrl: 'https://dev.myapp.com',
);
// Production environment with security
final prodConfig = DeepLinkConfig.production(
appScheme: 'myapp',
baseUrl: 'https://myapp.com',
allowedDomains: ['myapp.com', 'www.myapp.com'],
);
// Custom configuration
final customConfig = DeepLinkConfig(
base: BaseConfig(
appScheme: 'myapp',
baseUrl: 'https://myapp.com',
),
shortLink: ShortLinkConfig(
enabled: true,
apiBaseUrl: 'https://api.myapp.com/links',
defaultExpiration: Duration(days: 90),
enableAnalytics: true,
),
security: SecurityConfig(
enableUrlValidation: true,
allowedDomains: ['myapp.com'],
enableRateLimiting: true,
maxRequestsPerMinute: 100,
),
);
Custom Deeplink Strategies #
class CustomDeepLinkStrategy extends DeepLinkProcessingStrategy {
@override
bool canHandle(DeepLinkEntity deepLink) {
return deepLink.scheme == 'myapp' &&
deepLink.path?.startsWith('/custom') == true;
}
@override
Future<Result<DeepLinkProcessingResult>> process(
DeepLinkEntity deepLink,
DeepLinkValidation validation
) async {
// Custom processing logic
final route = _extractRoute(deepLink);
final arguments = _extractArguments(deepLink);
return Result.success(DeepLinkProcessingResult(
routePath: route,
arguments: arguments,
metadata: {'strategy': 'custom'},
));
}
String _extractRoute(DeepLinkEntity deepLink) {
// Custom route extraction logic
return '/custom-page';
}
Map<String, dynamic> _extractArguments(DeepLinkEntity deepLink) {
// Custom argument extraction logic
return deepLink.queryParameters;
}
}
// Register custom strategy
final strategyManager = DIContainer.get<DeepLinkStrategyManager>();
strategyManager.addStrategy(CustomDeepLinkStrategy());
Testing Support #
// Unit test example
void main() {
group('DeepLink Processing', () {
late DeepLinkFacade facade;
late MockShortLinkRepository mockRepository;
setUp(() {
mockRepository = MockShortLinkRepository();
facade = DeepLinkFacade(
shortLinkRepository: mockRepository,
// ... other dependencies
);
});
test('should handle valid deeplink', () async {
// Arrange
const deepLinkUrl = 'myapp://product?id=123';
// Act
final result = await facade.handleDeepLink(deepLinkUrl);
// Assert
expect(result, isTrue);
verify(mockRepository.recordClick(any)).called(1);
});
test('should create short link', () async {
// Arrange
when(mockRepository.createShortLink(any))
.thenAnswer((_) async => Result.success(mockShortLink));
// Act
final shortUrl = await facade.createStoreLink(123);
// Assert
expect(shortUrl, isNotEmpty);
expect(shortUrl, startsWith('https://'));
});
});
}
🏗️ Architecture Overview #
┌─────────────────────────────────────────────────────────────┐
│ Presentation Layer │
├─────────────────────────────────────────────────────────────┤
│ • DeepLinkHandler • ShareButton • RouteGenerator │
└─────────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────────┐
│ Application Layer │
├─────────────────────────────────────────────────────────────┤
│ • DeepLinkFacade • UseCases • Factories │
└─────────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────────┐
│ Domain Layer │
├─────────────────────────────────────────────────────────────┤
│ • Entities • Repositories • Services │
│ • Strategies • Value Objects • Domain Rules │
└─────────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────────┐
│ Infrastructure Layer │
├─────────────────────────────────────────────────────────────┤
│ • HTTP Clients • Data Sources • External APIs │
│ • Caching • Analytics • Platform Services │
└─────────────────────────────────────────────────────────────┘
📱 Platform Support #
- ✅ Android - App Links, Custom Schemes
- ✅ iOS - Universal Links, Custom Schemes
- ✅ Web - URL Routing, History API
- ✅ macOS - Custom URL Schemes
- ✅ Windows - Protocol Registration
- ✅ Linux - Desktop Integration
🤝 Contributing #
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
Development Setup #
git clone https://github.com/your-org/shyun_link.git
cd shyun_link
flutter packages get
flutter test
📄 License #
This project is licensed under the MIT License - see LICENSE file for details.
🙏 Acknowledgments #
- Inspired by Clean Architecture principles by Robert C. Martin
- Built with love for the Flutter community
- Thanks to all contributors and testers
Made with ❤️ for Flutter developers worldwide
If this package helped you, please consider giving it a ⭐ on GitHub!
If this package helped you, please consider giving it a ⭐ on GitHub!