35 lines
1.4 KiB
Dart
35 lines
1.4 KiB
Dart
import 'dart:io';
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:archive/archive_io.dart';
|
|
|
|
/// Packs a directory of static files into a gzip-compressed tar archive
|
|
/// (contents at the archive root) for a single-shot upload + remote extract.
|
|
class WebArchive {
|
|
/// Returns the .tar.gz bytes of [dir]'s contents and the number of files.
|
|
static (Uint8List, int) tarGz(Directory dir) {
|
|
final archive = createArchiveFromDirectory(dir, includeDirName: false);
|
|
// CRITICAL: on Windows the entry names use backslashes; a POSIX `tar` on
|
|
// the server would then create single files literally named
|
|
// `assets\main.js` instead of the `assets/main.js` tree — breaking any
|
|
// app with subdirectories (Angular/React assets, etc.). Force forward
|
|
// slashes so the archive is valid on Linux.
|
|
for (final f in archive.files) {
|
|
f.name = f.name.replaceAll('\\', '/');
|
|
}
|
|
final tar = TarEncoder().encode(archive);
|
|
final gz = GZipEncoder().encode(tar);
|
|
final count = archive.files.where((f) => f.isFile).length;
|
|
// Release the file handles opened while reading the directory so the
|
|
// source tree isn't left locked (notably on Windows).
|
|
for (final f in archive.files) {
|
|
f.closeSync();
|
|
}
|
|
return (Uint8List.fromList(gz), count);
|
|
}
|
|
}
|
|
|
|
/// Top-level entry so packaging can run off the UI isolate via `compute`.
|
|
(Uint8List, int) packageWebDir(String path) =>
|
|
WebArchive.tarGz(Directory(path));
|