| // Copyright (c) 2025, 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. |
| |
| // This file is generated, do not edit. |
| // File generated by pkgs/pub_formats/tool/generate.dart. |
| // Must be rerun when pkgs/pub_formats/doc/schema/ is modified. |
| |
| // ignore_for_file: unused_element, public_member_api_docs |
| |
| import 'dart:io'; |
| |
| class DependencySourceSyntax extends JsonObjectSyntax { |
| DependencySourceSyntax.fromJson(super.json, {super.path = const []}) |
| : super.fromJson(); |
| |
| DependencySourceSyntax({super.path = const []}) : super(); |
| |
| @override |
| List<String> validate() => [...super.validate()]; |
| |
| @override |
| String toString() => 'DependencySourceSyntax($json)'; |
| } |
| |
| class EnvironmentSyntax extends JsonObjectSyntax { |
| EnvironmentSyntax.fromJson(super.json, {super.path = const []}) |
| : super.fromJson(); |
| |
| EnvironmentSyntax({ |
| String? flutter, |
| required String sdk, |
| super.path = const [], |
| }) : super() { |
| _flutter = flutter; |
| _sdk = sdk; |
| json.sortOnKey(); |
| } |
| |
| String? get flutter => _reader.get<String?>('flutter'); |
| |
| set _flutter(String? value) { |
| json.setOrRemove('flutter', value); |
| } |
| |
| List<String> _validateFlutter() => _reader.validate<String?>('flutter'); |
| |
| String get sdk => _reader.get<String>('sdk'); |
| |
| set _sdk(String value) { |
| json.setOrRemove('sdk', value); |
| } |
| |
| List<String> _validateSdk() => _reader.validate<String>('sdk'); |
| |
| @override |
| List<String> validate() => [ |
| ...super.validate(), |
| ..._validateFlutter(), |
| ..._validateSdk(), |
| ]; |
| |
| @override |
| String toString() => 'EnvironmentSyntax($json)'; |
| } |
| |
| class GitSyntax extends JsonObjectSyntax { |
| GitSyntax.fromJson(super.json, {super.path = const []}) : super.fromJson(); |
| |
| GitSyntax({ |
| String? path$, |
| String? ref, |
| required String url, |
| super.path = const [], |
| }) : super() { |
| _path$ = path$; |
| _ref = ref; |
| _url = url; |
| json.sortOnKey(); |
| } |
| |
| String? get path$ => _reader.get<String?>('path'); |
| |
| set _path$(String? value) { |
| json.setOrRemove('path', value); |
| } |
| |
| List<String> _validatePath$() => _reader.validate<String?>('path'); |
| |
| String? get ref => _reader.get<String?>('ref'); |
| |
| set _ref(String? value) { |
| json.setOrRemove('ref', value); |
| } |
| |
| List<String> _validateRef() => _reader.validate<String?>('ref'); |
| |
| String get url => _reader.get<String>('url'); |
| |
| set _url(String value) { |
| json.setOrRemove('url', value); |
| } |
| |
| List<String> _validateUrl() => _reader.validate<String>('url'); |
| |
| @override |
| List<String> validate() => [ |
| ...super.validate(), |
| ..._validatePath$(), |
| ..._validateRef(), |
| ..._validateUrl(), |
| ]; |
| |
| @override |
| String toString() => 'GitSyntax($json)'; |
| } |
| |
| class GitDependencySourceSyntax extends DependencySourceSyntax { |
| GitDependencySourceSyntax.fromJson(super.json, {super.path}) |
| : super.fromJson(); |
| |
| GitDependencySourceSyntax({required GitSyntax git, super.path = const []}) |
| : super() { |
| _git = git; |
| json.sortOnKey(); |
| } |
| |
| /// Setup all fields for [GitDependencySourceSyntax] that are not in |
| /// [DependencySourceSyntax]. |
| void setup({required GitSyntax git}) { |
| _git = git; |
| json.sortOnKey(); |
| } |
| |
| GitSyntax get git { |
| final jsonValue = _reader.map$('git'); |
| return GitSyntax.fromJson(jsonValue, path: [...path, 'git']); |
| } |
| |
| set _git(GitSyntax value) { |
| json['git'] = value.json; |
| } |
| |
| List<String> _validateGit() { |
| final mapErrors = _reader.validate<Map<String, Object?>>('git'); |
| if (mapErrors.isNotEmpty) { |
| return mapErrors; |
| } |
| return git.validate(); |
| } |
| |
| @override |
| List<String> validate() => [...super.validate(), ..._validateGit()]; |
| |
| @override |
| String toString() => 'GitDependencySourceSyntax($json)'; |
| } |
| |
| class HooksSyntax extends JsonObjectSyntax { |
| HooksSyntax.fromJson(super.json, {super.path = const []}) : super.fromJson(); |
| |
| HooksSyntax({ |
| Map<String, Map<String, Object?>>? userDefines, |
| super.path = const [], |
| }) : super() { |
| _userDefines = userDefines; |
| json.sortOnKey(); |
| } |
| |
| static final _userDefinesKeyPattern = RegExp(r'^[a-zA-Z_]\w*$'); |
| |
| Map<String, Map<String, Object?>>? get userDefines => |
| _reader.optionalMap<Map<String, Object?>>( |
| 'user_defines', |
| keyPattern: _userDefinesKeyPattern, |
| ); |
| |
| set _userDefines(Map<String, Map<String, Object?>>? value) { |
| _checkArgumentMapKeys(value, keyPattern: _userDefinesKeyPattern); |
| json.setOrRemove('user_defines', value); |
| } |
| |
| List<String> _validateUserDefines() => |
| _reader.validateOptionalMap<Map<String, Object?>>( |
| 'user_defines', |
| keyPattern: _userDefinesKeyPattern, |
| ); |
| |
| @override |
| List<String> validate() => [...super.validate(), ..._validateUserDefines()]; |
| |
| @override |
| String toString() => 'HooksSyntax($json)'; |
| } |
| |
| class HostedDependencySourceSyntax extends DependencySourceSyntax { |
| HostedDependencySourceSyntax.fromJson(super.json, {super.path}) |
| : super.fromJson(); |
| |
| HostedDependencySourceSyntax({ |
| String? hosted, |
| required String version, |
| super.path = const [], |
| }) : super() { |
| _hosted = hosted; |
| _version = version; |
| json.sortOnKey(); |
| } |
| |
| /// Setup all fields for [HostedDependencySourceSyntax] that are not in |
| /// [DependencySourceSyntax]. |
| void setup({required String? hosted, required String version}) { |
| _hosted = hosted; |
| _version = version; |
| json.sortOnKey(); |
| } |
| |
| String? get hosted => _reader.get<String?>('hosted'); |
| |
| set _hosted(String? value) { |
| json.setOrRemove('hosted', value); |
| } |
| |
| List<String> _validateHosted() => _reader.validate<String?>('hosted'); |
| |
| String get version => _reader.get<String>('version'); |
| |
| set _version(String value) { |
| json.setOrRemove('version', value); |
| } |
| |
| List<String> _validateVersion() => _reader.validate<String>('version'); |
| |
| @override |
| List<String> validate() => [ |
| ...super.validate(), |
| ..._validateHosted(), |
| ..._validateVersion(), |
| ]; |
| |
| @override |
| String toString() => 'HostedDependencySourceSyntax($json)'; |
| } |
| |
| class PathDependencySourceSyntax extends DependencySourceSyntax { |
| PathDependencySourceSyntax.fromJson(super.json, {super.path}) |
| : super.fromJson(); |
| |
| PathDependencySourceSyntax({required String path$, super.path = const []}) |
| : super() { |
| _path$ = path$; |
| json.sortOnKey(); |
| } |
| |
| /// Setup all fields for [PathDependencySourceSyntax] that are not in |
| /// [DependencySourceSyntax]. |
| void setup({required String path$}) { |
| _path$ = path$; |
| json.sortOnKey(); |
| } |
| |
| String get path$ => _reader.get<String>('path'); |
| |
| set _path$(String value) { |
| json.setOrRemove('path', value); |
| } |
| |
| List<String> _validatePath$() => _reader.validate<String>('path'); |
| |
| @override |
| List<String> validate() => [...super.validate(), ..._validatePath$()]; |
| |
| @override |
| String toString() => 'PathDependencySourceSyntax($json)'; |
| } |
| |
| class PubspecYamlFileSyntax extends JsonObjectSyntax { |
| PubspecYamlFileSyntax.fromJson(super.json, {super.path = const []}) |
| : super.fromJson(); |
| |
| PubspecYamlFileSyntax({ |
| Map<String, DependencySourceSyntax>? dependencies, |
| Map<String, DependencySourceSyntax>? dependencyOverrides, |
| String? description, |
| Map<String, DependencySourceSyntax>? devDependencies, |
| String? documentation, |
| required EnvironmentSyntax environment, |
| Map<String, String?>? executables, |
| String? homepage, |
| HooksSyntax? hooks, |
| String? issueTracker, |
| required String name, |
| String? publishTo, |
| String? repository, |
| String? version, |
| super.path = const [], |
| }) : super() { |
| this.dependencies = dependencies; |
| this.dependencyOverrides = dependencyOverrides; |
| this.description = description; |
| this.devDependencies = devDependencies; |
| this.documentation = documentation; |
| this.environment = environment; |
| this.executables = executables; |
| this.homepage = homepage; |
| this.hooks = hooks; |
| this.issueTracker = issueTracker; |
| this.name = name; |
| this.publishTo = publishTo; |
| this.repository = repository; |
| this.version = version; |
| json.sortOnKey(); |
| } |
| |
| static final _dependenciesKeyPattern = RegExp(r'^[a-zA-Z_]\w*$'); |
| |
| Map<String, DependencySourceSyntax>? get dependencies { |
| final jsonValue = _reader.optionalMap( |
| 'dependencies', |
| keyPattern: _dependenciesKeyPattern, |
| ); |
| if (jsonValue == null) { |
| return null; |
| } |
| return { |
| for (final MapEntry(:key, :value) in jsonValue.entries) |
| key: DependencySourceSyntax.fromJson( |
| value as Map<String, Object?>, |
| path: [...path, key], |
| ), |
| }; |
| } |
| |
| set dependencies(Map<String, DependencySourceSyntax>? value) { |
| _checkArgumentMapKeys(value, keyPattern: _dependenciesKeyPattern); |
| if (value == null) { |
| json.remove('dependencies'); |
| } else { |
| json['dependencies'] = { |
| for (final MapEntry(:key, :value) in value.entries) key: value.json, |
| }; |
| } |
| json.sortOnKey(); |
| } |
| |
| List<String> validateDependencies() { |
| final mapErrors = _reader.validateOptionalMap( |
| 'dependencies', |
| keyPattern: _dependenciesKeyPattern, |
| ); |
| if (mapErrors.isNotEmpty) { |
| return mapErrors; |
| } |
| final jsonValue = _reader.optionalMap('dependencies'); |
| if (jsonValue == null) { |
| return []; |
| } |
| final result = <String>[]; |
| for (final value in dependencies!.values) { |
| result.addAll(value.validate()); |
| } |
| return result; |
| } |
| |
| static final _dependencyOverridesKeyPattern = RegExp(r'^[a-zA-Z_]\w*$'); |
| |
| Map<String, DependencySourceSyntax>? get dependencyOverrides { |
| final jsonValue = _reader.optionalMap( |
| 'dependency_overrides', |
| keyPattern: _dependencyOverridesKeyPattern, |
| ); |
| if (jsonValue == null) { |
| return null; |
| } |
| return { |
| for (final MapEntry(:key, :value) in jsonValue.entries) |
| key: DependencySourceSyntax.fromJson( |
| value as Map<String, Object?>, |
| path: [...path, key], |
| ), |
| }; |
| } |
| |
| set dependencyOverrides(Map<String, DependencySourceSyntax>? value) { |
| _checkArgumentMapKeys(value, keyPattern: _dependencyOverridesKeyPattern); |
| if (value == null) { |
| json.remove('dependency_overrides'); |
| } else { |
| json['dependency_overrides'] = { |
| for (final MapEntry(:key, :value) in value.entries) key: value.json, |
| }; |
| } |
| json.sortOnKey(); |
| } |
| |
| List<String> validateDependencyOverrides() { |
| final mapErrors = _reader.validateOptionalMap( |
| 'dependency_overrides', |
| keyPattern: _dependencyOverridesKeyPattern, |
| ); |
| if (mapErrors.isNotEmpty) { |
| return mapErrors; |
| } |
| final jsonValue = _reader.optionalMap('dependency_overrides'); |
| if (jsonValue == null) { |
| return []; |
| } |
| final result = <String>[]; |
| for (final value in dependencyOverrides!.values) { |
| result.addAll(value.validate()); |
| } |
| return result; |
| } |
| |
| String? get description => _reader.get<String?>('description'); |
| |
| set description(String? value) { |
| json.setOrRemove('description', value); |
| json.sortOnKey(); |
| } |
| |
| List<String> validateDescription() => |
| _reader.validate<String?>('description'); |
| |
| static final _devDependenciesKeyPattern = RegExp(r'^[a-zA-Z_]\w*$'); |
| |
| Map<String, DependencySourceSyntax>? get devDependencies { |
| final jsonValue = _reader.optionalMap( |
| 'dev_dependencies', |
| keyPattern: _devDependenciesKeyPattern, |
| ); |
| if (jsonValue == null) { |
| return null; |
| } |
| return { |
| for (final MapEntry(:key, :value) in jsonValue.entries) |
| key: DependencySourceSyntax.fromJson( |
| value as Map<String, Object?>, |
| path: [...path, key], |
| ), |
| }; |
| } |
| |
| set devDependencies(Map<String, DependencySourceSyntax>? value) { |
| _checkArgumentMapKeys(value, keyPattern: _devDependenciesKeyPattern); |
| if (value == null) { |
| json.remove('dev_dependencies'); |
| } else { |
| json['dev_dependencies'] = { |
| for (final MapEntry(:key, :value) in value.entries) key: value.json, |
| }; |
| } |
| json.sortOnKey(); |
| } |
| |
| List<String> validateDevDependencies() { |
| final mapErrors = _reader.validateOptionalMap( |
| 'dev_dependencies', |
| keyPattern: _devDependenciesKeyPattern, |
| ); |
| if (mapErrors.isNotEmpty) { |
| return mapErrors; |
| } |
| final jsonValue = _reader.optionalMap('dev_dependencies'); |
| if (jsonValue == null) { |
| return []; |
| } |
| final result = <String>[]; |
| for (final value in devDependencies!.values) { |
| result.addAll(value.validate()); |
| } |
| return result; |
| } |
| |
| String? get documentation => _reader.get<String?>('documentation'); |
| |
| set documentation(String? value) { |
| json.setOrRemove('documentation', value); |
| json.sortOnKey(); |
| } |
| |
| List<String> validateDocumentation() => |
| _reader.validate<String?>('documentation'); |
| |
| EnvironmentSyntax get environment { |
| final jsonValue = _reader.map$('environment'); |
| return EnvironmentSyntax.fromJson( |
| jsonValue, |
| path: [...path, 'environment'], |
| ); |
| } |
| |
| set environment(EnvironmentSyntax value) { |
| json['environment'] = value.json; |
| json.sortOnKey(); |
| } |
| |
| List<String> validateEnvironment() { |
| final mapErrors = _reader.validate<Map<String, Object?>>('environment'); |
| if (mapErrors.isNotEmpty) { |
| return mapErrors; |
| } |
| return environment.validate(); |
| } |
| |
| static final _executablesKeyPattern = RegExp( |
| r'^[a-zA-Z_]\w*(-[a-zA-Z_]\w*)*$', |
| ); |
| |
| static final _executablesValuePattern = RegExp(r'^[^/\\]*$'); |
| |
| Map<String, String?>? get executables { |
| final value = _reader.optionalMap<String?>( |
| 'executables', |
| keyPattern: _executablesKeyPattern, |
| ); |
| if (value == null) { |
| return value; |
| } |
| final valueErrors = _reader.validateMapStringElements( |
| value, |
| 'executables', |
| valuePattern: _executablesValuePattern, |
| ); |
| if (valueErrors.isNotEmpty) { |
| throw FormatException(valueErrors.join('\n')); |
| } |
| return value; |
| } |
| |
| set executables(Map<String, String?>? value) { |
| _checkArgumentMapKeys(value, keyPattern: _executablesKeyPattern); |
| _checkArgumentMapStringElements( |
| value, |
| valuePattern: _executablesValuePattern, |
| ); |
| json.setOrRemove('executables', value); |
| json.sortOnKey(); |
| } |
| |
| List<String> validateExecutables() { |
| final mapErrors = _reader.validateOptionalMap<String?>( |
| 'executables', |
| keyPattern: _executablesKeyPattern, |
| ); |
| if (mapErrors.isNotEmpty) { |
| return mapErrors; |
| } |
| final value = _reader.optionalMap<String?>('executables'); |
| if (value == null) { |
| return []; |
| } |
| return _reader.validateMapStringElements( |
| value, |
| 'executables', |
| valuePattern: _executablesValuePattern, |
| ); |
| } |
| |
| String? get homepage => _reader.get<String?>('homepage'); |
| |
| set homepage(String? value) { |
| json.setOrRemove('homepage', value); |
| json.sortOnKey(); |
| } |
| |
| List<String> validateHomepage() => _reader.validate<String?>('homepage'); |
| |
| HooksSyntax? get hooks { |
| final jsonValue = _reader.optionalMap('hooks'); |
| if (jsonValue == null) return null; |
| return HooksSyntax.fromJson(jsonValue, path: [...path, 'hooks']); |
| } |
| |
| set hooks(HooksSyntax? value) { |
| json.setOrRemove('hooks', value?.json); |
| json.sortOnKey(); |
| } |
| |
| List<String> validateHooks() { |
| final mapErrors = _reader.validate<Map<String, Object?>?>('hooks'); |
| if (mapErrors.isNotEmpty) { |
| return mapErrors; |
| } |
| return hooks?.validate() ?? []; |
| } |
| |
| String? get issueTracker => _reader.get<String?>('issue_tracker'); |
| |
| set issueTracker(String? value) { |
| json.setOrRemove('issue_tracker', value); |
| json.sortOnKey(); |
| } |
| |
| List<String> validateIssueTracker() => |
| _reader.validate<String?>('issue_tracker'); |
| |
| static final _namePattern = RegExp(r'^[a-zA-Z_]\w*$'); |
| |
| String get name => _reader.string('name', _namePattern); |
| |
| set name(String value) { |
| if (!_namePattern.hasMatch(value)) { |
| throw ArgumentError.value( |
| value, |
| 'value', |
| 'Value does not satisfy pattern: ${_namePattern.pattern}.', |
| ); |
| } |
| json.setOrRemove('name', value); |
| json.sortOnKey(); |
| } |
| |
| List<String> validateName() => _reader.validateString('name', _namePattern); |
| |
| String? get publishTo => _reader.get<String?>('publish_to'); |
| |
| set publishTo(String? value) { |
| json.setOrRemove('publish_to', value); |
| json.sortOnKey(); |
| } |
| |
| List<String> validatePublishTo() => _reader.validate<String?>('publish_to'); |
| |
| String? get repository => _reader.get<String?>('repository'); |
| |
| set repository(String? value) { |
| json.setOrRemove('repository', value); |
| json.sortOnKey(); |
| } |
| |
| List<String> validateRepository() => _reader.validate<String?>('repository'); |
| |
| static final _versionPattern = RegExp( |
| r'^[0-9]+\.[0-9]+\.[0-9]+(?:-[a-zA-Z0-9.\-]+)?(?:\+[a-zA-Z0-9.\-]+)?$', |
| ); |
| |
| String? get version => _reader.optionalString('version', _versionPattern); |
| |
| set version(String? value) { |
| if (value != null && !_versionPattern.hasMatch(value)) { |
| throw ArgumentError.value( |
| value, |
| 'value', |
| 'Value does not satisfy pattern: ${_versionPattern.pattern}.', |
| ); |
| } |
| json.setOrRemove('version', value); |
| json.sortOnKey(); |
| } |
| |
| List<String> validateVersion() => |
| _reader.validateOptionalString('version', _versionPattern); |
| |
| @override |
| List<String> validate() => [ |
| ...super.validate(), |
| ...validateDependencies(), |
| ...validateDependencyOverrides(), |
| ...validateDescription(), |
| ...validateDevDependencies(), |
| ...validateDocumentation(), |
| ...validateEnvironment(), |
| ...validateExecutables(), |
| ...validateHomepage(), |
| ...validateHooks(), |
| ...validateIssueTracker(), |
| ...validateName(), |
| ...validatePublishTo(), |
| ...validateRepository(), |
| ...validateVersion(), |
| ]; |
| |
| @override |
| String toString() => 'PubspecYamlFileSyntax($json)'; |
| } |
| |
| class SdkDependencySourceSyntax extends DependencySourceSyntax { |
| SdkDependencySourceSyntax.fromJson(super.json, {super.path}) |
| : super.fromJson(); |
| |
| SdkDependencySourceSyntax({required String sdk, super.path = const []}) |
| : super() { |
| _sdk = sdk; |
| json.sortOnKey(); |
| } |
| |
| /// Setup all fields for [SdkDependencySourceSyntax] that are not in |
| /// [DependencySourceSyntax]. |
| void setup({required String sdk}) { |
| _sdk = sdk; |
| json.sortOnKey(); |
| } |
| |
| String get sdk => _reader.get<String>('sdk'); |
| |
| set _sdk(String value) { |
| json.setOrRemove('sdk', value); |
| } |
| |
| List<String> _validateSdk() => _reader.validate<String>('sdk'); |
| |
| @override |
| List<String> validate() => [...super.validate(), ..._validateSdk()]; |
| |
| @override |
| String toString() => 'SdkDependencySourceSyntax($json)'; |
| } |
| |
| class JsonObjectSyntax { |
| final Map<String, Object?> json; |
| |
| final List<Object> path; |
| |
| _JsonReader get _reader => _JsonReader(json, path); |
| |
| JsonObjectSyntax({this.path = const []}) : json = {}; |
| |
| JsonObjectSyntax.fromJson(this.json, {this.path = const []}); |
| |
| List<String> validate() => []; |
| } |
| |
| class _JsonReader { |
| /// The JSON Object this reader is reading. |
| final Map<String, Object?> json; |
| |
| /// The path traversed by readers of the surrounding JSON. |
| /// |
| /// Contains [String] property keys and [int] indices. |
| /// |
| /// This is used to give more precise error messages. |
| final List<Object> path; |
| |
| _JsonReader(this.json, this.path); |
| |
| T get<T extends Object?>(String key) { |
| final value = json[key]; |
| if (value is T) return value; |
| throwFormatException(value, T, [key]); |
| } |
| |
| List<String> validate<T extends Object?>(String key) { |
| final value = json[key]; |
| if (value is T) return []; |
| return [ |
| errorString(value, T, [key]), |
| ]; |
| } |
| |
| List<T> list<T extends Object?>(String key) => |
| _castList<T>(get<List<Object?>>(key), key); |
| |
| List<String> validateList<T extends Object?>(String key) { |
| final listErrors = validate<List<Object?>>(key); |
| if (listErrors.isNotEmpty) { |
| return listErrors; |
| } |
| return _validateListElements(get<List<Object?>>(key), key); |
| } |
| |
| List<T>? optionalList<T extends Object?>(String key) => |
| switch (get<List<Object?>?>(key)?.cast<T>()) { |
| null => null, |
| final l => _castList<T>(l, key), |
| }; |
| |
| List<String> validateOptionalList<T extends Object?>(String key) { |
| final listErrors = validate<List<Object?>?>(key); |
| if (listErrors.isNotEmpty) { |
| return listErrors; |
| } |
| final list = get<List<Object?>?>(key); |
| if (list == null) { |
| return []; |
| } |
| return _validateListElements(list, key); |
| } |
| |
| /// [List.cast] but with [FormatException]s. |
| List<T> _castList<T extends Object?>(List<Object?> list, String key) { |
| for (final (index, value) in list.indexed) { |
| if (value is! T) { |
| throwFormatException(value, T, [key, index]); |
| } |
| } |
| return list.cast(); |
| } |
| |
| List<String> _validateListElements<T extends Object?>( |
| List<Object?> list, |
| String key, |
| ) { |
| final result = <String>[]; |
| for (final (index, value) in list.indexed) { |
| if (value is! T) { |
| result.add(errorString(value, T, [key, index])); |
| } |
| } |
| return result; |
| } |
| |
| Map<String, T> map$<T extends Object?>(String key, {RegExp? keyPattern}) { |
| final map = get<Map<String, Object?>>(key); |
| final keyErrors = _validateMapKeys(map, key, keyPattern: keyPattern); |
| if (keyErrors.isNotEmpty) { |
| throw FormatException(keyErrors.join('\n')); |
| } |
| return _castMap<T>(map, key); |
| } |
| |
| List<String> validateMap<T extends Object?>( |
| String key, { |
| RegExp? keyPattern, |
| }) { |
| final mapErrors = validate<Map<String, Object?>>(key); |
| if (mapErrors.isNotEmpty) { |
| return mapErrors; |
| } |
| final map = get<Map<String, Object?>>(key); |
| return [ |
| ..._validateMapKeys(map, key, keyPattern: keyPattern), |
| ..._validateMapElements<T>(map, key), |
| ]; |
| } |
| |
| Map<String, T>? optionalMap<T extends Object?>( |
| String key, { |
| RegExp? keyPattern, |
| }) { |
| final map = get<Map<String, Object?>?>(key); |
| if (map == null) return null; |
| final keyErrors = _validateMapKeys(map, key, keyPattern: keyPattern); |
| if (keyErrors.isNotEmpty) { |
| throw FormatException(keyErrors.join('\n')); |
| } |
| return _castMap<T>(map, key); |
| } |
| |
| List<String> validateOptionalMap<T extends Object?>( |
| String key, { |
| RegExp? keyPattern, |
| }) { |
| final mapErrors = validate<Map<String, Object?>?>(key); |
| if (mapErrors.isNotEmpty) { |
| return mapErrors; |
| } |
| final map = get<Map<String, Object?>?>(key); |
| if (map == null) { |
| return []; |
| } |
| return [ |
| ..._validateMapKeys(map, key, keyPattern: keyPattern), |
| ..._validateMapElements<T>(map, key), |
| ]; |
| } |
| |
| /// [Map.cast] but with [FormatException]s. |
| Map<String, T> _castMap<T extends Object?>( |
| Map<String, Object?> map_, |
| String parentKey, |
| ) { |
| for (final MapEntry(:key, :value) in map_.entries) { |
| if (value is! T) { |
| throwFormatException(value, T, [parentKey, key]); |
| } |
| } |
| return map_.cast(); |
| } |
| |
| List<String> _validateMapKeys( |
| Map<String, Object?> map_, |
| String parentKey, { |
| required RegExp? keyPattern, |
| }) { |
| if (keyPattern == null) return []; |
| final result = <String>[]; |
| for (final key in map_.keys) { |
| if (!keyPattern.hasMatch(key)) { |
| result.add( |
| keyErrorString(key, pattern: keyPattern, pathExtension: [parentKey]), |
| ); |
| } |
| } |
| return result; |
| } |
| |
| List<String> _validateMapElements<T extends Object?>( |
| Map<String, Object?> map_, |
| String parentKey, |
| ) { |
| final result = <String>[]; |
| for (final MapEntry(:key, :value) in map_.entries) { |
| if (value is! T) { |
| result.add(errorString(value, T, [parentKey, key])); |
| } |
| } |
| return result; |
| } |
| |
| List<String> validateMapStringElements<T extends Object?>( |
| Map<String, String?> map_, |
| String parentKey, { |
| RegExp? valuePattern, |
| }) { |
| final result = <String>[]; |
| for (final MapEntry(:key, :value) in map_.entries) { |
| if (value != null && |
| valuePattern != null && |
| !valuePattern.hasMatch(value)) { |
| result.add( |
| errorString(value, T, [parentKey, key], pattern: valuePattern), |
| ); |
| } |
| } |
| return result; |
| } |
| |
| String string(String key, RegExp? pattern) { |
| final value = get<String>(key); |
| if (pattern != null && !pattern.hasMatch(value)) { |
| throwFormatException(value, String, [key], pattern: pattern); |
| } |
| return value; |
| } |
| |
| String? optionalString(String key, RegExp? pattern) { |
| final value = get<String?>(key); |
| if (value == null) return null; |
| if (pattern != null && !pattern.hasMatch(value)) { |
| throwFormatException(value, String, [key], pattern: pattern); |
| } |
| return value; |
| } |
| |
| List<String> validateString(String key, RegExp? pattern) { |
| final errors = validate<String>(key); |
| if (errors.isNotEmpty) { |
| return errors; |
| } |
| final value = get<String>(key); |
| if (pattern != null && !pattern.hasMatch(value)) { |
| return [ |
| errorString(value, String, [key], pattern: pattern), |
| ]; |
| } |
| return []; |
| } |
| |
| List<String> validateOptionalString(String key, RegExp? pattern) { |
| final errors = validate<String?>(key); |
| if (errors.isNotEmpty) { |
| return errors; |
| } |
| final value = get<String?>(key); |
| if (value == null) return []; |
| if (pattern != null && !pattern.hasMatch(value)) { |
| return [ |
| errorString(value, String, [key], pattern: pattern), |
| ]; |
| } |
| return []; |
| } |
| |
| List<String>? optionalStringList(String key) => optionalList<String>(key); |
| |
| List<String> validateOptionalStringList(String key) => |
| validateOptionalList<String>(key); |
| |
| List<String> stringList(String key) => list<String>(key); |
| |
| List<String> validateStringList(String key) => validateList<String>(key); |
| |
| Uri path$(String key) => _fileSystemPathToUri(get<String>(key)); |
| |
| List<String> validatePath(String key) => validate<String>(key); |
| |
| Uri? optionalPath(String key) { |
| final value = get<String?>(key); |
| if (value == null) return null; |
| return _fileSystemPathToUri(value); |
| } |
| |
| List<String> validateOptionalPath(String key) => validate<String?>(key); |
| |
| List<Uri>? optionalPathList(String key) { |
| final strings = optionalStringList(key); |
| if (strings == null) { |
| return null; |
| } |
| return [for (final string in strings) _fileSystemPathToUri(string)]; |
| } |
| |
| List<String> validateOptionalPathList(String key) => |
| validateOptionalStringList(key); |
| |
| static Uri _fileSystemPathToUri(String path) { |
| if (path.endsWith(Platform.pathSeparator)) { |
| return Uri.directory(path); |
| } |
| return Uri.file(path); |
| } |
| |
| String _jsonPathToString(List<Object> pathEnding) => |
| [...path, ...pathEnding].join('.'); |
| |
| Never throwFormatException( |
| Object? value, |
| Type expectedType, |
| List<Object> pathExtension, { |
| RegExp? pattern, |
| }) { |
| throw FormatException( |
| errorString(value, expectedType, pathExtension, pattern: pattern), |
| ); |
| } |
| |
| String errorString( |
| Object? value, |
| Type expectedType, |
| List<Object> pathExtension, { |
| RegExp? pattern, |
| }) { |
| final pathString = _jsonPathToString(pathExtension); |
| if (value == null) { |
| return "No value was provided for '$pathString'." |
| ' Expected a $expectedType.'; |
| } |
| final satisfying = pattern == null ? '' : ' satisfying ${pattern.pattern}'; |
| return "Unexpected value '$value' (${value.runtimeType}) for '$pathString'." |
| ' Expected a $expectedType$satisfying.'; |
| } |
| |
| String keyErrorString( |
| String key, { |
| required RegExp pattern, |
| List<Object> pathExtension = const [], |
| }) { |
| final pathString = _jsonPathToString(pathExtension); |
| return "Unexpected key '$key' in '$pathString'." |
| ' Expected a key satisfying ${pattern.pattern}.'; |
| } |
| |
| /// Traverses a JSON path, returns `null` if the path cannot be traversed. |
| Object? tryTraverse(List<String> path) { |
| Object? json = this.json; |
| for (final key in path) { |
| if (json is! Map<String, Object?>) { |
| return null; |
| } |
| json = json[key]; |
| } |
| return json; |
| } |
| } |
| |
| extension on Map<String, Object?> { |
| void setOrRemove(String key, Object? value) { |
| if (value == null) { |
| remove(key); |
| } else { |
| this[key] = value; |
| } |
| } |
| } |
| |
| extension on List<Uri> { |
| List<String> toJson() => [for (final uri in this) uri.toFilePath()]; |
| } |
| |
| extension<K extends Comparable<K>, V extends Object?> on Map<K, V> { |
| void sortOnKey() { |
| final result = <K, V>{}; |
| final keysSorted = keys.toList()..sort(); |
| for (final key in keysSorted) { |
| result[key] = this[key] as V; |
| } |
| clear(); |
| addAll(result); |
| } |
| } |
| |
| void _checkArgumentMapKeys(Map<String, Object?>? map, {RegExp? keyPattern}) { |
| if (map == null) return; |
| if (keyPattern == null) return; |
| for (final key in map.keys) { |
| if (!keyPattern.hasMatch(key)) { |
| throw ArgumentError.value( |
| map, |
| "Unexpected key '$key'." |
| ' Expected a key satisfying ${keyPattern.pattern}.', |
| ); |
| } |
| } |
| } |
| |
| void _checkArgumentMapStringElements( |
| Map<String, String?>? map, { |
| RegExp? valuePattern, |
| }) { |
| if (map == null) return; |
| if (valuePattern == null) return; |
| for (final entry in map.entries) { |
| final value = entry.value; |
| if (value != null && !valuePattern.hasMatch(value)) { |
| throw ArgumentError.value( |
| map, |
| "Unexpected value '$value' under key '${entry.key}'." |
| ' Expected a value satisfying ${valuePattern.pattern}.', |
| ); |
| } |
| } |
| } |