create static method
Creates a new PeekAPI client, validates options, and starts the background flush timer.
Throws ArgumentError if the API key or endpoint is invalid.
Implementation
static Future<PeekApiClient> create(PeekApiOptions options) async {
// Validate API key
if (options.apiKey.isEmpty) {
throw ArgumentError('apiKey must not be empty');
}
if (options.apiKey.contains('\r') || options.apiKey.contains('\n')) {
throw ArgumentError('apiKey must not contain CRLF characters');
}
// Parse and validate endpoint
final uri = Uri.tryParse(options.endpoint);
if (uri == null || !uri.hasScheme || !uri.hasAuthority) {
throw ArgumentError('Invalid endpoint URL: ${options.endpoint}');
}
// Enforce HTTPS (HTTP only for localhost)
if (uri.scheme == 'http' && !SsrfProtection.isLocalhost(uri.host)) {
throw ArgumentError('HTTPS required for non-localhost endpoints');
}
// SSRF check
await SsrfProtection.validateHost(uri.host);
// Compute storage path
final storagePath = options.storagePath ??
DiskPersistence.defaultStoragePath(options.endpoint);
// Create HTTP client
final httpClient = HttpClient();
httpClient.connectionTimeout = _sendTimeout;
final client = PeekApiClient._(options, httpClient, storagePath, uri);
// Load persisted events from disk
client._loadFromDisk();
// Start flush timer
client._flushTimer = Timer.periodic(options.flushInterval, (_) {
client._tick();
});
// Register shutdown hooks
client._registerShutdownHooks();
if (options.debug) {
stderr.writeln(
'[PeekAPI] Client initialized (endpoint: ${options.endpoint})');
}
return client;
}