@@ -10,6 +10,18 @@ import "package:yaml/yaml.dart";
1010Future <int > main () async {
1111 final exampleDir =
1212 canonicalize (join (dirname (Platform .script.toFilePath ()), "../example" ));
13+ final buildFolder = join (exampleDir, "build/web" );
14+
15+ final PathInformation pathInformation = (
16+ mainLib: canonicalize (join (dirname (Platform .script.toFilePath ()), "../" )),
17+ exampleProject: exampleDir,
18+ buildFolder: buildFolder,
19+ dartSdk: canonicalize (join (Platform .resolvedExecutable, "../../" )),
20+ flutterWebSdk: canonicalize (
21+ join (Platform .resolvedExecutable, "../../../flutter_web_sdk" )),
22+ pubCache: getPubCacheFolder (),
23+ flutterSdk: await getFlutterSdk (),
24+ );
1325
1426 print ("building project" );
1527 final process = await Process .start (
@@ -23,7 +35,7 @@ Future<int> main() async {
2335 "--source-maps" ,
2436 "--dart-define=redirectToHttps=true" ,
2537 ],
26- workingDirectory: exampleDir );
38+ workingDirectory: pathInformation.exampleProject );
2739 await Future .wait ([
2840 process.stdout.forEach ((final element) {
2941 stdout.write (utf8.decode (element));
@@ -37,10 +49,9 @@ Future<int> main() async {
3749 return exitCode;
3850 }
3951
40- final buildFolder = join (exampleDir, "build/web" );
41-
42- print ("Updating service working" );
43- final serviceWorkerPath = join (buildFolder, "flutter_service_worker.js" );
52+ print ("Updating service worker" );
53+ final serviceWorkerPath =
54+ join (pathInformation.buildFolder, "flutter_service_worker.js" );
4455 final serviceWorkerFile = File (serviceWorkerPath);
4556 final serviceWorker = await serviceWorkerFile.readAsString ();
4657 await serviceWorkerFile.writeAsString (
@@ -49,7 +60,8 @@ Future<int> main() async {
4960 flush: true );
5061
5162 print ("Updating provided pubspec" );
52- final pubspecFilePath = join (buildFolder, "assets/pubspec.lock" );
63+ final pubspecFilePath =
64+ join (pathInformation.buildFolder, "assets/pubspec.lock" );
5365 final pubspecFile = File (pubspecFilePath);
5466 final pubspecContent = await pubspecFile.readAsString ();
5567
@@ -81,6 +93,9 @@ packages:
8193
8294 await pubspecFile.writeAsString (newPubspecContent);
8395
96+ print ("Updating source maps" );
97+ await handleSourceMaps (pathInformation);
98+
8499 return 0 ;
85100}
86101
@@ -106,3 +121,175 @@ Future<({String flutter, String dart})> getFlutterAndDartVersion() async {
106121
107122 return (flutter: flutterVersion, dart: dartVersion);
108123}
124+
125+ Future <void > handleSourceMaps (final PathInformation pathInformation) async {
126+ final dir = Directory (pathInformation.buildFolder);
127+ final mapFiles = await dir.list ().where ((final entry) {
128+ if (entry.path.endsWith (".map" )) {
129+ return true ;
130+ }
131+ return false ;
132+ }).toList ();
133+
134+ await Future .wait (mapFiles.map ((final fileEntry) {
135+ final mapFile = File (fileEntry.path);
136+ return handleSingleSourceMap (mapFile, pathInformation);
137+ }));
138+ }
139+
140+ Future <void > handleSingleSourceMap (
141+ final File mapFile, final PathInformation pathInformation) async {
142+ final data = await mapFile.readAsString ();
143+
144+ final parsedData = jsonDecode (data);
145+
146+ final sources = parsedData["sources" ] as List <dynamic >;
147+
148+ final sourcesParsed = sources
149+ .whereType <String >()
150+ .map (Uri .parse)
151+ .map ((final x) {
152+ if (x.scheme == "org-dartlang-sdk" ) {
153+ var path = x.path;
154+ if (path.startsWith ("/" )) {
155+ path = path.substring (1 );
156+ }
157+ if (path.startsWith ("dart-sdk" )) {
158+ path = canonicalize (join (pathInformation.dartSdk, "../" , path));
159+ } else {
160+ path = canonicalize (join (pathInformation.flutterWebSdk, path));
161+ }
162+ final fileExists = File (path).existsSync ();
163+ if (fileExists) {
164+ return Uri .parse (path);
165+ } else {
166+ print ("Could not find $path original: $x " );
167+ }
168+ } else {
169+ final path = x.path;
170+ final String joined;
171+ if (path == "web_plugin_registrant.dart" ) {
172+ joined = canonicalize (join (
173+ pathInformation.exampleProject, ".dart_tool" , "dartpad" , path));
174+ } else if (path == "main.dart" ) {
175+ joined =
176+ canonicalize (join (pathInformation.exampleProject, "lib" , path));
177+ } else {
178+ joined = canonicalize (
179+ join (pathInformation.buildFolder, "canvaskit" , path));
180+ }
181+ final fileExists = File (joined).existsSync ();
182+ if (fileExists) {
183+ return Uri .parse (joined);
184+ } else {
185+ print ("Could not find $joined original: $path " );
186+ }
187+ }
188+
189+ return x;
190+ })
191+ .where ((final x) => x.scheme == "" )
192+ .toList (growable: false );
193+
194+ final updatedSources =
195+ sourcesParsed.map ((final x) => x.toString ()).map ((final path) {
196+ if (path.startsWith (pathInformation.dartSdk)) {
197+ return "dart-sdk://${path .substring (pathInformation .dartSdk .length )}" ;
198+ } else if (path.startsWith (pathInformation.flutterWebSdk)) {
199+ return "flutter-web-sdk://${path .substring (pathInformation .flutterWebSdk .length )}" ;
200+ } else if (path.startsWith (pathInformation.pubCache)) {
201+ return "packages/${convertPackageSource (path .substring (pathInformation .pubCache .length + 1 ))}" ;
202+ } else if (path.startsWith (pathInformation.flutterSdk)) {
203+ return "flutter-sdk://${path .substring (pathInformation .flutterSdk .length )}" ;
204+ } else if (path.startsWith (pathInformation.exampleProject)) {
205+ return "packages/flutter_web_bluetooth_example${path .substring (pathInformation .exampleProject .length )}" ;
206+ } else if (path.startsWith (pathInformation.mainLib)) {
207+ return "packages/flutter_web_bluetooth${path .substring (pathInformation .mainLib .length )}" ;
208+ }
209+ print ("dunno: $path " );
210+ return path;
211+ }).toList (growable: false );
212+
213+ final sourceContent = await Future .wait (sourcesParsed.map ((final x) async {
214+ try {
215+ return await File (x.toString ()).readAsString ();
216+ } catch (_) {
217+ print ("Could not read $x " );
218+ return "" ;
219+ }
220+ }));
221+
222+ parsedData["sourcesContent" ] = sourceContent;
223+ parsedData["sources" ] = updatedSources;
224+
225+ final output = mapFile.absolute;
226+ if (await output.exists ()) {
227+ await output.delete ();
228+ }
229+ await output.create ();
230+ await output.writeAsString (jsonEncode (parsedData));
231+ print ("Writen sourcemap file ${output .path }" );
232+ }
233+
234+ typedef PathInformation = ({
235+ String mainLib,
236+ String exampleProject,
237+ String buildFolder,
238+ String dartSdk,
239+ String flutterWebSdk,
240+ String pubCache,
241+ String flutterSdk,
242+ });
243+
244+ // region HELPERS
245+
246+ String getPubCacheFolder () {
247+ final pubCacheEnv = Platform .environment["PUB_CACHE" ];
248+ if (pubCacheEnv != null ) {
249+ return absolute (canonicalize (pubCacheEnv));
250+ }
251+ if (Platform .isLinux || Platform .isMacOS) {
252+ return absolute (
253+ canonicalize (join (Platform .environment["HOME" ] ?? "/" , ".pub-cache" )));
254+ } else if (Platform .isWindows) {
255+ return absolute (canonicalize (join ("%LOCALAPPDATA%" , "Pub" , "Cache" )));
256+ } else {
257+ throw UnsupportedError ("Platform is not supported" );
258+ }
259+ }
260+
261+ Future <String > getFlutterSdk () async {
262+ final result = await Process .run (
263+ Platform .isWindows ? "where" : "which" , ["flutter" ],
264+ runInShell: true ,
265+ workingDirectory: "/" ,
266+ stdoutEncoding: Encoding .getByName ("UTF-8" ));
267+
268+ if (result.exitCode != 0 ) {
269+ throw ArgumentError ("Could not find flutter executable path" );
270+ }
271+ var flutterBin = (result.stdout as String ).trim ();
272+
273+ try {
274+ final file = File (flutterBin);
275+ flutterBin = await file.resolveSymbolicLinks ();
276+ } on Error {
277+ // nothing
278+ }
279+
280+ return absolute (canonicalize (join (flutterBin, "../../" )));
281+ }
282+
283+ String convertPackageSource (final String packageSource) {
284+ final parts = split (packageSource);
285+ if (parts[0 ] != "hosted" ) {
286+ throw UnsupportedError ("Not a hosted package $packageSource " );
287+ }
288+
289+ final regex = RegExp (r"^(.+)-\d+\.\d+\.\d+$" );
290+
291+ final package = regex.firstMatch (parts[2 ])? .group (1 ) ?? parts[2 ];
292+ return joinAll ([package, ...parts.skip (3 )]);
293+ }
294+
295+ // endregion
0 commit comments