diff --git a/packages/devtools_app/lib/src/shared/config_specific/server/_server_web.dart b/packages/devtools_app/lib/src/shared/config_specific/server/_server_web.dart index f19353280a8..50abddfbc5c 100644 --- a/packages/devtools_app/lib/src/shared/config_specific/server/_server_web.dart +++ b/packages/devtools_app/lib/src/shared/config_specific/server/_server_web.dart @@ -8,6 +8,7 @@ import 'dart:convert'; // ignore: avoid_web_libraries_in_flutter, as designed import 'dart:html'; +import 'package:collection/collection.dart'; import 'package:devtools_shared/devtools_extensions.dart'; import 'package:devtools_shared/devtools_shared.dart'; import 'package:logging/logging.dart'; @@ -351,6 +352,7 @@ Future> refreshAvailableExtensions( final parsedResult = json.decode(resp!.responseText!); final extensionsAsJson = (parsedResult[extensionsResultPropertyName]! as List) + .whereNotNull() .cast>(); return extensionsAsJson .map((p) => DevToolsExtensionConfig.parse(p)) diff --git a/packages/devtools_shared/lib/src/devtools_api.dart b/packages/devtools_shared/lib/src/devtools_api.dart index 3361786da3a..aeb2ee66719 100644 --- a/packages/devtools_shared/lib/src/devtools_api.dart +++ b/packages/devtools_shared/lib/src/devtools_api.dart @@ -3,73 +3,77 @@ // found in the LICENSE file. /// All server APIs prefix: -const String apiPrefix = 'api/'; +const apiPrefix = 'api/'; /// Flutter GA properties APIs: -const String apiGetFlutterGAEnabled = '${apiPrefix}getFlutterGAEnabled'; -const String apiGetFlutterGAClientId = '${apiPrefix}getFlutterGAClientId'; +const apiGetFlutterGAEnabled = '${apiPrefix}getFlutterGAEnabled'; +const apiGetFlutterGAClientId = '${apiPrefix}getFlutterGAClientId'; /// DevTools GA properties APIs: -const String apiResetDevTools = '${apiPrefix}resetDevTools'; -const String apiGetDevToolsFirstRun = '${apiPrefix}getDevToolsFirstRun'; -const String apiGetDevToolsEnabled = '${apiPrefix}getDevToolsEnabled'; -const String apiSetDevToolsEnabled = '${apiPrefix}setDevToolsEnabled'; +const apiResetDevTools = '${apiPrefix}resetDevTools'; +const apiGetDevToolsFirstRun = '${apiPrefix}getDevToolsFirstRun'; +const apiGetDevToolsEnabled = '${apiPrefix}getDevToolsEnabled'; +const apiSetDevToolsEnabled = '${apiPrefix}setDevToolsEnabled'; /// Property name to apiSetDevToolsEnabled the DevToolsEnabled is the name used /// in queryParameter: -const String devToolsEnabledPropertyName = 'enabled'; +const devToolsEnabledPropertyName = 'enabled'; /// Survey properties APIs: /// setActiveSurvey sets the survey property to fetch and save JSON values e.g., Q1-2020 -const String apiSetActiveSurvey = '${apiPrefix}setActiveSurvey'; +const apiSetActiveSurvey = '${apiPrefix}setActiveSurvey'; /// Survey name passed in apiSetActiveSurvey, the activeSurveyName is the property name /// passed as a queryParameter and is the property in ~/.devtools too. -const String activeSurveyName = 'activeSurveyName'; +const activeSurveyName = 'activeSurveyName'; /// Returns the surveyActionTaken of the activeSurvey (apiSetActiveSurvey). -const String apiGetSurveyActionTaken = '${apiPrefix}getSurveyActionTaken'; +const apiGetSurveyActionTaken = '${apiPrefix}getSurveyActionTaken'; /// Sets the surveyActionTaken of the of the activeSurvey (apiSetActiveSurvey). -const String apiSetSurveyActionTaken = '${apiPrefix}setSurveyActionTaken'; +const apiSetSurveyActionTaken = '${apiPrefix}setSurveyActionTaken'; /// Property name to apiSetSurveyActionTaken the surveyActionTaken is the name /// passed in queryParameter: -const String surveyActionTakenPropertyName = 'surveyActionTaken'; +const surveyActionTakenPropertyName = 'surveyActionTaken'; /// Returns the surveyShownCount of the of the activeSurvey (apiSetActiveSurvey). -const String apiGetSurveyShownCount = '${apiPrefix}getSurveyShownCount'; +const apiGetSurveyShownCount = '${apiPrefix}getSurveyShownCount'; /// Increments the surveyShownCount of the of the activeSurvey (apiSetActiveSurvey). -const String apiIncrementSurveyShownCount = +const apiIncrementSurveyShownCount = '${apiPrefix}incrementSurveyShownCount'; -const String lastReleaseNotesVersionPropertyName = 'lastReleaseNotesVersion'; +const lastReleaseNotesVersionPropertyName = 'lastReleaseNotesVersion'; /// Returns the last DevTools version for which we have shown release notes. -const String apiGetLastReleaseNotesVersion = +const apiGetLastReleaseNotesVersion = '${apiPrefix}getLastReleaseNotesVersion'; /// Sets the last DevTools version for which we have shown release notes. -const String apiSetLastReleaseNotesVersion = +const apiSetLastReleaseNotesVersion = '${apiPrefix}setLastReleaseNotesVersion'; /// Returns the base app size file, if present. -const String apiGetBaseAppSizeFile = '${apiPrefix}getBaseAppSizeFile'; +const apiGetBaseAppSizeFile = '${apiPrefix}getBaseAppSizeFile'; /// Returns the test app size file used for comparing two files in a diff, if /// present. -const String apiGetTestAppSizeFile = '${apiPrefix}getTestAppSizeFile'; +const apiGetTestAppSizeFile = '${apiPrefix}getTestAppSizeFile'; -const String baseAppSizeFilePropertyName = 'appSizeBase'; +const baseAppSizeFilePropertyName = 'appSizeBase'; -const String testAppSizeFilePropertyName = 'appSizeTest'; +const testAppSizeFilePropertyName = 'appSizeTest'; /// Serves any available extensions and returns a list of their configurations /// to DevTools. -const String apiServeAvailableExtensions = +const apiServeAvailableExtensions = '${apiPrefix}serveAvailableExtensions'; +/// The property name for the query parameter passed along with +/// [apiServeAvailableExtensions] requests to the server. const extensionRootPathPropertyName = 'rootPath'; +/// The property name for the response that the server sends back upon +/// receiving a [apiServeAvailableExtensions] request. const extensionsResultPropertyName = 'extensions'; diff --git a/packages/devtools_shared/lib/src/extensions/extension_manager.dart b/packages/devtools_shared/lib/src/extensions/extension_manager.dart index d0696cedecf..0567cc532d4 100644 --- a/packages/devtools_shared/lib/src/extensions/extension_manager.dart +++ b/packages/devtools_shared/lib/src/extensions/extension_manager.dart @@ -49,12 +49,12 @@ class ExtensionsManager { /// Serves any available DevTools extensions for the given [rootPath], where /// [rootPath] is the root for a Dart or Flutter project containing the /// `.dart_tool/` directory. - /// + /// /// 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. - void serveAvailableExtensions(String? rootPath) { + Future serveAvailableExtensions(String? rootPath) async { devtoolsExtensions.clear(); if (rootPath != null) { @@ -98,9 +98,10 @@ class ExtensionsManager { } _resetServedPluginsDir(); - for (final extension in devtoolsExtensions) { - _moveToServedExtensionsDir(extension.name, extension.path); - } + await Future.wait([ + for (final extension in devtoolsExtensions) + _moveToServedExtensionsDir(extension.name, extension.path), + ]); } void _resetServedPluginsDir() { @@ -118,15 +119,15 @@ class ExtensionsManager { servedExtensionsDir.createSync(); } - void _moveToServedExtensionsDir( + Future _moveToServedExtensionsDir( String extensionPackageName, String extensionPath, - ) { + ) async { final newExtensionPath = path.join( _servedExtensionsPath, extensionPackageName, ); - copyPathSync(extensionPath, newExtensionPath); + await copyPath(extensionPath, newExtensionPath); } } diff --git a/packages/devtools_shared/lib/src/server/server_api.dart b/packages/devtools_shared/lib/src/server/server_api.dart index 4c3dbfe56a0..ef43e809bc5 100644 --- a/packages/devtools_shared/lib/src/server/server_api.dart +++ b/packages/devtools_shared/lib/src/server/server_api.dart @@ -216,13 +216,13 @@ class ServerApi { ); } - extensionsManager.serveAvailableExtensions(rootPath); - final extensions = extensionsManager.devtoolsExtensions - .map((p) => p.toJson()) - .toList(); - final result = jsonEncode({extensionsResultPropertyName: extensions}); - - return api.getCompleted(result); + return extensionsManager.serveAvailableExtensions(rootPath).then((_) { + final extensions = extensionsManager.devtoolsExtensions + .map((p) => p.toJson()) + .toList(); + final result = jsonEncode({extensionsResultPropertyName: extensions}); + return api!.getCompleted(result); + }); default: return api.notImplemented();