Skip to content

[native_assets_cli] Syntax for assets_for_build and hooks/metadata #2163

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 4, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -10,6 +10,19 @@
},
{
"$ref": "../../../../hooks/doc/schema/shared/shared_definitions.schema.json#/definitions/BuildInput"
},
{
"properties": {
"assets": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"$ref": "shared_definitions.schema.json#/definitions/Asset"
}
}
}
}
}
]
},
@@ -32,6 +45,12 @@
}
}
},
"assets_for_build": {
"type": "array",
"items": {
"$ref": "shared_definitions.schema.json#/definitions/Asset"
}
},
"assets_for_linking": {
"type": "object",
"additionalProperties": {
24 changes: 12 additions & 12 deletions pkgs/code_assets/doc/schema/shared/shared_definitions.schema.json
Original file line number Diff line number Diff line change
@@ -38,10 +38,10 @@
"type": "string",
"anyOf": [
{
"const": "native_code"
"const": "code_assets/code"
},
{
"const": "code_assets/code"
"const": "native_code"
},
{
"type": "string"
@@ -54,7 +54,7 @@
"if": {
"properties": {
"type": {
"const": "native_code"
"const": "code_assets/code"
}
}
},
@@ -63,20 +63,14 @@
"encoding": {
"$ref": "#/definitions/NativeCodeAssetEncoding"
}
},
"allOf": [
{
"$comment": "Also include the fields parent object for backwards compatibility.",
"$ref": "#/definitions/NativeCodeAssetEncoding"
}
]
}
}
},
{
"if": {
"properties": {
"type": {
"const": "code_assets/code"
"const": "native_code"
}
}
},
@@ -85,7 +79,13 @@
"encoding": {
"$ref": "#/definitions/NativeCodeAssetEncoding"
}
}
},
"allOf": [
{
"$comment": "Also include the fields parent object for backwards compatibility.",
"$ref": "#/definitions/NativeCodeAssetEncoding"
}
]
}
}
]
23 changes: 23 additions & 0 deletions pkgs/code_assets/test/data/build_input_macos.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
{
"$schema": "../../doc/schema/sdk/build_input.generated.schema.json",
"assets": {
"some_package": [
{
"architecture": "arm64",
"encoding": {
"architecture": "arm64",
"file": "/private/var/folders/2y/mngq9h194yzglt4kzttzfq6800klzg/T/iv6i0d/native_add/.dart_tool/native_assets_builder/native_add/c6b312c90c95d2d98ffb6760a738fb36/out/libnative_add.a",
"id": "package:native_add/src/native_add_bindings_generated.dart",
"link_mode": {
"type": "static"
},
"os": "macos"
},
"file": "/private/var/folders/2y/mngq9h194yzglt4kzttzfq6800klzg/T/iv6i0d/native_add/.dart_tool/native_assets_builder/native_add/c6b312c90c95d2d98ffb6760a738fb36/out/libnative_add.a",
"id": "package:native_add/src/native_add_bindings_generated.dart",
"link_mode": {
"type": "static"
},
"os": "macos",
"type": "native_code"
}
]
},
"config": {
"build_asset_types": [
"native_code"
21 changes: 21 additions & 0 deletions pkgs/code_assets/test/data/build_output_macos.json
Original file line number Diff line number Diff line change
@@ -116,6 +116,27 @@
}
]
},
"assets_for_build": [
{
"architecture": "arm64",
"encoding": {
"architecture": "arm64",
"file": "/private/var/folders/2y/mngq9h194yzglt4kzttzfq6800klzg/T/iv6i0d/native_add/.dart_tool/native_assets_builder/native_add/c6b312c90c95d2d98ffb6760a738fb36/out/libnative_add.a",
"id": "package:native_add/src/native_add_bindings_generated.dart",
"link_mode": {
"type": "static"
},
"os": "macos"
},
"file": "/private/var/folders/2y/mngq9h194yzglt4kzttzfq6800klzg/T/iv6i0d/native_add/.dart_tool/native_assets_builder/native_add/c6b312c90c95d2d98ffb6760a738fb36/out/libnative_add.a",
"id": "package:native_add/src/native_add_bindings_generated.dart",
"link_mode": {
"type": "static"
},
"os": "macos",
"type": "native_code"
}
],
"assets_for_linking": {
"package_with_linker": [
{
18 changes: 5 additions & 13 deletions pkgs/code_assets/test/schema/schema_test.dart
Original file line number Diff line number Diff line change
@@ -127,20 +127,12 @@ FieldsFunction _codeFields(AllTestData allTestData) {
if (hook == Hook.build) ...[
for (final (field, expect) in codeAssetFields)
for (final encoding in _encoding)
for (final assetsForLinking in [
'assetsForLinking',
'assets_for_linking',
for (final path in [
['assets_for_build'],
['assetsForLinking', 'package_with_linker'],
['assets_for_linking', 'package_with_linker'],
])
(
[
assetsForLinking,
'package_with_linker',
0,
...encoding,
...field,
],
expect,
),
([...path, 0, ...encoding, ...field], expect),
],
(['assets', staticIndex, 'file'], expectRequiredFieldMissing),
(
Original file line number Diff line number Diff line change
@@ -10,6 +10,19 @@
},
{
"$ref": "../../../../hooks/doc/schema/shared/shared_definitions.schema.json#/definitions/BuildInput"
},
{
"properties": {
"assets": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"$ref": "shared_definitions.schema.json#/definitions/Asset"
}
}
}
}
}
]
},
@@ -32,6 +45,12 @@
}
}
},
"assets_for_build": {
"type": "array",
"items": {
"$ref": "shared_definitions.schema.json#/definitions/Asset"
}
},
"assets_for_linking": {
"type": "object",
"additionalProperties": {
26 changes: 26 additions & 0 deletions pkgs/data_assets/test/data/build_input.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,31 @@
{
"$schema": "../../doc/schema/sdk/build_input.generated.schema.json",
"assets": {
"some_package": [
{
"encoding": {
"file": "/private/var/folders/2y/mngq9h194yzglt4kzttzfq6800klzg/T/0s5bKi/simple_link/assets/data_0.json",
"name": "assets/data_0.json",
"package": "simple_link"
},
"file": "/private/var/folders/2y/mngq9h194yzglt4kzttzfq6800klzg/T/0s5bKi/simple_link/assets/data_0.json",
"name": "assets/data_0.json",
"package": "simple_link",
"type": "data"
},
{
"encoding": {
"file": "/private/var/folders/2y/mngq9h194yzglt4kzttzfq6800klzg/T/0s5bKi/simple_link/assets/data_1.json",
"name": "assets/data_1.json",
"package": "simple_link"
},
"file": "/private/var/folders/2y/mngq9h194yzglt4kzttzfq6800klzg/T/0s5bKi/simple_link/assets/data_1.json",
"name": "assets/data_1.json",
"package": "simple_link",
"type": "data"
}
]
},
"config": {
"build_asset_types": [
"data"
24 changes: 24 additions & 0 deletions pkgs/data_assets/test/data/build_output.json
Original file line number Diff line number Diff line change
@@ -50,6 +50,30 @@
}
]
},
"assets_for_build": [
{
"encoding": {
"file": "/private/var/folders/2y/mngq9h194yzglt4kzttzfq6800klzg/T/0s5bKi/simple_link/assets/data_0.json",
"name": "assets/data_0.json",
"package": "simple_link"
},
"file": "/private/var/folders/2y/mngq9h194yzglt4kzttzfq6800klzg/T/0s5bKi/simple_link/assets/data_0.json",
"name": "assets/data_0.json",
"package": "simple_link",
"type": "data"
},
{
"encoding": {
"file": "/private/var/folders/2y/mngq9h194yzglt4kzttzfq6800klzg/T/0s5bKi/simple_link/assets/data_1.json",
"name": "assets/data_1.json",
"package": "simple_link"
},
"file": "/private/var/folders/2y/mngq9h194yzglt4kzttzfq6800klzg/T/0s5bKi/simple_link/assets/data_1.json",
"name": "assets/data_1.json",
"package": "simple_link",
"type": "data"
}
],
"assets_for_linking": {
"package_with_linker": [
{
12 changes: 5 additions & 7 deletions pkgs/data_assets/test/schema/schema_test.dart
Original file line number Diff line number Diff line change
@@ -58,14 +58,12 @@ List<(List<Object>, void Function(ValidationResults result))> _dataFields({
if (hook == Hook.build) ...[
for (final field in _dataAssetFields)
for (final encoding in _encoding)
for (final assetsForLinking in [
'assetsForLinking',
'assets_for_linking',
for (final path in [
['assets_for_build'],
['assetsForLinking', 'package_with_linker'],
['assets_for_linking', 'package_with_linker'],
])
(
[assetsForLinking, 'package_with_linker', 0, ...encoding, field],
expectRequiredFieldMissing,
),
([...path, 0, ...encoding, field], expectRequiredFieldMissing),
],
],
];
58 changes: 57 additions & 1 deletion pkgs/hooks/doc/schema/shared/shared_definitions.schema.json
Original file line number Diff line number Diff line change
@@ -6,7 +6,15 @@
"type": "object",
"properties": {
"type": {
"type": "string"
"type": "string",
"anyOf": [
{
"const": "hooks/metadata"
},
{
"type": "string"
}
]
},
"encoding": {
"type": "object",
@@ -15,6 +23,27 @@
},
"required": [
"type"
],
"allOf": [
{
"if": {
"properties": {
"type": {
"const": "hooks/metadata"
}
}
},
"then": {
"properties": {
"encoding": {
"$ref": "#/definitions/MetadataAssetEncoding"
}
},
"required": [
"encoding"
]
}
}
]
},
"BuildConfig": {
@@ -36,6 +65,15 @@
},
"BuildInput": {
"properties": {
"assets": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"$ref": "#/definitions/Asset"
}
}
},
"config": {
"$ref": "#/definitions/BuildConfig"
},
@@ -65,6 +103,12 @@
}
}
},
"assets_for_build": {
"type": "array",
"items": {
"$ref": "#/definitions/Asset"
}
},
"assets_for_linking": {
"type": "object",
"additionalProperties": {
@@ -196,6 +240,18 @@
}
]
},
"MetadataAssetEncoding": {
"type": "object",
"properties": {
"key": {
"type": "string"
},
"value": {}
},
"required": [
"key"
]
},
"absolutePath": {
"type": "string",
"pattern": "^(\\/|[A-Za-z]:)"
15 changes: 15 additions & 0 deletions pkgs/hooks/test/data/build_input.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
{
"$schema": "../../doc/schema/sdk/build_input.generated.schema.json",
"assets": {
"some_package": [
{
"encoding": {
"key": "foo",
"value": "bar"
},
"type": "hooks/metadata"
},
{
"some_key": "some_value",
"type": "some_asset_type"
}
]
},
"config": {
"build_asset_types": [
"my_asset_type"
32 changes: 24 additions & 8 deletions pkgs/hooks/test/data/build_output.json
Original file line number Diff line number Diff line change
@@ -20,35 +20,51 @@
"package_with_linker": [
{
"encoding": {
"some_key": "some_value"
"a_key": "some_value"
},
"some_key": "some_value",
"type": "some_asset_type"
},
{
"encoding": {
"some_other_key": "some_value"
"key": "foo",
"value": "bar"
},
"some_other_key": "some_value",
"type": "some_other_asset_type"
"type": "hooks/metadata"
}
]
},
"assets_for_build": [
{
"encoding": {
"a_key": "some_value"
},
"some_key": "some_value",
"type": "some_asset_type"
},
{
"encoding": {
"key": "foo",
"value": "bar"
},
"type": "hooks/metadata"
}
],
"assets_for_linking": {
"package_with_linker": [
{
"encoding": {
"some_key": "some_value"
"a_key": "some_value"
},
"some_key": "some_value",
"type": "some_asset_type"
},
{
"encoding": {
"some_other_key": "some_value"
"key": "foo",
"value": "bar"
},
"some_other_key": "some_value",
"type": "some_other_asset_type"
"type": "hooks/metadata"
}
]
},
9 changes: 6 additions & 3 deletions pkgs/hooks/test/data/link_input.json
Original file line number Diff line number Diff line change
@@ -2,12 +2,15 @@
"$schema": "../../doc/schema/sdk/link_input.generated.schema.json",
"assets": [
{
"some_key": "some_value",
"a_key": "some_value",
"type": "some_asset_type"
},
{
"some_other_key": "some_value",
"type": "some_other_asset_type"
"encoding": {
"key": "foo",
"value": "bar"
},
"type": "hooks/metadata"
}
],
"config": {
49 changes: 29 additions & 20 deletions pkgs/hooks/test/schema/helpers.dart
Original file line number Diff line number Diff line change
@@ -159,13 +159,14 @@ void testAllTestData(AllSchemas allSchemas, AllTestData allTestData) {
/// [missingExpectations].
void testField({
required Uri schemaUri,
required Uri dataUri,
required JsonSchema schema,
required String data,
required List<Object> field,
required void Function(ValidationResults result) missingExpectations,
}) {
final fieldPath = field.join('.');
test('$schemaUri $fieldPath missing', () {
test('$schemaUri $dataUri $fieldPath missing', () {
final dataDecoded = jsonDecode(data);
final dataToModify = _traverseJson(
dataDecoded,
@@ -254,6 +255,7 @@ void testFields({
field: field,
schemaUri: schemaUri,
schema: schema,
dataUri: dataUri,
data: data,
missingExpectations: missingExpectations,
);
@@ -342,27 +344,34 @@ FieldsReturn _hookFields({
(['timestamp'], expectRequiredFieldMissing),
(['dependencies'], expectOptionalFieldMissing),
(['dependencies', 0], expectOptionalFieldMissing),
(['assets'], expectOptionalFieldMissing),
(['assets', 0], expectOptionalFieldMissing),
(['assets', 0, 'encoding'], expectOptionalFieldMissing),
(['assets', 0, 'type'], expectRequiredFieldMissing),
if (hook == Hook.build)
for (final assetsForLinking in [
'assetsForLinking',
'assets_for_linking',

if (hook == Hook.build) ...[
(['metadata'], expectOptionalFieldMissing),
for (final path in [
['assets_for_build'],
['assetsForLinking', 'package_with_linker'],
['assets_for_linking', 'package_with_linker'],
]) ...[
(['metadata'], expectOptionalFieldMissing),
([assetsForLinking], expectOptionalFieldMissing),
(
[assetsForLinking, 'package_with_linker', 0],
expectOptionalFieldMissing,
),
([assetsForLinking], expectOptionalFieldMissing),
(
[assetsForLinking, 'package_with_linker', 0, 'type'],
expectRequiredFieldMissing,
),
([...path], expectOptionalFieldMissing),
([...path, 0], expectOptionalFieldMissing),
([...path, 0, 'type'], expectRequiredFieldMissing),
([...path, 0, 'encoding'], expectOptionalFieldMissing),
],
],
],
for (final path in [
if (inputOrOutput == InputOrOutput.output || hook == Hook.link)
['assets'],
if (inputOrOutput == InputOrOutput.output && hook == Hook.build) ...[
['assets_for_build'],
['assetsForLinking', 'package_with_linker'],
['assets_for_linking', 'package_with_linker'],
],
]) ...[
([...path], expectOptionalFieldMissing),
([...path, 0], expectOptionalFieldMissing),
([...path, 0, 'type'], expectRequiredFieldMissing),
([...path, 0, 'encoding'], expectOptionalFieldMissing),
],
];
}
31 changes: 31 additions & 0 deletions pkgs/hooks/test/schema/schema_test.dart
Original file line number Diff line number Diff line change
@@ -2,6 +2,8 @@
// 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 'package:json_schema/json_schema.dart';

import 'helpers.dart';

void main() {
@@ -19,6 +21,35 @@ void main() {
allTestData: allTestData,
packageUri: packageUri,
);

testFields(
allSchemas: allSchemas,
allTestData: allTestData,
packageUri: packageUri,
fields: _metadataAssetFields,
);
}

Uri packageUri = findPackageRoot('hooks');

List<(List<Object>, void Function(ValidationResults result))>
_metadataAssetFields({
required InputOrOutput inputOrOutput,
required Hook hook,
required Party party,
}) => <(List<Object>, void Function(ValidationResults result))>[
for (final path in [
if (inputOrOutput == InputOrOutput.input && hook == Hook.link) ['assets'],
if (inputOrOutput == InputOrOutput.output && hook == Hook.build) ...[
['assets_for_build'],
['assetsForLinking', 'package_with_linker'],
['assets_for_linking', 'package_with_linker'],
],
]) ...[
([...path, 1], expectOptionalFieldMissing),
([...path, 1, 'type'], expectRequiredFieldMissing),
([...path, 1, 'encoding'], expectRequiredFieldMissing),
([...path, 1, 'encoding', 'key'], expectRequiredFieldMissing),
// Skip `encoding.value`, it's optional and may have any type.
],
];
21 changes: 21 additions & 0 deletions pkgs/hooks/tool/generate_schemas.dart
Original file line number Diff line number Diff line change
@@ -52,6 +52,23 @@ void generateSharedDefinitions() {
},
},
},
'assets_for_build': {
'type': 'array',
'items': {r'$ref': 'shared_definitions.schema.json#/definitions/Asset'},
},
},
};
const buildInputAssetOverride = {
'properties': {
'assets': {
'type': 'object',
'additionalProperties': {
'type': 'array',
'items': {
r'$ref': 'shared_definitions.schema.json#/definitions/Asset',
},
},
},
},
};
const linkInputAssetOverride = {
@@ -128,6 +145,10 @@ void generateSharedDefinitions() {
hook == Hook.hook &&
inputOrOutput == InputOrOutput.output)
hookOutputAssetOverride,
if (party == Party.shared &&
hook == Hook.build &&
inputOrOutput == InputOrOutput.input)
buildInputAssetOverride,
if (party == Party.shared &&
hook == Hook.link &&
inputOrOutput == InputOrOutput.input)
34 changes: 26 additions & 8 deletions pkgs/json_syntax_generator/lib/src/parser/schema_analyzer.dart
Original file line number Diff line number Diff line change
@@ -180,13 +180,18 @@ class SchemaAnalyzer {
properties: properties,
taggedUnionValue: taggedUnionValue,
taggedUnionProperty:
schemas.generateSubClasses ? properties.single.name : null,
schemas.generateSubClasses ? schemas.generateSubClassesKey! : null,
visibleTaggedUnion: visbleUnionTagValues.contains(typeName),
extraValidation: extraValidation,
);
_classes[typeName] = classInfo;
if (schemas.generateSubClasses) {
_analyzeSubClasses(schemas, name: name, superclass: classInfo);
_analyzeSubClasses(
schemas,
schemas.generateSubClassesKey!,
name: name,
superclass: classInfo,
);
return;
}
}
@@ -251,13 +256,13 @@ class SchemaAnalyzer {
}

void _analyzeSubClasses(
JsonSchemas schemas, {
JsonSchemas schemas,
String propertyKey, {
String? name,
NormalClassInfo? superclass,
}) {
final typeName = schemas.className;

final propertyKey = schemas.propertyKeys.single;
final typeProperty = schemas.property(propertyKey);
final subTypes = typeProperty.enumOrTaggedUnionValues;
for (final subType in subTypes) {
@@ -299,6 +304,8 @@ class SchemaAnalyzer {
final type = schemas.type;
final DartType dartType;
switch (type) {
case null:
dartType = ObjectDartType(isNullable: !required);
case SchemaType.boolean:
dartType = BoolDartType(isNullable: !required);
case SchemaType.integer:
@@ -650,10 +657,21 @@ extension on JsonSchemas {
(additionalPropertiesSchemas.isNotEmpty ||
additionalPropertiesBool == true);

bool get generateSubClasses =>
type == SchemaType.object &&
propertyKeys.length == 1 &&
property(propertyKeys.single).anyOfs.isNotEmpty;
bool get generateSubClasses => generateSubClassesKey != null;

String? get generateSubClassesKey {
if (type != SchemaType.object) return null;
// A tagged union either has only a key, or a key and an encoding.
// Classes with more than 2 properties have their a property that has
// predefined values generated as an enum class.
if (propertyKeys.length > 2) return null;
for (final p in propertyKeys) {
if (property(p).anyOfs.isNotEmpty) {
return p;
}
}
return null;
}

bool get generateClass => type == SchemaType.object && !generateMapOf;

1 change: 1 addition & 0 deletions pkgs/native_assets_cli/lib/src/config.dart
Original file line number Diff line number Diff line change
@@ -183,6 +183,7 @@ final class BuildInputBuilder extends HookInputBuilder {
dependencyMetadata: {
for (final key in metadata.keys) key: metadata[key]!.toJson(),
},
assets: null, // TODO: Implement this.
);
}

199 changes: 197 additions & 2 deletions pkgs/native_assets_cli/lib/src/hooks/syntax.g.dart
Original file line number Diff line number Diff line change
@@ -11,7 +11,18 @@
import 'dart:io';

class Asset extends JsonObject {
Asset.fromJson(super.json, {super.path = const []}) : super.fromJson();
factory Asset.fromJson(
Map<String, Object?> json, {
List<Object> path = const [],
}) {
final result = Asset._fromJson(json, path: path);
if (result.isHooksMetadataAsset) {
return result.asHooksMetadataAsset;
}
return result;
}

Asset._fromJson(super.json, {super.path = const []}) : super.fromJson();

Asset({required JsonObject? encoding, required String type}) : super() {
_encoding = encoding;
@@ -50,8 +61,25 @@ class Asset extends JsonObject {
...super.validate(),
..._validateEncoding(),
..._validateType(),
..._validateExtraRules(),
];

List<String> _validateExtraRules() {
final result = <String>[];
if (_reader.tryTraverse(['type']) == 'hooks/metadata') {
final objectErrors = _reader.validate<Map<String, Object?>?>('encoding');
result.addAll(objectErrors);
if (objectErrors.isEmpty) {
final jsonValue = _reader.get<Map<String, Object?>?>('encoding');
if (jsonValue != null) {
final reader = JsonReader(jsonValue, [...path, 'encoding']);
result.addAll(reader.validate<Object>('key'));
}
}
}
return result;
}

@override
String toString() => 'Asset($json)';
}
@@ -98,6 +126,7 @@ class BuildInput extends HookInput {
BuildInput.fromJson(super.json, {super.path}) : super.fromJson();

BuildInput({
required Map<String, List<Asset>>? assets,
required BuildConfig config,
required Map<String, Map<String, Object?>>? dependencyMetadata,
required super.outDir,
@@ -107,17 +136,69 @@ class BuildInput extends HookInput {
required super.packageRoot,
required super.version,
}) : super(config: config) {
_assets = assets;
_dependencyMetadata = dependencyMetadata;
json.sortOnKey();
}

/// Setup all fields for [BuildInput] that are not in
/// [HookInput].
void setup({required Map<String, Map<String, Object?>>? dependencyMetadata}) {
void setup({
required Map<String, List<Asset>>? assets,
required Map<String, Map<String, Object?>>? dependencyMetadata,
}) {
_assets = assets;
_dependencyMetadata = dependencyMetadata;
json.sortOnKey();
}

Map<String, List<Asset>>? get assets {
final jsonValue = _reader.optionalMap('assets');
if (jsonValue == null) {
return null;
}
final result = <String, List<Asset>>{};
for (final MapEntry(:key, :value) in jsonValue.entries) {
result[key] = [
for (final (index, item) in (value as List<Object?>).indexed)
Asset.fromJson(
item as Map<String, Object?>,
path: [...path, key, index],
),
];
}
return result;
}

set _assets(Map<String, List<Asset>>? value) {
if (value == null) {
json.remove('assets');
} else {
json['assets'] = {
for (final MapEntry(:key, :value) in value.entries)
key: [for (final item in value) item.json],
};
}
}

List<String> _validateAssets() {
final mapErrors = _reader.validateOptionalMap('assets');
if (mapErrors.isNotEmpty) {
return mapErrors;
}
final jsonValue = _reader.optionalMap('assets');
if (jsonValue == null) {
return [];
}
final result = <String>[];
for (final list in assets!.values) {
for (final element in list) {
result.addAll(element.validate());
}
}
return result;
}

@override
BuildConfig get config {
final jsonValue = _reader.map$('config');
@@ -137,6 +218,7 @@ class BuildInput extends HookInput {
@override
List<String> validate() => [
...super.validate(),
..._validateAssets(),
..._validateConfig(),
..._validateDependencyMetadata(),
];
@@ -150,6 +232,7 @@ class BuildOutput extends HookOutput {

BuildOutput({
required super.assets,
required List<Asset>? assetsForBuild,
required Map<String, List<Asset>>? assetsForLinking,
required Map<String, List<Asset>>? assetsForLinkingOld,
required super.dependencies,
@@ -158,6 +241,7 @@ class BuildOutput extends HookOutput {
required super.version,
}) : super() {
this.assetsForLinkingOld = assetsForLinkingOld;
this.assetsForBuild = assetsForBuild;
this.assetsForLinking = assetsForLinking;
this.metadata = metadata;
json.sortOnKey();
@@ -167,10 +251,12 @@ class BuildOutput extends HookOutput {
/// [HookOutput].
void setup({
required Map<String, List<Asset>>? assetsForLinkingOld,
required List<Asset>? assetsForBuild,
required Map<String, List<Asset>>? assetsForLinking,
required JsonObject? metadata,
}) {
this.assetsForLinkingOld = assetsForLinkingOld;
this.assetsForBuild = assetsForBuild;
this.assetsForLinking = assetsForLinking;
this.metadata = metadata;
json.sortOnKey();
@@ -224,6 +310,41 @@ class BuildOutput extends HookOutput {
return result;
}

List<Asset>? get assetsForBuild {
final jsonValue = _reader.optionalList('assets_for_build');
if (jsonValue == null) return null;
return [
for (final (index, element) in jsonValue.indexed)
Asset.fromJson(
element as Map<String, Object?>,
path: [...path, 'assets_for_build', index],
),
];
}

set assetsForBuild(List<Asset>? value) {
if (value == null) {
json.remove('assets_for_build');
} else {
json['assets_for_build'] = [for (final item in value) item.json];
}
json.sortOnKey();
}

List<String> _validateAssetsForBuild() {
final listErrors = _reader.validateOptionalList<Map<String, Object?>>(
'assets_for_build',
);
if (listErrors.isNotEmpty) {
return listErrors;
}
final elements = assetsForBuild;
if (elements == null) {
return [];
}
return [for (final element in elements) ...element.validate()];
}

Map<String, List<Asset>>? get assetsForLinking {
final jsonValue = _reader.optionalMap('assets_for_linking');
if (jsonValue == null) {
@@ -295,6 +416,7 @@ class BuildOutput extends HookOutput {
List<String> validate() => [
...super.validate(),
..._validateAssetsForLinkingOld(),
..._validateAssetsForBuild(),
..._validateAssetsForLinking(),
..._validateMetadata(),
];
@@ -559,6 +681,41 @@ class HookOutput extends JsonObject {
String toString() => 'HookOutput($json)';
}

class HooksMetadataAsset extends Asset {
static const typeValue = 'hooks/metadata';

HooksMetadataAsset.fromJson(super.json, {super.path}) : super._fromJson();

HooksMetadataAsset({required MetadataAssetEncoding encoding})
: super(type: 'hooks/metadata', encoding: encoding);

/// Setup all fields for [HooksMetadataAsset] that are not in
/// [Asset].
void setup() {}

@override
MetadataAssetEncoding get encoding {
final jsonValue = _reader.map$('encoding');
return MetadataAssetEncoding.fromJson(
jsonValue,
path: [...path, 'encoding'],
);
}

@override
List<String> validate() => [...super.validate(), ..._validateEncoding()];

@override
String toString() => 'HooksMetadataAsset($json)';
}

extension HooksMetadataAssetExtension on Asset {
bool get isHooksMetadataAsset => type == 'hooks/metadata';

HooksMetadataAsset get asHooksMetadataAsset =>
HooksMetadataAsset.fromJson(json, path: path);
}

class LinkInput extends HookInput {
LinkInput.fromJson(super.json, {super.path}) : super.fromJson();

@@ -660,6 +817,44 @@ class LinkOutput extends HookOutput {
String toString() => 'LinkOutput($json)';
}

class MetadataAssetEncoding extends JsonObject {
MetadataAssetEncoding.fromJson(super.json, {super.path = const []})
: super.fromJson();

MetadataAssetEncoding({required String key, required Object? value})
: super() {
_key = key;
_value = value;
json.sortOnKey();
}

String get key => _reader.get<String>('key');

set _key(String value) {
json.setOrRemove('key', value);
}

List<String> _validateKey() => _reader.validate<String>('key');

Object? get value => _reader.get<Object?>('value');

set _value(Object? value) {
json.setOrRemove('value', value);
}

List<String> _validateValue() => _reader.validate<Object?>('value');

@override
List<String> validate() => [
...super.validate(),
..._validateKey(),
..._validateValue(),
];

@override
String toString() => 'MetadataAssetEncoding($json)';
}

class JsonObject {
final Map<String, Object?> json;