flutterdartflutter-dependenciesdart-packages

External Package Dependency to my local package


if i am using an external package in my local package and i am using my local package in another project so do we have to add import of that external package in my project in flutter

Here is the code

Package :

main file 
library demopackage;
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:aad_oauth/model/config.dart';
import 'package:flutter/foundation.dart';
import 'package:aad_oauth/aad_oauth.dart';
part 'resources/resusable_functions/oauth_component.dart';
void main() {
  runApp(const QemDevRoot());
}

final navigatorKey = GlobalKey<NavigatorState>();

class QemDevRoot extends StatelessWidget {
  const QemDevRoot({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        shadowColor: Colors.white,
        useMaterial3: true,
      ),
      navigatorKey: navigatorKey,
    );
  }
}

auth file 

part of demopackage;

class AuthComponent {

  static final Config config = Config(
    tenant: 'Tenant Id',
    clientId: 'Client Id',
    scope: "openid offline_access",
    policy: "Policy Name",
    customTokenUrl: "https://<Tenant Name>.b2clogin.com/<Tenant Name>.onmicrosoft.com/<Policy Name>/oauth2/v2.0/token",
    navigatorKey: navigatorKey,
    customAuthorizationUrl: 'https://<Tenant Name>.b2clogin.com/<Tenant Name>.onmicrosoft.com/<Policy Name>/oauth2/v2.0/authorize',
    isB2C: true,
    webUseRedirect: true,
    redirectUri: 'Redirect Uri',
    loader: Container(
      decoration: const BoxDecoration(
        color: Colors.white
      ),
      child: const Center(
        child: CircularProgressIndicator(
          color: Colors.blueAccent,
        ),
      ),
    ),
    appBar: AppBar(
      automaticallyImplyLeading: false,
      backgroundColor: Colors.white,
      title: const Text('Title'),
    ),
  );


  static final AadOAuth oauth = AadOAuth(config);

  void login(BuildContext context , bool redirect) async {
    String errorMessage ='';
    config.webUseRedirect = redirect;
    final result = await oauth.login();
    String? refreshToken;
    int? expireTime;
    try {
      final jsonString = result.fold(
            (failure) => throw Exception("Error: $failure"), // Handle Failure case
            (token) => token, // Use the toString() method assuming it provides the JSON representation
      );

      refreshToken = jsonString.refreshToken;
      expireTime = jsonString.expireTimeStamp!.millisecondsSinceEpoch;

    } catch (e) {
      errorMessage = e.toString();
      if (kDebugMode) {
        print("Error parsing JSON: $e");
      }
    }


    var accessToken = await oauth.getAccessToken();
    // var refreshToken = await oauth.refreshToken();
    if (accessToken != null) {
      debugPrint('Access Token$accessToken');
      String? decodedPayload = extractAndDecodeJwt(accessToken);

      // Use the decoded payload as needed
      if (decodedPayload != null) {
        // Do something with the decoded payload
        if (kDebugMode) {
          print('Decoded JWT Payload: $decodedPayload');
        }
      }
    }
    else{
      var idToken = await oauth.getIdToken();
      debugPrint('idToken$idToken');

      if (idToken != null) {
        String? decodedPayload = extractAndDecodeJwt(idToken);

        if (decodedPayload != null) {
          // Print or use the decoded payload
          print('Decoded JWT Payload: $decodedPayload');

          // Decode JSON payload to Map<String, dynamic>

        }
      } else {
        print('Id token is null.');
      }


    }
    debugPrint('Config:${config.responseMode}');
  }

  String? extractAndDecodeJwt(String jwtToken) {
    try {
      // Split the token into three parts: header, payload, and signature
      List<String> parts = jwtToken.split('.');

      // Extract the payload (middle part)
      String encodedPayload = parts[1];

      // Base64 decode the payload
      String decodedPayload = utf8.decode(base64Url.decode(encodedPayload));

      return decodedPayload;
    } catch (e) {
      // voidBool(context);
      print('Error decoding JWT: $e');
      return null;
    }
  }

  void hasCachedAccountInformation(BuildContext context) async {
    var hasCachedAccountInformation = await oauth.hasCachedAccountInformation;
    ScaffoldMessenger.of(context).hideCurrentSnackBar();
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content:
        Text('hasCachedAccountInformation'),
      ),
    );
  }

  void logout() async {
    await oauth.logout();
  }
}

Flutter project

import 'dart:convert';

import 'package:demopackage/main.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

class Auth{
  static final Config config = Config(
    tenant: 'Tenant Id',
    clientId: 'Client Id',
    scope: "openid offline_access",
    policy: "Policy Name",
    customTokenUrl: "https://<Tenant Name>.b2clogin.com/<Tenant Name>.onmicrosoft.com/<Policy Name>/oauth2/v2.0/token",
    navigatorKey: navigatorKey,
    customAuthorizationUrl: 'https://<Tenant Name>.b2clogin.com/<Tenant Name>.onmicrosoft.com/<Policy Name>/oauth2/v2.0/authorize',
    isB2C: true,
    webUseRedirect: true,
    redirectUri: 'Redirect Uri',
    loader: Container(
      decoration: const BoxDecoration(
          color: Colors.white
      ),
      child: const Center(
        child: CircularProgressIndicator(
          color: Colors.blueAccent,
        ),
      ),
    ),
    appBar: AppBar(
      automaticallyImplyLeading: false,
      backgroundColor: Colors.white,
      title: const Text('Title'),
    ),
  );


  static final AadOAuth oauth = AadOAuth(config);


  void login(BuildContext context , bool redirect) async {
    String errorMessage ='';
    config.webUseRedirect = redirect;
    final result = await oauth.login();
    String? refreshToken;
    int? expireTime;
    try {
      final jsonString = result.fold(
            (failure) => throw Exception("Error: $failure"), // Handle Failure case
            (token) => token, // Use the toString() method assuming it provides the JSON representation
      );


      refreshToken = jsonString.refreshToken;
      expireTime = jsonString.expireTimeStamp!.millisecondsSinceEpoch;


    } catch (e) {
      errorMessage = e.toString();
      if (kDebugMode) {
        print("Error parsing JSON: $e");
      }
    }




    var accessToken = await oauth.getAccessToken();
    // var refreshToken = await oauth.refreshToken();
    if (accessToken != null) {
      debugPrint('Access Token$accessToken');
      String? decodedPayload = extractAndDecodeJwt(accessToken);


      // Use the decoded payload as needed
      if (decodedPayload != null) {
        // Do something with the decoded payload
        if (kDebugMode) {
          print('Decoded JWT Payload: $decodedPayload');
        }
      }
    }
    else{
      var idToken = await oauth.getIdToken();
      debugPrint('idToken$idToken');


      if (idToken != null) {
        String? decodedPayload = extractAndDecodeJwt(idToken);


        if (decodedPayload != null) {
          // Print or use the decoded payload
          print('Decoded JWT Payload: $decodedPayload');


          // Decode JSON payload to Map<String, dynamic>


        }
      } else {
        print('Id token is null.');
      }




    }
    debugPrint('Config:${config.responseMode}');
  }


  String? extractAndDecodeJwt(String jwtToken) {
    try {
      // Split the token into three parts: header, payload, and signature
      List<String> parts = jwtToken.split('.');


      // Extract the payload (middle part)
      String encodedPayload = parts[1];


      // Base64 decode the payload
      String decodedPayload = utf8.decode(base64Url.decode(encodedPayload));


      return decodedPayload;
    } catch (e) {
      // voidBool(context);
      print('Error decoding JWT: $e');
      return null;
    }
  }




  void logout() async {
    await oauth.logout();
  }

}

If i am using here Config gives error : undefined class

I am looking for the answer for it.

Thank you


Solution

  • If package A depends on package B and package B depends on package C, you don't need to put package C in the dependencies list of package A, as long as package B put package C in the dependencies list, not in dev_dependencies.

    See: Package dependencies

    Pub gets every package that your package depends on, and everything those packages depend on, transitively. It also gets your package’s dev dependencies, but it ignores the dev dependencies of any dependent packages. Pub only gets your package’s dev dependencies.


    To answer the edited question:

    Still on the same package A, B, and C example, you need to either make package A depend on package C or export package C in package B in order to use APIs from package C in package A.

    For the first case, it is very common for developers as we don't necessarily check if any of the current dependencies have already depend on another package that we want to depend on.

    For the second case, one of the examples is in the dartx package where it exports the time package, as you can see in its source file.