blob: 301d1af0fc9da70ed8151ff4ef963f698e1d490c [file] [log] [blame] [edit]
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:convert';
import 'dart:io';
import '../args_parser.dart';
import '../config.dart';
import '../validation.dart';
/// Links assets in a `hook/link.dart`.
///
/// Meant to be used in link hooks (`hook/link.dart`).
///
/// Can link native assets which are not already available, or expose existing
/// files. Each individual asset is assigned a unique asset ID.
///
/// The linking script may receive assets from build scripts, which are accessed
/// through [LinkInputAssets.encodedAssets]. They will only be bundled with the
/// final application if included in the [LinkOutput].
///
///
/// ```dart
/// import 'package:hooks/hooks.dart';
///
/// void main(List<String> args) async {
/// await link(args, (input, output) async {
/// final dataEncodedAssets = input.assets
/// .whereType<DataAsset>();
/// output.addEncodedAssets(dataEncodedAssets);
/// });
/// }
/// ```
/// If the [linker] fails, it must `throw`. Link hooks are guaranteed to be
/// invoked with a process invocation and should return a non-zero exit code on
/// failure. Throwing will lead to an uncaught exception, causing a non-zero
/// exit code.
Future<void> link(
List<String> arguments,
Future<void> Function(LinkInput input, LinkOutputBuilder output) linker,
) async {
final inputPath = getInputArgument(arguments);
final bytes = File(inputPath).readAsBytesSync();
final jsonInput =
const Utf8Decoder().fuse(const JsonDecoder()).convert(bytes)
as Map<String, Object?>;
final input = LinkInput(jsonInput);
final output = LinkOutputBuilder();
await linker(input, output);
final errors = await ProtocolBase.validateLinkOutput(
input,
LinkOutput(output.json),
);
if (errors.isEmpty) {
final jsonOutput = const JsonEncoder()
.fuse(const Utf8Encoder())
.convert(output.json);
await File.fromUri(input.outputFile).writeAsBytes(jsonOutput);
} else {
final message = [
'The output contained unsupported output:',
for (final error in errors) '- $error',
].join('\n');
throw UnsupportedError(message);
}
}