exec method
Run command.
The contents of katana.yaml and the arguments of the command are passed to context.
コマンドを実行します。
contextにkatana.yamlの内容やコマンドの引数が渡されます。
Implementation
@override
Future<void> exec(ExecContext context) async {
final firebase = context.yaml.getAsMap("firebase");
final project = firebase.get("project_id", "");
final expected = _option(context.args, "--auth-project");
final account = _option(context.args, "--auth-account");
if (isLocalApply ||
context.flavorContext?.explicit != true ||
context.flavorContext?.flavor != KatanaFlavor.dev ||
project.isEmpty ||
project != expected ||
!RegExp(r"^[a-z][a-z0-9-]{4,28}[a-z0-9]$").hasMatch(project) ||
!firebase.getAsMap("authentication").get("enable", false) ||
account == null ||
account.isEmpty) {
throw StateError(
"Auth config requires explicit dev flavor, matching --auth-project, enabled authentication, and --auth-account; --local is unsupported.");
}
// Capture credential output without printing or persisting it.
final credential = await Process.run("gcloud", [
"auth",
"print-access-token",
"--account=$account",
]).timeout(const Duration(seconds: 30));
if (credential.exitCode != 0 ||
credential.stdout.toString().trim().isEmpty) {
throw StateError("Could not obtain the selected account credential.");
}
final token = credential.stdout.toString().trim();
final client = HttpClient()
..connectionTimeout = const Duration(seconds: 30);
try {
final result = await configureFirebaseAnonymousAuth(
project: project,
initialize: context.args.contains("--initialize-auth"),
enableAnonymous: context.args.contains("--enable-anonymous"),
request: (method, path, body) async {
final uri = Uri.https(
"identitytoolkit.googleapis.com",
path,
method == "PATCH"
? {"updateMask": "signIn.anonymous.enabled"}
: null);
final request = await client.openUrl(method, uri);
request.headers.set(HttpHeaders.authorizationHeader, "Bearer $token");
request.headers.set("x-goog-user-project", project);
if (body != null) {
request.headers.contentType = ContentType.json;
request.write(jsonEncode(body));
}
final response = await request.close();
final text = await utf8.decoder.bind(response).join();
final decoded =
text.trim().isEmpty ? <String, dynamic>{} : jsonDecode(text);
return AuthConfigResponse(response.statusCode,
decoded is Map ? Map<String, dynamic>.from(decoded) : {});
},
).timeout(const Duration(seconds: 90));
stdout.writeln(jsonEncode(result));
} finally {
client.close(force: true);
}
}