serveAvailableExtensions method

Future<void> serveAvailableExtensions(
  1. String? rootPathFileUri
)

Serves any available DevTools extensions for the given rootPathFileUri, where rootPathFileUri is the root for a Dart or Flutter project containing the .dart_tool/ directory.

rootPathFileUri is expected to be a file uri (e.g. starting with 'file://').

This method first looks up the available extensions using package:extension_discovery, and the available extension's assets will be copied to the build/devtools_extensions directory that DevTools server is serving.

Implementation

Future<void> serveAvailableExtensions(String? rootPathFileUri) async {
  if (rootPathFileUri != null && !rootPathFileUri.startsWith('file://')) {
    throw ArgumentError.value(
      rootPathFileUri,
      'rootPathFileUri',
      'must be a file:// URI String',
    );
  }

  devtoolsExtensions.clear();
  final parsingErrors = StringBuffer();

  if (rootPathFileUri != null) {
    late final List<Extension> extensions;
    try {
      extensions = await findExtensions(
        'devtools',
        packageConfig: Uri.parse(
          path.posix.join(
            rootPathFileUri,
            '.dart_tool',
            'package_config.json',
          ),
        ),
      );
    } catch (e) {
      extensions = <Extension>[];
      rethrow;
    }

    for (final extension in extensions) {
      final config = extension.config;
      // TODO(https://github.com/dart-lang/pub/issues/4042): make this check
      // more robust.
      final isPubliclyHosted = (extension.rootUri.path.contains('pub.dev') ||
              extension.rootUri.path.contains('pub.flutter-io.cn'))
          .toString();

      // This should be relative to the 'extension/devtools/' directory and
      // defaults to 'build';
      final relativeExtensionLocation =
          config['buildLocation'] as String? ?? 'build';

      final location = path.join(
        extension.rootUri.toFilePath(),
        'extension',
        'devtools',
        relativeExtensionLocation,
      );

      try {
        final extensionConfig = DevToolsExtensionConfig.parse({
          ...config,
          DevToolsExtensionConfig.pathKey: location,
          DevToolsExtensionConfig.isPubliclyHostedKey: isPubliclyHosted,
        });
        devtoolsExtensions.add(extensionConfig);
      } on StateError catch (e) {
        parsingErrors.writeln(e.message);
        continue;
      }
    }
  }

  _resetServedPluginsDir();
  await Future.wait([
    for (final extension in devtoolsExtensions)
      _moveToServedExtensionsDir(extension.name, extension.path),
  ]);

  if (parsingErrors.isNotEmpty) {
    throw ExtensionParsingException(
      'Encountered errors while parsing extension config.yaml '
      'files:\n$parsingErrors',
    );
  }
}