init static method

Future<Nylo> init({
  1. required EnvGetter env,
  2. BootConfig? setup,
  3. Map<AppLifecycleState, dynamic Function()>? appLifecycle,
  4. List<FutureOr<Runnable>>? services,
})

Initialize Nylo

env - The environment getter function from your generated env.g.dart file. Run metro make:key then metro make:env to generate this file. Example: env: Env.get

services - List of services to initialize after setup completes. Services are initialized in order and must extend Runnable or NyService. Supports both sync and async service factories (e.g., Future<Runnable>).

Example:

await Nylo.init(
  env: Env.get,
  setup: Boot.nylo,
  services: [
    // Async factory pattern - returns Future<Runnable>
    FirebaseKit.init(
      options: DefaultFirebaseOptions.currentPlatform,
      services: [
        FirebaseKitMessaging(sendTokenOnBoot: true),
        FirebaseKitAnalytics(enableAutoTracking: true),
      ],
    ),
    // Direct instantiation
    MyCustomService(),
  ],
);

// Later in your app, retrieve services:
final firebase = service<FirebaseKit>();
final messaging = firebase.getService<FirebaseKitMessaging>();

Services go through three lifecycle phases:

  1. onInit() - Called for each service in order
  2. onReady() - Called after all services are initialized
  3. onAppReady() - Called when the app is fully ready

Implementation

static Future<Nylo> init({
  required EnvGetter env,
  BootConfig? setup,
  Map<AppLifecycleState, Function()>? appLifecycle,
  List<FutureOr<Runnable>>? services,
}) async {
  WidgetsFlutterBinding.ensureInitialized();
  // Register environment configuration first
  NyEnvRegistry.register(getter: env);

  Intl.defaultLocale = getEnv('DEFAULT_LOCALE', defaultValue: 'en');
  await Future.wait([
    initializeDateFormatting(),
    _configureLocalTimeZone().catchError((_) {
      // Timezone configuration failed, continue without it
    }),
  ]);

  Nylo nyloApp = Nylo();

  if (setup != null) {
    nyloApp = await setup.setup();
  }
  nyloApp._appLifecycle = appLifecycle;
  await Future.wait([
    if (!isTestMode)
      () async {
        try {
          nyloApp._cache = await NyCache.getInstance();
        } catch (e) {
          // Cache initialization failed (e.g. path_provider native library issue)
        }
      }(),
    NyThemeManager.instance.init(),
  ]);

  if (nyloApp._enableErrorStack == true) {
    await ErrorStack.init(
      level: nyloApp._errorStackLogLevel ?? ErrorStackLogLevel.verbose,
      initialRoute: nyloApp.getInitialRoute(),
      errorWidget: nyloApp._errorStackErrorWidget,
    );
    nyloApp.addNavigatorObserver(ErrorStackNavigatorObserver());
  }
  if (nyloApp._useLocalNotifications == true) {
    FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
        FlutterLocalNotificationsPlugin();
    if (nyloApp._initializationSettings != null) {
      nyloApp.setLocalNotifications(flutterLocalNotificationsPlugin);
    }
  }
  if (nyloApp._useDeepLinks == true && !isTestMode) {
    nyloApp._deepLinkHandler = NyDeepLinkHandler(
      fallbackRoute: nyloApp._deepLinkFallbackRoute,
    );
    try {
      await nyloApp._deepLinkHandler!.init();
      nyloApp._deepLinkHandler!.listen();
    } catch (e) {
      // Unsupported platform or plugin failure; continue without deep links.
      NyLogger.error('Deep link initialization failed: $e');
    }
  }

  // Initialize services
  if (services != null && services.isNotEmpty) {
    // Resolve all FutureOr<Runnable> to Runnable instances
    // Async factories are independent of each other, so resolve them in
    // parallel; onInit/onReady/onAppReady below still run in list order.
    final List<Runnable> resolvedServices = await Future.wait(
      services.map((serviceOrFuture) async => await serviceOrFuture),
    );
    for (final resolvedService in resolvedServices) {
      // Register in the service registry by type
      Runnable.register(resolvedService);
    }
    _services = resolvedServices;

    // Phase 1: Initialize all services
    for (final service in resolvedServices) {
      await service.onInit();
    }
    // Phase 2: All services ready
    for (final service in resolvedServices) {
      await service.onReady();
    }
    // Phase 3: App fully ready (navigation available)
    for (final service in resolvedServices) {
      await service.onAppReady();
    }
  }

  // Expose live commands to Metro (debug and profile builds only)
  if (!kReleaseMode && nyloApp.shouldUseLive()) {
    NyLive.install(nyloApp);
  }

  Backpack.instance.save("nylo", nyloApp);

  // Call boot after all initialization is complete
  if (setup != null) {
    await setup.boot(nyloApp);
  }

  return nyloApp;
}