Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Able to assign host and port for emualtor #35

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/dart_firebase_admin/lib/src/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ import 'package:meta/meta.dart';
part 'app/credential.dart';
part 'app/exception.dart';
part 'app/firebase_admin.dart';
part 'app/emulator.dart';
63 changes: 63 additions & 0 deletions packages/dart_firebase_admin/lib/src/app/emulator.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
part of '../app.dart';

/// Represents a Firebase Emulator.
/// Now for Auth and Firestore.
class Emulator {

rrousselGit marked this conversation as resolved.
Show resolved Hide resolved
/// If there is no environment variable set, please use this constructor.
/// For example, gcloud firestore emulators.
const Emulator(this.host, this.port);

/// Creates an [Emulator] from an environment variable.
/// For example, env key for auth is: FIREBASE_AUTH_EMULATOR_HOST
@internal
factory Emulator.fromEnvString(String envString) {
final parts = envString.split(':');
if (parts.length != 2) {
throw ArgumentError.value(envString, 'envString', 'Invalid format');
}
final host = parts[0];
final port = int.tryParse(parts[1]);
if (port == null) {
throw ArgumentError.value(envString, 'envString', 'Invalid port');
}
return Emulator(host, port);
}

/// The default Auth Emulator.
const Emulator._defaultAuth()
: host = '127.0.0.1',
port = 9099;

/// The default Firestore Emulator.
const Emulator._defaultFirestore()
: host = '127.0.0.1',
port = 8080;

/// Try to get the Auth Emulator from the environment variable.
/// If not found, use the default Auth Emulator.
factory Emulator.auth() {
if (!Platform.environment.containsKey('FIREBASE_AUTH_EMULATOR_HOST')) {
return const Emulator._defaultAuth();
} else {
return Emulator.fromEnvString(
Platform.environment['FIREBASE_AUTH_EMULATOR_HOST']!,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you remove this !?

This is possible by doing something like:

final env = Platform.environment['FIREBASE_AUTH_EMULATOR_HOST'];
if (env != null) {...}
else {...}

);
}
}

/// Try to get the Firestore Emulator from the environment variable.
/// If not found, use the default Firestore Emulator.
factory Emulator.firestore() {
if (!Platform.environment.containsKey('FIRESTORE_EMULATOR_HOST')) {
return const Emulator._defaultFirestore();
} else {
return Emulator.fromEnvString(
Platform.environment['FIRESTORE_EMULATOR_HOST']!,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

);
}
}

final String host;
final int port;
}
41 changes: 34 additions & 7 deletions packages/dart_firebase_admin/lib/src/app/firebase_admin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,46 @@ class FirebaseAdminApp {
/// The [Credential] used to authenticate the Admin SDK.
final Credential credential;

bool get isUsingEmulator => _isUsingEmulator;
var _isUsingEmulator = false;
bool get isUsingAuthEmulator => _isUsingAuthEmulator;

bool get isUsingFirestoreEmulator => _isUsingFirestoreEmulator;

bool get isUsingEmulator => _isUsingAuthEmulator || _isUsingFirestoreEmulator;

var _isUsingAuthEmulator = false;
var _isUsingFirestoreEmulator = false;

@internal
Uri authApiHost = Uri.https('identitytoolkit.googleapis.com', '/');
@internal
Uri firestoreApiHost = Uri.https('firestore.googleapis.com', '/');

/// Use the Firebase Emulator Suite to run the app locally.
void useEmulator() {
_isUsingEmulator = true;
authApiHost = Uri.http('127.0.0.1:9099', 'identitytoolkit.googleapis.com/');
firestoreApiHost = Uri.http('127.0.0.1:8080', '/');
/// Use the Firebase Emulator suite to run the app locally.
void useEmulator({
Emulator? authEmulator,
Emulator? firestoreEmulator,
}) {
useAuthEmulator(emulator: authEmulator);
useFirestoreEmulator(emulator: firestoreEmulator);
}

/// Use the Firebase Auth Emulator to run the app locally.
void useAuthEmulator({
Emulator? emulator
}) {
Comment on lines +36 to +38
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't a simpler API be this?

void useAuthEmulator([Uri? uri])

We can then remove that Emulator class.

_isUsingAuthEmulator = true;
emulator ??= Emulator.auth();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather have the environment logic directly in here, instead of a constructor inside a separate Emulator class.

authApiHost = Uri.http(
'${emulator.host}:${emulator.port}', 'identitytoolkit.googleapis.com/');
}

/// Use the Firebase Firestore Emulator to run the app locally.
void useFirestoreEmulator({
Emulator? emulator,
}) {
_isUsingFirestoreEmulator = true;
emulator ??= Emulator.firestore();
firestoreApiHost = Uri.http('${emulator.host}:${emulator.port}', '/');
}

@internal
Expand Down
67 changes: 66 additions & 1 deletion packages/dart_firebase_admin/test/firebase_admin_app_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,18 @@ void main() {
});

test('useEmulator() sets the apiHost to the emulator', () {
final app = FirebaseAdminApp.initializeApp(
var app = FirebaseAdminApp.initializeApp(
'dart-firebase-admin',
Credential.fromApplicationDefaultCredentials(),
);

/// Use both auth and firestore emulator.
app.useEmulator();

expect(app.isUsingAuthEmulator, true);
expect(app.isUsingFirestoreEmulator, true);
expect(app.isUsingEmulator, true);

expect(
app.authApiHost,
Uri.http('127.0.0.1:9099', 'identitytoolkit.googleapis.com/'),
Expand All @@ -33,6 +38,66 @@ void main() {
app.firestoreApiHost,
Uri.http('127.0.0.1:8080', '/'),
);

/// Use only auth emulator.
app = FirebaseAdminApp.initializeApp(
'dart-firebase-admin',
Credential.fromApplicationDefaultCredentials(),
);

app.useAuthEmulator(
emulator: const Emulator('192.168.1.1', 9),
);

expect(app.isUsingAuthEmulator, true);
expect(app.isUsingFirestoreEmulator, false);
expect(app.isUsingEmulator, true);

expect(
app.authApiHost,
Uri.http('192.168.1.1:9', 'identitytoolkit.googleapis.com/'),
);
expect(
app.firestoreApiHost,
Uri.https('firestore.googleapis.com', '/'),
);

/// Use only firestore emulator.
app = FirebaseAdminApp.initializeApp(
'dart-firebase-admin',
Credential.fromApplicationDefaultCredentials(),
);

app.useFirestoreEmulator();

expect(app.isUsingAuthEmulator, false);
expect(app.isUsingFirestoreEmulator, true);
expect(app.isUsingEmulator, true);

expect(
app.authApiHost,
Uri.https('identitytoolkit.googleapis.com', '/'),
);
expect(
app.firestoreApiHost,
Uri.http('127.0.0.1:8080', '/'),
);
});

test('Emulator is initiated as expected', () {
/// Test the parsing part of env string to Uri.
var emulator = Emulator.fromEnvString('192.168.0.1:9999');
expect(emulator.host, '192.168.0.1');
expect(emulator.port, 9999);

/// Test the default auth emulator is using the default host and port.
emulator = Emulator.auth();
expect(emulator.host, '127.0.0.1');
expect(emulator.port, 9099);

emulator = Emulator.firestore();
expect(emulator.host, '127.0.0.1');
expect(emulator.port, 8080);
});
});
}