create static method
Future<SDKServices>
create({
- required DigiaConfig config,
- required LocalStorage storage,
- required NetworkClientFactory networkClient,
- required void onLiveTestCampaign(
- LiveTestInvocation invocation
- Map<
String, dynamic> ? staticContext, - int clock()?,
The composition root: builds every service from config and storage.
Async only to read the static device/app context once, up front, so no
service is ever observed half-built.
storage must be the warmed root storage, after LocalStorageMigrator
has run. This is the only place storage is scoped per domain.
The process singletons the SDK still has (component registry, live test,
debug overlay) get their storage and client here too.
Implementation
static Future<SDKServices> create({
required DigiaConfig config,
required LocalStorage storage,
required NetworkClientFactory networkClient,
required void Function(LiveTestInvocation invocation) onLiveTestCampaign,
Map<String, dynamic>? staticContext,
int Function()? clock,
}) async {
if (staticContext == null) {
try {
staticContext = await DigiaAnalyticsService.buildStaticContext();
} catch (error) {
// Degrade, don't fail init: events and headers go out without it.
_log.e('Static context unavailable — continuing', error: error);
staticContext = const {};
}
}
final Map<String, dynamic> resolvedStaticContext = staticContext;
final systemDeviceId = await IdentityManager.systemDeviceId();
final identityManager = IdentityManager.create(
storage: storage.scoped('identity'),
newDeviceId: () => systemDeviceId,
);
final sessionManager = SessionManager.create(
storage: storage.scoped('session'),
timeoutMs: config.analyticsConfig.sessionTimeoutMs,
clock: clock,
);
final sessionLifecycleObserver = SessionLifecycleObserver(sessionManager);
WidgetsBinding.instance.addObserver(sessionLifecycleObserver);
final headers = EngageHeaders(
config: config,
identityManager: identityManager,
sessionManager: sessionManager,
staticContext: resolvedStaticContext,
);
final client = networkClient(headers.call);
final baseAnalyticsConfig = config.analyticsConfig;
final analyticsConfig = DigiaEndpoints.isTestMode
? DigiaAnalyticsConfig(
enabled: baseAnalyticsConfig.enabled,
flushBatchSize: 1,
flushIntervalMs: 100,
maxBatchSize: baseAnalyticsConfig.maxBatchSize,
queueMaxEvents: baseAnalyticsConfig.queueMaxEvents,
sessionTimeoutMs: baseAnalyticsConfig.sessionTimeoutMs,
)
: baseAnalyticsConfig;
final analyticsService = DigiaAnalyticsService(
config: analyticsConfig,
identityManager: identityManager,
sessionManager: sessionManager,
queue: AnalyticsQueue(storage: storage.scoped('analytics')),
networkClient: client,
staticContext: resolvedStaticContext,
);
final sessionReporter = SessionReporter(
sessionId: () => sessionManager.sessionId,
anonymousId: () => identityManager.deviceId,
userId: () => identityManager.userId,
context: () => resolvedStaticContext,
networkClient: client,
storage: storage.scoped('session'),
);
final sessionIdentityWiring = SessionIdentityWiring(
identityManager: identityManager,
sessionManager: sessionManager,
sessionReporter: config.analyticsConfig.enabled ? sessionReporter : null,
)..attach();
DigiaDebugOverlayController.instance.configure(storage.scoped('debug'));
final componentRegistry = ComponentRegistryService.instance
..networkClient = client
..configure(config, storage.scoped('registry'));
final liveTestService = LiveTestService.instance
..configure(
onCampaignTest: onLiveTestCampaign,
storage: storage.scoped('live_test'),
networkClient: client,
);
return SDKServices(
storage: storage,
identityManager: identityManager,
sessionManager: sessionManager,
networkClient: client,
analyticsService: analyticsService,
frequencyManager: FrequencyManager(
storage.scoped('frequency'),
() => sessionManager.sessionId,
),
campaignStore: CampaignStore(),
submissionReporter: SubmissionReporter(
networkClient: client,
sessionId: () => sessionManager.sessionId,
),
sessionReporter: sessionReporter,
sessionLifecycleObserver: sessionLifecycleObserver,
captureSession: CaptureSession(networkClient: client),
componentRegistry: componentRegistry,
liveTestService: liveTestService,
sessionIdentityWiring: sessionIdentityWiring,
captureStorage: storage.scoped('capture'),
);
}