exec method

  1. @override
Future<void> exec(
  1. ExecContext context
)
override

Run command.

The contents of katana.yaml and the arguments of the command are passed to context.

コマンドを実行します。

contextkatana.yamlの内容やコマンドの引数が渡されます。

Implementation

@override
Future<void> exec(ExecContext context) async {
  final bin = context.yaml.getAsMap("bin");
  final npm = bin.get("npm", "npm");
  final wrangler = bin.get("wrangler", "wrangler");
  final cloudflare = context.yaml.getAsMap("cloudflare");
  final workers = cloudflare.getAsMap("workers");
  final enabledWorkers = workers.get("enable", false);
  final enableFirebaseAuth = workers.get("enable_firebase_auth", false);
  final firebase = context.yaml.getAsMap("firebase");
  final firebaseProjectId = firebase.get("project_id", "");
  final pages = cloudflare.getAsMap("pages");
  final enabledPages = pages.get("enable", false);
  final pubspec = File("pubspec.yaml");
  final pubspecs = loadYaml(await pubspec.readAsString()) as Map;
  final projectIdFromPubspec = pubspecs.get("name", "");
  final projectIdFromYaml = cloudflare.get("project_id", "");
  final projectId =
      projectIdFromYaml.isEmpty ? projectIdFromPubspec : projectIdFromYaml;
  if ((enabledWorkers || enabledPages) && projectId.isEmpty) {
    error(
        "Project ID is not specified. Please enter [project_id] in `katana.yaml`.");
    return;
  }
  if (enableFirebaseAuth && firebaseProjectId.isEmpty) {
    error(
      "Firebase project ID is not specified. Please enter [project_id] in `katana.yaml`.",
    );
    return;
  }
  final workerIndexFile = File("cloudflare/src/index.ts");
  final pagesIndexFile = File("cloudflare/public/index.html");
  final wranglerJsonc = File("cloudflare/wrangler.jsonc");
  final cloudflareDir = Directory("cloudflare");
  final workerRulesFile = File("cloudflare/src/rules.json");
  if (!cloudflareDir.existsSync()) {
    await cloudflareDir.create();
  }
  if (enabledWorkers || enabledPages) {
    if (!wranglerJsonc.existsSync()) {
      await command(
        "Initialize Cloudflare Workers",
        [wrangler, "init", projectId, "--yes", "--cwd=cloudflare"],
        runInShell: true,
      );
      // wranglerはcloudflare/{projectId}/配下にファイルを生成するため、cloudflare/直下に移動
      label("Rename files");
      final generatedDir = Directory("cloudflare/$projectId");
      await for (final entity
          in generatedDir.list(recursive: false, followLinks: false)) {
        final name = entity.path.split(Platform.pathSeparator).last;
        final targetPath = "${cloudflareDir.path}/$name";
        await entity.rename(targetPath);
      }
      await generatedDir.delete(recursive: true);
      await workerIndexFile.delete();
      await pagesIndexFile.delete();
    }
  }

  if (enabledWorkers) {
    final functionsDir = Directory("cloudflare/src/functions");
    if (!functionsDir.existsSync()) {
      await functionsDir.create();
    }
    if (!workerIndexFile.existsSync()) {
      await CloudflareWorkersIndexCliCode(
        firebaseProjectId: enableFirebaseAuth ? firebaseProjectId : null,
      ).generateFile("index.ts");
    }
    if (!workerRulesFile.existsSync()) {
      await const CloudflareWorkersRulesCliCode().generateFile("rules.json");
    }
    await const CloudflareWranglerCliCode().generateFile("wrangler.jsonc");
    await command(
      "Package installation.",
      [
        npm,
        "install",
        "hono",
        "@mathrunet/masamune",
        "@mathrunet/masamune_cloudflare"
      ],
      workingDirectory: "cloudflare",
      runInShell: true,
    );
    await addFlutterImport(
      [
        "masamune_functions_cloudflare",
      ],
    );
  }
  if (enabledPages) {
    if (!pagesIndexFile.existsSync()) {
      await const CloudflarePagesIndexCliCode().generateFile("index.html");
    }
  }
}