validatePackageSwift function

PackageSwiftValidation validatePackageSwift(
  1. String path,
  2. String platform
)

Validates a Package.swift file for correct Nitro configuration.

Implementation

PackageSwiftValidation validatePackageSwift(String path, String platform) {
  final file = File(path);
  if (!file.existsSync()) {
    return PackageSwiftValidation(issues: ['$platform/Package.swift not found']);
  }

  final content = file.readAsStringSync();
  final issues = <String>[];
  final warnings = <String>[];

  // Check swift-tools-version
  if (!content.contains('swift-tools-version:')) {
    issues.add('$platform/Package.swift missing swift-tools-version');
  } else if (!RegExp(r'swift-tools-version:\s*5\.[9]').hasMatch(content) && !RegExp(r'swift-tools-version:\s*[6-9]').hasMatch(content)) {
    warnings.add('$platform/Package.swift should use swift-tools-version: 5.9 or later');
  }

  // Check platform version
  final expectedPlatform = platform == 'ios' ? '.iOS(.v13)' : '.macOS(.v10_15)';
  if (!content.contains('.iOS(') && !content.contains('.macOS(')) {
    issues.add('$platform/Package.swift missing platforms declaration');
  }

  // Check for C++ target (needed for Nitro)
  final hasCppTarget = content.contains('Cpp') && content.contains('.target(');
  if (!hasCppTarget) {
    warnings.add('$platform/Package.swift may be missing C++ target for bridges');
  }

  // Check for nitro include path.
  // Three valid layouts:
  //   1. Direct path:  headerSearchPath("…/nitro/src/native")
  //   2. Symlinks:     headerSearchPath("…/.symlinks/plugins/nitro/…")
  //   3. Nitrogen-managed nested SPM layout: nitrogen link copies nitro.h
  //      into Sources/<PluginCpp>/include/ and declares publicHeadersPath: "include".
  //      No explicit nitro path is needed in Package.swift.
  final hasNitroFlags = content.contains('nitro/src/native') ||
      content.contains('.symlinks/plugins/nitro') ||
      (content.contains('publicHeadersPath') && content.contains('Sources/'));
  if (!hasNitroFlags) {
    warnings.add('$platform/Package.swift missing nitro header search path');
  }

  // Check for Swift target
  final hasSwiftTarget = content.contains('.target(') && !content.replaceAll(RegExp(r'Cpp[^"]*'), '').contains('.target(');

  return PackageSwiftValidation(
    issues: issues,
    warnings: warnings,
    hasSwiftTarget: hasSwiftTarget,
    hasCppTarget: hasCppTarget,
    hasCorrectPlatform: content.contains(expectedPlatform),
    hasNitroFlags: hasNitroFlags,
  );
}