diff --git a/.cspell/misc.txt b/.cspell/misc.txt index 7f0602ed14f..3c3248982bc 100644 --- a/.cspell/misc.txt +++ b/.cspell/misc.txt @@ -15,6 +15,7 @@ postmarket provokateurin punycode STRFTIME +rescan subroutes testexample uncategorized diff --git a/.cspell/nextcloud.txt b/.cspell/nextcloud.txt index e32a0d2a8ab..96907207373 100644 --- a/.cspell/nextcloud.txt +++ b/.cspell/nextcloud.txt @@ -39,6 +39,7 @@ partlycloudy pollinterval productname rainshowers +reindex replyable requesttoken reshares diff --git a/.github/workflows/generate.yaml b/.github/workflows/generate.yaml index 7d0da84ef3f..b03b81a12d5 100644 --- a/.github/workflows/generate.yaml +++ b/.github/workflows/generate.yaml @@ -82,9 +82,13 @@ jobs: - name: Install php uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # v2 with: - php-version: '8.1' + php-version: "8.1" tools: composer + # Use https://github.com/kislyuk/yq + - name: Install yq + run: pip install yq + - name: Generate specs run: | ./tool/generate-specs.sh diff --git a/.gitmodules b/.gitmodules index 379e4395551..bf92b0aeabb 100644 --- a/.gitmodules +++ b/.gitmodules @@ -25,3 +25,6 @@ [submodule "external/nextcloud-drop_account"] path = external/nextcloud-drop_account url = https://framagit.org/framasoft/nextcloud/drop_account.git +[submodule "external/nextcloud-cookbook"] + path = external/nextcloud-cookbook + url = https://github.com/nextcloud/cookbook.git diff --git a/cspell.json b/cspell.json index c46a8079a55..477be61b06d 100644 --- a/cspell.json +++ b/cspell.json @@ -21,7 +21,8 @@ "packages/file_icons/lib/src/data.dart", "packages/neon_lints/lib", "packages/nextcloud/test/fixtures", - "packages/nextcloud_test/docker/static" + "packages/nextcloud_test/docker/static", + "/packages/nextcloud/test/files" ], "dictionaries": [ "bash", diff --git a/external/nextcloud-cookbook b/external/nextcloud-cookbook new file mode 160000 index 00000000000..22f6017ae64 --- /dev/null +++ b/external/nextcloud-cookbook @@ -0,0 +1 @@ +Subproject commit 22f6017ae643011c9beac2705d1c7c7f417b92cd diff --git a/packages/nextcloud/README.md b/packages/nextcloud/README.md index 0cf9356c532..737e944c54e 100644 --- a/packages/nextcloud/README.md +++ b/packages/nextcloud/README.md @@ -56,11 +56,12 @@ These OpenAPI specifications are [generated](https://github.com/nextcloud/openap | Component | Supported versions (1) | |------------------------------------------------------------------------------------|------------------------| | [Server](https://github.com/nextcloud/server) (2) | 28 - 29 | +| [Cookbook app](https://github.com/nextcloud/cookbook) | 0.11.1 | | [News app](https://github.com/nextcloud/news) | 25 | +| [NextPush app](https://codeberg.org/NextPush/uppush) | 1.4 | | [Notes app](https://github.com/nextcloud/notes) | 4.8 - 4.10 | | [Notifications app](https://github.com/nextcloud/notifications) | 28 - 29 | | [Talk app](https://github.com/nextcloud/spreed) | 18 - 19 | -| [NextPush app](https://codeberg.org/NextPush/uppush) | 1.4 | | [User account deletion app](https://framagit.org/framasoft/nextcloud/drop_account) | 2.4 - 2.5 | 1: Other versions might be supported too or at least mostly working, but we do not test against those. diff --git a/packages/nextcloud/lib/cookbook.dart b/packages/nextcloud/lib/cookbook.dart new file mode 100644 index 00000000000..54ba2973b7b --- /dev/null +++ b/packages/nextcloud/lib/cookbook.dart @@ -0,0 +1,14 @@ +// coverage:ignore-file +import 'package:nextcloud/src/api/cookbook.openapi.dart'; +import 'package:nextcloud/src/client.dart'; + +export 'src/api/cookbook.openapi.dart'; +export 'src/helpers/cookbook.dart'; + +// ignore: public_member_api_docs +extension CookbookExtension on NextcloudClient { + static final _cookbook = Expando<$Client>(); + + /// Client for the cookbook APIs + $Client get cookbook => _cookbook[this] ??= $Client.fromClient(this); +} diff --git a/packages/nextcloud/lib/ids.dart b/packages/nextcloud/lib/ids.dart index 4d44c98f697..200371fb111 100644 --- a/packages/nextcloud/lib/ids.dart +++ b/packages/nextcloud/lib/ids.dart @@ -3,6 +3,9 @@ final class AppIDs { /// ID for the comments app. static const comments = 'comments'; + /// ID for the cookbook app. + static const cookbook = 'cookbook'; + /// ID for the core app. static const core = 'core'; diff --git a/packages/nextcloud/lib/src/api/cookbook.openapi.dart b/packages/nextcloud/lib/src/api/cookbook.openapi.dart new file mode 100644 index 00000000000..d2dae7bee8c --- /dev/null +++ b/packages/nextcloud/lib/src/api/cookbook.openapi.dart @@ -0,0 +1,2542 @@ +// Use of this source code is governed by a AGPL-3 license. It can be obtained at `http://www.gnu.org/licenses/agpl-3.0.de.html`. + +// OpenAPI client generated by Dynamite. Do not manually edit this file. + +// ignore_for_file: camel_case_extensions, camel_case_types, cascade_invocations +// ignore_for_file: discarded_futures +// ignore_for_file: no_leading_underscores_for_local_identifiers +// ignore_for_file: non_constant_identifier_names, public_member_api_docs +// ignore_for_file: unreachable_switch_case + +/// Nextcloud cookbook app Version: 0.1.2. +/// +/// This is the public API definition of the [cookbook app](https://github.com/nextcloud/cookbook) for the [nextcloud server](http://nextcloud.com). +/// +/// The total API is separated into two parts: +/// - There is the public API part that can be used from 3rd party apps and scripts. +/// - There is the internal API that is used only by the web app of the cookbook app. This is described here. +/// +/// The internal part is intended only to be used by the internal web app. It uses session based authentication and thus requires a `requesttoken` to protect against CSRF attacks. The generation and updating of these tokens is not part of the app but the regular browser capabilities and the nextcloud web frontend is used here instead. +/// +/// In contrast, the External APIs are intended for use by external services. These endpoints require the user credentials to be present in every request. Thus, no session is created and no cookies or similar needs to be handled. Technically, there is a CORS preflight possible but it is not required for the function of the endpoints. +/// +/// Further contact can be found on the matrix.org server in the room [#nextcloud-cookbook:matrix.org](https://matrix.to/#/#nextcloud-cookbook:matrix.org) for general questions. Additionally, there is [#nextcloud-cookbook-integration:matrix.org](https://matrix.to/#/#nextcloud-cookbook-integration:matrix.org) for questions related to the API and third party integration. Further information on the different versions can be found in [the API overview page](https://nextcloud.github.io/cookbook/dev/api/index). +/// +/// Use of this source code is governed by a AGPL-3 license. +/// It can be obtained at `http://www.gnu.org/licenses/agpl-3.0.de.html`. +library; // ignore_for_file: no_leading_underscores_for_library_prefixes + +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:built_collection/built_collection.dart'; +import 'package:built_value/built_value.dart'; +import 'package:built_value/json_object.dart'; +import 'package:built_value/serializer.dart'; +import 'package:built_value/standard_json_plugin.dart' as _i7; +import 'package:collection/collection.dart' as _i4; +import 'package:dynamite_runtime/built_value.dart' as _i6; +import 'package:dynamite_runtime/http_client.dart' as _i1; +import 'package:http/http.dart' as _i3; +import 'package:meta/meta.dart' as _i2; +import 'package:uri/uri.dart' as _i5; + +part 'cookbook.openapi.g.dart'; + +class $Client extends _i1.DynamiteClient { + /// Creates a new `DynamiteClient` for untagged requests. + $Client( + super.baseURL, { + super.httpClient, + super.authentications, + }); + + /// Creates a new [$Client] from another [client]. + $Client.fromClient(_i1.DynamiteClient client) + : super( + client.baseURL, + httpClient: client.httpClient, + authentications: client.authentications, + ); + + /// Access to the categories of the recipes. + late final $CategoriesClient categories = $CategoriesClient(this); + + /// Other API endpoints. + late final $MiscClient misc = $MiscClient(this); + + /// Everything related to recipes and their usage. + late final $RecipesClient recipes = $RecipesClient(this); + + /// Access to tags/keywords of recipes. + late final $TagsClient tags = $TagsClient(this); +} + +/// Access to the categories of the recipes. +class $CategoriesClient { + /// Creates a new `DynamiteClient` for Categories requests. + $CategoriesClient(this._rootClient); + + final $Client _rootClient; + + /// Builds a serializer to parse the response of [$listCategories_Request]. + @_i2.experimental + _i1.DynamiteSerializer, void> $listCategories_Serializer() => _i1.DynamiteSerializer( + bodyType: const FullType(BuiltList, [FullType(Category)]), + headersType: null, + serializers: _$jsonSerializers, + validStatuses: const {200}, + ); + + /// Get all known categories. + /// + /// Returns a `DynamiteRequest` backing the [listCategories] operation. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: Sucessfully obtained all categories + /// + /// Please note: A category name of `*` indicates the number of recipes with no category associated. + /// + /// See: + /// * [listCategories] for a method executing this request and parsing the response. + /// * [$listCategories_Serializer] for a converter to parse the `Response` from an executed this request. + @_i2.experimental + _i3.Request $listCategories_Request() { + const _path = '/index.php/apps/cookbook/api/v1/categories'; + final _uri = Uri.parse('${_rootClient.baseURL}$_path'); + final _request = _i3.Request('get', _uri); + _request.headers['Accept'] = 'application/json'; +// coverage:ignore-start + final authentication = _i4.IterableExtension(_rootClient.authentications)?.firstWhereOrNull( + (auth) => switch (auth) { + _i1.DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + _request.headers.addAll( + authentication.headers, + ); + } else { + throw Exception('Missing authentication for app_password'); + } + +// coverage:ignore-end + return _request; + } + + /// Get all known categories. + /// + /// Returns a [Future] containing a `DynamiteResponse` with the status code, deserialized body and headers. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: Sucessfully obtained all categories + /// + /// Please note: A category name of `*` indicates the number of recipes with no category associated. + /// + /// See: + /// * [$listCategories_Request] for the request send by this method. + /// * [$listCategories_Serializer] for a converter to parse the `Response` from an executed request. + Future<_i1.DynamiteResponse, void>> listCategories() async { + final _request = $listCategories_Request(); + final _streamedResponse = await _rootClient.httpClient.send(_request); + final _response = await _i3.Response.fromStream(_streamedResponse); + + final _serializer = $listCategories_Serializer(); + return _i1.ResponseConverter, void>(_serializer).convert(_response); + } + + /// Builds a serializer to parse the response of [$recipesInCategory_Request]. + @_i2.experimental + _i1.DynamiteSerializer, void> $recipesInCategory_Serializer() => _i1.DynamiteSerializer( + bodyType: const FullType(BuiltList, [FullType(RecipeStub)]), + headersType: null, + serializers: _$jsonSerializers, + validStatuses: const {200}, + ); + + /// Get all recipes of a certain category. + /// + /// Returns a `DynamiteRequest` backing the [recipesInCategory] operation. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Parameters: + /// * [category] The name of the category to be queried as urlencoded string. + /// + /// Put the string `_` to obtain all recipes with no category. + /// + /// Status codes: + /// * 200: The filtered recipes belonging to the category + /// * 500: An exception was issued. + /// + /// See: + /// * [recipesInCategory] for a method executing this request and parsing the response. + /// * [$recipesInCategory_Serializer] for a converter to parse the `Response` from an executed this request. + @_i2.experimental + _i3.Request $recipesInCategory_Request({required String category}) { + final _parameters = {}; + final __category = _$jsonSerializers.serialize(category, specifiedType: const FullType(String)); + _parameters['category'] = __category; + + final _path = _i5.UriTemplate('/index.php/apps/cookbook/api/v1/category/{category}').expand(_parameters); + final _uri = Uri.parse('${_rootClient.baseURL}$_path'); + final _request = _i3.Request('get', _uri); + _request.headers['Accept'] = 'application/json'; +// coverage:ignore-start + final authentication = _i4.IterableExtension(_rootClient.authentications)?.firstWhereOrNull( + (auth) => switch (auth) { + _i1.DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + _request.headers.addAll( + authentication.headers, + ); + } else { + throw Exception('Missing authentication for app_password'); + } + +// coverage:ignore-end + return _request; + } + + /// Get all recipes of a certain category. + /// + /// Returns a [Future] containing a `DynamiteResponse` with the status code, deserialized body and headers. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Parameters: + /// * [category] The name of the category to be queried as urlencoded string. + /// + /// Put the string `_` to obtain all recipes with no category. + /// + /// Status codes: + /// * 200: The filtered recipes belonging to the category + /// * 500: An exception was issued. + /// + /// See: + /// * [$recipesInCategory_Request] for the request send by this method. + /// * [$recipesInCategory_Serializer] for a converter to parse the `Response` from an executed request. + Future<_i1.DynamiteResponse, void>> recipesInCategory({required String category}) async { + final _request = $recipesInCategory_Request( + category: category, + ); + final _streamedResponse = await _rootClient.httpClient.send(_request); + final _response = await _i3.Response.fromStream(_streamedResponse); + + final _serializer = $recipesInCategory_Serializer(); + return _i1.ResponseConverter, void>(_serializer).convert(_response); + } + + /// Builds a serializer to parse the response of [$renameCategory_Request]. + @_i2.experimental + _i1.DynamiteSerializer $renameCategory_Serializer() => _i1.DynamiteSerializer( + bodyType: const FullType(String), + headersType: null, + serializers: _$jsonSerializers, + validStatuses: const {200}, + ); + + /// Rename a category. + /// + /// Returns a `DynamiteRequest` backing the [renameCategory] operation. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Parameters: + /// * [category] The name of the category to be queried as urlencoded string. + /// + /// Put the string `_` to obtain all recipes with no category. + /// + /// Status codes: + /// * 200: The category was renamed successfully + /// * 400: The new category name was not included during the request. + /// * 500: The renaming did not succeed. + /// + /// See: + /// * [renameCategory] for a method executing this request and parsing the response. + /// * [$renameCategory_Serializer] for a converter to parse the `Response` from an executed this request. + @_i2.experimental + _i3.Request $renameCategory_Request({ + required String category, + required RenameCategoryRequestApplicationJson $body, + }) { + final _parameters = {}; + final __category = _$jsonSerializers.serialize(category, specifiedType: const FullType(String)); + _parameters['category'] = __category; + + final _path = _i5.UriTemplate('/index.php/apps/cookbook/api/v1/category/{category}').expand(_parameters); + final _uri = Uri.parse('${_rootClient.baseURL}$_path'); + final _request = _i3.Request('put', _uri); + _request.headers['Accept'] = 'application/json'; +// coverage:ignore-start + final authentication = _i4.IterableExtension(_rootClient.authentications)?.firstWhereOrNull( + (auth) => switch (auth) { + _i1.DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + _request.headers.addAll( + authentication.headers, + ); + } else { + throw Exception('Missing authentication for app_password'); + } + +// coverage:ignore-end + _request.headers['Content-Type'] = 'application/json'; + _request.body = json.encode( + _$jsonSerializers.serialize($body, specifiedType: const FullType(RenameCategoryRequestApplicationJson)), + ); + return _request; + } + + /// Rename a category. + /// + /// Returns a [Future] containing a `DynamiteResponse` with the status code, deserialized body and headers. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Parameters: + /// * [category] The name of the category to be queried as urlencoded string. + /// + /// Put the string `_` to obtain all recipes with no category. + /// + /// Status codes: + /// * 200: The category was renamed successfully + /// * 400: The new category name was not included during the request. + /// * 500: The renaming did not succeed. + /// + /// See: + /// * [$renameCategory_Request] for the request send by this method. + /// * [$renameCategory_Serializer] for a converter to parse the `Response` from an executed request. + Future<_i1.DynamiteResponse> renameCategory({ + required String category, + required RenameCategoryRequestApplicationJson $body, + }) async { + final _request = $renameCategory_Request( + category: category, + $body: $body, + ); + final _streamedResponse = await _rootClient.httpClient.send(_request); + final _response = await _i3.Response.fromStream(_streamedResponse); + + final _serializer = $renameCategory_Serializer(); + return _i1.ResponseConverter(_serializer).convert(_response); + } +} + +/// Other API endpoints. +class $MiscClient { + /// Creates a new `DynamiteClient` for Misc requests. + $MiscClient(this._rootClient); + + final $Client _rootClient; + + /// Builds a serializer to parse the response of [$version_Request]. + @_i2.experimental + _i1.DynamiteSerializer $version_Serializer() => _i1.DynamiteSerializer( + bodyType: const FullType(Version), + headersType: null, + serializers: _$jsonSerializers, + validStatuses: const {200}, + ); + + /// Get the version of the API endpoint. + /// + /// Returns a `DynamiteRequest` backing the [version] operation. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: API version + /// + /// See: + /// * [version] for a method executing this request and parsing the response. + /// * [$version_Serializer] for a converter to parse the `Response` from an executed this request. + @_i2.experimental + _i3.Request $version_Request() { + const _path = '/index.php/apps/cookbook/api/version'; + final _uri = Uri.parse('${_rootClient.baseURL}$_path'); + final _request = _i3.Request('get', _uri); + _request.headers['Accept'] = 'application/json'; +// coverage:ignore-start + final authentication = _i4.IterableExtension(_rootClient.authentications)?.firstWhereOrNull( + (auth) => switch (auth) { + _i1.DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + _request.headers.addAll( + authentication.headers, + ); + } else { + throw Exception('Missing authentication for app_password'); + } + +// coverage:ignore-end + return _request; + } + + /// Get the version of the API endpoint. + /// + /// Returns a [Future] containing a `DynamiteResponse` with the status code, deserialized body and headers. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: API version + /// + /// See: + /// * [$version_Request] for the request send by this method. + /// * [$version_Serializer] for a converter to parse the `Response` from an executed request. + Future<_i1.DynamiteResponse> version() async { + final _request = $version_Request(); + final _streamedResponse = await _rootClient.httpClient.send(_request); + final _response = await _i3.Response.fromStream(_streamedResponse); + + final _serializer = $version_Serializer(); + return _i1.ResponseConverter(_serializer).convert(_response); + } + + /// Builds a serializer to parse the response of [$reindex_Request]. + @_i2.experimental + _i1.DynamiteSerializer $reindex_Serializer() => _i1.DynamiteSerializer( + bodyType: const FullType(String), + headersType: null, + serializers: _$jsonSerializers, + validStatuses: const {200}, + ); + + /// Trigger a rescan of all recipes into the caching database. + /// + /// Returns a `DynamiteRequest` backing the [reindex] operation. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: The reindex process was done. + /// + /// See: + /// * [reindex] for a method executing this request and parsing the response. + /// * [$reindex_Serializer] for a converter to parse the `Response` from an executed this request. + @_i2.experimental + _i3.Request $reindex_Request() { + const _path = '/index.php/apps/cookbook/api/v1/reindex'; + final _uri = Uri.parse('${_rootClient.baseURL}$_path'); + final _request = _i3.Request('post', _uri); + _request.headers['Accept'] = 'application/json'; +// coverage:ignore-start + final authentication = _i4.IterableExtension(_rootClient.authentications)?.firstWhereOrNull( + (auth) => switch (auth) { + _i1.DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + _request.headers.addAll( + authentication.headers, + ); + } else { + throw Exception('Missing authentication for app_password'); + } + +// coverage:ignore-end + return _request; + } + + /// Trigger a rescan of all recipes into the caching database. + /// + /// Returns a [Future] containing a `DynamiteResponse` with the status code, deserialized body and headers. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: The reindex process was done. + /// + /// See: + /// * [$reindex_Request] for the request send by this method. + /// * [$reindex_Serializer] for a converter to parse the `Response` from an executed request. + Future<_i1.DynamiteResponse> reindex() async { + final _request = $reindex_Request(); + final _streamedResponse = await _rootClient.httpClient.send(_request); + final _response = await _i3.Response.fromStream(_streamedResponse); + + final _serializer = $reindex_Serializer(); + return _i1.ResponseConverter(_serializer).convert(_response); + } + + /// Builds a serializer to parse the response of [$getConfig_Request]. + @_i2.experimental + _i1.DynamiteSerializer $getConfig_Serializer() => _i1.DynamiteSerializer( + bodyType: const FullType(Config), + headersType: null, + serializers: _$jsonSerializers, + validStatuses: const {200}, + ); + + /// Get the current configuration of the app. + /// + /// Returns a `DynamiteRequest` backing the [getConfig] operation. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: The config was read successfully + /// + /// See: + /// * [getConfig] for a method executing this request and parsing the response. + /// * [$getConfig_Serializer] for a converter to parse the `Response` from an executed this request. + @_i2.experimental + _i3.Request $getConfig_Request() { + const _path = '/index.php/apps/cookbook/api/v1/config'; + final _uri = Uri.parse('${_rootClient.baseURL}$_path'); + final _request = _i3.Request('get', _uri); + _request.headers['Accept'] = 'application/json'; +// coverage:ignore-start + final authentication = _i4.IterableExtension(_rootClient.authentications)?.firstWhereOrNull( + (auth) => switch (auth) { + _i1.DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + _request.headers.addAll( + authentication.headers, + ); + } else { + throw Exception('Missing authentication for app_password'); + } + +// coverage:ignore-end + return _request; + } + + /// Get the current configuration of the app. + /// + /// Returns a [Future] containing a `DynamiteResponse` with the status code, deserialized body and headers. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: The config was read successfully + /// + /// See: + /// * [$getConfig_Request] for the request send by this method. + /// * [$getConfig_Serializer] for a converter to parse the `Response` from an executed request. + Future<_i1.DynamiteResponse> getConfig() async { + final _request = $getConfig_Request(); + final _streamedResponse = await _rootClient.httpClient.send(_request); + final _response = await _i3.Response.fromStream(_streamedResponse); + + final _serializer = $getConfig_Serializer(); + return _i1.ResponseConverter(_serializer).convert(_response); + } + + /// Builds a serializer to parse the response of [$setConfig_Request]. + @_i2.experimental + _i1.DynamiteSerializer $setConfig_Serializer() => _i1.DynamiteSerializer( + bodyType: const FullType(String), + headersType: null, + serializers: _$jsonSerializers, + validStatuses: const {200}, + ); + + /// Set the configuration for the current user. + /// + /// Returns a `DynamiteRequest` backing the [setConfig] operation. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: The configuration was successfully saved. + /// + /// See: + /// * [setConfig] for a method executing this request and parsing the response. + /// * [$setConfig_Serializer] for a converter to parse the `Response` from an executed this request. + @_i2.experimental + _i3.Request $setConfig_Request({required Config $body}) { + const _path = '/index.php/apps/cookbook/api/v1/config'; + final _uri = Uri.parse('${_rootClient.baseURL}$_path'); + final _request = _i3.Request('post', _uri); + _request.headers['Accept'] = 'application/json'; +// coverage:ignore-start + final authentication = _i4.IterableExtension(_rootClient.authentications)?.firstWhereOrNull( + (auth) => switch (auth) { + _i1.DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + _request.headers.addAll( + authentication.headers, + ); + } else { + throw Exception('Missing authentication for app_password'); + } + +// coverage:ignore-end + _request.headers['Content-Type'] = 'application/json'; + _request.body = json.encode(_$jsonSerializers.serialize($body, specifiedType: const FullType(Config))); + return _request; + } + + /// Set the configuration for the current user. + /// + /// Returns a [Future] containing a `DynamiteResponse` with the status code, deserialized body and headers. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: The configuration was successfully saved. + /// + /// See: + /// * [$setConfig_Request] for the request send by this method. + /// * [$setConfig_Serializer] for a converter to parse the `Response` from an executed request. + Future<_i1.DynamiteResponse> setConfig({required Config $body}) async { + final _request = $setConfig_Request( + $body: $body, + ); + final _streamedResponse = await _rootClient.httpClient.send(_request); + final _response = await _i3.Response.fromStream(_streamedResponse); + + final _serializer = $setConfig_Serializer(); + return _i1.ResponseConverter(_serializer).convert(_response); + } +} + +/// Everything related to recipes and their usage. +class $RecipesClient { + /// Creates a new `DynamiteClient` for Recipes requests. + $RecipesClient(this._rootClient); + + final $Client _rootClient; + + /// Builds a serializer to parse the response of [$$import_Request]. + @_i2.experimental + _i1.DynamiteSerializer $$import_Serializer() => _i1.DynamiteSerializer( + bodyType: const FullType(Recipe), + headersType: null, + serializers: _$jsonSerializers, + validStatuses: const {200}, + ); + + /// Import a recipe using schema.org metadata from a website. + /// + /// Returns a `DynamiteRequest` backing the [$import] operation. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: Successfully imported recipe + /// * 400: The URL to be imported was not inserted in the request or any other issue was rosen. + /// * 409: There exists a recipe with that name already. Import was aborted. + /// + /// See: + /// * [$import] for a method executing this request and parsing the response. + /// * [$$import_Serializer] for a converter to parse the `Response` from an executed this request. + @_i2.experimental + _i3.Request $$import_Request({required Url $body}) { + const _path = '/index.php/apps/cookbook/api/v1/import'; + final _uri = Uri.parse('${_rootClient.baseURL}$_path'); + final _request = _i3.Request('post', _uri); + _request.headers['Accept'] = 'application/json'; +// coverage:ignore-start + final authentication = _i4.IterableExtension(_rootClient.authentications)?.firstWhereOrNull( + (auth) => switch (auth) { + _i1.DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + _request.headers.addAll( + authentication.headers, + ); + } else { + throw Exception('Missing authentication for app_password'); + } + +// coverage:ignore-end + _request.headers['Content-Type'] = 'application/json'; + _request.body = json.encode(_$jsonSerializers.serialize($body, specifiedType: const FullType(Url))); + return _request; + } + + /// Import a recipe using schema.org metadata from a website. + /// + /// Returns a [Future] containing a `DynamiteResponse` with the status code, deserialized body and headers. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: Successfully imported recipe + /// * 400: The URL to be imported was not inserted in the request or any other issue was rosen. + /// * 409: There exists a recipe with that name already. Import was aborted. + /// + /// See: + /// * [$$import_Request] for the request send by this method. + /// * [$$import_Serializer] for a converter to parse the `Response` from an executed request. + Future<_i1.DynamiteResponse> $import({required Url $body}) async { + final _request = $$import_Request( + $body: $body, + ); + final _streamedResponse = await _rootClient.httpClient.send(_request); + final _response = await _i3.Response.fromStream(_streamedResponse); + + final _serializer = $$import_Serializer(); + return _i1.ResponseConverter(_serializer).convert(_response); + } + + /// Builds a serializer to parse the response of [$getImage_Request]. + @_i2.experimental + _i1.DynamiteSerializer $getImage_Serializer() => _i1.DynamiteSerializer( + bodyType: const FullType(Uint8List), + headersType: null, + serializers: _$jsonSerializers, + validStatuses: const {200}, + ); + + /// Get the main image of a recipe. If no image is stored a fallback image is delivered. + /// + /// Returns a `DynamiteRequest` backing the [getImage] operation. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Parameters: + /// * [id] The id of the recipe to obtain the image for. + /// * [size] The size of the requested image. + /// * `full` - Full resolution image (size full res) * `thumb` - thumbnail of the image (size 250px) * `thumb16` - icon of the image (size 16px). + /// by default the full size image will be returned. + /// + /// + /// Status codes: + /// * 200: Image was obtained and will be in response either as image/jpeg or image/svg+xml + /// * 406: The recipe has no image whose MIME type matches the Accept header + /// + /// See: + /// * [getImage] for a method executing this request and parsing the response. + /// * [$getImage_Serializer] for a converter to parse the `Response` from an executed this request. + @_i2.experimental + _i3.Request $getImage_Request({ + required String id, + GetImageSize? size, + }) { + final _parameters = {}; + final __id = _$jsonSerializers.serialize(id, specifiedType: const FullType(String)); + _parameters['id'] = __id; + + final __size = _$jsonSerializers.serialize(size, specifiedType: const FullType(GetImageSize)); + _parameters['size'] = __size; + + final _path = _i5.UriTemplate('/index.php/apps/cookbook/api/v1/recipes/{id}/image{?size*}').expand(_parameters); + final _uri = Uri.parse('${_rootClient.baseURL}$_path'); + final _request = _i3.Request('get', _uri); + _request.headers['Accept'] = 'image/jpeg,image/svg+xml'; +// coverage:ignore-start + final authentication = _i4.IterableExtension(_rootClient.authentications)?.firstWhereOrNull( + (auth) => switch (auth) { + _i1.DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + _request.headers.addAll( + authentication.headers, + ); + } else { + throw Exception('Missing authentication for app_password'); + } + +// coverage:ignore-end + return _request; + } + + /// Get the main image of a recipe. If no image is stored a fallback image is delivered. + /// + /// Returns a [Future] containing a `DynamiteResponse` with the status code, deserialized body and headers. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Parameters: + /// * [id] The id of the recipe to obtain the image for. + /// * [size] The size of the requested image. + /// * `full` - Full resolution image (size full res) * `thumb` - thumbnail of the image (size 250px) * `thumb16` - icon of the image (size 16px). + /// by default the full size image will be returned. + /// + /// + /// Status codes: + /// * 200: Image was obtained and will be in response either as image/jpeg or image/svg+xml + /// * 406: The recipe has no image whose MIME type matches the Accept header + /// + /// See: + /// * [$getImage_Request] for the request send by this method. + /// * [$getImage_Serializer] for a converter to parse the `Response` from an executed request. + Future<_i1.DynamiteResponse> getImage({ + required String id, + GetImageSize? size, + }) async { + final _request = $getImage_Request( + id: id, + size: size, + ); + final _streamedResponse = await _rootClient.httpClient.send(_request); + final _response = await _i3.Response.fromStream(_streamedResponse); + + final _serializer = $getImage_Serializer(); + return _i1.ResponseConverter(_serializer).convert(_response); + } + + /// Builds a serializer to parse the response of [$search_Request]. + @_i2.experimental + _i1.DynamiteSerializer, void> $search_Serializer() => _i1.DynamiteSerializer( + bodyType: const FullType(BuiltList, [FullType(RecipeStub)]), + headersType: null, + serializers: _$jsonSerializers, + validStatuses: const {200}, + ); + + /// Search for recipes for keywords, tags and categories with the named search string. + /// + /// Returns a `DynamiteRequest` backing the [search] operation. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: The recipes were obtained successfully + /// * 500: An error has been thrown + /// + /// See: + /// * [search] for a method executing this request and parsing the response. + /// * [$search_Serializer] for a converter to parse the `Response` from an executed this request. + @_i2.experimental + _i3.Request $search_Request({required String query}) { + final _parameters = {}; + final __query = _$jsonSerializers.serialize(query, specifiedType: const FullType(String)); + _parameters['query'] = __query; + + final _path = _i5.UriTemplate('/index.php/apps/cookbook/api/v1/search/{query}').expand(_parameters); + final _uri = Uri.parse('${_rootClient.baseURL}$_path'); + final _request = _i3.Request('get', _uri); + _request.headers['Accept'] = 'application/json'; +// coverage:ignore-start + final authentication = _i4.IterableExtension(_rootClient.authentications)?.firstWhereOrNull( + (auth) => switch (auth) { + _i1.DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + _request.headers.addAll( + authentication.headers, + ); + } else { + throw Exception('Missing authentication for app_password'); + } + +// coverage:ignore-end + return _request; + } + + /// Search for recipes for keywords, tags and categories with the named search string. + /// + /// Returns a [Future] containing a `DynamiteResponse` with the status code, deserialized body and headers. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: The recipes were obtained successfully + /// * 500: An error has been thrown + /// + /// See: + /// * [$search_Request] for the request send by this method. + /// * [$search_Serializer] for a converter to parse the `Response` from an executed request. + Future<_i1.DynamiteResponse, void>> search({required String query}) async { + final _request = $search_Request( + query: query, + ); + final _streamedResponse = await _rootClient.httpClient.send(_request); + final _response = await _i3.Response.fromStream(_streamedResponse); + + final _serializer = $search_Serializer(); + return _i1.ResponseConverter, void>(_serializer).convert(_response); + } + + /// Builds a serializer to parse the response of [$listRecipes_Request]. + @_i2.experimental + _i1.DynamiteSerializer, void> $listRecipes_Serializer() => _i1.DynamiteSerializer( + bodyType: const FullType(BuiltList, [FullType(RecipeStub)]), + headersType: null, + serializers: _$jsonSerializers, + validStatuses: const {200}, + ); + + /// Get all recipes in the database. + /// + /// Returns a `DynamiteRequest` backing the [listRecipes] operation. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: Successfully obtained all recipes + /// + /// See: + /// * [listRecipes] for a method executing this request and parsing the response. + /// * [$listRecipes_Serializer] for a converter to parse the `Response` from an executed this request. + @_i2.experimental + _i3.Request $listRecipes_Request() { + const _path = '/index.php/apps/cookbook/api/v1/recipes'; + final _uri = Uri.parse('${_rootClient.baseURL}$_path'); + final _request = _i3.Request('get', _uri); + _request.headers['Accept'] = 'application/json'; +// coverage:ignore-start + final authentication = _i4.IterableExtension(_rootClient.authentications)?.firstWhereOrNull( + (auth) => switch (auth) { + _i1.DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + _request.headers.addAll( + authentication.headers, + ); + } else { + throw Exception('Missing authentication for app_password'); + } + +// coverage:ignore-end + return _request; + } + + /// Get all recipes in the database. + /// + /// Returns a [Future] containing a `DynamiteResponse` with the status code, deserialized body and headers. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: Successfully obtained all recipes + /// + /// See: + /// * [$listRecipes_Request] for the request send by this method. + /// * [$listRecipes_Serializer] for a converter to parse the `Response` from an executed request. + Future<_i1.DynamiteResponse, void>> listRecipes() async { + final _request = $listRecipes_Request(); + final _streamedResponse = await _rootClient.httpClient.send(_request); + final _response = await _i3.Response.fromStream(_streamedResponse); + + final _serializer = $listRecipes_Serializer(); + return _i1.ResponseConverter, void>(_serializer).convert(_response); + } + + /// Builds a serializer to parse the response of [$newRecipe_Request]. + @_i2.experimental + _i1.DynamiteSerializer $newRecipe_Serializer() => _i1.DynamiteSerializer( + bodyType: const FullType(int), + headersType: null, + serializers: _$jsonSerializers, + validStatuses: const {200}, + ); + + /// Create a new recipe. + /// + /// Returns a `DynamiteRequest` backing the [newRecipe] operation. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: Successfully created new recipe + /// * 409: A recipe with the name was already found on the server. No recipe is created. + /// * 422: There was no name in the request given for the recipe. Cannot save the recipe. + /// + /// See: + /// * [newRecipe] for a method executing this request and parsing the response. + /// * [$newRecipe_Serializer] for a converter to parse the `Response` from an executed this request. + @_i2.experimental + _i3.Request $newRecipe_Request({required Recipe $body}) { + const _path = '/index.php/apps/cookbook/api/v1/recipes'; + final _uri = Uri.parse('${_rootClient.baseURL}$_path'); + final _request = _i3.Request('post', _uri); + _request.headers['Accept'] = 'application/json'; +// coverage:ignore-start + final authentication = _i4.IterableExtension(_rootClient.authentications)?.firstWhereOrNull( + (auth) => switch (auth) { + _i1.DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + _request.headers.addAll( + authentication.headers, + ); + } else { + throw Exception('Missing authentication for app_password'); + } + +// coverage:ignore-end + _request.headers['Content-Type'] = 'application/json'; + _request.body = json.encode(_$jsonSerializers.serialize($body, specifiedType: const FullType(Recipe))); + return _request; + } + + /// Create a new recipe. + /// + /// Returns a [Future] containing a `DynamiteResponse` with the status code, deserialized body and headers. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: Successfully created new recipe + /// * 409: A recipe with the name was already found on the server. No recipe is created. + /// * 422: There was no name in the request given for the recipe. Cannot save the recipe. + /// + /// See: + /// * [$newRecipe_Request] for the request send by this method. + /// * [$newRecipe_Serializer] for a converter to parse the `Response` from an executed request. + Future<_i1.DynamiteResponse> newRecipe({required Recipe $body}) async { + final _request = $newRecipe_Request( + $body: $body, + ); + final _streamedResponse = await _rootClient.httpClient.send(_request); + final _response = await _i3.Response.fromStream(_streamedResponse); + + final _serializer = $newRecipe_Serializer(); + return _i1.ResponseConverter(_serializer).convert(_response); + } + + /// Builds a serializer to parse the response of [$recipeDetails_Request]. + @_i2.experimental + _i1.DynamiteSerializer $recipeDetails_Serializer() => _i1.DynamiteSerializer( + bodyType: const FullType(Recipe), + headersType: null, + serializers: _$jsonSerializers, + validStatuses: const {200}, + ); + + /// Get a single recipe from the server. + /// + /// Returns a `DynamiteRequest` backing the [recipeDetails] operation. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: Recipe was sucessfully obtained + /// * 404: The given recipe id was not found + /// + /// See: + /// * [recipeDetails] for a method executing this request and parsing the response. + /// * [$recipeDetails_Serializer] for a converter to parse the `Response` from an executed this request. + @_i2.experimental + _i3.Request $recipeDetails_Request({required String id}) { + final _parameters = {}; + final __id = _$jsonSerializers.serialize(id, specifiedType: const FullType(String)); + _parameters['id'] = __id; + + final _path = _i5.UriTemplate('/index.php/apps/cookbook/api/v1/recipes/{id}').expand(_parameters); + final _uri = Uri.parse('${_rootClient.baseURL}$_path'); + final _request = _i3.Request('get', _uri); + _request.headers['Accept'] = 'application/json'; +// coverage:ignore-start + final authentication = _i4.IterableExtension(_rootClient.authentications)?.firstWhereOrNull( + (auth) => switch (auth) { + _i1.DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + _request.headers.addAll( + authentication.headers, + ); + } else { + throw Exception('Missing authentication for app_password'); + } + +// coverage:ignore-end + return _request; + } + + /// Get a single recipe from the server. + /// + /// Returns a [Future] containing a `DynamiteResponse` with the status code, deserialized body and headers. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: Recipe was sucessfully obtained + /// * 404: The given recipe id was not found + /// + /// See: + /// * [$recipeDetails_Request] for the request send by this method. + /// * [$recipeDetails_Serializer] for a converter to parse the `Response` from an executed request. + Future<_i1.DynamiteResponse> recipeDetails({required String id}) async { + final _request = $recipeDetails_Request( + id: id, + ); + final _streamedResponse = await _rootClient.httpClient.send(_request); + final _response = await _i3.Response.fromStream(_streamedResponse); + + final _serializer = $recipeDetails_Serializer(); + return _i1.ResponseConverter(_serializer).convert(_response); + } + + /// Builds a serializer to parse the response of [$updateRecipe_Request]. + @_i2.experimental + _i1.DynamiteSerializer $updateRecipe_Serializer() => _i1.DynamiteSerializer( + bodyType: const FullType(int), + headersType: null, + serializers: _$jsonSerializers, + validStatuses: const {200}, + ); + + /// Update a recipe. + /// + /// Returns a `DynamiteRequest` backing the [updateRecipe] operation. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: The recipe was sucessfully updated + /// * 422: There was no name in the request given for the recipe. Cannot save the recipe. + /// + /// See: + /// * [updateRecipe] for a method executing this request and parsing the response. + /// * [$updateRecipe_Serializer] for a converter to parse the `Response` from an executed this request. + @_i2.experimental + _i3.Request $updateRecipe_Request({ + required String id, + required Recipe $body, + }) { + final _parameters = {}; + final __id = _$jsonSerializers.serialize(id, specifiedType: const FullType(String)); + _parameters['id'] = __id; + + final _path = _i5.UriTemplate('/index.php/apps/cookbook/api/v1/recipes/{id}').expand(_parameters); + final _uri = Uri.parse('${_rootClient.baseURL}$_path'); + final _request = _i3.Request('put', _uri); + _request.headers['Accept'] = 'application/json'; +// coverage:ignore-start + final authentication = _i4.IterableExtension(_rootClient.authentications)?.firstWhereOrNull( + (auth) => switch (auth) { + _i1.DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + _request.headers.addAll( + authentication.headers, + ); + } else { + throw Exception('Missing authentication for app_password'); + } + +// coverage:ignore-end + _request.headers['Content-Type'] = 'application/json'; + _request.body = json.encode(_$jsonSerializers.serialize($body, specifiedType: const FullType(Recipe))); + return _request; + } + + /// Update a recipe. + /// + /// Returns a [Future] containing a `DynamiteResponse` with the status code, deserialized body and headers. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: The recipe was sucessfully updated + /// * 422: There was no name in the request given for the recipe. Cannot save the recipe. + /// + /// See: + /// * [$updateRecipe_Request] for the request send by this method. + /// * [$updateRecipe_Serializer] for a converter to parse the `Response` from an executed request. + Future<_i1.DynamiteResponse> updateRecipe({ + required String id, + required Recipe $body, + }) async { + final _request = $updateRecipe_Request( + id: id, + $body: $body, + ); + final _streamedResponse = await _rootClient.httpClient.send(_request); + final _response = await _i3.Response.fromStream(_streamedResponse); + + final _serializer = $updateRecipe_Serializer(); + return _i1.ResponseConverter(_serializer).convert(_response); + } + + /// Builds a serializer to parse the response of [$deleteRecipe_Request]. + @_i2.experimental + _i1.DynamiteSerializer $deleteRecipe_Serializer() => _i1.DynamiteSerializer( + bodyType: const FullType(String), + headersType: null, + serializers: _$jsonSerializers, + validStatuses: const {200}, + ); + + /// Delete an existing recipe. + /// + /// Returns a `DynamiteRequest` backing the [deleteRecipe] operation. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: The recipe was deleted successfully + /// * 502: An Exception was thrown + /// + /// See: + /// * [deleteRecipe] for a method executing this request and parsing the response. + /// * [$deleteRecipe_Serializer] for a converter to parse the `Response` from an executed this request. + @_i2.experimental + _i3.Request $deleteRecipe_Request({required String id}) { + final _parameters = {}; + final __id = _$jsonSerializers.serialize(id, specifiedType: const FullType(String)); + _parameters['id'] = __id; + + final _path = _i5.UriTemplate('/index.php/apps/cookbook/api/v1/recipes/{id}').expand(_parameters); + final _uri = Uri.parse('${_rootClient.baseURL}$_path'); + final _request = _i3.Request('delete', _uri); + _request.headers['Accept'] = 'application/json'; +// coverage:ignore-start + final authentication = _i4.IterableExtension(_rootClient.authentications)?.firstWhereOrNull( + (auth) => switch (auth) { + _i1.DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + _request.headers.addAll( + authentication.headers, + ); + } else { + throw Exception('Missing authentication for app_password'); + } + +// coverage:ignore-end + return _request; + } + + /// Delete an existing recipe. + /// + /// Returns a [Future] containing a `DynamiteResponse` with the status code, deserialized body and headers. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: The recipe was deleted successfully + /// * 502: An Exception was thrown + /// + /// See: + /// * [$deleteRecipe_Request] for the request send by this method. + /// * [$deleteRecipe_Serializer] for a converter to parse the `Response` from an executed request. + Future<_i1.DynamiteResponse> deleteRecipe({required String id}) async { + final _request = $deleteRecipe_Request( + id: id, + ); + final _streamedResponse = await _rootClient.httpClient.send(_request); + final _response = await _i3.Response.fromStream(_streamedResponse); + + final _serializer = $deleteRecipe_Serializer(); + return _i1.ResponseConverter(_serializer).convert(_response); + } +} + +/// Access to tags/keywords of recipes. +class $TagsClient { + /// Creates a new `DynamiteClient` for Tags requests. + $TagsClient(this._rootClient); + + final $Client _rootClient; + + /// Builds a serializer to parse the response of [$listKeywords_Request]. + @_i2.experimental + _i1.DynamiteSerializer, void> $listKeywords_Serializer() => _i1.DynamiteSerializer( + bodyType: const FullType(BuiltList, [FullType(Keyword)]), + headersType: null, + serializers: _$jsonSerializers, + validStatuses: const {200}, + ); + + /// Get all known keywords. + /// + /// Returns a `DynamiteRequest` backing the [listKeywords] operation. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: Successfully obtained all keywords + /// + /// See: + /// * [listKeywords] for a method executing this request and parsing the response. + /// * [$listKeywords_Serializer] for a converter to parse the `Response` from an executed this request. + @_i2.experimental + _i3.Request $listKeywords_Request() { + const _path = '/index.php/apps/cookbook/api/v1/keywords'; + final _uri = Uri.parse('${_rootClient.baseURL}$_path'); + final _request = _i3.Request('get', _uri); + _request.headers['Accept'] = 'application/json'; +// coverage:ignore-start + final authentication = _i4.IterableExtension(_rootClient.authentications)?.firstWhereOrNull( + (auth) => switch (auth) { + _i1.DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + _request.headers.addAll( + authentication.headers, + ); + } else { + throw Exception('Missing authentication for app_password'); + } + +// coverage:ignore-end + return _request; + } + + /// Get all known keywords. + /// + /// Returns a [Future] containing a `DynamiteResponse` with the status code, deserialized body and headers. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: Successfully obtained all keywords + /// + /// See: + /// * [$listKeywords_Request] for the request send by this method. + /// * [$listKeywords_Serializer] for a converter to parse the `Response` from an executed request. + Future<_i1.DynamiteResponse, void>> listKeywords() async { + final _request = $listKeywords_Request(); + final _streamedResponse = await _rootClient.httpClient.send(_request); + final _response = await _i3.Response.fromStream(_streamedResponse); + + final _serializer = $listKeywords_Serializer(); + return _i1.ResponseConverter, void>(_serializer).convert(_response); + } + + /// Builds a serializer to parse the response of [$recipesWithKeyword_Request]. + @_i2.experimental + _i1.DynamiteSerializer, void> $recipesWithKeyword_Serializer() => _i1.DynamiteSerializer( + bodyType: const FullType(BuiltList, [FullType(RecipeStub)]), + headersType: null, + serializers: _$jsonSerializers, + validStatuses: const {200}, + ); + + /// Get all recipes associated with certain keywords. + /// + /// Returns a `DynamiteRequest` backing the [recipesWithKeyword] operation. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Parameters: + /// * [keywords] Comma separated list of keywords, urlencoded. + /// + /// Status codes: + /// * 200: Recipes were successfully obtained + /// * 500: An error occured + /// + /// See: + /// * [recipesWithKeyword] for a method executing this request and parsing the response. + /// * [$recipesWithKeyword_Serializer] for a converter to parse the `Response` from an executed this request. + @_i2.experimental + _i3.Request $recipesWithKeyword_Request({required String keywords}) { + final _parameters = {}; + final __keywords = _$jsonSerializers.serialize(keywords, specifiedType: const FullType(String)); + _parameters['keywords'] = __keywords; + + final _path = _i5.UriTemplate('/index.php/apps/cookbook/api/v1/tags/{keywords}').expand(_parameters); + final _uri = Uri.parse('${_rootClient.baseURL}$_path'); + final _request = _i3.Request('get', _uri); + _request.headers['Accept'] = 'application/json'; +// coverage:ignore-start + final authentication = _i4.IterableExtension(_rootClient.authentications)?.firstWhereOrNull( + (auth) => switch (auth) { + _i1.DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + _request.headers.addAll( + authentication.headers, + ); + } else { + throw Exception('Missing authentication for app_password'); + } + +// coverage:ignore-end + return _request; + } + + /// Get all recipes associated with certain keywords. + /// + /// Returns a [Future] containing a `DynamiteResponse` with the status code, deserialized body and headers. + /// Throws a `DynamiteApiException` if the API call does not return an expected status code. + /// + /// Parameters: + /// * [keywords] Comma separated list of keywords, urlencoded. + /// + /// Status codes: + /// * 200: Recipes were successfully obtained + /// * 500: An error occured + /// + /// See: + /// * [$recipesWithKeyword_Request] for the request send by this method. + /// * [$recipesWithKeyword_Serializer] for a converter to parse the `Response` from an executed request. + Future<_i1.DynamiteResponse, void>> recipesWithKeyword({required String keywords}) async { + final _request = $recipesWithKeyword_Request( + keywords: keywords, + ); + final _streamedResponse = await _rootClient.httpClient.send(_request); + final _response = await _i3.Response.fromStream(_streamedResponse); + + final _serializer = $recipesWithKeyword_Serializer(); + return _i1.ResponseConverter, void>(_serializer).convert(_response); + } +} + +/// A single tool for a recipe. A tool is not consumed but only used. +typedef Tool = String; + +/// A single ingredient for a recipe. +typedef Ingredient = String; + +/// An instruction step for processing the recipe. +typedef Instruction = String; + +/// The very basic information of a category. +/// Please note: A category name of `*` indicates the number of recipes with no category associated. +@BuiltValue(instantiable: false) +sealed class $CategoryInformationInterface { + /// The name of the category. + String get name; + + /// The number of recipes in the category. + @BuiltValueField(wireName: 'recipe_count') + int get recipeCount; + + /// Rebuilds the instance. + /// + /// The result is the same as this instance but with [updates] applied. + /// [updates] is a function that takes a builder [$CategoryInformationInterfaceBuilder]. + $CategoryInformationInterface rebuild(void Function($CategoryInformationInterfaceBuilder) updates); + + /// Converts the instance to a builder [$CategoryInformationInterfaceBuilder]. + $CategoryInformationInterfaceBuilder toBuilder(); + @BuiltValueHook(initializeBuilder: true) + static void _defaults($CategoryInformationInterfaceBuilder b) {} + @BuiltValueHook(finalizeBuilder: true) + static void _validate($CategoryInformationInterfaceBuilder b) {} +} + +/// The very basic information of a category. +/// Please note: A category name of `*` indicates the number of recipes with no category associated. +abstract class CategoryInformation + implements $CategoryInformationInterface, Built { + /// Creates a new CategoryInformation object using the builder pattern. + factory CategoryInformation([void Function(CategoryInformationBuilder)? b]) = _$CategoryInformation; + + // coverage:ignore-start + const CategoryInformation._(); + // coverage:ignore-end + + /// Creates a new object from the given [json] data. + /// + /// Use [toJson] to serialize it back into json. + // coverage:ignore-start + factory CategoryInformation.fromJson(Map json) => + _$jsonSerializers.deserializeWith(serializer, json)!; + // coverage:ignore-end + + /// Parses this object into a json like map. + /// + /// Use the fromJson factory to revive it again. + // coverage:ignore-start + Map toJson() => _$jsonSerializers.serializeWith(serializer, this)! as Map; + // coverage:ignore-end + + /// Serializer for CategoryInformation. + static Serializer get serializer => _$categoryInformationSerializer; + + @BuiltValueHook(initializeBuilder: true) + static void _defaults(CategoryInformationBuilder b) { + $CategoryInformationInterface._defaults(b); + } + + @BuiltValueHook(finalizeBuilder: true) + static void _validate(CategoryInformationBuilder b) { + $CategoryInformationInterface._validate(b); + } +} + +/// A category. +@BuiltValue(instantiable: false) +sealed class $CategoryInterface implements $CategoryInformationInterface { + /// Rebuilds the instance. + /// + /// The result is the same as this instance but with [updates] applied. + /// [updates] is a function that takes a builder [$CategoryInterfaceBuilder]. + @override + $CategoryInterface rebuild(void Function($CategoryInterfaceBuilder) updates); + + /// Converts the instance to a builder [$CategoryInterfaceBuilder]. + @override + $CategoryInterfaceBuilder toBuilder(); + @BuiltValueHook(initializeBuilder: true) + static void _defaults($CategoryInterfaceBuilder b) { + $CategoryInformationInterface._defaults(b); + } + + @BuiltValueHook(finalizeBuilder: true) + static void _validate($CategoryInterfaceBuilder b) { + $CategoryInformationInterface._validate(b); + } +} + +/// A category. +abstract class Category implements $CategoryInterface, Built { + /// Creates a new Category object using the builder pattern. + factory Category([void Function(CategoryBuilder)? b]) = _$Category; + + // coverage:ignore-start + const Category._(); + // coverage:ignore-end + + /// Creates a new object from the given [json] data. + /// + /// Use [toJson] to serialize it back into json. + // coverage:ignore-start + factory Category.fromJson(Map json) => _$jsonSerializers.deserializeWith(serializer, json)!; + // coverage:ignore-end + + /// Parses this object into a json like map. + /// + /// Use the fromJson factory to revive it again. + // coverage:ignore-start + Map toJson() => _$jsonSerializers.serializeWith(serializer, this)! as Map; + // coverage:ignore-end + + /// Serializer for Category. + static Serializer get serializer => _$categorySerializer; + + @BuiltValueHook(initializeBuilder: true) + static void _defaults(CategoryBuilder b) { + $CategoryInterface._defaults(b); + } + + @BuiltValueHook(finalizeBuilder: true) + static void _validate(CategoryBuilder b) { + $CategoryInterface._validate(b); + } +} + +/// The very basic information of a recipe. +@BuiltValue(instantiable: false) +sealed class $RecipeStubInformationInterface { + static final _$keywords = _$jsonSerializers.deserialize( + '', + specifiedType: const FullType(String), + )! as String; + + static final _$imageUrl = _$jsonSerializers.deserialize( + '', + specifiedType: const FullType(String), + )! as String; + + static final _$imagePlaceholderUrl = _$jsonSerializers.deserialize( + '', + specifiedType: const FullType(String), + )! as String; + + /// The name of the recipe. + String get name; + + /// A comma-separated list of recipe keywords, can be empty string. + String get keywords; + + /// The date the recipe was created in the app. + String get dateCreated; + + /// The date the recipe was modified lastly in the app. + String? get dateModified; + + /// The URL of the recipe image. + String get imageUrl; + + /// The URL of the placeholder of the recipe image. + String get imagePlaceholderUrl; + + /// Rebuilds the instance. + /// + /// The result is the same as this instance but with [updates] applied. + /// [updates] is a function that takes a builder [$RecipeStubInformationInterfaceBuilder]. + $RecipeStubInformationInterface rebuild(void Function($RecipeStubInformationInterfaceBuilder) updates); + + /// Converts the instance to a builder [$RecipeStubInformationInterfaceBuilder]. + $RecipeStubInformationInterfaceBuilder toBuilder(); + @BuiltValueHook(initializeBuilder: true) + static void _defaults($RecipeStubInformationInterfaceBuilder b) { + b.keywords = _$keywords; + b.imageUrl = _$imageUrl; + b.imagePlaceholderUrl = _$imagePlaceholderUrl; + } + + @BuiltValueHook(finalizeBuilder: true) + static void _validate($RecipeStubInformationInterfaceBuilder b) {} +} + +/// The very basic information of a recipe. +abstract class RecipeStubInformation + implements $RecipeStubInformationInterface, Built { + /// Creates a new RecipeStubInformation object using the builder pattern. + factory RecipeStubInformation([void Function(RecipeStubInformationBuilder)? b]) = _$RecipeStubInformation; + + // coverage:ignore-start + const RecipeStubInformation._(); + // coverage:ignore-end + + /// Creates a new object from the given [json] data. + /// + /// Use [toJson] to serialize it back into json. + // coverage:ignore-start + factory RecipeStubInformation.fromJson(Map json) => + _$jsonSerializers.deserializeWith(serializer, json)!; + // coverage:ignore-end + + /// Parses this object into a json like map. + /// + /// Use the fromJson factory to revive it again. + // coverage:ignore-start + Map toJson() => _$jsonSerializers.serializeWith(serializer, this)! as Map; + // coverage:ignore-end + + /// Serializer for RecipeStubInformation. + static Serializer get serializer => _$recipeStubInformationSerializer; + + @BuiltValueHook(initializeBuilder: true) + static void _defaults(RecipeStubInformationBuilder b) { + $RecipeStubInformationInterface._defaults(b); + } + + @BuiltValueHook(finalizeBuilder: true) + static void _validate(RecipeStubInformationBuilder b) { + $RecipeStubInformationInterface._validate(b); + } +} + +/// A stub of a recipe with some basic information present. +@BuiltValue(instantiable: false) +sealed class $RecipeStubInterface implements $RecipeStubInformationInterface { + /// The index of the recipe. + @Deprecated('') + @BuiltValueField(wireName: 'recipe_id') + int get recipeId; + + /// The identifier of the recipe. + String get id; + + /// Rebuilds the instance. + /// + /// The result is the same as this instance but with [updates] applied. + /// [updates] is a function that takes a builder [$RecipeStubInterfaceBuilder]. + @override + $RecipeStubInterface rebuild(void Function($RecipeStubInterfaceBuilder) updates); + + /// Converts the instance to a builder [$RecipeStubInterfaceBuilder]. + @override + $RecipeStubInterfaceBuilder toBuilder(); + @BuiltValueHook(initializeBuilder: true) + static void _defaults($RecipeStubInterfaceBuilder b) { + $RecipeStubInformationInterface._defaults(b); + } + + @BuiltValueHook(finalizeBuilder: true) + static void _validate($RecipeStubInterfaceBuilder b) { + $RecipeStubInformationInterface._validate(b); + } +} + +/// A stub of a recipe with some basic information present. +abstract class RecipeStub implements $RecipeStubInterface, Built { + /// Creates a new RecipeStub object using the builder pattern. + factory RecipeStub([void Function(RecipeStubBuilder)? b]) = _$RecipeStub; + + // coverage:ignore-start + const RecipeStub._(); + // coverage:ignore-end + + /// Creates a new object from the given [json] data. + /// + /// Use [toJson] to serialize it back into json. + // coverage:ignore-start + factory RecipeStub.fromJson(Map json) => _$jsonSerializers.deserializeWith(serializer, json)!; + // coverage:ignore-end + + /// Parses this object into a json like map. + /// + /// Use the fromJson factory to revive it again. + // coverage:ignore-start + Map toJson() => _$jsonSerializers.serializeWith(serializer, this)! as Map; + // coverage:ignore-end + + /// Serializer for RecipeStub. + static Serializer get serializer => _$recipeStubSerializer; + + @BuiltValueHook(initializeBuilder: true) + static void _defaults(RecipeStubBuilder b) { + $RecipeStubInterface._defaults(b); + } + + @BuiltValueHook(finalizeBuilder: true) + static void _validate(RecipeStubBuilder b) { + $RecipeStubInterface._validate(b); + } +} + +@BuiltValue(instantiable: false) +sealed class $RenameCategoryRequestApplicationJsonInterface { + /// The new name to rename the category to. + String get name; + + /// Rebuilds the instance. + /// + /// The result is the same as this instance but with [updates] applied. + /// [updates] is a function that takes a builder [$RenameCategoryRequestApplicationJsonInterfaceBuilder]. + $RenameCategoryRequestApplicationJsonInterface rebuild( + void Function($RenameCategoryRequestApplicationJsonInterfaceBuilder) updates, + ); + + /// Converts the instance to a builder [$RenameCategoryRequestApplicationJsonInterfaceBuilder]. + $RenameCategoryRequestApplicationJsonInterfaceBuilder toBuilder(); + @BuiltValueHook(initializeBuilder: true) + static void _defaults($RenameCategoryRequestApplicationJsonInterfaceBuilder b) {} + @BuiltValueHook(finalizeBuilder: true) + static void _validate($RenameCategoryRequestApplicationJsonInterfaceBuilder b) {} +} + +abstract class RenameCategoryRequestApplicationJson + implements + $RenameCategoryRequestApplicationJsonInterface, + Built { + /// Creates a new RenameCategoryRequestApplicationJson object using the builder pattern. + factory RenameCategoryRequestApplicationJson([void Function(RenameCategoryRequestApplicationJsonBuilder)? b]) = + _$RenameCategoryRequestApplicationJson; + + // coverage:ignore-start + const RenameCategoryRequestApplicationJson._(); + // coverage:ignore-end + + /// Creates a new object from the given [json] data. + /// + /// Use [toJson] to serialize it back into json. + // coverage:ignore-start + factory RenameCategoryRequestApplicationJson.fromJson(Map json) => + _$jsonSerializers.deserializeWith(serializer, json)!; + // coverage:ignore-end + + /// Parses this object into a json like map. + /// + /// Use the fromJson factory to revive it again. + // coverage:ignore-start + Map toJson() => _$jsonSerializers.serializeWith(serializer, this)! as Map; + // coverage:ignore-end + + /// Serializer for RenameCategoryRequestApplicationJson. + static Serializer get serializer => + _$renameCategoryRequestApplicationJsonSerializer; + + @BuiltValueHook(initializeBuilder: true) + static void _defaults(RenameCategoryRequestApplicationJsonBuilder b) { + $RenameCategoryRequestApplicationJsonInterface._defaults(b); + } + + @BuiltValueHook(finalizeBuilder: true) + static void _validate(RenameCategoryRequestApplicationJsonBuilder b) { + $RenameCategoryRequestApplicationJsonInterface._validate(b); + } +} + +@BuiltValue(instantiable: false) +sealed class $APIVersionInterface { + /// An epoch to cope with bad API versions. + int get epoch; + + /// The major number of the API. + int get major; + + /// The minor number of the API. + int get minor; + + /// Rebuilds the instance. + /// + /// The result is the same as this instance but with [updates] applied. + /// [updates] is a function that takes a builder [$APIVersionInterfaceBuilder]. + $APIVersionInterface rebuild(void Function($APIVersionInterfaceBuilder) updates); + + /// Converts the instance to a builder [$APIVersionInterfaceBuilder]. + $APIVersionInterfaceBuilder toBuilder(); + @BuiltValueHook(initializeBuilder: true) + static void _defaults($APIVersionInterfaceBuilder b) {} + @BuiltValueHook(finalizeBuilder: true) + static void _validate($APIVersionInterfaceBuilder b) {} +} + +abstract class APIVersion implements $APIVersionInterface, Built { + /// Creates a new APIVersion object using the builder pattern. + factory APIVersion([void Function(APIVersionBuilder)? b]) = _$APIVersion; + + // coverage:ignore-start + const APIVersion._(); + // coverage:ignore-end + + /// Creates a new object from the given [json] data. + /// + /// Use [toJson] to serialize it back into json. + // coverage:ignore-start + factory APIVersion.fromJson(Map json) => _$jsonSerializers.deserializeWith(serializer, json)!; + // coverage:ignore-end + + /// Parses this object into a json like map. + /// + /// Use the fromJson factory to revive it again. + // coverage:ignore-start + Map toJson() => _$jsonSerializers.serializeWith(serializer, this)! as Map; + // coverage:ignore-end + + /// Serializer for APIVersion. + static Serializer get serializer => _$aPIVersionSerializer; + + @BuiltValueHook(initializeBuilder: true) + static void _defaults(APIVersionBuilder b) { + $APIVersionInterface._defaults(b); + } + + @BuiltValueHook(finalizeBuilder: true) + static void _validate(APIVersionBuilder b) { + $APIVersionInterface._validate(b); + } +} + +@BuiltValue(instantiable: false) +sealed class $VersionInterface { + @BuiltValueField(wireName: 'cookbook_version') + BuiltList? get cookbookVersion; + @BuiltValueField(wireName: 'api_version') + APIVersion? get apiVersion; + + /// Rebuilds the instance. + /// + /// The result is the same as this instance but with [updates] applied. + /// [updates] is a function that takes a builder [$VersionInterfaceBuilder]. + $VersionInterface rebuild(void Function($VersionInterfaceBuilder) updates); + + /// Converts the instance to a builder [$VersionInterfaceBuilder]. + $VersionInterfaceBuilder toBuilder(); + @BuiltValueHook(initializeBuilder: true) + static void _defaults($VersionInterfaceBuilder b) {} + @BuiltValueHook(finalizeBuilder: true) + static void _validate($VersionInterfaceBuilder b) {} +} + +abstract class Version implements $VersionInterface, Built { + /// Creates a new Version object using the builder pattern. + factory Version([void Function(VersionBuilder)? b]) = _$Version; + + // coverage:ignore-start + const Version._(); + // coverage:ignore-end + + /// Creates a new object from the given [json] data. + /// + /// Use [toJson] to serialize it back into json. + // coverage:ignore-start + factory Version.fromJson(Map json) => _$jsonSerializers.deserializeWith(serializer, json)!; + // coverage:ignore-end + + /// Parses this object into a json like map. + /// + /// Use the fromJson factory to revive it again. + // coverage:ignore-start + Map toJson() => _$jsonSerializers.serializeWith(serializer, this)! as Map; + // coverage:ignore-end + + /// Serializer for Version. + static Serializer get serializer => _$versionSerializer; + + @BuiltValueHook(initializeBuilder: true) + static void _defaults(VersionBuilder b) { + $VersionInterface._defaults(b); + } + + @BuiltValueHook(finalizeBuilder: true) + static void _validate(VersionBuilder b) { + $VersionInterface._validate(b); + } +} + +@BuiltValue(instantiable: false) +sealed class $VisibleInfoBlocksInterface { + /// Show the preparation time in UI. + @BuiltValueField(wireName: 'preparation-time') + bool? get preparationTime; + + /// Show the time required for cooking in the UI. + @BuiltValueField(wireName: 'cooking-time') + bool? get cookingTime; + + /// Show the total time required to carry out the complee recipe. + @BuiltValueField(wireName: 'total-time') + bool? get totalTime; + + /// Show the nutrition information in the UI. + @BuiltValueField(wireName: 'nutrition-information') + bool? get nutritionInformation; + + /// Show the list of tools in the UI. + bool? get tools; + + /// Rebuilds the instance. + /// + /// The result is the same as this instance but with [updates] applied. + /// [updates] is a function that takes a builder [$VisibleInfoBlocksInterfaceBuilder]. + $VisibleInfoBlocksInterface rebuild(void Function($VisibleInfoBlocksInterfaceBuilder) updates); + + /// Converts the instance to a builder [$VisibleInfoBlocksInterfaceBuilder]. + $VisibleInfoBlocksInterfaceBuilder toBuilder(); + @BuiltValueHook(initializeBuilder: true) + static void _defaults($VisibleInfoBlocksInterfaceBuilder b) {} + @BuiltValueHook(finalizeBuilder: true) + static void _validate($VisibleInfoBlocksInterfaceBuilder b) {} +} + +abstract class VisibleInfoBlocks + implements $VisibleInfoBlocksInterface, Built { + /// Creates a new VisibleInfoBlocks object using the builder pattern. + factory VisibleInfoBlocks([void Function(VisibleInfoBlocksBuilder)? b]) = _$VisibleInfoBlocks; + + // coverage:ignore-start + const VisibleInfoBlocks._(); + // coverage:ignore-end + + /// Creates a new object from the given [json] data. + /// + /// Use [toJson] to serialize it back into json. + // coverage:ignore-start + factory VisibleInfoBlocks.fromJson(Map json) => _$jsonSerializers.deserializeWith(serializer, json)!; + // coverage:ignore-end + + /// Parses this object into a json like map. + /// + /// Use the fromJson factory to revive it again. + // coverage:ignore-start + Map toJson() => _$jsonSerializers.serializeWith(serializer, this)! as Map; + // coverage:ignore-end + + /// Serializer for VisibleInfoBlocks. + static Serializer get serializer => _$visibleInfoBlocksSerializer; + + @BuiltValueHook(initializeBuilder: true) + static void _defaults(VisibleInfoBlocksBuilder b) { + $VisibleInfoBlocksInterface._defaults(b); + } + + @BuiltValueHook(finalizeBuilder: true) + static void _validate(VisibleInfoBlocksBuilder b) { + $VisibleInfoBlocksInterface._validate(b); + } +} + +/// An object describing the configuration of the web app. +@BuiltValue(instantiable: false) +sealed class $ConfigInterface { + /// The folder in the user's files that contains the recipes. + String? get folder; + + /// The interval between automatic rescans to rebuild the database cache in minutes. + @BuiltValueField(wireName: 'update_interval') + int? get updateInterval; + + /// True, if the user wished to print the recipe images with the rest of the recipes. + @BuiltValueField(wireName: 'print_image') + bool? get printImage; + VisibleInfoBlocks? get visibleInfoBlocks; + + /// Rebuilds the instance. + /// + /// The result is the same as this instance but with [updates] applied. + /// [updates] is a function that takes a builder [$ConfigInterfaceBuilder]. + $ConfigInterface rebuild(void Function($ConfigInterfaceBuilder) updates); + + /// Converts the instance to a builder [$ConfigInterfaceBuilder]. + $ConfigInterfaceBuilder toBuilder(); + @BuiltValueHook(initializeBuilder: true) + static void _defaults($ConfigInterfaceBuilder b) {} + @BuiltValueHook(finalizeBuilder: true) + static void _validate($ConfigInterfaceBuilder b) {} +} + +/// An object describing the configuration of the web app. +abstract class Config implements $ConfigInterface, Built { + /// Creates a new Config object using the builder pattern. + factory Config([void Function(ConfigBuilder)? b]) = _$Config; + + // coverage:ignore-start + const Config._(); + // coverage:ignore-end + + /// Creates a new object from the given [json] data. + /// + /// Use [toJson] to serialize it back into json. + // coverage:ignore-start + factory Config.fromJson(Map json) => _$jsonSerializers.deserializeWith(serializer, json)!; + // coverage:ignore-end + + /// Parses this object into a json like map. + /// + /// Use the fromJson factory to revive it again. + // coverage:ignore-start + Map toJson() => _$jsonSerializers.serializeWith(serializer, this)! as Map; + // coverage:ignore-end + + /// Serializer for Config. + static Serializer get serializer => _$configSerializer; + + @BuiltValueHook(initializeBuilder: true) + static void _defaults(ConfigBuilder b) { + $ConfigInterface._defaults(b); + } + + @BuiltValueHook(finalizeBuilder: true) + static void _validate(ConfigBuilder b) { + $ConfigInterface._validate(b); + } +} + +@BuiltValue(instantiable: false) +sealed class $UrlInterface { + String get url; + + /// Rebuilds the instance. + /// + /// The result is the same as this instance but with [updates] applied. + /// [updates] is a function that takes a builder [$UrlInterfaceBuilder]. + $UrlInterface rebuild(void Function($UrlInterfaceBuilder) updates); + + /// Converts the instance to a builder [$UrlInterfaceBuilder]. + $UrlInterfaceBuilder toBuilder(); + @BuiltValueHook(initializeBuilder: true) + static void _defaults($UrlInterfaceBuilder b) {} + @BuiltValueHook(finalizeBuilder: true) + static void _validate($UrlInterfaceBuilder b) {} +} + +abstract class Url implements $UrlInterface, Built { + /// Creates a new Url object using the builder pattern. + factory Url([void Function(UrlBuilder)? b]) = _$Url; + + // coverage:ignore-start + const Url._(); + // coverage:ignore-end + + /// Creates a new object from the given [json] data. + /// + /// Use [toJson] to serialize it back into json. + // coverage:ignore-start + factory Url.fromJson(Map json) => _$jsonSerializers.deserializeWith(serializer, json)!; + // coverage:ignore-end + + /// Parses this object into a json like map. + /// + /// Use the fromJson factory to revive it again. + // coverage:ignore-start + Map toJson() => _$jsonSerializers.serializeWith(serializer, this)! as Map; + // coverage:ignore-end + + /// Serializer for Url. + static Serializer get serializer => _$urlSerializer; + + @BuiltValueHook(initializeBuilder: true) + static void _defaults(UrlBuilder b) { + $UrlInterface._defaults(b); + } + + @BuiltValueHook(finalizeBuilder: true) + static void _validate(UrlBuilder b) { + $UrlInterface._validate(b); + } +} + +@BuiltValue(instantiable: false) +sealed class $NutritionInterface { + static final _$type = _$jsonSerializers.deserialize( + 'NutritionInformation', + specifiedType: const FullType(String), + )! as String; + + /// Schema.org object description. + @BuiltValueField(wireName: '@type') + String get type; + + /// The number of calories for the given amount. + String? get calories; + + /// The number of grams of carbohydrates. + String? get carbohydrateContent; + + /// The number of milligrams of cholesterol. + String? get cholesterolContent; + + /// The number of grams of fat. + String? get fatContent; + + /// The number of grams of fiber. + String? get fiberContent; + + /// The number of grams of protein. + String? get proteinContent; + + /// The number of grams of saturated fat. + String? get saturatedFatContent; + + /// The serving size, in terms of the number of volume or mass. + String? get servingSize; + + /// The number of milligrams of sodium. + String? get sodiumContent; + + /// The number of grams of sugar. + String? get sugarContent; + + /// The number of grams of trans fat. + String? get transFatContent; + + /// The number of grams of unsaturated fat. + String? get unsaturatedFatContent; + + /// Rebuilds the instance. + /// + /// The result is the same as this instance but with [updates] applied. + /// [updates] is a function that takes a builder [$NutritionInterfaceBuilder]. + $NutritionInterface rebuild(void Function($NutritionInterfaceBuilder) updates); + + /// Converts the instance to a builder [$NutritionInterfaceBuilder]. + $NutritionInterfaceBuilder toBuilder(); + @BuiltValueHook(initializeBuilder: true) + static void _defaults($NutritionInterfaceBuilder b) { + b.type = _$type; + } + + @BuiltValueHook(finalizeBuilder: true) + static void _validate($NutritionInterfaceBuilder b) {} +} + +abstract class Nutrition implements $NutritionInterface, Built { + /// Creates a new Nutrition object using the builder pattern. + factory Nutrition([void Function(NutritionBuilder)? b]) = _$Nutrition; + + // coverage:ignore-start + const Nutrition._(); + // coverage:ignore-end + + /// Creates a new object from the given [json] data. + /// + /// Use [toJson] to serialize it back into json. + // coverage:ignore-start + factory Nutrition.fromJson(Map json) => _$jsonSerializers.deserializeWith(serializer, json)!; + // coverage:ignore-end + + /// Parses this object into a json like map. + /// + /// Use the fromJson factory to revive it again. + // coverage:ignore-start + Map toJson() => _$jsonSerializers.serializeWith(serializer, this)! as Map; + // coverage:ignore-end + + /// Serializer for Nutrition. + static Serializer get serializer => _$nutritionSerializer; + + @BuiltValueHook(initializeBuilder: true) + static void _defaults(NutritionBuilder b) { + $NutritionInterface._defaults(b); + } + + @BuiltValueHook(finalizeBuilder: true) + static void _validate(NutritionBuilder b) { + $NutritionInterface._validate(b); + } +} + +/// A recipe according to [schema.org](http://schema.org/Recipe). +@BuiltValue(instantiable: false) +sealed class $RecipeInterface implements $RecipeStubInformationInterface { + static final _$type = _$jsonSerializers.deserialize( + 'Recipe', + specifiedType: const FullType(String), + )! as String; + + static final _$description = _$jsonSerializers.deserialize( + '', + specifiedType: const FullType(String), + )! as String; + + static final _$url = _$jsonSerializers.deserialize( + '', + specifiedType: const FullType(String), + )! as String; + + static final _$image = _$jsonSerializers.deserialize( + '', + specifiedType: const FullType(String), + )! as String; + + static final _$recipeYield = _$jsonSerializers.deserialize( + 1, + specifiedType: const FullType(int), + )! as int; + + static final _$recipeCategory = _$jsonSerializers.deserialize( + '', + specifiedType: const FullType(String), + )! as String; + + /// Schema.org object type identifier. + @BuiltValueField(wireName: '@type') + String get type; + + /// The index of the recipe. Note the representation as a string as the representation might change in the future. + String? get id; + + /// The time required for preparation in ISO8601 format. + String? get prepTime; + + /// The time required for cooking in ISO8601 format. + String? get cookTime; + + /// The time required for the complete processing in ISO8601 format. + String? get totalTime; + + /// A description of the recipe or the empty string. + String get description; + + /// The URL the recipe was found at or the empty string. + String get url; + + /// The URL of the original recipe. + String get image; + + /// Number of servings in recipe. + int get recipeYield; + + /// The category of the recipe. + String get recipeCategory; + BuiltList get tool; + BuiltList get recipeIngredient; + BuiltList get recipeInstructions; + Nutrition get nutrition; + + /// Rebuilds the instance. + /// + /// The result is the same as this instance but with [updates] applied. + /// [updates] is a function that takes a builder [$RecipeInterfaceBuilder]. + @override + $RecipeInterface rebuild(void Function($RecipeInterfaceBuilder) updates); + + /// Converts the instance to a builder [$RecipeInterfaceBuilder]. + @override + $RecipeInterfaceBuilder toBuilder(); + @BuiltValueHook(initializeBuilder: true) + static void _defaults($RecipeInterfaceBuilder b) { + $RecipeStubInformationInterface._defaults(b); + b.type = _$type; + b.description = _$description; + b.url = _$url; + b.image = _$image; + b.recipeYield = _$recipeYield; + b.recipeCategory = _$recipeCategory; + } + + @BuiltValueHook(finalizeBuilder: true) + static void _validate($RecipeInterfaceBuilder b) { + $RecipeStubInformationInterface._validate(b); + } +} + +/// A recipe according to [schema.org](http://schema.org/Recipe). +abstract class Recipe implements $RecipeInterface, Built { + /// Creates a new Recipe object using the builder pattern. + factory Recipe([void Function(RecipeBuilder)? b]) = _$Recipe; + + // coverage:ignore-start + const Recipe._(); + // coverage:ignore-end + + /// Creates a new object from the given [json] data. + /// + /// Use [toJson] to serialize it back into json. + // coverage:ignore-start + factory Recipe.fromJson(Map json) => _$jsonSerializers.deserializeWith(serializer, json)!; + // coverage:ignore-end + + /// Parses this object into a json like map. + /// + /// Use the fromJson factory to revive it again. + // coverage:ignore-start + Map toJson() => _$jsonSerializers.serializeWith(serializer, this)! as Map; + // coverage:ignore-end + + /// Serializer for Recipe. + static Serializer get serializer => _$recipeSerializer; + + @BuiltValueHook(initializeBuilder: true) + static void _defaults(RecipeBuilder b) { + $RecipeInterface._defaults(b); + } + + @BuiltValueHook(finalizeBuilder: true) + static void _validate(RecipeBuilder b) { + $RecipeInterface._validate(b); + } +} + +class GetImageSize extends EnumClass { + const GetImageSize._(super.name); + + /// `full` + static const GetImageSize full = _$getImageSizeFull; + + /// `thumb` + static const GetImageSize thumb = _$getImageSizeThumb; + + /// `thumb16` + static const GetImageSize thumb16 = _$getImageSizeThumb16; + + /// Returns a set with all values this enum contains. + // coverage:ignore-start + static BuiltSet get values => _$getImageSizeValues; + // coverage:ignore-end + + /// Returns the enum value associated to the [name]. + static GetImageSize valueOf(String name) => _$valueOfGetImageSize(name); + + /// Returns the serialized value of this enum value. + String get value => _$jsonSerializers.serializeWith(serializer, this)! as String; + + /// Serializer for GetImageSize. + @BuiltValueSerializer(custom: true) + static Serializer get serializer => const _$GetImageSizeSerializer(); +} + +class _$GetImageSizeSerializer implements PrimitiveSerializer { + const _$GetImageSizeSerializer(); + + static const Map _toWire = { + GetImageSize.full: 'full', + GetImageSize.thumb: 'thumb', + GetImageSize.thumb16: 'thumb16', + }; + + static const Map _fromWire = { + 'full': GetImageSize.full, + 'thumb': GetImageSize.thumb, + 'thumb16': GetImageSize.thumb16, + }; + + @override + Iterable get types => const [GetImageSize]; + + @override + String get wireName => 'GetImageSize'; + + @override + Object serialize( + Serializers serializers, + GetImageSize object, { + FullType specifiedType = FullType.unspecified, + }) => + _toWire[object]!; + + @override + GetImageSize deserialize( + Serializers serializers, + Object serialized, { + FullType specifiedType = FullType.unspecified, + }) => + _fromWire[serialized]!; +} + +/// An Keyword. +@BuiltValue(instantiable: false) +sealed class $KeywordInterface implements $CategoryInformationInterface { + /// Rebuilds the instance. + /// + /// The result is the same as this instance but with [updates] applied. + /// [updates] is a function that takes a builder [$KeywordInterfaceBuilder]. + @override + $KeywordInterface rebuild(void Function($KeywordInterfaceBuilder) updates); + + /// Converts the instance to a builder [$KeywordInterfaceBuilder]. + @override + $KeywordInterfaceBuilder toBuilder(); + @BuiltValueHook(initializeBuilder: true) + static void _defaults($KeywordInterfaceBuilder b) { + $CategoryInformationInterface._defaults(b); + } + + @BuiltValueHook(finalizeBuilder: true) + static void _validate($KeywordInterfaceBuilder b) { + $CategoryInformationInterface._validate(b); + } +} + +/// An Keyword. +abstract class Keyword implements $KeywordInterface, Built { + /// Creates a new Keyword object using the builder pattern. + factory Keyword([void Function(KeywordBuilder)? b]) = _$Keyword; + + // coverage:ignore-start + const Keyword._(); + // coverage:ignore-end + + /// Creates a new object from the given [json] data. + /// + /// Use [toJson] to serialize it back into json. + // coverage:ignore-start + factory Keyword.fromJson(Map json) => _$jsonSerializers.deserializeWith(serializer, json)!; + // coverage:ignore-end + + /// Parses this object into a json like map. + /// + /// Use the fromJson factory to revive it again. + // coverage:ignore-start + Map toJson() => _$jsonSerializers.serializeWith(serializer, this)! as Map; + // coverage:ignore-end + + /// Serializer for Keyword. + static Serializer get serializer => _$keywordSerializer; + + @BuiltValueHook(initializeBuilder: true) + static void _defaults(KeywordBuilder b) { + $KeywordInterface._defaults(b); + } + + @BuiltValueHook(finalizeBuilder: true) + static void _validate(KeywordBuilder b) { + $KeywordInterface._validate(b); + } +} + +/// An error description. +@BuiltValue(instantiable: false) +sealed class $ErrorInterface { + /// The error message. + String? get msg; + + /// The file in which the exception was thrown. + String? get file; + + /// The line where the exception is thrown. + int? get line; + + /// Rebuilds the instance. + /// + /// The result is the same as this instance but with [updates] applied. + /// [updates] is a function that takes a builder [$ErrorInterfaceBuilder]. + $ErrorInterface rebuild(void Function($ErrorInterfaceBuilder) updates); + + /// Converts the instance to a builder [$ErrorInterfaceBuilder]. + $ErrorInterfaceBuilder toBuilder(); + @BuiltValueHook(initializeBuilder: true) + static void _defaults($ErrorInterfaceBuilder b) {} + @BuiltValueHook(finalizeBuilder: true) + static void _validate($ErrorInterfaceBuilder b) {} +} + +/// An error description. +abstract class Error implements $ErrorInterface, Built { + /// Creates a new Error object using the builder pattern. + factory Error([void Function(ErrorBuilder)? b]) = _$Error; + + // coverage:ignore-start + const Error._(); + // coverage:ignore-end + + /// Creates a new object from the given [json] data. + /// + /// Use [toJson] to serialize it back into json. + // coverage:ignore-start + factory Error.fromJson(Map json) => _$jsonSerializers.deserializeWith(serializer, json)!; + // coverage:ignore-end + + /// Parses this object into a json like map. + /// + /// Use the fromJson factory to revive it again. + // coverage:ignore-start + Map toJson() => _$jsonSerializers.serializeWith(serializer, this)! as Map; + // coverage:ignore-end + + /// Serializer for Error. + static Serializer get serializer => _$errorSerializer; + + @BuiltValueHook(initializeBuilder: true) + static void _defaults(ErrorBuilder b) { + $ErrorInterface._defaults(b); + } + + @BuiltValueHook(finalizeBuilder: true) + static void _validate(ErrorBuilder b) { + $ErrorInterface._validate(b); + } +} + +// coverage:ignore-start +/// Serializer for all values in this library. +/// +/// Serializes values into the `built_value` wire format. +/// See: [$jsonSerializers] for serializing into json. +@_i2.visibleForTesting +final Serializers $serializers = _$serializers; +final Serializers _$serializers = (Serializers().toBuilder() + ..addBuilderFactory(const FullType(Category), CategoryBuilder.new) + ..add(Category.serializer) + ..addBuilderFactory(const FullType(CategoryInformation), CategoryInformationBuilder.new) + ..add(CategoryInformation.serializer) + ..addBuilderFactory(const FullType(BuiltList, [FullType(Category)]), ListBuilder.new) + ..addBuilderFactory(const FullType(RecipeStub), RecipeStubBuilder.new) + ..add(RecipeStub.serializer) + ..addBuilderFactory(const FullType(RecipeStubInformation), RecipeStubInformationBuilder.new) + ..add(RecipeStubInformation.serializer) + ..addBuilderFactory(const FullType(BuiltList, [FullType(RecipeStub)]), ListBuilder.new) + ..addBuilderFactory( + const FullType(RenameCategoryRequestApplicationJson), + RenameCategoryRequestApplicationJsonBuilder.new, + ) + ..add(RenameCategoryRequestApplicationJson.serializer) + ..addBuilderFactory(const FullType(Version), VersionBuilder.new) + ..add(Version.serializer) + ..addBuilderFactory(const FullType(BuiltList, [FullType(JsonObject)]), ListBuilder.new) + ..addBuilderFactory(const FullType(APIVersion), APIVersionBuilder.new) + ..add(APIVersion.serializer) + ..addBuilderFactory(const FullType(Config), ConfigBuilder.new) + ..add(Config.serializer) + ..addBuilderFactory(const FullType(VisibleInfoBlocks), VisibleInfoBlocksBuilder.new) + ..add(VisibleInfoBlocks.serializer) + ..addBuilderFactory(const FullType(Url), UrlBuilder.new) + ..add(Url.serializer) + ..addBuilderFactory(const FullType(Recipe), RecipeBuilder.new) + ..add(Recipe.serializer) + ..addBuilderFactory(const FullType(BuiltList, [FullType(String)]), ListBuilder.new) + ..addBuilderFactory(const FullType(Nutrition), NutritionBuilder.new) + ..add(Nutrition.serializer) + ..add(GetImageSize.serializer) + ..addBuilderFactory(const FullType(Keyword), KeywordBuilder.new) + ..add(Keyword.serializer) + ..addBuilderFactory(const FullType(BuiltList, [FullType(Keyword)]), ListBuilder.new) + ..addBuilderFactory(const FullType(Error), ErrorBuilder.new) + ..add(Error.serializer) + ..addBuilderFactory(const FullType(BuiltList, [FullType(Recipe)]), ListBuilder.new)) + .build(); + +/// Serializer for all values in this library. +/// +/// Serializes values into the json. Json serialization is more expensive than the built_value wire format. +/// See: [$serializers] for serializing into the `built_value` wire format. +@_i2.visibleForTesting +final Serializers $jsonSerializers = _$jsonSerializers; +final Serializers _$jsonSerializers = (_$serializers.toBuilder() + ..add(_i6.DynamiteDoubleSerializer()) + ..addPlugin(_i7.StandardJsonPlugin()) + ..addPlugin(const _i6.HeaderPlugin()) + ..addPlugin(const _i6.ContentStringPlugin())) + .build(); +// coverage:ignore-end diff --git a/packages/nextcloud/lib/src/api/cookbook.openapi.g.dart b/packages/nextcloud/lib/src/api/cookbook.openapi.g.dart new file mode 100644 index 00000000000..4863cfb1bf4 --- /dev/null +++ b/packages/nextcloud/lib/src/api/cookbook.openapi.g.dart @@ -0,0 +1,3184 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'cookbook.openapi.dart'; + +// ************************************************************************** +// BuiltValueGenerator +// ************************************************************************** + +const GetImageSize _$getImageSizeFull = GetImageSize._('full'); +const GetImageSize _$getImageSizeThumb = GetImageSize._('thumb'); +const GetImageSize _$getImageSizeThumb16 = GetImageSize._('thumb16'); + +GetImageSize _$valueOfGetImageSize(String name) { + switch (name) { + case 'full': + return _$getImageSizeFull; + case 'thumb': + return _$getImageSizeThumb; + case 'thumb16': + return _$getImageSizeThumb16; + default: + throw ArgumentError(name); + } +} + +final BuiltSet _$getImageSizeValues = BuiltSet(const [ + _$getImageSizeFull, + _$getImageSizeThumb, + _$getImageSizeThumb16, +]); + +Serializer _$categoryInformationSerializer = _$CategoryInformationSerializer(); +Serializer _$categorySerializer = _$CategorySerializer(); +Serializer _$recipeStubInformationSerializer = _$RecipeStubInformationSerializer(); +Serializer _$recipeStubSerializer = _$RecipeStubSerializer(); +Serializer _$renameCategoryRequestApplicationJsonSerializer = + _$RenameCategoryRequestApplicationJsonSerializer(); +Serializer _$aPIVersionSerializer = _$APIVersionSerializer(); +Serializer _$versionSerializer = _$VersionSerializer(); +Serializer _$visibleInfoBlocksSerializer = _$VisibleInfoBlocksSerializer(); +Serializer _$configSerializer = _$ConfigSerializer(); +Serializer _$urlSerializer = _$UrlSerializer(); +Serializer _$nutritionSerializer = _$NutritionSerializer(); +Serializer _$recipeSerializer = _$RecipeSerializer(); +Serializer _$keywordSerializer = _$KeywordSerializer(); +Serializer _$errorSerializer = _$ErrorSerializer(); + +class _$CategoryInformationSerializer implements StructuredSerializer { + @override + final Iterable types = const [CategoryInformation, _$CategoryInformation]; + @override + final String wireName = 'CategoryInformation'; + + @override + Iterable serialize(Serializers serializers, CategoryInformation object, + {FullType specifiedType = FullType.unspecified}) { + final result = [ + 'name', + serializers.serialize(object.name, specifiedType: const FullType(String)), + 'recipe_count', + serializers.serialize(object.recipeCount, specifiedType: const FullType(int)), + ]; + + return result; + } + + @override + CategoryInformation deserialize(Serializers serializers, Iterable serialized, + {FullType specifiedType = FullType.unspecified}) { + final result = CategoryInformationBuilder(); + + final iterator = serialized.iterator; + while (iterator.moveNext()) { + final key = iterator.current! as String; + iterator.moveNext(); + final Object? value = iterator.current; + switch (key) { + case 'name': + result.name = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + case 'recipe_count': + result.recipeCount = serializers.deserialize(value, specifiedType: const FullType(int))! as int; + break; + } + } + + return result.build(); + } +} + +class _$CategorySerializer implements StructuredSerializer { + @override + final Iterable types = const [Category, _$Category]; + @override + final String wireName = 'Category'; + + @override + Iterable serialize(Serializers serializers, Category object, + {FullType specifiedType = FullType.unspecified}) { + final result = [ + 'name', + serializers.serialize(object.name, specifiedType: const FullType(String)), + 'recipe_count', + serializers.serialize(object.recipeCount, specifiedType: const FullType(int)), + ]; + + return result; + } + + @override + Category deserialize(Serializers serializers, Iterable serialized, + {FullType specifiedType = FullType.unspecified}) { + final result = CategoryBuilder(); + + final iterator = serialized.iterator; + while (iterator.moveNext()) { + final key = iterator.current! as String; + iterator.moveNext(); + final Object? value = iterator.current; + switch (key) { + case 'name': + result.name = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + case 'recipe_count': + result.recipeCount = serializers.deserialize(value, specifiedType: const FullType(int))! as int; + break; + } + } + + return result.build(); + } +} + +class _$RecipeStubInformationSerializer implements StructuredSerializer { + @override + final Iterable types = const [RecipeStubInformation, _$RecipeStubInformation]; + @override + final String wireName = 'RecipeStubInformation'; + + @override + Iterable serialize(Serializers serializers, RecipeStubInformation object, + {FullType specifiedType = FullType.unspecified}) { + final result = [ + 'name', + serializers.serialize(object.name, specifiedType: const FullType(String)), + 'keywords', + serializers.serialize(object.keywords, specifiedType: const FullType(String)), + 'dateCreated', + serializers.serialize(object.dateCreated, specifiedType: const FullType(String)), + 'imageUrl', + serializers.serialize(object.imageUrl, specifiedType: const FullType(String)), + 'imagePlaceholderUrl', + serializers.serialize(object.imagePlaceholderUrl, specifiedType: const FullType(String)), + ]; + Object? value; + value = object.dateModified; + if (value != null) { + result + ..add('dateModified') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + return result; + } + + @override + RecipeStubInformation deserialize(Serializers serializers, Iterable serialized, + {FullType specifiedType = FullType.unspecified}) { + final result = RecipeStubInformationBuilder(); + + final iterator = serialized.iterator; + while (iterator.moveNext()) { + final key = iterator.current! as String; + iterator.moveNext(); + final Object? value = iterator.current; + switch (key) { + case 'name': + result.name = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + case 'keywords': + result.keywords = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + case 'dateCreated': + result.dateCreated = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + case 'dateModified': + result.dateModified = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'imageUrl': + result.imageUrl = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + case 'imagePlaceholderUrl': + result.imagePlaceholderUrl = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + } + } + + return result.build(); + } +} + +class _$RecipeStubSerializer implements StructuredSerializer { + @override + final Iterable types = const [RecipeStub, _$RecipeStub]; + @override + final String wireName = 'RecipeStub'; + + @override + Iterable serialize(Serializers serializers, RecipeStub object, + {FullType specifiedType = FullType.unspecified}) { + final result = [ + 'recipe_id', + serializers.serialize(object.recipeId, specifiedType: const FullType(int)), + 'id', + serializers.serialize(object.id, specifiedType: const FullType(String)), + 'name', + serializers.serialize(object.name, specifiedType: const FullType(String)), + 'keywords', + serializers.serialize(object.keywords, specifiedType: const FullType(String)), + 'dateCreated', + serializers.serialize(object.dateCreated, specifiedType: const FullType(String)), + 'imageUrl', + serializers.serialize(object.imageUrl, specifiedType: const FullType(String)), + 'imagePlaceholderUrl', + serializers.serialize(object.imagePlaceholderUrl, specifiedType: const FullType(String)), + ]; + Object? value; + value = object.dateModified; + if (value != null) { + result + ..add('dateModified') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + return result; + } + + @override + RecipeStub deserialize(Serializers serializers, Iterable serialized, + {FullType specifiedType = FullType.unspecified}) { + final result = RecipeStubBuilder(); + + final iterator = serialized.iterator; + while (iterator.moveNext()) { + final key = iterator.current! as String; + iterator.moveNext(); + final Object? value = iterator.current; + switch (key) { + case 'recipe_id': + result.recipeId = serializers.deserialize(value, specifiedType: const FullType(int))! as int; + break; + case 'id': + result.id = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + case 'name': + result.name = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + case 'keywords': + result.keywords = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + case 'dateCreated': + result.dateCreated = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + case 'dateModified': + result.dateModified = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'imageUrl': + result.imageUrl = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + case 'imagePlaceholderUrl': + result.imagePlaceholderUrl = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + } + } + + return result.build(); + } +} + +class _$RenameCategoryRequestApplicationJsonSerializer + implements StructuredSerializer { + @override + final Iterable types = const [RenameCategoryRequestApplicationJson, _$RenameCategoryRequestApplicationJson]; + @override + final String wireName = 'RenameCategoryRequestApplicationJson'; + + @override + Iterable serialize(Serializers serializers, RenameCategoryRequestApplicationJson object, + {FullType specifiedType = FullType.unspecified}) { + final result = [ + 'name', + serializers.serialize(object.name, specifiedType: const FullType(String)), + ]; + + return result; + } + + @override + RenameCategoryRequestApplicationJson deserialize(Serializers serializers, Iterable serialized, + {FullType specifiedType = FullType.unspecified}) { + final result = RenameCategoryRequestApplicationJsonBuilder(); + + final iterator = serialized.iterator; + while (iterator.moveNext()) { + final key = iterator.current! as String; + iterator.moveNext(); + final Object? value = iterator.current; + switch (key) { + case 'name': + result.name = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + } + } + + return result.build(); + } +} + +class _$APIVersionSerializer implements StructuredSerializer { + @override + final Iterable types = const [APIVersion, _$APIVersion]; + @override + final String wireName = 'APIVersion'; + + @override + Iterable serialize(Serializers serializers, APIVersion object, + {FullType specifiedType = FullType.unspecified}) { + final result = [ + 'epoch', + serializers.serialize(object.epoch, specifiedType: const FullType(int)), + 'major', + serializers.serialize(object.major, specifiedType: const FullType(int)), + 'minor', + serializers.serialize(object.minor, specifiedType: const FullType(int)), + ]; + + return result; + } + + @override + APIVersion deserialize(Serializers serializers, Iterable serialized, + {FullType specifiedType = FullType.unspecified}) { + final result = APIVersionBuilder(); + + final iterator = serialized.iterator; + while (iterator.moveNext()) { + final key = iterator.current! as String; + iterator.moveNext(); + final Object? value = iterator.current; + switch (key) { + case 'epoch': + result.epoch = serializers.deserialize(value, specifiedType: const FullType(int))! as int; + break; + case 'major': + result.major = serializers.deserialize(value, specifiedType: const FullType(int))! as int; + break; + case 'minor': + result.minor = serializers.deserialize(value, specifiedType: const FullType(int))! as int; + break; + } + } + + return result.build(); + } +} + +class _$VersionSerializer implements StructuredSerializer { + @override + final Iterable types = const [Version, _$Version]; + @override + final String wireName = 'Version'; + + @override + Iterable serialize(Serializers serializers, Version object, + {FullType specifiedType = FullType.unspecified}) { + final result = []; + Object? value; + value = object.cookbookVersion; + if (value != null) { + result + ..add('cookbook_version') + ..add(serializers.serialize(value, specifiedType: const FullType(BuiltList, [FullType(JsonObject)]))); + } + value = object.apiVersion; + if (value != null) { + result + ..add('api_version') + ..add(serializers.serialize(value, specifiedType: const FullType(APIVersion))); + } + return result; + } + + @override + Version deserialize(Serializers serializers, Iterable serialized, + {FullType specifiedType = FullType.unspecified}) { + final result = VersionBuilder(); + + final iterator = serialized.iterator; + while (iterator.moveNext()) { + final key = iterator.current! as String; + iterator.moveNext(); + final Object? value = iterator.current; + switch (key) { + case 'cookbook_version': + result.cookbookVersion.replace(serializers.deserialize(value, + specifiedType: const FullType(BuiltList, [FullType(JsonObject)]))! as BuiltList); + break; + case 'api_version': + result.apiVersion + .replace(serializers.deserialize(value, specifiedType: const FullType(APIVersion))! as APIVersion); + break; + } + } + + return result.build(); + } +} + +class _$VisibleInfoBlocksSerializer implements StructuredSerializer { + @override + final Iterable types = const [VisibleInfoBlocks, _$VisibleInfoBlocks]; + @override + final String wireName = 'VisibleInfoBlocks'; + + @override + Iterable serialize(Serializers serializers, VisibleInfoBlocks object, + {FullType specifiedType = FullType.unspecified}) { + final result = []; + Object? value; + value = object.preparationTime; + if (value != null) { + result + ..add('preparation-time') + ..add(serializers.serialize(value, specifiedType: const FullType(bool))); + } + value = object.cookingTime; + if (value != null) { + result + ..add('cooking-time') + ..add(serializers.serialize(value, specifiedType: const FullType(bool))); + } + value = object.totalTime; + if (value != null) { + result + ..add('total-time') + ..add(serializers.serialize(value, specifiedType: const FullType(bool))); + } + value = object.nutritionInformation; + if (value != null) { + result + ..add('nutrition-information') + ..add(serializers.serialize(value, specifiedType: const FullType(bool))); + } + value = object.tools; + if (value != null) { + result + ..add('tools') + ..add(serializers.serialize(value, specifiedType: const FullType(bool))); + } + return result; + } + + @override + VisibleInfoBlocks deserialize(Serializers serializers, Iterable serialized, + {FullType specifiedType = FullType.unspecified}) { + final result = VisibleInfoBlocksBuilder(); + + final iterator = serialized.iterator; + while (iterator.moveNext()) { + final key = iterator.current! as String; + iterator.moveNext(); + final Object? value = iterator.current; + switch (key) { + case 'preparation-time': + result.preparationTime = serializers.deserialize(value, specifiedType: const FullType(bool)) as bool?; + break; + case 'cooking-time': + result.cookingTime = serializers.deserialize(value, specifiedType: const FullType(bool)) as bool?; + break; + case 'total-time': + result.totalTime = serializers.deserialize(value, specifiedType: const FullType(bool)) as bool?; + break; + case 'nutrition-information': + result.nutritionInformation = serializers.deserialize(value, specifiedType: const FullType(bool)) as bool?; + break; + case 'tools': + result.tools = serializers.deserialize(value, specifiedType: const FullType(bool)) as bool?; + break; + } + } + + return result.build(); + } +} + +class _$ConfigSerializer implements StructuredSerializer { + @override + final Iterable types = const [Config, _$Config]; + @override + final String wireName = 'Config'; + + @override + Iterable serialize(Serializers serializers, Config object, {FullType specifiedType = FullType.unspecified}) { + final result = []; + Object? value; + value = object.folder; + if (value != null) { + result + ..add('folder') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.updateInterval; + if (value != null) { + result + ..add('update_interval') + ..add(serializers.serialize(value, specifiedType: const FullType(int))); + } + value = object.printImage; + if (value != null) { + result + ..add('print_image') + ..add(serializers.serialize(value, specifiedType: const FullType(bool))); + } + value = object.visibleInfoBlocks; + if (value != null) { + result + ..add('visibleInfoBlocks') + ..add(serializers.serialize(value, specifiedType: const FullType(VisibleInfoBlocks))); + } + return result; + } + + @override + Config deserialize(Serializers serializers, Iterable serialized, + {FullType specifiedType = FullType.unspecified}) { + final result = ConfigBuilder(); + + final iterator = serialized.iterator; + while (iterator.moveNext()) { + final key = iterator.current! as String; + iterator.moveNext(); + final Object? value = iterator.current; + switch (key) { + case 'folder': + result.folder = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'update_interval': + result.updateInterval = serializers.deserialize(value, specifiedType: const FullType(int)) as int?; + break; + case 'print_image': + result.printImage = serializers.deserialize(value, specifiedType: const FullType(bool)) as bool?; + break; + case 'visibleInfoBlocks': + result.visibleInfoBlocks.replace( + serializers.deserialize(value, specifiedType: const FullType(VisibleInfoBlocks))! as VisibleInfoBlocks); + break; + } + } + + return result.build(); + } +} + +class _$UrlSerializer implements StructuredSerializer { + @override + final Iterable types = const [Url, _$Url]; + @override + final String wireName = 'Url'; + + @override + Iterable serialize(Serializers serializers, Url object, {FullType specifiedType = FullType.unspecified}) { + final result = [ + 'url', + serializers.serialize(object.url, specifiedType: const FullType(String)), + ]; + + return result; + } + + @override + Url deserialize(Serializers serializers, Iterable serialized, + {FullType specifiedType = FullType.unspecified}) { + final result = UrlBuilder(); + + final iterator = serialized.iterator; + while (iterator.moveNext()) { + final key = iterator.current! as String; + iterator.moveNext(); + final Object? value = iterator.current; + switch (key) { + case 'url': + result.url = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + } + } + + return result.build(); + } +} + +class _$NutritionSerializer implements StructuredSerializer { + @override + final Iterable types = const [Nutrition, _$Nutrition]; + @override + final String wireName = 'Nutrition'; + + @override + Iterable serialize(Serializers serializers, Nutrition object, + {FullType specifiedType = FullType.unspecified}) { + final result = [ + '@type', + serializers.serialize(object.type, specifiedType: const FullType(String)), + ]; + Object? value; + value = object.calories; + if (value != null) { + result + ..add('calories') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.carbohydrateContent; + if (value != null) { + result + ..add('carbohydrateContent') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.cholesterolContent; + if (value != null) { + result + ..add('cholesterolContent') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.fatContent; + if (value != null) { + result + ..add('fatContent') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.fiberContent; + if (value != null) { + result + ..add('fiberContent') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.proteinContent; + if (value != null) { + result + ..add('proteinContent') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.saturatedFatContent; + if (value != null) { + result + ..add('saturatedFatContent') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.servingSize; + if (value != null) { + result + ..add('servingSize') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.sodiumContent; + if (value != null) { + result + ..add('sodiumContent') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.sugarContent; + if (value != null) { + result + ..add('sugarContent') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.transFatContent; + if (value != null) { + result + ..add('transFatContent') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.unsaturatedFatContent; + if (value != null) { + result + ..add('unsaturatedFatContent') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + return result; + } + + @override + Nutrition deserialize(Serializers serializers, Iterable serialized, + {FullType specifiedType = FullType.unspecified}) { + final result = NutritionBuilder(); + + final iterator = serialized.iterator; + while (iterator.moveNext()) { + final key = iterator.current! as String; + iterator.moveNext(); + final Object? value = iterator.current; + switch (key) { + case '@type': + result.type = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + case 'calories': + result.calories = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'carbohydrateContent': + result.carbohydrateContent = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'cholesterolContent': + result.cholesterolContent = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'fatContent': + result.fatContent = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'fiberContent': + result.fiberContent = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'proteinContent': + result.proteinContent = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'saturatedFatContent': + result.saturatedFatContent = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'servingSize': + result.servingSize = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'sodiumContent': + result.sodiumContent = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'sugarContent': + result.sugarContent = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'transFatContent': + result.transFatContent = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'unsaturatedFatContent': + result.unsaturatedFatContent = + serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + } + } + + return result.build(); + } +} + +class _$RecipeSerializer implements StructuredSerializer { + @override + final Iterable types = const [Recipe, _$Recipe]; + @override + final String wireName = 'Recipe'; + + @override + Iterable serialize(Serializers serializers, Recipe object, {FullType specifiedType = FullType.unspecified}) { + final result = [ + '@type', + serializers.serialize(object.type, specifiedType: const FullType(String)), + 'description', + serializers.serialize(object.description, specifiedType: const FullType(String)), + 'url', + serializers.serialize(object.url, specifiedType: const FullType(String)), + 'image', + serializers.serialize(object.image, specifiedType: const FullType(String)), + 'recipeYield', + serializers.serialize(object.recipeYield, specifiedType: const FullType(int)), + 'recipeCategory', + serializers.serialize(object.recipeCategory, specifiedType: const FullType(String)), + 'tool', + serializers.serialize(object.tool, specifiedType: const FullType(BuiltList, [FullType(String)])), + 'recipeIngredient', + serializers.serialize(object.recipeIngredient, specifiedType: const FullType(BuiltList, [FullType(String)])), + 'recipeInstructions', + serializers.serialize(object.recipeInstructions, specifiedType: const FullType(BuiltList, [FullType(String)])), + 'nutrition', + serializers.serialize(object.nutrition, specifiedType: const FullType(Nutrition)), + 'name', + serializers.serialize(object.name, specifiedType: const FullType(String)), + 'keywords', + serializers.serialize(object.keywords, specifiedType: const FullType(String)), + 'dateCreated', + serializers.serialize(object.dateCreated, specifiedType: const FullType(String)), + 'imageUrl', + serializers.serialize(object.imageUrl, specifiedType: const FullType(String)), + 'imagePlaceholderUrl', + serializers.serialize(object.imagePlaceholderUrl, specifiedType: const FullType(String)), + ]; + Object? value; + value = object.id; + if (value != null) { + result + ..add('id') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.prepTime; + if (value != null) { + result + ..add('prepTime') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.cookTime; + if (value != null) { + result + ..add('cookTime') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.totalTime; + if (value != null) { + result + ..add('totalTime') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.dateModified; + if (value != null) { + result + ..add('dateModified') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + return result; + } + + @override + Recipe deserialize(Serializers serializers, Iterable serialized, + {FullType specifiedType = FullType.unspecified}) { + final result = RecipeBuilder(); + + final iterator = serialized.iterator; + while (iterator.moveNext()) { + final key = iterator.current! as String; + iterator.moveNext(); + final Object? value = iterator.current; + switch (key) { + case '@type': + result.type = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + case 'id': + result.id = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'prepTime': + result.prepTime = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'cookTime': + result.cookTime = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'totalTime': + result.totalTime = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'description': + result.description = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + case 'url': + result.url = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + case 'image': + result.image = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + case 'recipeYield': + result.recipeYield = serializers.deserialize(value, specifiedType: const FullType(int))! as int; + break; + case 'recipeCategory': + result.recipeCategory = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + case 'tool': + result.tool.replace(serializers.deserialize(value, + specifiedType: const FullType(BuiltList, [FullType(String)]))! as BuiltList); + break; + case 'recipeIngredient': + result.recipeIngredient.replace(serializers.deserialize(value, + specifiedType: const FullType(BuiltList, [FullType(String)]))! as BuiltList); + break; + case 'recipeInstructions': + result.recipeInstructions.replace(serializers.deserialize(value, + specifiedType: const FullType(BuiltList, [FullType(String)]))! as BuiltList); + break; + case 'nutrition': + result.nutrition + .replace(serializers.deserialize(value, specifiedType: const FullType(Nutrition))! as Nutrition); + break; + case 'name': + result.name = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + case 'keywords': + result.keywords = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + case 'dateCreated': + result.dateCreated = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + case 'dateModified': + result.dateModified = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'imageUrl': + result.imageUrl = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + case 'imagePlaceholderUrl': + result.imagePlaceholderUrl = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + } + } + + return result.build(); + } +} + +class _$KeywordSerializer implements StructuredSerializer { + @override + final Iterable types = const [Keyword, _$Keyword]; + @override + final String wireName = 'Keyword'; + + @override + Iterable serialize(Serializers serializers, Keyword object, + {FullType specifiedType = FullType.unspecified}) { + final result = [ + 'name', + serializers.serialize(object.name, specifiedType: const FullType(String)), + 'recipe_count', + serializers.serialize(object.recipeCount, specifiedType: const FullType(int)), + ]; + + return result; + } + + @override + Keyword deserialize(Serializers serializers, Iterable serialized, + {FullType specifiedType = FullType.unspecified}) { + final result = KeywordBuilder(); + + final iterator = serialized.iterator; + while (iterator.moveNext()) { + final key = iterator.current! as String; + iterator.moveNext(); + final Object? value = iterator.current; + switch (key) { + case 'name': + result.name = serializers.deserialize(value, specifiedType: const FullType(String))! as String; + break; + case 'recipe_count': + result.recipeCount = serializers.deserialize(value, specifiedType: const FullType(int))! as int; + break; + } + } + + return result.build(); + } +} + +class _$ErrorSerializer implements StructuredSerializer { + @override + final Iterable types = const [Error, _$Error]; + @override + final String wireName = 'Error'; + + @override + Iterable serialize(Serializers serializers, Error object, {FullType specifiedType = FullType.unspecified}) { + final result = []; + Object? value; + value = object.msg; + if (value != null) { + result + ..add('msg') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.file; + if (value != null) { + result + ..add('file') + ..add(serializers.serialize(value, specifiedType: const FullType(String))); + } + value = object.line; + if (value != null) { + result + ..add('line') + ..add(serializers.serialize(value, specifiedType: const FullType(int))); + } + return result; + } + + @override + Error deserialize(Serializers serializers, Iterable serialized, + {FullType specifiedType = FullType.unspecified}) { + final result = ErrorBuilder(); + + final iterator = serialized.iterator; + while (iterator.moveNext()) { + final key = iterator.current! as String; + iterator.moveNext(); + final Object? value = iterator.current; + switch (key) { + case 'msg': + result.msg = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'file': + result.file = serializers.deserialize(value, specifiedType: const FullType(String)) as String?; + break; + case 'line': + result.line = serializers.deserialize(value, specifiedType: const FullType(int)) as int?; + break; + } + } + + return result.build(); + } +} + +abstract mixin class $CategoryInformationInterfaceBuilder { + void replace($CategoryInformationInterface other); + void update(void Function($CategoryInformationInterfaceBuilder) updates); + String? get name; + set name(String? name); + + int? get recipeCount; + set recipeCount(int? recipeCount); +} + +class _$CategoryInformation extends CategoryInformation { + @override + final String name; + @override + final int recipeCount; + + factory _$CategoryInformation([void Function(CategoryInformationBuilder)? updates]) => + (CategoryInformationBuilder()..update(updates))._build(); + + _$CategoryInformation._({required this.name, required this.recipeCount}) : super._() { + BuiltValueNullFieldError.checkNotNull(name, r'CategoryInformation', 'name'); + BuiltValueNullFieldError.checkNotNull(recipeCount, r'CategoryInformation', 'recipeCount'); + } + + @override + CategoryInformation rebuild(void Function(CategoryInformationBuilder) updates) => + (toBuilder()..update(updates)).build(); + + @override + CategoryInformationBuilder toBuilder() => CategoryInformationBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is CategoryInformation && name == other.name && recipeCount == other.recipeCount; + } + + @override + int get hashCode { + var _$hash = 0; + _$hash = $jc(_$hash, name.hashCode); + _$hash = $jc(_$hash, recipeCount.hashCode); + _$hash = $jf(_$hash); + return _$hash; + } + + @override + String toString() { + return (newBuiltValueToStringHelper(r'CategoryInformation') + ..add('name', name) + ..add('recipeCount', recipeCount)) + .toString(); + } +} + +class CategoryInformationBuilder + implements Builder, $CategoryInformationInterfaceBuilder { + _$CategoryInformation? _$v; + + String? _name; + String? get name => _$this._name; + set name(covariant String? name) => _$this._name = name; + + int? _recipeCount; + int? get recipeCount => _$this._recipeCount; + set recipeCount(covariant int? recipeCount) => _$this._recipeCount = recipeCount; + + CategoryInformationBuilder() { + CategoryInformation._defaults(this); + } + + CategoryInformationBuilder get _$this { + final $v = _$v; + if ($v != null) { + _name = $v.name; + _recipeCount = $v.recipeCount; + _$v = null; + } + return this; + } + + @override + void replace(covariant CategoryInformation other) { + ArgumentError.checkNotNull(other, 'other'); + _$v = other as _$CategoryInformation; + } + + @override + void update(void Function(CategoryInformationBuilder)? updates) { + if (updates != null) updates(this); + } + + @override + CategoryInformation build() => _build(); + + _$CategoryInformation _build() { + CategoryInformation._validate(this); + final _$result = _$v ?? + _$CategoryInformation._( + name: BuiltValueNullFieldError.checkNotNull(name, r'CategoryInformation', 'name'), + recipeCount: BuiltValueNullFieldError.checkNotNull(recipeCount, r'CategoryInformation', 'recipeCount')); + replace(_$result); + return _$result; + } +} + +abstract mixin class $CategoryInterfaceBuilder implements $CategoryInformationInterfaceBuilder { + void replace(covariant $CategoryInterface other); + void update(void Function($CategoryInterfaceBuilder) updates); + String? get name; + set name(covariant String? name); + + int? get recipeCount; + set recipeCount(covariant int? recipeCount); +} + +class _$Category extends Category { + @override + final String name; + @override + final int recipeCount; + + factory _$Category([void Function(CategoryBuilder)? updates]) => (CategoryBuilder()..update(updates))._build(); + + _$Category._({required this.name, required this.recipeCount}) : super._() { + BuiltValueNullFieldError.checkNotNull(name, r'Category', 'name'); + BuiltValueNullFieldError.checkNotNull(recipeCount, r'Category', 'recipeCount'); + } + + @override + Category rebuild(void Function(CategoryBuilder) updates) => (toBuilder()..update(updates)).build(); + + @override + CategoryBuilder toBuilder() => CategoryBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is Category && name == other.name && recipeCount == other.recipeCount; + } + + @override + int get hashCode { + var _$hash = 0; + _$hash = $jc(_$hash, name.hashCode); + _$hash = $jc(_$hash, recipeCount.hashCode); + _$hash = $jf(_$hash); + return _$hash; + } + + @override + String toString() { + return (newBuiltValueToStringHelper(r'Category') + ..add('name', name) + ..add('recipeCount', recipeCount)) + .toString(); + } +} + +class CategoryBuilder implements Builder, $CategoryInterfaceBuilder { + _$Category? _$v; + + String? _name; + String? get name => _$this._name; + set name(covariant String? name) => _$this._name = name; + + int? _recipeCount; + int? get recipeCount => _$this._recipeCount; + set recipeCount(covariant int? recipeCount) => _$this._recipeCount = recipeCount; + + CategoryBuilder() { + Category._defaults(this); + } + + CategoryBuilder get _$this { + final $v = _$v; + if ($v != null) { + _name = $v.name; + _recipeCount = $v.recipeCount; + _$v = null; + } + return this; + } + + @override + void replace(covariant Category other) { + ArgumentError.checkNotNull(other, 'other'); + _$v = other as _$Category; + } + + @override + void update(void Function(CategoryBuilder)? updates) { + if (updates != null) updates(this); + } + + @override + Category build() => _build(); + + _$Category _build() { + Category._validate(this); + final _$result = _$v ?? + _$Category._( + name: BuiltValueNullFieldError.checkNotNull(name, r'Category', 'name'), + recipeCount: BuiltValueNullFieldError.checkNotNull(recipeCount, r'Category', 'recipeCount')); + replace(_$result); + return _$result; + } +} + +abstract mixin class $RecipeStubInformationInterfaceBuilder { + void replace($RecipeStubInformationInterface other); + void update(void Function($RecipeStubInformationInterfaceBuilder) updates); + String? get name; + set name(String? name); + + String? get keywords; + set keywords(String? keywords); + + String? get dateCreated; + set dateCreated(String? dateCreated); + + String? get dateModified; + set dateModified(String? dateModified); + + String? get imageUrl; + set imageUrl(String? imageUrl); + + String? get imagePlaceholderUrl; + set imagePlaceholderUrl(String? imagePlaceholderUrl); +} + +class _$RecipeStubInformation extends RecipeStubInformation { + @override + final String name; + @override + final String keywords; + @override + final String dateCreated; + @override + final String? dateModified; + @override + final String imageUrl; + @override + final String imagePlaceholderUrl; + + factory _$RecipeStubInformation([void Function(RecipeStubInformationBuilder)? updates]) => + (RecipeStubInformationBuilder()..update(updates))._build(); + + _$RecipeStubInformation._( + {required this.name, + required this.keywords, + required this.dateCreated, + this.dateModified, + required this.imageUrl, + required this.imagePlaceholderUrl}) + : super._() { + BuiltValueNullFieldError.checkNotNull(name, r'RecipeStubInformation', 'name'); + BuiltValueNullFieldError.checkNotNull(keywords, r'RecipeStubInformation', 'keywords'); + BuiltValueNullFieldError.checkNotNull(dateCreated, r'RecipeStubInformation', 'dateCreated'); + BuiltValueNullFieldError.checkNotNull(imageUrl, r'RecipeStubInformation', 'imageUrl'); + BuiltValueNullFieldError.checkNotNull(imagePlaceholderUrl, r'RecipeStubInformation', 'imagePlaceholderUrl'); + } + + @override + RecipeStubInformation rebuild(void Function(RecipeStubInformationBuilder) updates) => + (toBuilder()..update(updates)).build(); + + @override + RecipeStubInformationBuilder toBuilder() => RecipeStubInformationBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is RecipeStubInformation && + name == other.name && + keywords == other.keywords && + dateCreated == other.dateCreated && + dateModified == other.dateModified && + imageUrl == other.imageUrl && + imagePlaceholderUrl == other.imagePlaceholderUrl; + } + + @override + int get hashCode { + var _$hash = 0; + _$hash = $jc(_$hash, name.hashCode); + _$hash = $jc(_$hash, keywords.hashCode); + _$hash = $jc(_$hash, dateCreated.hashCode); + _$hash = $jc(_$hash, dateModified.hashCode); + _$hash = $jc(_$hash, imageUrl.hashCode); + _$hash = $jc(_$hash, imagePlaceholderUrl.hashCode); + _$hash = $jf(_$hash); + return _$hash; + } + + @override + String toString() { + return (newBuiltValueToStringHelper(r'RecipeStubInformation') + ..add('name', name) + ..add('keywords', keywords) + ..add('dateCreated', dateCreated) + ..add('dateModified', dateModified) + ..add('imageUrl', imageUrl) + ..add('imagePlaceholderUrl', imagePlaceholderUrl)) + .toString(); + } +} + +class RecipeStubInformationBuilder + implements Builder, $RecipeStubInformationInterfaceBuilder { + _$RecipeStubInformation? _$v; + + String? _name; + String? get name => _$this._name; + set name(covariant String? name) => _$this._name = name; + + String? _keywords; + String? get keywords => _$this._keywords; + set keywords(covariant String? keywords) => _$this._keywords = keywords; + + String? _dateCreated; + String? get dateCreated => _$this._dateCreated; + set dateCreated(covariant String? dateCreated) => _$this._dateCreated = dateCreated; + + String? _dateModified; + String? get dateModified => _$this._dateModified; + set dateModified(covariant String? dateModified) => _$this._dateModified = dateModified; + + String? _imageUrl; + String? get imageUrl => _$this._imageUrl; + set imageUrl(covariant String? imageUrl) => _$this._imageUrl = imageUrl; + + String? _imagePlaceholderUrl; + String? get imagePlaceholderUrl => _$this._imagePlaceholderUrl; + set imagePlaceholderUrl(covariant String? imagePlaceholderUrl) => _$this._imagePlaceholderUrl = imagePlaceholderUrl; + + RecipeStubInformationBuilder() { + RecipeStubInformation._defaults(this); + } + + RecipeStubInformationBuilder get _$this { + final $v = _$v; + if ($v != null) { + _name = $v.name; + _keywords = $v.keywords; + _dateCreated = $v.dateCreated; + _dateModified = $v.dateModified; + _imageUrl = $v.imageUrl; + _imagePlaceholderUrl = $v.imagePlaceholderUrl; + _$v = null; + } + return this; + } + + @override + void replace(covariant RecipeStubInformation other) { + ArgumentError.checkNotNull(other, 'other'); + _$v = other as _$RecipeStubInformation; + } + + @override + void update(void Function(RecipeStubInformationBuilder)? updates) { + if (updates != null) updates(this); + } + + @override + RecipeStubInformation build() => _build(); + + _$RecipeStubInformation _build() { + RecipeStubInformation._validate(this); + final _$result = _$v ?? + _$RecipeStubInformation._( + name: BuiltValueNullFieldError.checkNotNull(name, r'RecipeStubInformation', 'name'), + keywords: BuiltValueNullFieldError.checkNotNull(keywords, r'RecipeStubInformation', 'keywords'), + dateCreated: BuiltValueNullFieldError.checkNotNull(dateCreated, r'RecipeStubInformation', 'dateCreated'), + dateModified: dateModified, + imageUrl: BuiltValueNullFieldError.checkNotNull(imageUrl, r'RecipeStubInformation', 'imageUrl'), + imagePlaceholderUrl: BuiltValueNullFieldError.checkNotNull( + imagePlaceholderUrl, r'RecipeStubInformation', 'imagePlaceholderUrl')); + replace(_$result); + return _$result; + } +} + +abstract mixin class $RecipeStubInterfaceBuilder implements $RecipeStubInformationInterfaceBuilder { + void replace(covariant $RecipeStubInterface other); + void update(void Function($RecipeStubInterfaceBuilder) updates); + int? get recipeId; + set recipeId(covariant int? recipeId); + + String? get id; + set id(covariant String? id); + + String? get name; + set name(covariant String? name); + + String? get keywords; + set keywords(covariant String? keywords); + + String? get dateCreated; + set dateCreated(covariant String? dateCreated); + + String? get dateModified; + set dateModified(covariant String? dateModified); + + String? get imageUrl; + set imageUrl(covariant String? imageUrl); + + String? get imagePlaceholderUrl; + set imagePlaceholderUrl(covariant String? imagePlaceholderUrl); +} + +class _$RecipeStub extends RecipeStub { + @override + final int recipeId; + @override + final String id; + @override + final String name; + @override + final String keywords; + @override + final String dateCreated; + @override + final String? dateModified; + @override + final String imageUrl; + @override + final String imagePlaceholderUrl; + + factory _$RecipeStub([void Function(RecipeStubBuilder)? updates]) => (RecipeStubBuilder()..update(updates))._build(); + + _$RecipeStub._( + {required this.recipeId, + required this.id, + required this.name, + required this.keywords, + required this.dateCreated, + this.dateModified, + required this.imageUrl, + required this.imagePlaceholderUrl}) + : super._() { + BuiltValueNullFieldError.checkNotNull(recipeId, r'RecipeStub', 'recipeId'); + BuiltValueNullFieldError.checkNotNull(id, r'RecipeStub', 'id'); + BuiltValueNullFieldError.checkNotNull(name, r'RecipeStub', 'name'); + BuiltValueNullFieldError.checkNotNull(keywords, r'RecipeStub', 'keywords'); + BuiltValueNullFieldError.checkNotNull(dateCreated, r'RecipeStub', 'dateCreated'); + BuiltValueNullFieldError.checkNotNull(imageUrl, r'RecipeStub', 'imageUrl'); + BuiltValueNullFieldError.checkNotNull(imagePlaceholderUrl, r'RecipeStub', 'imagePlaceholderUrl'); + } + + @override + RecipeStub rebuild(void Function(RecipeStubBuilder) updates) => (toBuilder()..update(updates)).build(); + + @override + RecipeStubBuilder toBuilder() => RecipeStubBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is RecipeStub && + recipeId == other.recipeId && + id == other.id && + name == other.name && + keywords == other.keywords && + dateCreated == other.dateCreated && + dateModified == other.dateModified && + imageUrl == other.imageUrl && + imagePlaceholderUrl == other.imagePlaceholderUrl; + } + + @override + int get hashCode { + var _$hash = 0; + _$hash = $jc(_$hash, recipeId.hashCode); + _$hash = $jc(_$hash, id.hashCode); + _$hash = $jc(_$hash, name.hashCode); + _$hash = $jc(_$hash, keywords.hashCode); + _$hash = $jc(_$hash, dateCreated.hashCode); + _$hash = $jc(_$hash, dateModified.hashCode); + _$hash = $jc(_$hash, imageUrl.hashCode); + _$hash = $jc(_$hash, imagePlaceholderUrl.hashCode); + _$hash = $jf(_$hash); + return _$hash; + } + + @override + String toString() { + return (newBuiltValueToStringHelper(r'RecipeStub') + ..add('recipeId', recipeId) + ..add('id', id) + ..add('name', name) + ..add('keywords', keywords) + ..add('dateCreated', dateCreated) + ..add('dateModified', dateModified) + ..add('imageUrl', imageUrl) + ..add('imagePlaceholderUrl', imagePlaceholderUrl)) + .toString(); + } +} + +class RecipeStubBuilder implements Builder, $RecipeStubInterfaceBuilder { + _$RecipeStub? _$v; + + int? _recipeId; + int? get recipeId => _$this._recipeId; + set recipeId(covariant int? recipeId) => _$this._recipeId = recipeId; + + String? _id; + String? get id => _$this._id; + set id(covariant String? id) => _$this._id = id; + + String? _name; + String? get name => _$this._name; + set name(covariant String? name) => _$this._name = name; + + String? _keywords; + String? get keywords => _$this._keywords; + set keywords(covariant String? keywords) => _$this._keywords = keywords; + + String? _dateCreated; + String? get dateCreated => _$this._dateCreated; + set dateCreated(covariant String? dateCreated) => _$this._dateCreated = dateCreated; + + String? _dateModified; + String? get dateModified => _$this._dateModified; + set dateModified(covariant String? dateModified) => _$this._dateModified = dateModified; + + String? _imageUrl; + String? get imageUrl => _$this._imageUrl; + set imageUrl(covariant String? imageUrl) => _$this._imageUrl = imageUrl; + + String? _imagePlaceholderUrl; + String? get imagePlaceholderUrl => _$this._imagePlaceholderUrl; + set imagePlaceholderUrl(covariant String? imagePlaceholderUrl) => _$this._imagePlaceholderUrl = imagePlaceholderUrl; + + RecipeStubBuilder() { + RecipeStub._defaults(this); + } + + RecipeStubBuilder get _$this { + final $v = _$v; + if ($v != null) { + _recipeId = $v.recipeId; + _id = $v.id; + _name = $v.name; + _keywords = $v.keywords; + _dateCreated = $v.dateCreated; + _dateModified = $v.dateModified; + _imageUrl = $v.imageUrl; + _imagePlaceholderUrl = $v.imagePlaceholderUrl; + _$v = null; + } + return this; + } + + @override + void replace(covariant RecipeStub other) { + ArgumentError.checkNotNull(other, 'other'); + _$v = other as _$RecipeStub; + } + + @override + void update(void Function(RecipeStubBuilder)? updates) { + if (updates != null) updates(this); + } + + @override + RecipeStub build() => _build(); + + _$RecipeStub _build() { + RecipeStub._validate(this); + final _$result = _$v ?? + _$RecipeStub._( + recipeId: BuiltValueNullFieldError.checkNotNull(recipeId, r'RecipeStub', 'recipeId'), + id: BuiltValueNullFieldError.checkNotNull(id, r'RecipeStub', 'id'), + name: BuiltValueNullFieldError.checkNotNull(name, r'RecipeStub', 'name'), + keywords: BuiltValueNullFieldError.checkNotNull(keywords, r'RecipeStub', 'keywords'), + dateCreated: BuiltValueNullFieldError.checkNotNull(dateCreated, r'RecipeStub', 'dateCreated'), + dateModified: dateModified, + imageUrl: BuiltValueNullFieldError.checkNotNull(imageUrl, r'RecipeStub', 'imageUrl'), + imagePlaceholderUrl: + BuiltValueNullFieldError.checkNotNull(imagePlaceholderUrl, r'RecipeStub', 'imagePlaceholderUrl')); + replace(_$result); + return _$result; + } +} + +abstract mixin class $RenameCategoryRequestApplicationJsonInterfaceBuilder { + void replace($RenameCategoryRequestApplicationJsonInterface other); + void update(void Function($RenameCategoryRequestApplicationJsonInterfaceBuilder) updates); + String? get name; + set name(String? name); +} + +class _$RenameCategoryRequestApplicationJson extends RenameCategoryRequestApplicationJson { + @override + final String name; + + factory _$RenameCategoryRequestApplicationJson( + [void Function(RenameCategoryRequestApplicationJsonBuilder)? updates]) => + (RenameCategoryRequestApplicationJsonBuilder()..update(updates))._build(); + + _$RenameCategoryRequestApplicationJson._({required this.name}) : super._() { + BuiltValueNullFieldError.checkNotNull(name, r'RenameCategoryRequestApplicationJson', 'name'); + } + + @override + RenameCategoryRequestApplicationJson rebuild(void Function(RenameCategoryRequestApplicationJsonBuilder) updates) => + (toBuilder()..update(updates)).build(); + + @override + RenameCategoryRequestApplicationJsonBuilder toBuilder() => + RenameCategoryRequestApplicationJsonBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is RenameCategoryRequestApplicationJson && name == other.name; + } + + @override + int get hashCode { + var _$hash = 0; + _$hash = $jc(_$hash, name.hashCode); + _$hash = $jf(_$hash); + return _$hash; + } + + @override + String toString() { + return (newBuiltValueToStringHelper(r'RenameCategoryRequestApplicationJson')..add('name', name)).toString(); + } +} + +class RenameCategoryRequestApplicationJsonBuilder + implements + Builder, + $RenameCategoryRequestApplicationJsonInterfaceBuilder { + _$RenameCategoryRequestApplicationJson? _$v; + + String? _name; + String? get name => _$this._name; + set name(covariant String? name) => _$this._name = name; + + RenameCategoryRequestApplicationJsonBuilder() { + RenameCategoryRequestApplicationJson._defaults(this); + } + + RenameCategoryRequestApplicationJsonBuilder get _$this { + final $v = _$v; + if ($v != null) { + _name = $v.name; + _$v = null; + } + return this; + } + + @override + void replace(covariant RenameCategoryRequestApplicationJson other) { + ArgumentError.checkNotNull(other, 'other'); + _$v = other as _$RenameCategoryRequestApplicationJson; + } + + @override + void update(void Function(RenameCategoryRequestApplicationJsonBuilder)? updates) { + if (updates != null) updates(this); + } + + @override + RenameCategoryRequestApplicationJson build() => _build(); + + _$RenameCategoryRequestApplicationJson _build() { + RenameCategoryRequestApplicationJson._validate(this); + final _$result = _$v ?? + _$RenameCategoryRequestApplicationJson._( + name: BuiltValueNullFieldError.checkNotNull(name, r'RenameCategoryRequestApplicationJson', 'name')); + replace(_$result); + return _$result; + } +} + +abstract mixin class $APIVersionInterfaceBuilder { + void replace($APIVersionInterface other); + void update(void Function($APIVersionInterfaceBuilder) updates); + int? get epoch; + set epoch(int? epoch); + + int? get major; + set major(int? major); + + int? get minor; + set minor(int? minor); +} + +class _$APIVersion extends APIVersion { + @override + final int epoch; + @override + final int major; + @override + final int minor; + + factory _$APIVersion([void Function(APIVersionBuilder)? updates]) => (APIVersionBuilder()..update(updates))._build(); + + _$APIVersion._({required this.epoch, required this.major, required this.minor}) : super._() { + BuiltValueNullFieldError.checkNotNull(epoch, r'APIVersion', 'epoch'); + BuiltValueNullFieldError.checkNotNull(major, r'APIVersion', 'major'); + BuiltValueNullFieldError.checkNotNull(minor, r'APIVersion', 'minor'); + } + + @override + APIVersion rebuild(void Function(APIVersionBuilder) updates) => (toBuilder()..update(updates)).build(); + + @override + APIVersionBuilder toBuilder() => APIVersionBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is APIVersion && epoch == other.epoch && major == other.major && minor == other.minor; + } + + @override + int get hashCode { + var _$hash = 0; + _$hash = $jc(_$hash, epoch.hashCode); + _$hash = $jc(_$hash, major.hashCode); + _$hash = $jc(_$hash, minor.hashCode); + _$hash = $jf(_$hash); + return _$hash; + } + + @override + String toString() { + return (newBuiltValueToStringHelper(r'APIVersion') + ..add('epoch', epoch) + ..add('major', major) + ..add('minor', minor)) + .toString(); + } +} + +class APIVersionBuilder implements Builder, $APIVersionInterfaceBuilder { + _$APIVersion? _$v; + + int? _epoch; + int? get epoch => _$this._epoch; + set epoch(covariant int? epoch) => _$this._epoch = epoch; + + int? _major; + int? get major => _$this._major; + set major(covariant int? major) => _$this._major = major; + + int? _minor; + int? get minor => _$this._minor; + set minor(covariant int? minor) => _$this._minor = minor; + + APIVersionBuilder() { + APIVersion._defaults(this); + } + + APIVersionBuilder get _$this { + final $v = _$v; + if ($v != null) { + _epoch = $v.epoch; + _major = $v.major; + _minor = $v.minor; + _$v = null; + } + return this; + } + + @override + void replace(covariant APIVersion other) { + ArgumentError.checkNotNull(other, 'other'); + _$v = other as _$APIVersion; + } + + @override + void update(void Function(APIVersionBuilder)? updates) { + if (updates != null) updates(this); + } + + @override + APIVersion build() => _build(); + + _$APIVersion _build() { + APIVersion._validate(this); + final _$result = _$v ?? + _$APIVersion._( + epoch: BuiltValueNullFieldError.checkNotNull(epoch, r'APIVersion', 'epoch'), + major: BuiltValueNullFieldError.checkNotNull(major, r'APIVersion', 'major'), + minor: BuiltValueNullFieldError.checkNotNull(minor, r'APIVersion', 'minor')); + replace(_$result); + return _$result; + } +} + +abstract mixin class $VersionInterfaceBuilder { + void replace($VersionInterface other); + void update(void Function($VersionInterfaceBuilder) updates); + ListBuilder get cookbookVersion; + set cookbookVersion(ListBuilder? cookbookVersion); + + APIVersionBuilder get apiVersion; + set apiVersion(APIVersionBuilder? apiVersion); +} + +class _$Version extends Version { + @override + final BuiltList? cookbookVersion; + @override + final APIVersion? apiVersion; + + factory _$Version([void Function(VersionBuilder)? updates]) => (VersionBuilder()..update(updates))._build(); + + _$Version._({this.cookbookVersion, this.apiVersion}) : super._(); + + @override + Version rebuild(void Function(VersionBuilder) updates) => (toBuilder()..update(updates)).build(); + + @override + VersionBuilder toBuilder() => VersionBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is Version && cookbookVersion == other.cookbookVersion && apiVersion == other.apiVersion; + } + + @override + int get hashCode { + var _$hash = 0; + _$hash = $jc(_$hash, cookbookVersion.hashCode); + _$hash = $jc(_$hash, apiVersion.hashCode); + _$hash = $jf(_$hash); + return _$hash; + } + + @override + String toString() { + return (newBuiltValueToStringHelper(r'Version') + ..add('cookbookVersion', cookbookVersion) + ..add('apiVersion', apiVersion)) + .toString(); + } +} + +class VersionBuilder implements Builder, $VersionInterfaceBuilder { + _$Version? _$v; + + ListBuilder? _cookbookVersion; + ListBuilder get cookbookVersion => _$this._cookbookVersion ??= ListBuilder(); + set cookbookVersion(covariant ListBuilder? cookbookVersion) => _$this._cookbookVersion = cookbookVersion; + + APIVersionBuilder? _apiVersion; + APIVersionBuilder get apiVersion => _$this._apiVersion ??= APIVersionBuilder(); + set apiVersion(covariant APIVersionBuilder? apiVersion) => _$this._apiVersion = apiVersion; + + VersionBuilder() { + Version._defaults(this); + } + + VersionBuilder get _$this { + final $v = _$v; + if ($v != null) { + _cookbookVersion = $v.cookbookVersion?.toBuilder(); + _apiVersion = $v.apiVersion?.toBuilder(); + _$v = null; + } + return this; + } + + @override + void replace(covariant Version other) { + ArgumentError.checkNotNull(other, 'other'); + _$v = other as _$Version; + } + + @override + void update(void Function(VersionBuilder)? updates) { + if (updates != null) updates(this); + } + + @override + Version build() => _build(); + + _$Version _build() { + Version._validate(this); + _$Version _$result; + try { + _$result = _$v ?? _$Version._(cookbookVersion: _cookbookVersion?.build(), apiVersion: _apiVersion?.build()); + } catch (_) { + late String _$failedField; + try { + _$failedField = 'cookbookVersion'; + _cookbookVersion?.build(); + _$failedField = 'apiVersion'; + _apiVersion?.build(); + } catch (e) { + throw BuiltValueNestedFieldError(r'Version', _$failedField, e.toString()); + } + rethrow; + } + replace(_$result); + return _$result; + } +} + +abstract mixin class $VisibleInfoBlocksInterfaceBuilder { + void replace($VisibleInfoBlocksInterface other); + void update(void Function($VisibleInfoBlocksInterfaceBuilder) updates); + bool? get preparationTime; + set preparationTime(bool? preparationTime); + + bool? get cookingTime; + set cookingTime(bool? cookingTime); + + bool? get totalTime; + set totalTime(bool? totalTime); + + bool? get nutritionInformation; + set nutritionInformation(bool? nutritionInformation); + + bool? get tools; + set tools(bool? tools); +} + +class _$VisibleInfoBlocks extends VisibleInfoBlocks { + @override + final bool? preparationTime; + @override + final bool? cookingTime; + @override + final bool? totalTime; + @override + final bool? nutritionInformation; + @override + final bool? tools; + + factory _$VisibleInfoBlocks([void Function(VisibleInfoBlocksBuilder)? updates]) => + (VisibleInfoBlocksBuilder()..update(updates))._build(); + + _$VisibleInfoBlocks._({this.preparationTime, this.cookingTime, this.totalTime, this.nutritionInformation, this.tools}) + : super._(); + + @override + VisibleInfoBlocks rebuild(void Function(VisibleInfoBlocksBuilder) updates) => (toBuilder()..update(updates)).build(); + + @override + VisibleInfoBlocksBuilder toBuilder() => VisibleInfoBlocksBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is VisibleInfoBlocks && + preparationTime == other.preparationTime && + cookingTime == other.cookingTime && + totalTime == other.totalTime && + nutritionInformation == other.nutritionInformation && + tools == other.tools; + } + + @override + int get hashCode { + var _$hash = 0; + _$hash = $jc(_$hash, preparationTime.hashCode); + _$hash = $jc(_$hash, cookingTime.hashCode); + _$hash = $jc(_$hash, totalTime.hashCode); + _$hash = $jc(_$hash, nutritionInformation.hashCode); + _$hash = $jc(_$hash, tools.hashCode); + _$hash = $jf(_$hash); + return _$hash; + } + + @override + String toString() { + return (newBuiltValueToStringHelper(r'VisibleInfoBlocks') + ..add('preparationTime', preparationTime) + ..add('cookingTime', cookingTime) + ..add('totalTime', totalTime) + ..add('nutritionInformation', nutritionInformation) + ..add('tools', tools)) + .toString(); + } +} + +class VisibleInfoBlocksBuilder + implements Builder, $VisibleInfoBlocksInterfaceBuilder { + _$VisibleInfoBlocks? _$v; + + bool? _preparationTime; + bool? get preparationTime => _$this._preparationTime; + set preparationTime(covariant bool? preparationTime) => _$this._preparationTime = preparationTime; + + bool? _cookingTime; + bool? get cookingTime => _$this._cookingTime; + set cookingTime(covariant bool? cookingTime) => _$this._cookingTime = cookingTime; + + bool? _totalTime; + bool? get totalTime => _$this._totalTime; + set totalTime(covariant bool? totalTime) => _$this._totalTime = totalTime; + + bool? _nutritionInformation; + bool? get nutritionInformation => _$this._nutritionInformation; + set nutritionInformation(covariant bool? nutritionInformation) => _$this._nutritionInformation = nutritionInformation; + + bool? _tools; + bool? get tools => _$this._tools; + set tools(covariant bool? tools) => _$this._tools = tools; + + VisibleInfoBlocksBuilder() { + VisibleInfoBlocks._defaults(this); + } + + VisibleInfoBlocksBuilder get _$this { + final $v = _$v; + if ($v != null) { + _preparationTime = $v.preparationTime; + _cookingTime = $v.cookingTime; + _totalTime = $v.totalTime; + _nutritionInformation = $v.nutritionInformation; + _tools = $v.tools; + _$v = null; + } + return this; + } + + @override + void replace(covariant VisibleInfoBlocks other) { + ArgumentError.checkNotNull(other, 'other'); + _$v = other as _$VisibleInfoBlocks; + } + + @override + void update(void Function(VisibleInfoBlocksBuilder)? updates) { + if (updates != null) updates(this); + } + + @override + VisibleInfoBlocks build() => _build(); + + _$VisibleInfoBlocks _build() { + VisibleInfoBlocks._validate(this); + final _$result = _$v ?? + _$VisibleInfoBlocks._( + preparationTime: preparationTime, + cookingTime: cookingTime, + totalTime: totalTime, + nutritionInformation: nutritionInformation, + tools: tools); + replace(_$result); + return _$result; + } +} + +abstract mixin class $ConfigInterfaceBuilder { + void replace($ConfigInterface other); + void update(void Function($ConfigInterfaceBuilder) updates); + String? get folder; + set folder(String? folder); + + int? get updateInterval; + set updateInterval(int? updateInterval); + + bool? get printImage; + set printImage(bool? printImage); + + VisibleInfoBlocksBuilder get visibleInfoBlocks; + set visibleInfoBlocks(VisibleInfoBlocksBuilder? visibleInfoBlocks); +} + +class _$Config extends Config { + @override + final String? folder; + @override + final int? updateInterval; + @override + final bool? printImage; + @override + final VisibleInfoBlocks? visibleInfoBlocks; + + factory _$Config([void Function(ConfigBuilder)? updates]) => (ConfigBuilder()..update(updates))._build(); + + _$Config._({this.folder, this.updateInterval, this.printImage, this.visibleInfoBlocks}) : super._(); + + @override + Config rebuild(void Function(ConfigBuilder) updates) => (toBuilder()..update(updates)).build(); + + @override + ConfigBuilder toBuilder() => ConfigBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is Config && + folder == other.folder && + updateInterval == other.updateInterval && + printImage == other.printImage && + visibleInfoBlocks == other.visibleInfoBlocks; + } + + @override + int get hashCode { + var _$hash = 0; + _$hash = $jc(_$hash, folder.hashCode); + _$hash = $jc(_$hash, updateInterval.hashCode); + _$hash = $jc(_$hash, printImage.hashCode); + _$hash = $jc(_$hash, visibleInfoBlocks.hashCode); + _$hash = $jf(_$hash); + return _$hash; + } + + @override + String toString() { + return (newBuiltValueToStringHelper(r'Config') + ..add('folder', folder) + ..add('updateInterval', updateInterval) + ..add('printImage', printImage) + ..add('visibleInfoBlocks', visibleInfoBlocks)) + .toString(); + } +} + +class ConfigBuilder implements Builder, $ConfigInterfaceBuilder { + _$Config? _$v; + + String? _folder; + String? get folder => _$this._folder; + set folder(covariant String? folder) => _$this._folder = folder; + + int? _updateInterval; + int? get updateInterval => _$this._updateInterval; + set updateInterval(covariant int? updateInterval) => _$this._updateInterval = updateInterval; + + bool? _printImage; + bool? get printImage => _$this._printImage; + set printImage(covariant bool? printImage) => _$this._printImage = printImage; + + VisibleInfoBlocksBuilder? _visibleInfoBlocks; + VisibleInfoBlocksBuilder get visibleInfoBlocks => _$this._visibleInfoBlocks ??= VisibleInfoBlocksBuilder(); + set visibleInfoBlocks(covariant VisibleInfoBlocksBuilder? visibleInfoBlocks) => + _$this._visibleInfoBlocks = visibleInfoBlocks; + + ConfigBuilder() { + Config._defaults(this); + } + + ConfigBuilder get _$this { + final $v = _$v; + if ($v != null) { + _folder = $v.folder; + _updateInterval = $v.updateInterval; + _printImage = $v.printImage; + _visibleInfoBlocks = $v.visibleInfoBlocks?.toBuilder(); + _$v = null; + } + return this; + } + + @override + void replace(covariant Config other) { + ArgumentError.checkNotNull(other, 'other'); + _$v = other as _$Config; + } + + @override + void update(void Function(ConfigBuilder)? updates) { + if (updates != null) updates(this); + } + + @override + Config build() => _build(); + + _$Config _build() { + Config._validate(this); + _$Config _$result; + try { + _$result = _$v ?? + _$Config._( + folder: folder, + updateInterval: updateInterval, + printImage: printImage, + visibleInfoBlocks: _visibleInfoBlocks?.build()); + } catch (_) { + late String _$failedField; + try { + _$failedField = 'visibleInfoBlocks'; + _visibleInfoBlocks?.build(); + } catch (e) { + throw BuiltValueNestedFieldError(r'Config', _$failedField, e.toString()); + } + rethrow; + } + replace(_$result); + return _$result; + } +} + +abstract mixin class $UrlInterfaceBuilder { + void replace($UrlInterface other); + void update(void Function($UrlInterfaceBuilder) updates); + String? get url; + set url(String? url); +} + +class _$Url extends Url { + @override + final String url; + + factory _$Url([void Function(UrlBuilder)? updates]) => (UrlBuilder()..update(updates))._build(); + + _$Url._({required this.url}) : super._() { + BuiltValueNullFieldError.checkNotNull(url, r'Url', 'url'); + } + + @override + Url rebuild(void Function(UrlBuilder) updates) => (toBuilder()..update(updates)).build(); + + @override + UrlBuilder toBuilder() => UrlBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is Url && url == other.url; + } + + @override + int get hashCode { + var _$hash = 0; + _$hash = $jc(_$hash, url.hashCode); + _$hash = $jf(_$hash); + return _$hash; + } + + @override + String toString() { + return (newBuiltValueToStringHelper(r'Url')..add('url', url)).toString(); + } +} + +class UrlBuilder implements Builder, $UrlInterfaceBuilder { + _$Url? _$v; + + String? _url; + String? get url => _$this._url; + set url(covariant String? url) => _$this._url = url; + + UrlBuilder() { + Url._defaults(this); + } + + UrlBuilder get _$this { + final $v = _$v; + if ($v != null) { + _url = $v.url; + _$v = null; + } + return this; + } + + @override + void replace(covariant Url other) { + ArgumentError.checkNotNull(other, 'other'); + _$v = other as _$Url; + } + + @override + void update(void Function(UrlBuilder)? updates) { + if (updates != null) updates(this); + } + + @override + Url build() => _build(); + + _$Url _build() { + Url._validate(this); + final _$result = _$v ?? _$Url._(url: BuiltValueNullFieldError.checkNotNull(url, r'Url', 'url')); + replace(_$result); + return _$result; + } +} + +abstract mixin class $NutritionInterfaceBuilder { + void replace($NutritionInterface other); + void update(void Function($NutritionInterfaceBuilder) updates); + String? get type; + set type(String? type); + + String? get calories; + set calories(String? calories); + + String? get carbohydrateContent; + set carbohydrateContent(String? carbohydrateContent); + + String? get cholesterolContent; + set cholesterolContent(String? cholesterolContent); + + String? get fatContent; + set fatContent(String? fatContent); + + String? get fiberContent; + set fiberContent(String? fiberContent); + + String? get proteinContent; + set proteinContent(String? proteinContent); + + String? get saturatedFatContent; + set saturatedFatContent(String? saturatedFatContent); + + String? get servingSize; + set servingSize(String? servingSize); + + String? get sodiumContent; + set sodiumContent(String? sodiumContent); + + String? get sugarContent; + set sugarContent(String? sugarContent); + + String? get transFatContent; + set transFatContent(String? transFatContent); + + String? get unsaturatedFatContent; + set unsaturatedFatContent(String? unsaturatedFatContent); +} + +class _$Nutrition extends Nutrition { + @override + final String type; + @override + final String? calories; + @override + final String? carbohydrateContent; + @override + final String? cholesterolContent; + @override + final String? fatContent; + @override + final String? fiberContent; + @override + final String? proteinContent; + @override + final String? saturatedFatContent; + @override + final String? servingSize; + @override + final String? sodiumContent; + @override + final String? sugarContent; + @override + final String? transFatContent; + @override + final String? unsaturatedFatContent; + + factory _$Nutrition([void Function(NutritionBuilder)? updates]) => (NutritionBuilder()..update(updates))._build(); + + _$Nutrition._( + {required this.type, + this.calories, + this.carbohydrateContent, + this.cholesterolContent, + this.fatContent, + this.fiberContent, + this.proteinContent, + this.saturatedFatContent, + this.servingSize, + this.sodiumContent, + this.sugarContent, + this.transFatContent, + this.unsaturatedFatContent}) + : super._() { + BuiltValueNullFieldError.checkNotNull(type, r'Nutrition', 'type'); + } + + @override + Nutrition rebuild(void Function(NutritionBuilder) updates) => (toBuilder()..update(updates)).build(); + + @override + NutritionBuilder toBuilder() => NutritionBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is Nutrition && + type == other.type && + calories == other.calories && + carbohydrateContent == other.carbohydrateContent && + cholesterolContent == other.cholesterolContent && + fatContent == other.fatContent && + fiberContent == other.fiberContent && + proteinContent == other.proteinContent && + saturatedFatContent == other.saturatedFatContent && + servingSize == other.servingSize && + sodiumContent == other.sodiumContent && + sugarContent == other.sugarContent && + transFatContent == other.transFatContent && + unsaturatedFatContent == other.unsaturatedFatContent; + } + + @override + int get hashCode { + var _$hash = 0; + _$hash = $jc(_$hash, type.hashCode); + _$hash = $jc(_$hash, calories.hashCode); + _$hash = $jc(_$hash, carbohydrateContent.hashCode); + _$hash = $jc(_$hash, cholesterolContent.hashCode); + _$hash = $jc(_$hash, fatContent.hashCode); + _$hash = $jc(_$hash, fiberContent.hashCode); + _$hash = $jc(_$hash, proteinContent.hashCode); + _$hash = $jc(_$hash, saturatedFatContent.hashCode); + _$hash = $jc(_$hash, servingSize.hashCode); + _$hash = $jc(_$hash, sodiumContent.hashCode); + _$hash = $jc(_$hash, sugarContent.hashCode); + _$hash = $jc(_$hash, transFatContent.hashCode); + _$hash = $jc(_$hash, unsaturatedFatContent.hashCode); + _$hash = $jf(_$hash); + return _$hash; + } + + @override + String toString() { + return (newBuiltValueToStringHelper(r'Nutrition') + ..add('type', type) + ..add('calories', calories) + ..add('carbohydrateContent', carbohydrateContent) + ..add('cholesterolContent', cholesterolContent) + ..add('fatContent', fatContent) + ..add('fiberContent', fiberContent) + ..add('proteinContent', proteinContent) + ..add('saturatedFatContent', saturatedFatContent) + ..add('servingSize', servingSize) + ..add('sodiumContent', sodiumContent) + ..add('sugarContent', sugarContent) + ..add('transFatContent', transFatContent) + ..add('unsaturatedFatContent', unsaturatedFatContent)) + .toString(); + } +} + +class NutritionBuilder implements Builder, $NutritionInterfaceBuilder { + _$Nutrition? _$v; + + String? _type; + String? get type => _$this._type; + set type(covariant String? type) => _$this._type = type; + + String? _calories; + String? get calories => _$this._calories; + set calories(covariant String? calories) => _$this._calories = calories; + + String? _carbohydrateContent; + String? get carbohydrateContent => _$this._carbohydrateContent; + set carbohydrateContent(covariant String? carbohydrateContent) => _$this._carbohydrateContent = carbohydrateContent; + + String? _cholesterolContent; + String? get cholesterolContent => _$this._cholesterolContent; + set cholesterolContent(covariant String? cholesterolContent) => _$this._cholesterolContent = cholesterolContent; + + String? _fatContent; + String? get fatContent => _$this._fatContent; + set fatContent(covariant String? fatContent) => _$this._fatContent = fatContent; + + String? _fiberContent; + String? get fiberContent => _$this._fiberContent; + set fiberContent(covariant String? fiberContent) => _$this._fiberContent = fiberContent; + + String? _proteinContent; + String? get proteinContent => _$this._proteinContent; + set proteinContent(covariant String? proteinContent) => _$this._proteinContent = proteinContent; + + String? _saturatedFatContent; + String? get saturatedFatContent => _$this._saturatedFatContent; + set saturatedFatContent(covariant String? saturatedFatContent) => _$this._saturatedFatContent = saturatedFatContent; + + String? _servingSize; + String? get servingSize => _$this._servingSize; + set servingSize(covariant String? servingSize) => _$this._servingSize = servingSize; + + String? _sodiumContent; + String? get sodiumContent => _$this._sodiumContent; + set sodiumContent(covariant String? sodiumContent) => _$this._sodiumContent = sodiumContent; + + String? _sugarContent; + String? get sugarContent => _$this._sugarContent; + set sugarContent(covariant String? sugarContent) => _$this._sugarContent = sugarContent; + + String? _transFatContent; + String? get transFatContent => _$this._transFatContent; + set transFatContent(covariant String? transFatContent) => _$this._transFatContent = transFatContent; + + String? _unsaturatedFatContent; + String? get unsaturatedFatContent => _$this._unsaturatedFatContent; + set unsaturatedFatContent(covariant String? unsaturatedFatContent) => + _$this._unsaturatedFatContent = unsaturatedFatContent; + + NutritionBuilder() { + Nutrition._defaults(this); + } + + NutritionBuilder get _$this { + final $v = _$v; + if ($v != null) { + _type = $v.type; + _calories = $v.calories; + _carbohydrateContent = $v.carbohydrateContent; + _cholesterolContent = $v.cholesterolContent; + _fatContent = $v.fatContent; + _fiberContent = $v.fiberContent; + _proteinContent = $v.proteinContent; + _saturatedFatContent = $v.saturatedFatContent; + _servingSize = $v.servingSize; + _sodiumContent = $v.sodiumContent; + _sugarContent = $v.sugarContent; + _transFatContent = $v.transFatContent; + _unsaturatedFatContent = $v.unsaturatedFatContent; + _$v = null; + } + return this; + } + + @override + void replace(covariant Nutrition other) { + ArgumentError.checkNotNull(other, 'other'); + _$v = other as _$Nutrition; + } + + @override + void update(void Function(NutritionBuilder)? updates) { + if (updates != null) updates(this); + } + + @override + Nutrition build() => _build(); + + _$Nutrition _build() { + Nutrition._validate(this); + final _$result = _$v ?? + _$Nutrition._( + type: BuiltValueNullFieldError.checkNotNull(type, r'Nutrition', 'type'), + calories: calories, + carbohydrateContent: carbohydrateContent, + cholesterolContent: cholesterolContent, + fatContent: fatContent, + fiberContent: fiberContent, + proteinContent: proteinContent, + saturatedFatContent: saturatedFatContent, + servingSize: servingSize, + sodiumContent: sodiumContent, + sugarContent: sugarContent, + transFatContent: transFatContent, + unsaturatedFatContent: unsaturatedFatContent); + replace(_$result); + return _$result; + } +} + +abstract mixin class $RecipeInterfaceBuilder implements $RecipeStubInformationInterfaceBuilder { + void replace(covariant $RecipeInterface other); + void update(void Function($RecipeInterfaceBuilder) updates); + String? get type; + set type(covariant String? type); + + String? get id; + set id(covariant String? id); + + String? get prepTime; + set prepTime(covariant String? prepTime); + + String? get cookTime; + set cookTime(covariant String? cookTime); + + String? get totalTime; + set totalTime(covariant String? totalTime); + + String? get description; + set description(covariant String? description); + + String? get url; + set url(covariant String? url); + + String? get image; + set image(covariant String? image); + + int? get recipeYield; + set recipeYield(covariant int? recipeYield); + + String? get recipeCategory; + set recipeCategory(covariant String? recipeCategory); + + ListBuilder get tool; + set tool(covariant ListBuilder? tool); + + ListBuilder get recipeIngredient; + set recipeIngredient(covariant ListBuilder? recipeIngredient); + + ListBuilder get recipeInstructions; + set recipeInstructions(covariant ListBuilder? recipeInstructions); + + NutritionBuilder get nutrition; + set nutrition(covariant NutritionBuilder? nutrition); + + String? get name; + set name(covariant String? name); + + String? get keywords; + set keywords(covariant String? keywords); + + String? get dateCreated; + set dateCreated(covariant String? dateCreated); + + String? get dateModified; + set dateModified(covariant String? dateModified); + + String? get imageUrl; + set imageUrl(covariant String? imageUrl); + + String? get imagePlaceholderUrl; + set imagePlaceholderUrl(covariant String? imagePlaceholderUrl); +} + +class _$Recipe extends Recipe { + @override + final String type; + @override + final String? id; + @override + final String? prepTime; + @override + final String? cookTime; + @override + final String? totalTime; + @override + final String description; + @override + final String url; + @override + final String image; + @override + final int recipeYield; + @override + final String recipeCategory; + @override + final BuiltList tool; + @override + final BuiltList recipeIngredient; + @override + final BuiltList recipeInstructions; + @override + final Nutrition nutrition; + @override + final String name; + @override + final String keywords; + @override + final String dateCreated; + @override + final String? dateModified; + @override + final String imageUrl; + @override + final String imagePlaceholderUrl; + + factory _$Recipe([void Function(RecipeBuilder)? updates]) => (RecipeBuilder()..update(updates))._build(); + + _$Recipe._( + {required this.type, + this.id, + this.prepTime, + this.cookTime, + this.totalTime, + required this.description, + required this.url, + required this.image, + required this.recipeYield, + required this.recipeCategory, + required this.tool, + required this.recipeIngredient, + required this.recipeInstructions, + required this.nutrition, + required this.name, + required this.keywords, + required this.dateCreated, + this.dateModified, + required this.imageUrl, + required this.imagePlaceholderUrl}) + : super._() { + BuiltValueNullFieldError.checkNotNull(type, r'Recipe', 'type'); + BuiltValueNullFieldError.checkNotNull(description, r'Recipe', 'description'); + BuiltValueNullFieldError.checkNotNull(url, r'Recipe', 'url'); + BuiltValueNullFieldError.checkNotNull(image, r'Recipe', 'image'); + BuiltValueNullFieldError.checkNotNull(recipeYield, r'Recipe', 'recipeYield'); + BuiltValueNullFieldError.checkNotNull(recipeCategory, r'Recipe', 'recipeCategory'); + BuiltValueNullFieldError.checkNotNull(tool, r'Recipe', 'tool'); + BuiltValueNullFieldError.checkNotNull(recipeIngredient, r'Recipe', 'recipeIngredient'); + BuiltValueNullFieldError.checkNotNull(recipeInstructions, r'Recipe', 'recipeInstructions'); + BuiltValueNullFieldError.checkNotNull(nutrition, r'Recipe', 'nutrition'); + BuiltValueNullFieldError.checkNotNull(name, r'Recipe', 'name'); + BuiltValueNullFieldError.checkNotNull(keywords, r'Recipe', 'keywords'); + BuiltValueNullFieldError.checkNotNull(dateCreated, r'Recipe', 'dateCreated'); + BuiltValueNullFieldError.checkNotNull(imageUrl, r'Recipe', 'imageUrl'); + BuiltValueNullFieldError.checkNotNull(imagePlaceholderUrl, r'Recipe', 'imagePlaceholderUrl'); + } + + @override + Recipe rebuild(void Function(RecipeBuilder) updates) => (toBuilder()..update(updates)).build(); + + @override + RecipeBuilder toBuilder() => RecipeBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is Recipe && + type == other.type && + id == other.id && + prepTime == other.prepTime && + cookTime == other.cookTime && + totalTime == other.totalTime && + description == other.description && + url == other.url && + image == other.image && + recipeYield == other.recipeYield && + recipeCategory == other.recipeCategory && + tool == other.tool && + recipeIngredient == other.recipeIngredient && + recipeInstructions == other.recipeInstructions && + nutrition == other.nutrition && + name == other.name && + keywords == other.keywords && + dateCreated == other.dateCreated && + dateModified == other.dateModified && + imageUrl == other.imageUrl && + imagePlaceholderUrl == other.imagePlaceholderUrl; + } + + @override + int get hashCode { + var _$hash = 0; + _$hash = $jc(_$hash, type.hashCode); + _$hash = $jc(_$hash, id.hashCode); + _$hash = $jc(_$hash, prepTime.hashCode); + _$hash = $jc(_$hash, cookTime.hashCode); + _$hash = $jc(_$hash, totalTime.hashCode); + _$hash = $jc(_$hash, description.hashCode); + _$hash = $jc(_$hash, url.hashCode); + _$hash = $jc(_$hash, image.hashCode); + _$hash = $jc(_$hash, recipeYield.hashCode); + _$hash = $jc(_$hash, recipeCategory.hashCode); + _$hash = $jc(_$hash, tool.hashCode); + _$hash = $jc(_$hash, recipeIngredient.hashCode); + _$hash = $jc(_$hash, recipeInstructions.hashCode); + _$hash = $jc(_$hash, nutrition.hashCode); + _$hash = $jc(_$hash, name.hashCode); + _$hash = $jc(_$hash, keywords.hashCode); + _$hash = $jc(_$hash, dateCreated.hashCode); + _$hash = $jc(_$hash, dateModified.hashCode); + _$hash = $jc(_$hash, imageUrl.hashCode); + _$hash = $jc(_$hash, imagePlaceholderUrl.hashCode); + _$hash = $jf(_$hash); + return _$hash; + } + + @override + String toString() { + return (newBuiltValueToStringHelper(r'Recipe') + ..add('type', type) + ..add('id', id) + ..add('prepTime', prepTime) + ..add('cookTime', cookTime) + ..add('totalTime', totalTime) + ..add('description', description) + ..add('url', url) + ..add('image', image) + ..add('recipeYield', recipeYield) + ..add('recipeCategory', recipeCategory) + ..add('tool', tool) + ..add('recipeIngredient', recipeIngredient) + ..add('recipeInstructions', recipeInstructions) + ..add('nutrition', nutrition) + ..add('name', name) + ..add('keywords', keywords) + ..add('dateCreated', dateCreated) + ..add('dateModified', dateModified) + ..add('imageUrl', imageUrl) + ..add('imagePlaceholderUrl', imagePlaceholderUrl)) + .toString(); + } +} + +class RecipeBuilder implements Builder, $RecipeInterfaceBuilder { + _$Recipe? _$v; + + String? _type; + String? get type => _$this._type; + set type(covariant String? type) => _$this._type = type; + + String? _id; + String? get id => _$this._id; + set id(covariant String? id) => _$this._id = id; + + String? _prepTime; + String? get prepTime => _$this._prepTime; + set prepTime(covariant String? prepTime) => _$this._prepTime = prepTime; + + String? _cookTime; + String? get cookTime => _$this._cookTime; + set cookTime(covariant String? cookTime) => _$this._cookTime = cookTime; + + String? _totalTime; + String? get totalTime => _$this._totalTime; + set totalTime(covariant String? totalTime) => _$this._totalTime = totalTime; + + String? _description; + String? get description => _$this._description; + set description(covariant String? description) => _$this._description = description; + + String? _url; + String? get url => _$this._url; + set url(covariant String? url) => _$this._url = url; + + String? _image; + String? get image => _$this._image; + set image(covariant String? image) => _$this._image = image; + + int? _recipeYield; + int? get recipeYield => _$this._recipeYield; + set recipeYield(covariant int? recipeYield) => _$this._recipeYield = recipeYield; + + String? _recipeCategory; + String? get recipeCategory => _$this._recipeCategory; + set recipeCategory(covariant String? recipeCategory) => _$this._recipeCategory = recipeCategory; + + ListBuilder? _tool; + ListBuilder get tool => _$this._tool ??= ListBuilder(); + set tool(covariant ListBuilder? tool) => _$this._tool = tool; + + ListBuilder? _recipeIngredient; + ListBuilder get recipeIngredient => _$this._recipeIngredient ??= ListBuilder(); + set recipeIngredient(covariant ListBuilder? recipeIngredient) => _$this._recipeIngredient = recipeIngredient; + + ListBuilder? _recipeInstructions; + ListBuilder get recipeInstructions => _$this._recipeInstructions ??= ListBuilder(); + set recipeInstructions(covariant ListBuilder? recipeInstructions) => + _$this._recipeInstructions = recipeInstructions; + + NutritionBuilder? _nutrition; + NutritionBuilder get nutrition => _$this._nutrition ??= NutritionBuilder(); + set nutrition(covariant NutritionBuilder? nutrition) => _$this._nutrition = nutrition; + + String? _name; + String? get name => _$this._name; + set name(covariant String? name) => _$this._name = name; + + String? _keywords; + String? get keywords => _$this._keywords; + set keywords(covariant String? keywords) => _$this._keywords = keywords; + + String? _dateCreated; + String? get dateCreated => _$this._dateCreated; + set dateCreated(covariant String? dateCreated) => _$this._dateCreated = dateCreated; + + String? _dateModified; + String? get dateModified => _$this._dateModified; + set dateModified(covariant String? dateModified) => _$this._dateModified = dateModified; + + String? _imageUrl; + String? get imageUrl => _$this._imageUrl; + set imageUrl(covariant String? imageUrl) => _$this._imageUrl = imageUrl; + + String? _imagePlaceholderUrl; + String? get imagePlaceholderUrl => _$this._imagePlaceholderUrl; + set imagePlaceholderUrl(covariant String? imagePlaceholderUrl) => _$this._imagePlaceholderUrl = imagePlaceholderUrl; + + RecipeBuilder() { + Recipe._defaults(this); + } + + RecipeBuilder get _$this { + final $v = _$v; + if ($v != null) { + _type = $v.type; + _id = $v.id; + _prepTime = $v.prepTime; + _cookTime = $v.cookTime; + _totalTime = $v.totalTime; + _description = $v.description; + _url = $v.url; + _image = $v.image; + _recipeYield = $v.recipeYield; + _recipeCategory = $v.recipeCategory; + _tool = $v.tool.toBuilder(); + _recipeIngredient = $v.recipeIngredient.toBuilder(); + _recipeInstructions = $v.recipeInstructions.toBuilder(); + _nutrition = $v.nutrition.toBuilder(); + _name = $v.name; + _keywords = $v.keywords; + _dateCreated = $v.dateCreated; + _dateModified = $v.dateModified; + _imageUrl = $v.imageUrl; + _imagePlaceholderUrl = $v.imagePlaceholderUrl; + _$v = null; + } + return this; + } + + @override + void replace(covariant Recipe other) { + ArgumentError.checkNotNull(other, 'other'); + _$v = other as _$Recipe; + } + + @override + void update(void Function(RecipeBuilder)? updates) { + if (updates != null) updates(this); + } + + @override + Recipe build() => _build(); + + _$Recipe _build() { + Recipe._validate(this); + _$Recipe _$result; + try { + _$result = _$v ?? + _$Recipe._( + type: BuiltValueNullFieldError.checkNotNull(type, r'Recipe', 'type'), + id: id, + prepTime: prepTime, + cookTime: cookTime, + totalTime: totalTime, + description: BuiltValueNullFieldError.checkNotNull(description, r'Recipe', 'description'), + url: BuiltValueNullFieldError.checkNotNull(url, r'Recipe', 'url'), + image: BuiltValueNullFieldError.checkNotNull(image, r'Recipe', 'image'), + recipeYield: BuiltValueNullFieldError.checkNotNull(recipeYield, r'Recipe', 'recipeYield'), + recipeCategory: BuiltValueNullFieldError.checkNotNull(recipeCategory, r'Recipe', 'recipeCategory'), + tool: tool.build(), + recipeIngredient: recipeIngredient.build(), + recipeInstructions: recipeInstructions.build(), + nutrition: nutrition.build(), + name: BuiltValueNullFieldError.checkNotNull(name, r'Recipe', 'name'), + keywords: BuiltValueNullFieldError.checkNotNull(keywords, r'Recipe', 'keywords'), + dateCreated: BuiltValueNullFieldError.checkNotNull(dateCreated, r'Recipe', 'dateCreated'), + dateModified: dateModified, + imageUrl: BuiltValueNullFieldError.checkNotNull(imageUrl, r'Recipe', 'imageUrl'), + imagePlaceholderUrl: + BuiltValueNullFieldError.checkNotNull(imagePlaceholderUrl, r'Recipe', 'imagePlaceholderUrl')); + } catch (_) { + late String _$failedField; + try { + _$failedField = 'tool'; + tool.build(); + _$failedField = 'recipeIngredient'; + recipeIngredient.build(); + _$failedField = 'recipeInstructions'; + recipeInstructions.build(); + _$failedField = 'nutrition'; + nutrition.build(); + } catch (e) { + throw BuiltValueNestedFieldError(r'Recipe', _$failedField, e.toString()); + } + rethrow; + } + replace(_$result); + return _$result; + } +} + +abstract mixin class $KeywordInterfaceBuilder implements $CategoryInformationInterfaceBuilder { + void replace(covariant $KeywordInterface other); + void update(void Function($KeywordInterfaceBuilder) updates); + String? get name; + set name(covariant String? name); + + int? get recipeCount; + set recipeCount(covariant int? recipeCount); +} + +class _$Keyword extends Keyword { + @override + final String name; + @override + final int recipeCount; + + factory _$Keyword([void Function(KeywordBuilder)? updates]) => (KeywordBuilder()..update(updates))._build(); + + _$Keyword._({required this.name, required this.recipeCount}) : super._() { + BuiltValueNullFieldError.checkNotNull(name, r'Keyword', 'name'); + BuiltValueNullFieldError.checkNotNull(recipeCount, r'Keyword', 'recipeCount'); + } + + @override + Keyword rebuild(void Function(KeywordBuilder) updates) => (toBuilder()..update(updates)).build(); + + @override + KeywordBuilder toBuilder() => KeywordBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is Keyword && name == other.name && recipeCount == other.recipeCount; + } + + @override + int get hashCode { + var _$hash = 0; + _$hash = $jc(_$hash, name.hashCode); + _$hash = $jc(_$hash, recipeCount.hashCode); + _$hash = $jf(_$hash); + return _$hash; + } + + @override + String toString() { + return (newBuiltValueToStringHelper(r'Keyword') + ..add('name', name) + ..add('recipeCount', recipeCount)) + .toString(); + } +} + +class KeywordBuilder implements Builder, $KeywordInterfaceBuilder { + _$Keyword? _$v; + + String? _name; + String? get name => _$this._name; + set name(covariant String? name) => _$this._name = name; + + int? _recipeCount; + int? get recipeCount => _$this._recipeCount; + set recipeCount(covariant int? recipeCount) => _$this._recipeCount = recipeCount; + + KeywordBuilder() { + Keyword._defaults(this); + } + + KeywordBuilder get _$this { + final $v = _$v; + if ($v != null) { + _name = $v.name; + _recipeCount = $v.recipeCount; + _$v = null; + } + return this; + } + + @override + void replace(covariant Keyword other) { + ArgumentError.checkNotNull(other, 'other'); + _$v = other as _$Keyword; + } + + @override + void update(void Function(KeywordBuilder)? updates) { + if (updates != null) updates(this); + } + + @override + Keyword build() => _build(); + + _$Keyword _build() { + Keyword._validate(this); + final _$result = _$v ?? + _$Keyword._( + name: BuiltValueNullFieldError.checkNotNull(name, r'Keyword', 'name'), + recipeCount: BuiltValueNullFieldError.checkNotNull(recipeCount, r'Keyword', 'recipeCount')); + replace(_$result); + return _$result; + } +} + +abstract mixin class $ErrorInterfaceBuilder { + void replace($ErrorInterface other); + void update(void Function($ErrorInterfaceBuilder) updates); + String? get msg; + set msg(String? msg); + + String? get file; + set file(String? file); + + int? get line; + set line(int? line); +} + +class _$Error extends Error { + @override + final String? msg; + @override + final String? file; + @override + final int? line; + + factory _$Error([void Function(ErrorBuilder)? updates]) => (ErrorBuilder()..update(updates))._build(); + + _$Error._({this.msg, this.file, this.line}) : super._(); + + @override + Error rebuild(void Function(ErrorBuilder) updates) => (toBuilder()..update(updates)).build(); + + @override + ErrorBuilder toBuilder() => ErrorBuilder()..replace(this); + + @override + bool operator ==(Object other) { + if (identical(other, this)) return true; + return other is Error && msg == other.msg && file == other.file && line == other.line; + } + + @override + int get hashCode { + var _$hash = 0; + _$hash = $jc(_$hash, msg.hashCode); + _$hash = $jc(_$hash, file.hashCode); + _$hash = $jc(_$hash, line.hashCode); + _$hash = $jf(_$hash); + return _$hash; + } + + @override + String toString() { + return (newBuiltValueToStringHelper(r'Error') + ..add('msg', msg) + ..add('file', file) + ..add('line', line)) + .toString(); + } +} + +class ErrorBuilder implements Builder, $ErrorInterfaceBuilder { + _$Error? _$v; + + String? _msg; + String? get msg => _$this._msg; + set msg(covariant String? msg) => _$this._msg = msg; + + String? _file; + String? get file => _$this._file; + set file(covariant String? file) => _$this._file = file; + + int? _line; + int? get line => _$this._line; + set line(covariant int? line) => _$this._line = line; + + ErrorBuilder() { + Error._defaults(this); + } + + ErrorBuilder get _$this { + final $v = _$v; + if ($v != null) { + _msg = $v.msg; + _file = $v.file; + _line = $v.line; + _$v = null; + } + return this; + } + + @override + void replace(covariant Error other) { + ArgumentError.checkNotNull(other, 'other'); + _$v = other as _$Error; + } + + @override + void update(void Function(ErrorBuilder)? updates) { + if (updates != null) updates(this); + } + + @override + Error build() => _build(); + + _$Error _build() { + Error._validate(this); + final _$result = _$v ?? _$Error._(msg: msg, file: file, line: line); + replace(_$result); + return _$result; + } +} + +// ignore_for_file: deprecated_member_use_from_same_package,type=lint diff --git a/packages/nextcloud/lib/src/api/cookbook.openapi.json b/packages/nextcloud/lib/src/api/cookbook.openapi.json new file mode 100644 index 00000000000..dd476f97e0c --- /dev/null +++ b/packages/nextcloud/lib/src/api/cookbook.openapi.json @@ -0,0 +1,1301 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "Nextcloud cookbook app", + "description": "This is the public API definition of the [cookbook app](https://github.com/nextcloud/cookbook) for the [nextcloud server](http://nextcloud.com).\n\nThe total API is separated into two parts:\n- There is the public API part that can be used from 3rd party apps and scripts.\n- There is the internal API that is used only by the web app of the cookbook app. This is described here.\n\nThe internal part is intended only to be used by the internal web app. It uses session based authentication and thus requires a `requesttoken` to protect against CSRF attacks. The generation and updating of these tokens is not part of the app but the regular browser capabilities and the nextcloud web frontend is used here instead.\n\nIn contrast, the External APIs are intended for use by external services. These endpoints require the user credentials to be present in every request. Thus, no session is created and no cookies or similar needs to be handled. Technically, there is a CORS preflight possible but it is not required for the function of the endpoints.\n\nFurther contact can be found on the matrix.org server in the room [#nextcloud-cookbook:matrix.org](https://matrix.to/#/#nextcloud-cookbook:matrix.org) for general questions. Additionally, there is [#nextcloud-cookbook-integration:matrix.org](https://matrix.to/#/#nextcloud-cookbook-integration:matrix.org) for questions related to the API and third party integration. Further information on the different versions can be found in [the API overview page](https://nextcloud.github.io/cookbook/dev/api/index).", + "license": { + "name": "AGPL-3", + "url": "http://www.gnu.org/licenses/agpl-3.0.de.html" + }, + "version": "0.1.2" + }, + "servers": [ + { + "url": "http://localhost:8000/apps/cookbook" + }, + { + "url": "{protocol}://{server}", + "variables": { + "protocol": { + "enum": [ + "http", + "https" + ], + "default": "https" + }, + "server": { + "default": "example.com" + } + } + } + ], + "tags": [ + { + "name": "Recipes", + "description": "Everything related to recipes and their usage" + }, + { + "name": "Categories", + "description": "Access to the categories of the recipes" + }, + { + "name": "Tags", + "description": "Access to tags/keywords of recipes" + }, + { + "name": "Misc", + "description": "Other API endpoints" + } + ], + "components": { + "schemas": { + "Category": { + "type": "object", + "description": "A category", + "allOf": [ + { + "$ref": "#/components/schemas/CategoryInformation" + } + ] + }, + "CategoryInformation": { + "type": "object", + "description": "The very basic information of a category\nPlease note: A category name of `*` indicates the number of recipes with no category associated.", + "properties": { + "name": { + "type": "string", + "description": "The name of the category", + "example": "Dinner" + }, + "recipe_count": { + "type": "integer", + "description": "The number of recipes in the category", + "example": 21 + } + }, + "required": [ + "name", + "recipe_count" + ] + }, + "VisibleInfoBlocks": { + "type": "object", + "properties": { + "preparation-time": { + "type": "boolean", + "example": true, + "description": "Show the preparation time in UI" + }, + "cooking-time": { + "type": "boolean", + "example": true, + "description": "Show the time required for cooking in the UI" + }, + "total-time": { + "type": "boolean", + "example": false, + "description": "Show the total time required to carry out the complee recipe" + }, + "nutrition-information": { + "type": "boolean", + "example": true, + "description": "Show the nutrition information in the UI" + }, + "tools": { + "type": "boolean", + "example": false, + "description": "Show the list of tools in the UI" + } + } + }, + "Config": { + "type": "object", + "description": "An object describing the configuration of the web app", + "properties": { + "folder": { + "type": "string", + "example": "/Recipes", + "description": "The folder in the user's files that contains the recipes" + }, + "update_interval": { + "type": "integer", + "example": 10, + "description": "The interval between automatic rescans to rebuild the database cache in minutes" + }, + "print_image": { + "type": "boolean", + "example": true, + "description": "True, if the user wished to print the recipe images with the rest of the recipes" + }, + "visibleInfoBlocks": { + "$ref": "#/components/schemas/VisibleInfoBlocks" + } + } + }, + "Error": { + "type": "object", + "description": "An error description", + "properties": { + "msg": { + "type": "string", + "description": "The error message", + "example": "Recipe could not be found" + }, + "file": { + "type": "string", + "description": "The file in which the exception was thrown", + "example": "/var/www/custom_apps/cookbook/Service/RecipeService.php" + }, + "line": { + "type": "integer", + "description": "The line where the exception is thrown", + "example": 223 + } + } + }, + "Keyword": { + "type": "object", + "description": "An Keyword", + "allOf": [ + { + "$ref": "#/components/schemas/CategoryInformation" + } + ] + }, + "RecipeStubInformation": { + "type": "object", + "description": "The very basic information of a recipe", + "properties": { + "name": { + "type": "string", + "description": "The name of the recipe", + "example": "Baked bananas" + }, + "keywords": { + "type": "string", + "description": "A comma-separated list of recipe keywords, can be empty string", + "example": "sweets,fruit", + "default": "" + }, + "dateCreated": { + "type": "string", + "description": "The date the recipe was created in the app", + "format": "date-time", + "example": "2022-01-02T16:12:41+0000" + }, + "dateModified": { + "type": "string", + "description": "The date the recipe was modified lastly in the app", + "format": "date-time", + "example": "2022-01-10T10:02:52+0000" + }, + "imageUrl": { + "type": "string", + "description": "The URL of the recipe image", + "example": "http://example.com/path/to/image.jpg", + "default": "" + }, + "imagePlaceholderUrl": { + "type": "string", + "description": "The URL of the placeholder of the recipe image", + "example": "http://example.com/path/to/image_thumb.jpg", + "default": "" + } + }, + "required": [ + "name", + "keywords", + "imageUrl", + "imagePlaceholderUrl", + "dateCreated" + ] + }, + "RecipeStub": { + "type": "object", + "description": "A stub of a recipe with some basic information present", + "allOf": [ + { + "$ref": "#/components/schemas/RecipeStubInformation" + }, + { + "type": "object", + "properties": { + "recipe_id": { + "type": "integer", + "description": "The index of the recipe.", + "example": 123, + "deprecated": true + }, + "id": { + "type": "string", + "description": "The identifier of the recipe", + "example": "1" + } + }, + "required": [ + "recipe_id", + "id", + "id" + ] + } + ] + }, + "StubList": { + "type": "array", + "items": { + "$ref": "#/components/schemas/RecipeStub" + } + }, + "Tool": { + "type": "string", + "example": "Flat and fire-resistent bowl", + "description": "A single tool for a recipe. A tool is not consumed but only used." + }, + "Ingredient": { + "type": "string", + "example": "100g ripe Bananas", + "description": "A single ingredient for a recipe" + }, + "Instruction": { + "type": "string", + "example": "Peel the bananas", + "description": "An instruction step for processing the recipe" + }, + "Nutrition": { + "type": "object", + "properties": { + "@type": { + "type": "string", + "example": "NutritionInformation", + "description": "Schema.org object description", + "default": "NutritionInformation" + }, + "calories": { + "type": "string", + "description": "The number of calories for the given amount", + "example": "650 kcal" + }, + "carbohydrateContent": { + "type": "string", + "description": "The number of grams of carbohydrates", + "example": "300 g" + }, + "cholesterolContent": { + "type": "string", + "description": "The number of milligrams of cholesterol", + "example": "10 g" + }, + "fatContent": { + "type": "string", + "description": "The number of grams of fat", + "example": "45 g" + }, + "fiberContent": { + "type": "string", + "description": "The number of grams of fiber", + "example": "50 g" + }, + "proteinContent": { + "type": "string", + "description": "The number of grams of protein", + "example": "80 g" + }, + "saturatedFatContent": { + "type": "string", + "description": "The number of grams of saturated fat", + "example": "5 g" + }, + "servingSize": { + "type": "string", + "description": "The serving size, in terms of the number of volume or mass", + "example": "One plate, sufficient for one person as dessert" + }, + "sodiumContent": { + "type": "string", + "description": "The number of milligrams of sodium", + "example": "10 mg" + }, + "sugarContent": { + "type": "string", + "description": "The number of grams of sugar", + "example": "5 g" + }, + "transFatContent": { + "type": "string", + "description": "The number of grams of trans fat", + "example": "10 g" + }, + "unsaturatedFatContent": { + "type": "string", + "description": "The number of grams of unsaturated fat", + "example": "40 g" + } + }, + "required": [ + "@type" + ] + }, + "Recipe": { + "description": "A recipe according to [schema.org](http://schema.org/Recipe)", + "allOf": [ + { + "$ref": "#/components/schemas/RecipeStubInformation" + }, + { + "type": "object", + "properties": { + "@type": { + "type": "string", + "example": "Recipe", + "default": "Recipe", + "description": "Schema.org object type identifier" + }, + "id": { + "type": "string", + "description": "The index of the recipe. Note the representation as a string as the representation might change in the future.", + "example": "123", + "nullable": true + }, + "prepTime": { + "type": "string", + "nullable": true, + "description": "The time required for preparation in ISO8601 format", + "example": "PT0H10M" + }, + "cookTime": { + "type": "string", + "nullable": true, + "description": "The time required for cooking in ISO8601 format", + "example": "PT1H20M" + }, + "totalTime": { + "type": "string", + "nullable": true, + "description": "The time required for the complete processing in ISO8601 format", + "example": "PT1H30M" + }, + "description": { + "type": "string", + "example": "A very easy way to make children happy", + "description": "A description of the recipe or the empty string", + "default": "" + }, + "url": { + "type": "string", + "example": "http://exmaple.com/my-recipe.html", + "description": "The URL the recipe was found at or the empty string", + "default": "" + }, + "image": { + "type": "string", + "example": "http://example.com/my-recipe-image.jpeg", + "description": "The URL of the original recipe", + "default": "" + }, + "recipeYield": { + "type": "integer", + "example": 4, + "description": "Number of servings in recipe", + "default": 1 + }, + "recipeCategory": { + "type": "string", + "example": "Dessert", + "description": "The category of the recipe", + "default": "" + }, + "tool": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Tool" + } + }, + "recipeIngredient": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Ingredient" + } + }, + "recipeInstructions": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Instruction" + } + }, + "nutrition": { + "$ref": "#/components/schemas/Nutrition" + } + }, + "required": [ + "id", + "prepTime", + "cookTime", + "totalTime", + "description", + "url", + "recipeYield", + "recipeCategory", + "tool", + "recipeIngredient", + "recipeInstructions", + "nutrition" + ], + "additionalProperties": true + } + ], + "example": { + "name": "Baked bananas", + "@type": "Recipe", + "id": "123", + "description": "A very delightful recipe of the best baked bananas ever", + "image": "http://example.com/path/to/image.jpg", + "recipeYield": 5, + "prepTime": "PT0H15M", + "cookTime": null, + "totalTime": "PT1H20M", + "url": "", + "tool": [], + "recipeIngredient": [ + "3 ripe bananas", + "100g sugar", + "20 teaspoons of cinamon" + ], + "resipeInstructions": [ + "Peel the bananas", + "Dip the bananas in the pot of sugar", + "Put the banans in the oven and let the cinamon soak in for 10 minutes", + "After 5 hours of baking, they are ready" + ], + "recipeCategory": "Dessert", + "keywords": "banana,cinnamon,sweet,untested recipe", + "nutrition": [] + } + }, + "RecipeList": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Recipe" + }, + "example": [ + { + "name": "Baked bananas", + "@type": "Recipe", + "id": "123", + "description": "A very delightful recipe of the best baked bananas ever", + "image": "http://example.com/path/to/image.jpg", + "recipeYield": 5, + "prepTime": "PT0H15M", + "recipeIngredient": [ + "3 ripe bananas", + "100g sugar", + "20 teaspoons of cinamon" + ], + "resipeInstructions": [ + "Peel the bananas", + "Dip the bananas in the pot of sugar", + "Put the banans in the oven and let the cinamon soak in for 10 minutes", + "After 5 hours of baking, they are ready" + ], + "recipeCategory": "Dessert", + "keywords": "banana,cinnamon,sweet,untested recipe" + }, + { + "name": "Homemade Apple Butter", + "@type": "Recipe", + "id": "267", + "author": { + "@type": "Person", + "name": "Julie Clark" + }, + "description": "A simple recipe for Homemade Apple Butter that you can make in the slow cooker. Use as a spread, a syrup or in your fall recipes!", + "datePublished": "2016-09-01T01:58:54+00:00", + "image": "https://www.tastesoflizzyt.com/wp-content/uploads/2016/08/homemade-apple-butter-2-480x270.jpg", + "recipeYield": 20, + "prepTime": "PT0H25M", + "cookTime": "PT10H0M", + "totalTime": "PT10H25M", + "recipeIngredient": [ + "6 1/2 pounds apples (peeled, cored and sliced)", + "1/2 cup granulated sugar", + "1/2 cup packed brown sugar", + "1 1/2 tablespoons ground cinnamon", + "1/4 teaspoon salt", + "1 tablespoon vanilla extract" + ], + "recipeInstructions": [ + "Place the apples in a slow cooker.", + "Add the sugars, cinnamon, salt and vanilla to the crockpot. Mix well.", + "Cook in slow cooker on low for about 10 hours, stirring every couple hours. The apple butter should be thick and dark brown.", + "If desired, use a blender to puree the apple butter until smooth.", + "Cover and refrigerate for up to two weeks or freeze in small containers." + ], + "aggregateRating": { + "@type": "AggregateRating", + "ratingValue": "4.87", + "ratingCount": "38" + }, + "recipeCategory": "Breakfast", + "keywords": "apple butter recipes,apple recipes,fall recipes", + "nutrition": { + "@type": "NutritionInformation", + "calories": "120 kcal", + "carbohydrateContent": "31 g", + "sodiumContent": "32 mg", + "fiberContent": "3 g", + "sugarContent": "25 g", + "servingSize": "1 serving" + }, + "tool": [], + "url": "https://www.tastesoflizzyt.com/homemade-apple-butter/", + "dateModified": "2021-05-23T17:10:25+0000", + "dateCreated": "2021-05-23T17:10:25+0000" + } + ] + }, + "AppVersion": { + "type": "array", + "items": { + "type": "object" + }, + "minItems": 4, + "maxItems": 4, + "description": "The installed release of the cookbook app", + "example": [ + 0, + 9, + 14, + "-rc1" + ] + }, + "APIVersion": { + "type": "object", + "properties": { + "epoch": { + "type": "integer", + "description": "An epoch to cope with bad API versions" + }, + "major": { + "type": "integer", + "description": "The major number of the API" + }, + "minor": { + "type": "integer", + "description": "The minor number of the API" + } + }, + "required": [ + "epoch", + "major", + "minor" + ], + "example": { + "epoch": 0, + "major": 1, + "minor": 3 + } + }, + "Url": { + "type": "object", + "properties": { + "url": { + "type": "string", + "example": "http://www.chefkoch.de/2345" + } + }, + "required": [ + "url" + ] + }, + "Version": { + "type": "object", + "properties": { + "cookbook_version": { + "$ref": "#/components/schemas/AppVersion" + }, + "api_version": { + "$ref": "#/components/schemas/APIVersion" + } + } + } + }, + "securitySchemes": { + "app_password": { + "type": "http", + "scheme": "basic", + "description": "Use username and app password" + } + } + }, + "security": [ + { + "app_password": [] + } + ], + "paths": { + "/index.php/apps/cookbook/api/version": { + "get": { + "tags": [ + "Misc" + ], + "summary": "Get the version of the API endpoint", + "operationId": "version", + "responses": { + "200": { + "description": "API version", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Version" + } + } + } + } + } + } + }, + "/index.php/apps/cookbook/api/v1/reindex": { + "post": { + "tags": [ + "Misc" + ], + "summary": "Trigger a rescan of all recipes into the caching database", + "operationId": "reindex", + "responses": { + "200": { + "description": "The reindex process was done.", + "content": { + "application/json": { + "schema": { + "type": "string", + "example": "Search index rebuilt successfully" + } + } + } + } + } + } + }, + "/index.php/apps/cookbook/api/v1/config": { + "get": { + "tags": [ + "Misc" + ], + "summary": "Get the current configuration of the app", + "operationId": "getConfig", + "responses": { + "200": { + "description": "The config was read successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Config" + } + } + } + } + } + }, + "post": { + "tags": [ + "Misc" + ], + "summary": "Set the configuration for the current user", + "operationId": "setConfig", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Config" + } + } + } + }, + "responses": { + "200": { + "description": "The configuration was successfully saved.", + "content": { + "application/json": { + "schema": { + "type": "string", + "example": "OK" + } + } + } + } + } + } + }, + "/index.php/apps/cookbook/api/v1/import": { + "post": { + "tags": [ + "Recipes" + ], + "summary": "Import a recipe using schema.org metadata from a website", + "operationId": "import", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Url" + } + } + } + }, + "responses": { + "200": { + "description": "Successfully imported recipe", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Recipe" + } + } + } + }, + "400": { + "description": "The URL to be imported was not inserted in the request or any other issue was rosen.", + "content": { + "application/json": { + "schema": { + "type": "string", + "example": "Field \"url\" is required" + } + } + } + }, + "409": { + "description": "There exists a recipe with that name already. Import was aborted.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/index.php/apps/cookbook/api/v1/recipes/{id}/image": { + "get": { + "tags": [ + "Recipes" + ], + "summary": "Get the main image of a recipe. If no image is stored a fallback image is delivered.", + "operationId": "getImage", + "parameters": [ + { + "in": "path", + "name": "id", + "description": "The id of the recipe to obtain the image for.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "size", + "description": "The size of the requested image\n* `full` - Full resolution image (size full res) * `thumb` - thumbnail of the image (size 250px) * `thumb16` - icon of the image (size 16px)\nby default the full size image will be returned\n", + "required": false, + "schema": { + "type": "string", + "enum": [ + "full", + "thumb", + "thumb16" + ] + } + } + ], + "responses": { + "200": { + "description": "Image was obtained and will be in response either as image/jpeg or image/svg+xml", + "content": { + "image/jpeg": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "image/svg+xml": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + }, + "406": { + "description": "The recipe has no image whose MIME type matches the Accept header" + } + } + } + }, + "/index.php/apps/cookbook/api/v1/search/{query}": { + "parameters": [ + { + "in": "path", + "name": "query", + "required": true, + "description": "The search string, urlencoded, separated with spaces and/or commas", + "schema": { + "type": "string" + } + } + ], + "get": { + "tags": [ + "Recipes" + ], + "summary": "Search for recipes for keywords, tags and categories with the named search string", + "operationId": "search", + "responses": { + "200": { + "description": "The recipes were obtained successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StubList" + } + } + } + }, + "500": { + "description": "An error has been thrown", + "content": { + "application/json": { + "schema": { + "type": "string", + "description": "The error message" + } + } + } + } + } + } + }, + "/index.php/apps/cookbook/api/v1/recipes": { + "get": { + "tags": [ + "Recipes" + ], + "summary": "Get all recipes in the database", + "operationId": "listRecipes", + "responses": { + "200": { + "description": "Successfully obtained all recipes", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StubList" + } + } + } + } + } + }, + "post": { + "tags": [ + "Recipes" + ], + "summary": "Create a new recipe", + "operationId": "newRecipe", + "requestBody": { + "description": "A JSON representation of the recipe to be saved.\n\nSee also the structure at https://schema.org/Recipe\n", + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Recipe", + "example": { + "name": "Chips", + "description": "A very delicious way of getting kids quiet", + "ingredients": [ + "1 pack of pre-fried chips" + ], + "tools": [ + "common oven" + ], + "instructions": [ + "Put the chips in the oven", + "Wait until the are due" + ] + } + } + } + } + }, + "responses": { + "200": { + "description": "Successfully created new recipe", + "content": { + "application/json": { + "schema": { + "type": "integer", + "example": 2462, + "description": "The id of the newly created recipe" + } + } + } + }, + "409": { + "description": "A recipe with the name was already found on the server. No recipe is created.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "422": { + "description": "There was no name in the request given for the recipe. Cannot save the recipe.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/index.php/apps/cookbook/api/v1/recipes/{id}": { + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "description": "The id of the recipe", + "schema": { + "type": "string" + } + } + ], + "get": { + "tags": [ + "Recipes" + ], + "summary": "Get a single recipe from the server", + "operationId": "recipeDetails", + "responses": { + "200": { + "description": "Recipe was sucessfully obtained", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Recipe" + } + } + } + }, + "404": { + "description": "The given recipe id was not found", + "content": { + "application/json": { + "schema": { + "type": "integer", + "example": 2345, + "description": "The id of the recipe that was not found" + } + } + } + } + } + }, + "put": { + "tags": [ + "Recipes" + ], + "summary": "Update a recipe", + "operationId": "updateRecipe", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Recipe" + } + } + } + }, + "responses": { + "200": { + "description": "The recipe was sucessfully updated", + "content": { + "application/json": { + "schema": { + "type": "integer", + "description": "The id of the updated recipe", + "example": 2345 + } + } + } + }, + "422": { + "description": "There was no name in the request given for the recipe. Cannot save the recipe.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + }, + "delete": { + "tags": [ + "Recipes" + ], + "summary": "Delete an existing recipe", + "operationId": "deleteRecipe", + "responses": { + "200": { + "description": "The recipe was deleted successfully", + "content": { + "application/json": { + "schema": { + "type": "string", + "example": "Recipe 2345 deleted successfully" + } + } + } + }, + "502": { + "description": "An Exception was thrown", + "content": { + "application/json": { + "schema": { + "type": "string", + "example": "Recipe with id 2345 was not found.", + "description": "Error message" + } + } + } + } + } + } + }, + "/index.php/apps/cookbook/api/v1/keywords": { + "get": { + "tags": [ + "Tags" + ], + "summary": "Get all known keywords", + "operationId": "listKeywords", + "responses": { + "200": { + "description": "Successfully obtained all keywords", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Keyword" + } + } + } + } + } + } + } + }, + "/index.php/apps/cookbook/api/v1/tags/{keywords}": { + "get": { + "tags": [ + "Tags" + ], + "summary": "Get all recipes associated with certain keywords", + "operationId": "recipesWithKeyword", + "parameters": [ + { + "in": "path", + "name": "keywords", + "required": true, + "description": "Comma separated list of keywords, urlencoded", + "schema": { + "type": "string", + "example": "vegetarian,sweet" + } + } + ], + "responses": { + "200": { + "description": "Recipes were successfully obtained", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StubList" + } + } + } + }, + "500": { + "description": "An error occured", + "content": { + "application/json": { + "schema": { + "type": "string", + "example": "SQLException: Something went wrong." + } + } + } + } + } + } + }, + "/index.php/apps/cookbook/api/v1/categories": { + "get": { + "tags": [ + "Categories" + ], + "summary": "Get all known categories", + "operationId": "listCategories", + "responses": { + "200": { + "description": "Sucessfully obtained all categories\n\nPlease note: A category name of `*` indicates the number of recipes with no category associated.", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Category" + } + }, + "example": [ + { + "name": "Dinner", + "recipe_count": 21 + }, + { + "name": "Lunch", + "recipe_count": 10 + }, + { + "name": "*", + "recipe_count": 3 + } + ] + } + } + } + } + } + }, + "/index.php/apps/cookbook/api/v1/category/{category}": { + "get": { + "tags": [ + "Categories" + ], + "summary": "Get all recipes of a certain category", + "operationId": "recipesInCategory", + "parameters": [ + { + "in": "path", + "name": "category", + "required": true, + "description": "The name of the category to be queried as urlencoded string\n\nPut the string `_` to obtain all recipes with no category", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The filtered recipes belonging to the category", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StubList" + } + } + } + }, + "500": { + "description": "An exception was issued.", + "content": { + "application/json": { + "schema": { + "type": "string", + "description": "The error message", + "example": "Could not find category foo." + } + } + } + } + } + }, + "put": { + "tags": [ + "Categories" + ], + "summary": "Rename a category", + "operationId": "renameCategory", + "parameters": [ + { + "in": "path", + "name": "category", + "required": true, + "description": "The name of the category to be queried as urlencoded string\n\nPut the string `_` to obtain all recipes with no category", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "example": "Lunch", + "description": "The new name to rename the category to" + } + }, + "required": [ + "name" + ] + } + } + } + }, + "responses": { + "200": { + "description": "The category was renamed successfully", + "content": { + "application/json": { + "schema": { + "type": "string", + "example": "Lunch" + } + } + } + }, + "400": { + "description": "The new category name was not included during the request." + }, + "500": { + "description": "The renaming did not succeed.", + "content": { + "application/json": { + "schema": { + "type": "string", + "description": "The error message", + "example": "There exists already a category of that name." + } + } + } + } + } + } + } + } +} diff --git a/packages/nextcloud/lib/src/helpers/cookbook.dart b/packages/nextcloud/lib/src/helpers/cookbook.dart new file mode 100644 index 00000000000..dc9bdc4e107 --- /dev/null +++ b/packages/nextcloud/lib/src/helpers/cookbook.dart @@ -0,0 +1,35 @@ +import 'package:built_collection/built_collection.dart'; +import 'package:nextcloud/src/api/cookbook.openapi.dart' as cookbook; +import 'package:nextcloud/src/helpers/common.dart'; +import 'package:version/version.dart'; + +/// Minimum version of the cookbook app supported. +final minAppVersion = Version(0, 11, 1); + +/// Extension for checking the version compatibility of the installed cookbook app. +extension CookbookVersionCheck on cookbook.$Client { + /// Check if the cookbook app version is supported by this client. + /// + /// Also returns the supported APP version. + Future getVersionCheck() async { + final response = await misc.version(); + final version = response.body.cookbookVersion; + + BuiltList? versions; + if (version != null) { + versions = BuiltList([ + Version( + version[0].asNum as int, + version[1].asNum as int, + version[2].asNum as int, + ), + ]); + } + + return VersionCheck( + versions: versions, + minimumVersion: minAppVersion, + maximumMajor: null, + ); + } +} diff --git a/packages/nextcloud/lib/src/patches/cookbook/0-app-version.json b/packages/nextcloud/lib/src/patches/cookbook/0-app-version.json new file mode 100644 index 00000000000..cc68f319b81 --- /dev/null +++ b/packages/nextcloud/lib/src/patches/cookbook/0-app-version.json @@ -0,0 +1,29 @@ +[ + { + "op": "remove", + "path": "/components/schemas/PreReleaseVersion" + }, + { + "op": "remove", + "path": "/components/schemas/ReleaseVersion" + }, + { + "op": "replace", + "path": "/components/schemas/AppVersion", + "value": { + "type": "array", + "items": { + "type": "object" + }, + "minItems": 4, + "maxItems": 4, + "description": "The installed release of the cookbook app", + "example": [ + 0, + 9, + 14, + "-rc1" + ] + } + } +] diff --git a/packages/nextcloud/lib/src/patches/cookbook/1-recipe-stub-required.json b/packages/nextcloud/lib/src/patches/cookbook/1-recipe-stub-required.json new file mode 100644 index 00000000000..346ab97fe23 --- /dev/null +++ b/packages/nextcloud/lib/src/patches/cookbook/1-recipe-stub-required.json @@ -0,0 +1,7 @@ +[ + { + "op": "add", + "path": "/components/schemas/RecipeStub/allOf/1/required/1", + "value": "id" + } +] diff --git a/packages/nextcloud/lib/src/patches/cookbook/2-recipe-id-integer.json b/packages/nextcloud/lib/src/patches/cookbook/2-recipe-id-integer.json new file mode 100644 index 00000000000..9f42cf6a2ea --- /dev/null +++ b/packages/nextcloud/lib/src/patches/cookbook/2-recipe-id-integer.json @@ -0,0 +1,17 @@ +[ + { + "op": "replace", + "path": "/components/schemas/RecipeStub/allOf/1/properties/recipe_id/description", + "value": "The index of the recipe." + }, + { + "op": "replace", + "path": "/paths/~1index.php~1apps~1cookbook~1api~1v1~1recipes~1{id}/parameters/0/schema/type", + "value": "string" + }, + { + "op": "replace", + "path": "/paths/~1index.php~1apps~1cookbook~1api~1v1~1recipes~1{id}~1image/get/parameters/0/schema/type", + "value": "string" + } +] diff --git a/packages/nextcloud/pubspec.yaml b/packages/nextcloud/pubspec.yaml index 7002bb01c98..afeabe4e8de 100644 --- a/packages/nextcloud/pubspec.yaml +++ b/packages/nextcloud/pubspec.yaml @@ -33,6 +33,7 @@ dependencies: dev_dependencies: build_runner: ^2.4.11 built_value_generator: ^8.9.2 + built_value_test: ^8.9.2 dynamite: ^0.4.0 mocktail: ^1.0.4 neon_lints: diff --git a/packages/nextcloud/test/cookbook_test.dart b/packages/nextcloud/test/cookbook_test.dart new file mode 100644 index 00000000000..1a87b435f38 --- /dev/null +++ b/packages/nextcloud/test/cookbook_test.dart @@ -0,0 +1,192 @@ +import 'package:built_value/json_object.dart'; +import 'package:built_value_test/matcher.dart'; +import 'package:nextcloud/cookbook.dart' as cookbook; +import 'package:nextcloud/nextcloud.dart'; +import 'package:nextcloud/src/api/cookbook.openapi.dart'; +import 'package:nextcloud_test/nextcloud_test.dart'; +import 'package:test/test.dart'; + +void main() { + presets( + 'cookbook', + 'cookbook', + (preset) { + late DockerContainer container; + late NextcloudClient client; + + setUp(() async { + container = await DockerContainer.create(preset); + client = await TestNextcloudClient.create(container); + }); + + tearDown(() async { + await container.destroy(); + }); + + group('CookbookVersionCheck', () { + test('Is supported', () async { + final response = await client.cookbook.getVersionCheck(); + + expect(response.isSupported, isTrue); + }); + }); + + group('categories', () { + test('listCategories', () async { + final response = await client.cookbook.categories.listCategories(); + + expect(response.body, hasLength(7)); + }); + + test('recipesInCategory', () async { + final response = await client.cookbook.categories.recipesInCategory(category: 'Soup'); + + expect(response.body, hasLength(2)); + }); + + test('renameCategory', () async { + final request = cookbook.RenameCategoryRequestApplicationJsonBuilder()..name = 'Delicious Soup'; + + final response = await client.cookbook.categories.renameCategory( + category: 'Soup', + $body: request.build(), + ); + + expect(response.body, request.name); + }); + }); + + group('misc', () { + test('getConfig', () async { + final response = await client.cookbook.misc.getConfig(); + final visibleInfoBlocks = cookbook.VisibleInfoBlocksBuilder() + ..preparationTime = true + ..cookingTime = true + ..totalTime = true + ..nutritionInformation = true + ..tools = true; + final expected = cookbook.ConfigBuilder() + ..folder = '/Recipes' + ..updateInterval = 5 + ..printImage = true + ..visibleInfoBlocks = visibleInfoBlocks; + + expect(response.body, equalsBuilt(expected.build())); + }); + + test('reindex', () async { + final response = await client.cookbook.misc.reindex(); + + expect(response.body, 'Search index rebuilt successfully'); + }); + + test('setConfig', () async { + final config = cookbook.ConfigBuilder()..folder = '/'; + final response = await client.cookbook.misc.setConfig($body: config.build()); + + expect(response.body, 'OK'); + }); + + test('version', () async { + final response = await client.cookbook.misc.version(); + + final cookbookVersion = response.body.cookbookVersion!; + expect(cookbookVersion[0], JsonObject(preset.version.major)); + expect(cookbookVersion[1], JsonObject(preset.version.minor)); + }); + }); + + group('recipes', () { + test('callImport', () async { + final url = cookbook.UrlBuilder()..url = 'http://localhost/static/recipe.html'; + final response = await client.cookbook.recipes.$import($body: url.build()); + + expect(response.body, isA()); + }); + + test('deleteRecipe', () async { + const id = '0'; + final response = await client.cookbook.recipes.deleteRecipe(id: id); + + expect(response.body, equals('Recipe $id deleted successfully')); + }); + + test('getImage', () async { + final recipes = await client.cookbook.recipes.listRecipes(); + final recipeWithoutImage = recipes.body.firstWhere((stub) => stub.name == 'Recipe Without an image'); + final response = await client.cookbook.recipes.getImage( + id: recipeWithoutImage.id, + ); + + expect(response.body, isNotNull); + + final recipeWithImage = recipes.body.firstWhere((stub) => stub.name == "Chef John's Gazpacho"); + final response2 = await client.cookbook.recipes.getImage( + id: recipeWithImage.id, + size: GetImageSize.full, + ); + + expect(response2.body, isNotNull); + }); + + test('listRecipes', () async { + final response = await client.cookbook.recipes.listRecipes(); + + expect(response.body, hasLength(19)); + }); + + test('newRecipe', () async { + final recipe = cookbook.RecipeBuilder() + ..name = 'My super cool recipe' + ..dateCreated = DateTime.utc(2023).toIso8601String(); + final response = await client.cookbook.recipes.newRecipe($body: recipe.build()); + + expect(response.body, isNotNull); + }); + + test('recipeDetails', () async { + final recipes = await client.cookbook.recipes.listRecipes(); + + for (final recipe in recipes.body) { + final response = await client.cookbook.recipes.recipeDetails( + id: recipe.id, + ); + + expect(response.body, isNotNull); + } + }); + + test('search', () async { + final response = await client.cookbook.recipes.search(query: 'Vegan'); + + expect(response.body, hasLength(2)); + }); + + test('updateRecipe', () async { + final recipe = cookbook.RecipeBuilder() + ..name = 'My super cool recipe' + ..dateCreated = DateTime.utc(2023).toIso8601String(); + final response = await client.cookbook.recipes.updateRecipe(id: '0', $body: recipe.build()); + + expect(response.body, isNotNull); + }); + }); + + group('tags', () { + test('listKeywords', () async { + final response = await client.cookbook.tags.listKeywords(); + + expect(response.body, hasLength(16)); + }); + + test('recipesWithKeyword', () async { + final response = await client.cookbook.tags.recipesWithKeyword(keywords: 'Desserts'); + + expect(response.body, hasLength(0)); + }); + }); + }, + retry: retryCount, + timeout: timeout, + ); +} diff --git a/packages/nextcloud/test/core_test.dart b/packages/nextcloud/test/core_test.dart index 88e439c040c..c414934aa32 100644 --- a/packages/nextcloud/test/core_test.dart +++ b/packages/nextcloud/test/core_test.dart @@ -85,15 +85,21 @@ void main() { final response = await client.core.navigation.getAppsNavigation(); expect(response.statusCode, 200); expect(() => response.headers, isA()); - expect(response.body.ocs.data, hasLength(7)); - - expect(response.body.ocs.data[0].id, 'dashboard'); - expect(response.body.ocs.data[1].id, 'files'); - expect(response.body.ocs.data[2].id, 'photos'); - expect(response.body.ocs.data[3].id, 'activity'); - expect(response.body.ocs.data[4].id, 'spreed'); - expect(response.body.ocs.data[5].id, 'notes'); - expect(response.body.ocs.data[6].id, 'news'); + expect(response.body.ocs.data, hasLength(8)); + + expect( + response.body.ocs.data.map((e) => e.id), + containsAllInOrder([ + 'dashboard', + 'files', + 'photos', + 'activity', + 'spreed', + 'notes', + 'news', + 'cookbook', + ]), + ); }); }); diff --git a/packages/nextcloud/test/fixtures/cookbook/categories/test_listcategories.regexp b/packages/nextcloud/test/fixtures/cookbook/categories/test_listcategories.regexp new file mode 100644 index 00000000000..42dc1da7db8 --- /dev/null +++ b/packages/nextcloud/test/fixtures/cookbook/categories/test_listcategories.regexp @@ -0,0 +1,3 @@ +GET http://localhost/index\.php/apps/cookbook/api/v1/categories +accept: application/json +authorization: Basic mock \ No newline at end of file diff --git a/packages/nextcloud/test/fixtures/cookbook/categories/test_recipesincategory.regexp b/packages/nextcloud/test/fixtures/cookbook/categories/test_recipesincategory.regexp new file mode 100644 index 00000000000..89c27139678 --- /dev/null +++ b/packages/nextcloud/test/fixtures/cookbook/categories/test_recipesincategory.regexp @@ -0,0 +1,3 @@ +GET http://localhost/index\.php/apps/cookbook/api/v1/category/Soup +accept: application/json +authorization: Basic mock \ No newline at end of file diff --git a/packages/nextcloud/test/fixtures/cookbook/categories/test_renamecategory.regexp b/packages/nextcloud/test/fixtures/cookbook/categories/test_renamecategory.regexp new file mode 100644 index 00000000000..b6cc835da22 --- /dev/null +++ b/packages/nextcloud/test/fixtures/cookbook/categories/test_renamecategory.regexp @@ -0,0 +1,5 @@ +PUT http://localhost/index\.php/apps/cookbook/api/v1/category/Soup +accept: application/json +authorization: Basic mock +content-type: application/json; charset=utf-8 +\{"name":"Delicious Soup"\} \ No newline at end of file diff --git a/packages/nextcloud/test/fixtures/cookbook/cookbookversioncheck/is_supported.regexp b/packages/nextcloud/test/fixtures/cookbook/cookbookversioncheck/is_supported.regexp new file mode 100644 index 00000000000..c79c54c37d4 --- /dev/null +++ b/packages/nextcloud/test/fixtures/cookbook/cookbookversioncheck/is_supported.regexp @@ -0,0 +1,3 @@ +GET http://localhost/index\.php/apps/cookbook/api/version +accept: application/json +authorization: Basic mock \ No newline at end of file diff --git a/packages/nextcloud/test/fixtures/cookbook/misc/test_getconfig.regexp b/packages/nextcloud/test/fixtures/cookbook/misc/test_getconfig.regexp new file mode 100644 index 00000000000..f6aec6e0934 --- /dev/null +++ b/packages/nextcloud/test/fixtures/cookbook/misc/test_getconfig.regexp @@ -0,0 +1,3 @@ +GET http://localhost/index\.php/apps/cookbook/api/v1/config +accept: application/json +authorization: Basic mock \ No newline at end of file diff --git a/packages/nextcloud/test/fixtures/cookbook/misc/test_reindex.regexp b/packages/nextcloud/test/fixtures/cookbook/misc/test_reindex.regexp new file mode 100644 index 00000000000..5c3adcfb24a --- /dev/null +++ b/packages/nextcloud/test/fixtures/cookbook/misc/test_reindex.regexp @@ -0,0 +1,3 @@ +POST http://localhost/index\.php/apps/cookbook/api/v1/reindex +accept: application/json +authorization: Basic mock \ No newline at end of file diff --git a/packages/nextcloud/test/fixtures/cookbook/misc/test_setconfig.regexp b/packages/nextcloud/test/fixtures/cookbook/misc/test_setconfig.regexp new file mode 100644 index 00000000000..2fd4a424641 --- /dev/null +++ b/packages/nextcloud/test/fixtures/cookbook/misc/test_setconfig.regexp @@ -0,0 +1,5 @@ +POST http://localhost/index\.php/apps/cookbook/api/v1/config +accept: application/json +authorization: Basic mock +content-type: application/json; charset=utf-8 +\{"folder":"/"\} \ No newline at end of file diff --git a/packages/nextcloud/test/fixtures/cookbook/misc/test_version.regexp b/packages/nextcloud/test/fixtures/cookbook/misc/test_version.regexp new file mode 100644 index 00000000000..c79c54c37d4 --- /dev/null +++ b/packages/nextcloud/test/fixtures/cookbook/misc/test_version.regexp @@ -0,0 +1,3 @@ +GET http://localhost/index\.php/apps/cookbook/api/version +accept: application/json +authorization: Basic mock \ No newline at end of file diff --git a/packages/nextcloud/test/fixtures/cookbook/recipes/callimport.regexp b/packages/nextcloud/test/fixtures/cookbook/recipes/callimport.regexp new file mode 100644 index 00000000000..8c76767b471 --- /dev/null +++ b/packages/nextcloud/test/fixtures/cookbook/recipes/callimport.regexp @@ -0,0 +1,5 @@ +POST http://localhost/index\.php/apps/cookbook/api/v1/import +accept: application/json +authorization: Basic mock +content-type: application/json; charset=utf-8 +\{"url":"http://localhost/static/recipe\.html"\} \ No newline at end of file diff --git a/packages/nextcloud/test/fixtures/cookbook/recipes/test_callimport.regexp b/packages/nextcloud/test/fixtures/cookbook/recipes/test_callimport.regexp new file mode 100644 index 00000000000..192fcfd0e16 --- /dev/null +++ b/packages/nextcloud/test/fixtures/cookbook/recipes/test_callimport.regexp @@ -0,0 +1,5 @@ +POST http://localhost/index\.php/apps/cookbook/api/v1/import +accept: application/json +authorization: Basic mock +content-type: application/json; charset=utf-8 +\{"url":"https://www\.chefkoch\.de/rezepte/126221054029392/Germknoedel-mit-Powidl\.html"\} \ No newline at end of file diff --git a/packages/nextcloud/test/fixtures/cookbook/recipes/test_deleterecipe.regexp b/packages/nextcloud/test/fixtures/cookbook/recipes/test_deleterecipe.regexp new file mode 100644 index 00000000000..a198deb5489 --- /dev/null +++ b/packages/nextcloud/test/fixtures/cookbook/recipes/test_deleterecipe.regexp @@ -0,0 +1,3 @@ +DELETE http://localhost/index\.php/apps/cookbook/api/v1/recipes/0 +accept: application/json +authorization: Basic mock \ No newline at end of file diff --git a/packages/nextcloud/test/fixtures/cookbook/recipes/test_getimage.regexp b/packages/nextcloud/test/fixtures/cookbook/recipes/test_getimage.regexp new file mode 100644 index 00000000000..a42f5b1d16e --- /dev/null +++ b/packages/nextcloud/test/fixtures/cookbook/recipes/test_getimage.regexp @@ -0,0 +1,9 @@ +GET http://localhost/index\.php/apps/cookbook/api/v1/recipes +accept: application/json +authorization: Basic mock +GET http://localhost/index\.php/apps/cookbook/api/v1/recipes/[0-9]+/image +accept: image/jpeg,image/svg\+xml +authorization: Basic mock +GET http://localhost/index\.php/apps/cookbook/api/v1/recipes/[0-9]+/image\?size=full +accept: image/jpeg,image/svg\+xml +authorization: Basic mock \ No newline at end of file diff --git a/packages/nextcloud/test/fixtures/cookbook/recipes/test_listrecipes.regexp b/packages/nextcloud/test/fixtures/cookbook/recipes/test_listrecipes.regexp new file mode 100644 index 00000000000..a5f09542969 --- /dev/null +++ b/packages/nextcloud/test/fixtures/cookbook/recipes/test_listrecipes.regexp @@ -0,0 +1,3 @@ +GET http://localhost/index\.php/apps/cookbook/api/v1/recipes +accept: application/json +authorization: Basic mock \ No newline at end of file diff --git a/packages/nextcloud/test/fixtures/cookbook/recipes/test_newrecipe.regexp b/packages/nextcloud/test/fixtures/cookbook/recipes/test_newrecipe.regexp new file mode 100644 index 00000000000..acba3ce5e68 --- /dev/null +++ b/packages/nextcloud/test/fixtures/cookbook/recipes/test_newrecipe.regexp @@ -0,0 +1,5 @@ +POST http://localhost/index\.php/apps/cookbook/api/v1/recipes +accept: application/json +authorization: Basic mock +content-type: application/json; charset=utf-8 +\{"@type":"Recipe","description":"","url":"","image":"","recipeYield":1,"recipeCategory":"","tool":\[\],"recipeIngredient":\[\],"recipeInstructions":\[\],"nutrition":\{"@type":"NutritionInformation"\},"name":"My super cool recipe","keywords":"","dateCreated":"2023-01-01T00:00:00\.000Z","imageUrl":"","imagePlaceholderUrl":""\} \ No newline at end of file diff --git a/packages/nextcloud/test/fixtures/cookbook/recipes/test_recipedetails.regexp b/packages/nextcloud/test/fixtures/cookbook/recipes/test_recipedetails.regexp new file mode 100644 index 00000000000..2ebf6810af6 --- /dev/null +++ b/packages/nextcloud/test/fixtures/cookbook/recipes/test_recipedetails.regexp @@ -0,0 +1,60 @@ +GET http://localhost/index\.php/apps/cookbook/api/v1/recipes +accept: application/json +authorization: Basic mock +GET http://localhost/index\.php/apps/cookbook/api/v1/recipes/[0-9]+ +accept: application/json +authorization: Basic mock +GET http://localhost/index\.php/apps/cookbook/api/v1/recipes/[0-9]+ +accept: application/json +authorization: Basic mock +GET http://localhost/index\.php/apps/cookbook/api/v1/recipes/[0-9]+ +accept: application/json +authorization: Basic mock +GET http://localhost/index\.php/apps/cookbook/api/v1/recipes/[0-9]+ +accept: application/json +authorization: Basic mock +GET http://localhost/index\.php/apps/cookbook/api/v1/recipes/[0-9]+ +accept: application/json +authorization: Basic mock +GET http://localhost/index\.php/apps/cookbook/api/v1/recipes/[0-9]+ +accept: application/json +authorization: Basic mock +GET http://localhost/index\.php/apps/cookbook/api/v1/recipes/[0-9]+ +accept: application/json +authorization: Basic mock +GET http://localhost/index\.php/apps/cookbook/api/v1/recipes/[0-9]+ +accept: application/json +authorization: Basic mock +GET http://localhost/index\.php/apps/cookbook/api/v1/recipes/[0-9]+ +accept: application/json +authorization: Basic mock +GET http://localhost/index\.php/apps/cookbook/api/v1/recipes/[0-9]+ +accept: application/json +authorization: Basic mock +GET http://localhost/index\.php/apps/cookbook/api/v1/recipes/[0-9]+ +accept: application/json +authorization: Basic mock +GET http://localhost/index\.php/apps/cookbook/api/v1/recipes/[0-9]+ +accept: application/json +authorization: Basic mock +GET http://localhost/index\.php/apps/cookbook/api/v1/recipes/[0-9]+ +accept: application/json +authorization: Basic mock +GET http://localhost/index\.php/apps/cookbook/api/v1/recipes/[0-9]+ +accept: application/json +authorization: Basic mock +GET http://localhost/index\.php/apps/cookbook/api/v1/recipes/[0-9]+ +accept: application/json +authorization: Basic mock +GET http://localhost/index\.php/apps/cookbook/api/v1/recipes/[0-9]+ +accept: application/json +authorization: Basic mock +GET http://localhost/index\.php/apps/cookbook/api/v1/recipes/[0-9]+ +accept: application/json +authorization: Basic mock +GET http://localhost/index\.php/apps/cookbook/api/v1/recipes/[0-9]+ +accept: application/json +authorization: Basic mock +GET http://localhost/index\.php/apps/cookbook/api/v1/recipes/[0-9]+ +accept: application/json +authorization: Basic mock \ No newline at end of file diff --git a/packages/nextcloud/test/fixtures/cookbook/recipes/test_search.regexp b/packages/nextcloud/test/fixtures/cookbook/recipes/test_search.regexp new file mode 100644 index 00000000000..5b3eb4b2922 --- /dev/null +++ b/packages/nextcloud/test/fixtures/cookbook/recipes/test_search.regexp @@ -0,0 +1,3 @@ +GET http://localhost/index\.php/apps/cookbook/api/v1/search/Vegan +accept: application/json +authorization: Basic mock \ No newline at end of file diff --git a/packages/nextcloud/test/fixtures/cookbook/recipes/test_updaterecipe.regexp b/packages/nextcloud/test/fixtures/cookbook/recipes/test_updaterecipe.regexp new file mode 100644 index 00000000000..544ebbf5fba --- /dev/null +++ b/packages/nextcloud/test/fixtures/cookbook/recipes/test_updaterecipe.regexp @@ -0,0 +1,5 @@ +PUT http://localhost/index\.php/apps/cookbook/api/v1/recipes/0 +accept: application/json +authorization: Basic mock +content-type: application/json; charset=utf-8 +\{"@type":"Recipe","description":"","url":"","image":"","recipeYield":1,"recipeCategory":"","tool":\[\],"recipeIngredient":\[\],"recipeInstructions":\[\],"nutrition":\{"@type":"NutritionInformation"\},"name":"My super cool recipe","keywords":"","dateCreated":"2023-01-01T00:00:00\.000Z","imageUrl":"","imagePlaceholderUrl":""\} \ No newline at end of file diff --git a/packages/nextcloud/test/fixtures/cookbook/tags/test_listkeywords.regexp b/packages/nextcloud/test/fixtures/cookbook/tags/test_listkeywords.regexp new file mode 100644 index 00000000000..771607c1463 --- /dev/null +++ b/packages/nextcloud/test/fixtures/cookbook/tags/test_listkeywords.regexp @@ -0,0 +1,3 @@ +GET http://localhost/index\.php/apps/cookbook/api/v1/keywords +accept: application/json +authorization: Basic mock \ No newline at end of file diff --git a/packages/nextcloud/test/fixtures/cookbook/tags/test_recipeswithkeyword.regexp b/packages/nextcloud/test/fixtures/cookbook/tags/test_recipeswithkeyword.regexp new file mode 100644 index 00000000000..508250ba7c1 --- /dev/null +++ b/packages/nextcloud/test/fixtures/cookbook/tags/test_recipeswithkeyword.regexp @@ -0,0 +1,3 @@ +GET http://localhost/index\.php/apps/cookbook/api/v1/tags/Desserts +accept: application/json +authorization: Basic mock \ No newline at end of file diff --git a/packages/nextcloud_test/bin/generate_presets.dart b/packages/nextcloud_test/bin/generate_presets.dart index 7f5568bf603..01ca8b74864 100644 --- a/packages/nextcloud_test/bin/generate_presets.dart +++ b/packages/nextcloud_test/bin/generate_presets.dart @@ -8,6 +8,7 @@ import 'package:version/version.dart'; Future main() async { const appIDs = [ + 'cookbook', 'news', 'notes', 'spreed', diff --git a/packages/nextcloud_test/docker/Dockerfile b/packages/nextcloud_test/docker/Dockerfile index 7a47a8019a5..fcca04e5593 100644 --- a/packages/nextcloud_test/docker/Dockerfile +++ b/packages/nextcloud_test/docker/Dockerfile @@ -21,6 +21,11 @@ RUN (sh /entrypoint.sh php -S 0.0.0.0:80 &) && \ for user in admin user1 user2; do curl -u "$user:$user" -H "ocs-apirequest: true" -s -o /dev/null http://localhost/ocs/v2.php/cloud/user; done COPY static /usr/src/nextcloud/static +COPY assets/Recipes /usr/src/nextcloud/data/admin/files/Recipes +COPY assets/Recipes /usr/src/nextcloud/data/user1/files/Recipes +COPY assets/Recipes /usr/src/nextcloud/data/user2/files/Recipes + +RUN ./occ files:scan --all ENV PHP_CLI_SERVER_WORKERS=10 CMD ["php", "-S", "0.0.0.0:80"] @@ -28,6 +33,11 @@ CMD ["php", "-S", "0.0.0.0:80"] FROM alpine:latest@sha256:b89d9c93e9ed3597455c90a0b88a8bbb5cb7188438f70953fede212a0c4394e0 AS apps RUN apk add curl + +FROM apps AS cookbook +ARG COOKBOOK_URL +RUN curl -L "$COOKBOOK_URL" | tar -xz -C / + FROM apps AS news ARG NEWS_URL RUN curl -L "$NEWS_URL" | tar -xz -C / @@ -50,6 +60,9 @@ RUN curl -L "$DROP_ACCOUNT_URL" | tar -xz -C / FROM nextcloud +COPY --from=cookbook /cookbook /usr/src/nextcloud/apps/cookbook +RUN ./occ app:enable cookbook + COPY --from=news /news /usr/src/nextcloud/apps/news RUN ./occ app:enable news diff --git a/packages/nextcloud_test/docker/assets/Recipes/Bauernbrot mit Sauerteig/recipe.json b/packages/nextcloud_test/docker/assets/Recipes/Bauernbrot mit Sauerteig/recipe.json new file mode 100644 index 00000000000..fd53b44b132 --- /dev/null +++ b/packages/nextcloud_test/docker/assets/Recipes/Bauernbrot mit Sauerteig/recipe.json @@ -0,0 +1,101 @@ +{ + "@context": "http:\/\/schema.org", + "@type": "Recipe", + "image": "https:\/\/img.chefkoch-cdn.de\/rezepte\/1769311286873269\/bilder\/1314890\/crop-960x540\/bauernbrot-mit-sauerteig.jpg", + "recipeCategory": "Brot und Br\u00f6tchen", + "recipeIngredient": [ + "400 g Roggenmehl , 997, alternativ 1150", + "400 ml Wasser", + "80 g Sauerteig , (aktives Roggen - ASG)", + "400 g Roggenmehl , 997, alternativ 1150", + "300 g Weizenmehl , 550", + "3 TL, gestr. Salz", + "800 g Sauerteig , vorbereiter Ansatz", + "2 g Hefe ( je nach aktivit\u00e4t des Sauerteiges)", + "6 g Malz , (Roggenmalz)", + "300 g Wasser , lauwarmes" + ], + "name": "Bauernbrot mit Sauerteig", + "description": "Bauernbrot mit Sauerteig - gelingsicheres Roggenbrot. \u00dcber 150 Bewertungen und f\u00fcr mega befunden. Mit \u25ba Portionsrechner \u25ba Kochbuch \u25ba Video-Tipps!", + "recipeInstructions": [ + "F\u00fcr den Sauerteigansatz Roggenmehl, Wasser und aktives Roggen-ASG miteinander verr\u00fchren und bei Zimmertemperatur \u00fcber Nacht, am besten 15 - 17 Stunden stehen lassen.", + "Beide Mehlsorten in einer R\u00fchrsch\u00fcssel vermischen und in die Mitte eine Mulde dr\u00fccken. Das Salz und das Roggenmalz an den Rand streuen. Ggf. 1 - 20 g Hefe (ich verwende gar keine Hefe, da mein ASG sehr aktiv ist) mit dem lauwarmen Wasser verschl\u00e4mmen und in die Mulde gie\u00dfen. Den Sauerteigansatz dazugeben und alles in der Knetmaschine 5-10 Minuten kneten. Danach folgt eine Teigruhe von 30 Minuten.", + "Den Teig aus der Sch\u00fcssel nehmen und auf der Arbeitsfl\u00e4che kr\u00e4ftig kneten und rund wirken. Der Teig klebt kaum. Den Teig in zwei Portionen teilen, diese in gut bemehlten G\u00e4rk\u00f6rbchen mit dem Schluss nach oben zur Gare stellen.", + "Nach 60 Minuten, je nach Zugabe von Hefe (Fingerprobe), das Brot auf einen Schie\u00dfer st\u00fcrzen, einschneiden und in den auf gut 250\u00b0 vorgeheizten Backofen oder auf einen Backstein schie\u00dfen. In den ersten 15 Minuten mit kr\u00e4ftigen Schwaden anbacken, dann die Schwaden ablassen und das Brot in ca. 60 Minuten bei 200\u00b0 fertig backen. Ca. 10 Minuten vor Ende der Backzeit die Ofent\u00fcr leicht \u00f6ffnen (einen Kochl\u00f6ffelstiel dazwischen klemmen) und zu Ende backen.", + "Klopftest: Das Brot sollte an der Unterseite sch\u00f6n hohl klingen, wenn man dagegen klopft.", + "Ergibt zwei kleine Roggenbrote \u00e0 750 g." + ], + "author": { + "@type": "Person", + "name": "zaubermaus558" + }, + "publisher": { + "@type": "Organization", + "name": "Chefkoch.de" + }, + "datePublished": "2010-10-13", + "prepTime": "PT0H30M", + "totalTime": "PT17H30M", + "recipeYield": 1, + "aggregateRating": { + "@type": "AggregateRating", + "ratingCount": 150, + "ratingValue": 4.7, + "reviewCount": 262, + "worstRating": 0, + "bestRating": 5 + }, + "keywords": "Backen,Brot oder Br\u00f6tchen", + "reviews": [ + { + "@type": "Review", + "reviewBody": "Liebe Zaubermaus558,\r\nvielen Dank f\u00fcr dieses tolle und einfache Brotrezept.\r\nIch habe ein ASG geschenkt bekommen und wollte nun auch mal ein Sauerteigbrot backen. Einen G\u00e4rkorb habe ich mir dann auch angeschafft und heute wurde gebacken.\r\nMein G\u00e4rkorb ist gro\u00df genug und ich habe es gefragt, ein gro\u00dfes Brot zu backen.\r\nWas soll ich sagen, es hat alles funktioniert, ganz ohne klebrigen Teig.\r\nDie Backzeit habe ich trotz Gr\u00f6\u00dfe nicht ver\u00e4ndert. Es hat auch ohne Schieber und Backstein geklappt, habe es auf das vorgeheizte Backblech gest\u00fcrzt. Ist wundersch\u00f6n in Form geblieben, ohne zu zerlaufen.\r\nKaum war mein Brot fertig, stand mein Vater spontan an der T\u00fcr (vom himmlischen Duft angezogen). Nat\u00fcrlich musste ich ihm ein St\u00fcck vom frischen Brot mitgeben. Au\u00dfen sehr knusprig und innen wunderbar fluffig. Bei der Gr\u00f6\u00dfe des Brotes gibt man ja gerne etwas ab.\r\nIch bin sehr begeistert.\r\nIch pflege mein ASG liebevoll weiter und bleibe beim Brotbacken.\r\nDenke jetzt mal \u00fcber die Anschaffung eines Backsteins nach!\r\nDanke auch an alle USER f\u00fcr die wertvollen Tipps\ud83d\ude4f!\r\nLiebe Gr\u00fc\u00dfe !", + "datePublished": "2021-12-13", + "author": { + "@type": "Person", + "name": "Djangolinchen" + } + }, + { + "@type": "Review", + "reviewBody": "Hallo, eine Frage, wenn Hefewasser benutzt wird, l\u00e4\u00dft man dann die Hefe weg,?", + "datePublished": "2021-11-19", + "author": { + "@type": "Person", + "name": "Nette444" + } + }, + { + "@type": "Review", + "reviewBody": "Danke Zaubermaus558,\nwar sehr informativ und hilfreich\n\ud83d\udc4d", + "datePublished": "2021-11-11", + "author": { + "@type": "Person", + "name": "tema2" + } + }, + { + "@type": "Review", + "reviewBody": "Hi Lizzy,\r\n\r\nda hast du ja ein super Brotrezept eingestellt.\r\n\r\nDas hat schon lecker durchs ganze Haus geduftet beim Backen.\r\n\r\nEs schmeckt uns sehr gut und es ist auch wundersch\u00f6n anzuschauen - Bilder sind hochgeladen!\r\n\r\nHere are the results of the Amboss family: 5 stars!!!!\r\n\r\nLiebe Gr\u00fc\u00dfe\r\nAmboss110", + "datePublished": "2010-12-13", + "author": { + "@type": "Person", + "name": "Amboss110" + } + }, + { + "@type": "Review", + "reviewBody": "Hallo Sabine,\r\nfreud mich sehr, da\u00df dir das bauernbrot gut gelungen und geschmeckt hat. Wegen dem Salz finde ich, das ist Gesckmacksache und Brotgew\u00fcrze vertragen wir leider nicht. Aber man kann ja Salz und Gew\u00fcrze nach eigenem gutd\u00fcnken dazu tun. Dank f\u00fcr deine positive Beurteilung.\r\nLiebe Gr\u00fc\u00dfe\r\nLizzy", + "datePublished": "2010-11-09", + "author": { + "@type": "Person", + "name": "zaubermaus558" + } + } + ], + "tool": [], + "url": "https:\/\/www.chefkoch.de\/rezepte\/1769311286873269\/Bauernbrot-mit-Sauerteig.html", + "nutrition": [], + "dateModified": "2021-12-19T01:30:41+0000", + "dateCreated": "2021-12-19T01:30:41+0000" +} diff --git a/packages/nextcloud_test/docker/assets/Recipes/Blaubeer Cluster/recipe.json b/packages/nextcloud_test/docker/assets/Recipes/Blaubeer Cluster/recipe.json new file mode 100644 index 00000000000..01a59ae7f3d --- /dev/null +++ b/packages/nextcloud_test/docker/assets/Recipes/Blaubeer Cluster/recipe.json @@ -0,0 +1,25 @@ +{ + "name": "Blaubeer Cluster", + "image": "https:\/\/recipecontent.fooby.ch\/16683_3-2_480-320.jpg", + "recipeYield": 20, + "keywords": "Desserts,Sommer,Herbst", + "recipeIngredient": [ + " 120 vegane, helle Schokolade (70 % Kakao), fein gehackt", + " 1 EL Kokos\u00f6l", + " 1 Prise Meersalz", + " 250 g Heidelbeeren (oder Blaubeeren)", + " 2 TL Kokosraspel" + ], + "recipeInstructions": [ + "\n \n \n \n Schokolade in einer d\u00fcnnwandigen Sch\u00fcssel \u00fcber dem nur leicht siedenden Wasserbad schmelzen, glatt r\u00fchren, Kokos\u00f6l und Salz darunterr\u00fchren. Mit einem Teel\u00f6ffel wenig Schokolade auf die Beeren geben, je 3-5 Beeren zusammenkleben, auf ein Blech legen, ca. 10 Min. gefrieren. Die einzelnen Cluster mit einer Gabel in die restliche Schokolade tauchen, nebeneinander auf ein Backpapier legen, Kokosraspel dar\u00fcber streuen, bis zum Naschen ca. 15 Min. k\u00fchl stellen.\n \n \n " + ], + "@context": "http:\/\/schema.org", + "@type": "Recipe", + "recipeCategory": "", + "tool": [], + "description": "", + "url": "https:\/\/fooby.ch\/de\/rezepte\/16683\/blaubeer-cluster", + "nutrition": [], + "dateModified": "2021-04-17T12:51:51+0000", + "dateCreated": "2021-04-17T12:51:51+0000" +} diff --git a/packages/nextcloud_test/docker/assets/Recipes/Chantal's New York Cheesecake/recipe.json b/packages/nextcloud_test/docker/assets/Recipes/Chantal's New York Cheesecake/recipe.json new file mode 100644 index 00000000000..7544c07f2fe --- /dev/null +++ b/packages/nextcloud_test/docker/assets/Recipes/Chantal's New York Cheesecake/recipe.json @@ -0,0 +1,265 @@ +{ + "@context": "http:\/\/schema.org", + "@type": "Recipe", + "mainEntityOfPage": "https:\/\/www.allrecipes.com\/recipe\/8350\/chantals-new-york-cheesecake\/", + "name": "Chantal's New York Cheesecake", + "image": "https:\/\/imagesvc.meredithcorp.io\/v3\/mm\/image?url=https%3A%2F%2Fimages.media-allrecipes.com%2Fuserphotos%2F5185165.jpg", + "datePublished": "1999-06-04T20:26:00.000Z", + "description": "This cake is easy to make, and it's so delicious. Everyone that's tried it has said it tasted just like the ones in a deli! You'll love it!", + "prepTime": "PT0H30M", + "cookTime": "PT1H0M", + "totalTime": "PT7H30M", + "recipeYield": 1, + "recipeIngredient": [ + "15 graham crackers, crushed", + "2 tablespoons butter, melted", + "4 (8 ounce) packages cream cheese", + "1\u2009\u00bd cups white sugar", + "\u00be cup milk", + "4 eggs", + "1 cup sour cream", + "1 tablespoon vanilla extract", + "\u00bc cup all-purpose flour" + ], + "recipeInstructions": [ + "Preheat oven to 350 degrees F (175 degrees C). Grease a 9 inch springform pan.\n", + "In a medium bowl, mix graham cracker crumbs with melted butter. Press onto bottom of springform pan.\n", + "In a large bowl, mix cream cheese with sugar until smooth. Blend in milk, and then mix in the eggs one at a time, mixing just enough to incorporate. Mix in sour cream, vanilla and flour until smooth. Pour filling into prepared crust.\n", + "Bake in preheated oven for 1 hour. Turn the oven off, and let cake cool in oven with the door closed for 5 to 6 hours; this prevents cracking. Chill in refrigerator until serving.\n" + ], + "recipeCategory": "Dessert", + "recipeCuisine": [], + "author": [ + { + "@type": "Person", + "name": "Taliesen" + } + ], + "aggregateRating": { + "@type": "AggregateRating", + "ratingValue": 4.710150891632373, + "ratingCount": 7290, + "itemReviewed": "Chantal's New York Cheesecake", + "bestRating": "5", + "worstRating": "1" + }, + "nutrition": { + "@type": "NutritionInformation", + "calories": "533.4 calories", + "carbohydrateContent": "44.2 g", + "cholesterolContent": "158.9 mg", + "fatContent": "35.7 g", + "fiberContent": "0.6 g", + "proteinContent": "10.3 g", + "saturatedFatContent": "21.1 g", + "sodiumContent": "380.4 mg", + "sugarContent": "31.6 g" + }, + "review": [ + { + "@type": "Review", + "datePublished": "2007-02-25T13:23:56.767Z", + "reviewBody": "OK - I don't want to be rude, but this is the deal: this is a perfect recipe, and if it fails for you, it's your fault, not the recipe's. A couple of things you should know about cheesecakes:\n\nOVERBEATING WILL CAUSE A CHEESECAKE TO CRACK. Beat cream cheese with sugar only until smooth. Proceed with a wooden spoon for the rest of the recipe.\n\nOVERBEATING WILL CAUSE A CHEESECAKE TO HAVE THE \"WRONG\" TEXTURE. Air bubbles, gritty\/not creamy texture, etc., are fixed my the same instructions above.\n\nOVERCOOKING WILL CAUSE A CHEESECAKE TO CRACK. Do NOT cook this cheesecake until it's set. Matter of fact, don't check it at all. Put the cheesecake in the oven, set the timer to 60 min., turn the oven off, and forget it. I mean it! Don't open the oven, just leave it alone to do its thing.\n\nAnd that's it. A beautiful cheesecake. Far from bland: this is a PURIST'S cheesecake. It's great as is, but also a great foil for other flavours. I serve mine with passionfruit pulp or mango puree.", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "Morena", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/528228\/" + } + }, + { + "@type": "Review", + "datePublished": "2007-06-24T02:00:34.703Z", + "reviewBody": "I would like to update my review on this cheesecake. I originally gave it a five and still give it a five. I have made this cheesecake many times; sometimes it cracks sometimes it doesn't. Finally I read that if you grease the sides of your pan, it will not crack, since cracking often happens in the cooling process as the cake pulls away from the sides. Since I began greasing the sides,I have not had a cracked cheesecake. People who like the NY style of cheesecake love this recipe.", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "MARY DOMAZ", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/278426\/" + } + }, + { + "@type": "Review", + "datePublished": "2003-10-30T06:31:27.513Z", + "reviewBody": "I've made cheesecakes many times, only to have them crack and sink after cooling. With the tips that I picked up on allrecipes.com, Chantal's New York Cheesecake was a hit with my family & friends. After cooling, the top remained level and the center firmed up. The top was a beautiful golden brown with no dry edges. The inside was creamy and smooth, and not too sweet.\r\n\r\nThe tips are as follows:\r\n\r\n1. Make sure that your ingredients are around room temperature, not cold, otherwise your batter will be lumpy.\r\n\r\n2. Wrap your springform pan with 2 layers of aluminum foil to prevent water in the bain marie (water bath) from seeping in.\r\n\r\n3. Place your springform pan in a water bath in the oven, filled with 1 inch of very hot water, then proceed to bake as instructed in the recipe.\r\n\r\n4. Right after baking, run a warm or greased knife around the rim of the cake to prevent cracking while cooling.\r\n\r\n5. Leave the cake in the oven for 2 hours to cool. (I didn't have time to leave it in for the recommended 6 hrs, and it still works.)\r\n\r\nI'll make variations of this cheesecake, such as blueberry topping, oreo base and filling etc.\r\n\r\nENJOY!", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "CHUNG_BRENDA", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/417098\/" + } + }, + { + "@type": "Review", + "datePublished": "2003-11-10T09:22:46.247Z", + "reviewBody": "AMAZING! The KING of all cheesecakes! This is the recipe you are looking for, Thick and Creamy! Ive made this 2X now with tremendous sucess. However, I found this crust to need some work, so this is the recipe I use: 1 1 \/2 c. graham cracker crumbs, 1\/2 c. white sugar, 1\/4 c. finely chopped Unsalted nuts (walnuts, pecans), 1\/4 c. melted butter, 1 tsp. cinnamon and a 1\/4 tsp. nutmeg. Mix together and press into 9\" springform pan. As for the cheesecake mixture, make Sure to start with room temp. ingredients, use a mixer to beat cream cheese and sugar, then hand-mix from there on. Feel free to add chocolate chips, toffee bits, etc. to the mixture before transferring into graham cracker crust. Use a water bath, (See Cheesecake section under Cooking Basics on this site) with the pan double wrapped in foil. When cheesecake is done, turn oven off, run knife around edge of the cake to completely loosen from the pan. Close oven door, leave in for 3+ hours, until completely cool. Refrigerate overnight. I make a homemade raspberry topping, as follows: 1 10oz. pkg frozen raspb., 2 tblsp. white sugar, 2 tsp. cornstarch & 1\/2 c. water. In med. saucepan, mix sugar & corn starch well. Add water & bring to a boil. Add raspberries & boil for 5 minutes, or until thick. If you wish, strain the hot mixture to remove seeds. Place in refrigerator to completely cool. Place 1-2 tablespoons over chilled cheesecake, top with a curl of white chocolate. Award Winning!", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "SCIOTA", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/515622\/" + } + }, + { + "@type": "Review", + "datePublished": "2007-10-13T19:30:08.953Z", + "reviewBody": "I have been working with this recipe for a couple of years now. Yesterday, one of my co-workers and I had a cheesecake cook-off. Everyone RAVED about my cheesecake and I felt bad for the other guy. His was made with Cool-Whip and took 20-30 minutes to make. Mine was Chantal's (with modifications) and took me 16 hours from start to serve (including chilling).\n\nI have been adjusting this recipe to get the perfect weight, density, and creaminess (to MY tastes) and I THINK I've got it! (By George, I think she's got it!) I like a HEAVY New York-Style Cheesecake that's not TOO cakey (translation: DRY!). So here is what I've come up with:\n\nI use 2 TBSP. flour instead of 1\/4 cup AND use a water bath.\nI baked it at 225 degrees for 3 hours and 40 minutes (I KNOW that sounds like a LONG time, but remember, I've been working on this for a couple of years - OK.......not consistantly, but whenever I feel like making a cheesecake. I make myself notes on the back of the recipe.) After it has baked 3 hours and 40 minutes, I turn off the oven and crack the oven door for a few minutes to get it to cool down more quickly. I leave the cheesecake in the oven for 6 hours and then put it in the refrigerator until WELL chilled (about 6 more hours).\n\n(More on next post)\n", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "LAURELC43", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/1465812\/" + } + }, + { + "@type": "Review", + "datePublished": "2003-10-30T06:31:59.293Z", + "reviewBody": "Was a big hit at my husband's office! Mine didn't crack, but I was careful not to overmix and had the cream cheese at room temperature, and these are supposed to help prevent cracking. I also used a water bath, and I made sure that the side of the springform pan, not just the bottom, was well greased. (I read in a magazine that cheesecakes shrink from the sides of the pan as they cool, and if the side isn't well greased, the cheesecake will stick and, thus, crack.) Per previous reviewers, I baked it at 325 deg. and made the crust as follows: 1 1\/2 cups graham cracker crumbs, 1\/4 cup melted butter, 1\/2 tsp. ground cinnamon, and 1\/4 cup sugar. I substituted Bailey's Irish Cream for the milk. I had a can of cherry pie filling available for those who wanted a topping. A picture-perfect cheesecake!", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "KIMAR", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/276377\/" + } + }, + { + "@type": "Review", + "datePublished": "2005-08-20T18:04:21.247Z", + "reviewBody": "I found this recipe a few years ago, and have been making it ever since. I have changed a few things according to my taste. I bake mine in a water bath, and that helps to keep it more moist, and also to avoid cracking. Make sure you put it into boiling water instead of cold. Also, put your cheesecake in an oven bag before you put it into the water bath. Wrapping the pan in tin \r\nfoil just doesn't seem to keep the water away from the crust. I also don't even add the flour. It allows the cake to be less like cake, and it makes it so creamy and rich. I also double the butter in the crust, and I add the whites of one egg. This allows it to hold together better, so it's a lot less crumbly. Lastly, I don't let mine sit in the oven for 5 to 6 hours, who has the time? I put mine straight into the fridge. It seems to turn out just as well. Good luck! :)", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "Melanie Anderson", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/1480463\/" + } + }, + { + "@type": "Review", + "datePublished": "2004-02-12T20:52:19.473Z", + "reviewBody": "Recipe turned out great! I didn't have a pan big enough to put my 9-inch springform pan in for a water bath, so I just put it on a rack and put a pan of water underneath it. It was steamy enough to produce a perfectly uncracked cake (325F for 1 hr). At end of baking, unlike what it says in the cheesecake tips in the reference section, cake was completely SOLID, WITHOUT a \"3-inch circle\" that was still un-set. Cake texture still turned out PERFECT, so don't worry if there isn't a wobbly center after baking.\r\n\r\nI used \"Baker's Secret Pie Crust\" (bake crust for 15 mins, not 10) instead of the grahan cracker crust, and made a sour cream topping for a professional touch (1 cup sour cream, 2 tablespoons white sugar, 1 teaspoon vanilla extract. Combine and spread evenly after cheesecake has baked and cooled for 10 mins. Bake at 325F for 10 mins to set. Spread EVENLY, as the sour cream will not melt; it will only set, so any imperfection before you put it in the oven will show after baking. Leave in oven to cool for 6 hrs. chill and serve!). \r\n\r\n\r\nYou might want to decrease the amount of milk to 1\/2 cup for a denser cake, although do so with caution. My version as outlined above makes a 5lb cheesecake, which is about 1 1\/2 inches high using a 9-inch springform pan. Everyone who tasted my cheesecake said it was as good as the famed cheesecake of a local 5-star hotel, whose cheesecake is widely regarded as the best cheesecake in the city! (my homecity has over 7 million inhabitants, s", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "MARIGOBOE", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/730175\/" + } + }, + { + "@type": "Review", + "datePublished": "2003-10-30T06:33:22.763Z", + "reviewBody": "Amazing cheesecake! 5 stars! People don't realize that *Cracking* comes from overmixing a cheesecake or having too many air bubbles- as well as rapid cooling. \r\nThe method of cooling this cheesecake WILL prevent cracking- if you don't overmix it. Follow the recipe exactly, and it will turn out awesome.", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "MICHELLE Z", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/499610\/" + } + }, + { + "@type": "Review", + "datePublished": "2006-01-16T16:00:03.000Z", + "reviewBody": "I gave it two stars because it tasted \"like\" cheesecake, but that's the only reason. I was hesitant at first as with most recipes. I was puzzled by the use of milk with the sour cream. I was also curious about the amount of flour, and extra 1\/2 cup sugar. Now I'm no stranger to cheesecake. I used to own a bakery up in Washington and I made close to 20 different varieties of cheesecake, most of which were customer requests and were sold by the whole cake. Enough of me. I was diligent in following this recipe as directed and it \"fell flat\". Here's why: The heat is too high (burns cake), the milk creates too much moisture and it takes too long to cook, too much flour made it too dry, and I don't know if it was the flour, or the extra 1\/2 cup sugar, or the milk but it was hard to get the flavor and texture of the cream cheese to jump out at you. I think the people that are giving this recipe five stars really need to try some other cheesecake recipes and then rate this one. Okay, thanks but \"no thanks\".", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 2 + }, + "author": { + "@type": "Person", + "name": "Rollin", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/1608271\/" + } + } + ], + "video": { + "@context": "http:\/\/schema.org", + "@type": "VideoObject", + "name": "Chantal\u2019s New York Cheesecake", + "description": "See how to make a top-rated cheesecake.", + "uploadDate": "2012-11-08T00:11:02.402Z", + "duration": "PT3M31.211S", + "thumbnailUrl": "https:\/\/imagesvc.meredithcorp.io\/v3\/mm\/image?url=https%3A%2F%2Fcf-images.us-east-1.prod.boltdns.net%2Fv1%2Fstatic%2F1033249144001%2F6e28a2d8-f3aa-45ed-8e46-7b09221d6569%2F9c32422c-d6db-44e4-9414-b4500af9c0c6%2F160x90%2Fmatch%2Fimage.jpg", + "publisher": { + "@type": "Organization", + "name": "Allrecipes", + "url": "https:\/\/www.allrecipes.com", + "logo": { + "@type": "ImageObject", + "url": "https:\/\/www.allrecipes.com\/img\/logo.png", + "width": 209, + "height": 60 + }, + "sameAs": [ + "https:\/\/www.facebook.com\/allrecipes", + "https:\/\/twitter.com\/Allrecipes", + "https:\/\/www.pinterest.com\/allrecipes\/", + "https:\/\/www.instagram.com\/allrecipes\/" + ] + }, + "embedUrl": "https:\/\/players.brightcove.net\/1033249144001\/default_default\/index.html?videoId=1954487107001" + }, + "keywords": "", + "tool": [], + "url": "https:\/\/www.allrecipes.com\/recipe\/8350\/chantals-new-york-cheesecake\/", + "dateModified": "2021-01-30T15:00:53+0000", + "dateCreated": "2021-01-30T14:57:47+0000", + "id": 908718, + "printImage": false, + "imageUrl": "\/apps\/cookbook\/recipes\/908718\/image?size=full" +} diff --git a/packages/nextcloud_test/docker/assets/Recipes/Chef John's Gazpacho/recipe.json b/packages/nextcloud_test/docker/assets/Recipes/Chef John's Gazpacho/recipe.json new file mode 100644 index 00000000000..33915017deb --- /dev/null +++ b/packages/nextcloud_test/docker/assets/Recipes/Chef John's Gazpacho/recipe.json @@ -0,0 +1,256 @@ +{ + "@context": "http:\/\/schema.org", + "@type": "Recipe", + "mainEntityOfPage": "https:\/\/www.allrecipes.com\/recipe\/222331\/chef-johns-gazpacho\/", + "datePublished": "2012-05-09T23:49:30.000Z", + "recipeCuisine": [], + "author": [ + { + "@type": "Person", + "name": "Chef John" + } + ], + "aggregateRating": { + "@type": "AggregateRating", + "ratingValue": 4.795321637426901, + "ratingCount": 342, + "itemReviewed": "Chef John's Gazpacho", + "bestRating": "5", + "worstRating": "1" + }, + "nutrition": { + "@type": "NutritionInformation", + "calories": "131.7 calories", + "carbohydrateContent": "10.5 g", + "fatContent": "9.9 g", + "fiberContent": "2.8 g", + "proteinContent": "2 g", + "saturatedFatContent": "1.4 g", + "sodiumContent": "410.3 mg", + "sugarContent": "4.5 g" + }, + "review": [ + { + "@type": "Review", + "datePublished": "2012-06-02T23:53:32.307Z", + "reviewBody": "Oh Chef John, your reputation precedes you! From your how-to videos to your numerous published recipes, you've earned your title. I was craving Summer and happened to find this recipe, and while I don't have end of season tomatoes yet, this gazpacho turned out incredibly. If you love to cook, but take satisfaction in the preparation of the dish, then try this recipe. I had some time on a Saturday afternoon all to myself to create, and chopping the vegetables was a great source of relaxation. I felt like a character in a movie (have you ever seen Julia & Julia?) while I was preparing this soup. OK, maybe that's a bit dramatic, but the finished product is DELICIOUS! Don't be intimidated by the steps, and here is a great tip from the video--to peel tomatoes easily, dip them in a pot of boiling water for a few seconds. You'll be able to pull the peel off easily before dicing them. THANKS for a wonderful, fresh, healthy recipe! I can't wait to share this with my friends.", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "Jennifer Baker", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/jrbaker\/" + } + }, + { + "@type": "Review", + "datePublished": "2012-06-06T18:25:01.79Z", + "reviewBody": "This might be one of my favorite recipes of all time. Delicious, simple to make and tastes as good or better the next day. I've already had 5 people ask me for the recipe. I made this over the weekend and I am now making it again for an end of school party on Friday for the teachers. I didn't change a single thing in this recipe. This is an absolute MUST try recipe. On a side ntoe - I served this for dinner, but I also served it for brunch along with a southwestern breakfast casserole and it worked very well together. Thank you again Chef John - your flavor combinations are ALWAYS spot on!", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "Stirring up Trouble", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/7111996\/" + } + }, + { + "@type": "Review", + "datePublished": "2012-07-29T22:35:21.49Z", + "reviewBody": "WOW! As a registered nutritionist and personal chef I always look for healthy foods that are quick to make and great tasting. Just last Friday I held a workshop at our local Cancer Center and wowed the participants. This recipe is quick and easy to prepare and has great texture and taste. Thank you Chef John!", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "Chef Ian", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/4395436\/" + } + }, + { + "@type": "Review", + "datePublished": "2012-07-08T08:47:38.37Z", + "reviewBody": "After trying Chef John's Gazpacho a few days ago I have now pitched my own recipe of over 20 years! Yes folks it is true! You can teach an old dog new tricks or new recipes anyway.;) I made no changes to it and my family and friends loved it! Gazpacho can be time consuming to make but John's isn't but 45 minutes and viewing his video to make it makes it all the more easy. Plus his voice is so relaxing to me!;) The only thing I added was a cucumber slice and a dollop of Daisy Sour Cream to the top of each serving. Bon appetit!", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "Herbies Mom", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/2380426\/" + } + }, + { + "@type": "Review", + "datePublished": "2013-07-17T00:19:25.123Z", + "reviewBody": "SHUT THE FRONT DOOR PEOPLE! This soup is phenomenal. Who knew that a simple cold tomato summer soup could taste like this? I'd all but given up but this recipe showed up in my inbox and I thought \"what the heck we'll try one more gazpacho recipe.\" SO THANKFUL I DID!!! and I'm sorry to say I did change one thing. I did not see the 4 tomatoes called for first thing. so I got home and had all the rest of the ingredients but not those. So-what to do??? I followed the rest of the directions and then added 2 cups of low-sodium V8. This soup is amazing. I'm letting it chill now as I write but it already tastes so good I know this is going to be a once-a-weeker for the rest of the summer! and I am doing great things for my body!!! also I didn't strain the blenderized cherry tomatoes. and I used 1\/4 of a yellow onion and blenderized that with the cherry tomatoes. I'm coming in with a spoon boys and y'all better get out of the way!!!!", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "patreeseeya", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/9872596\/" + } + }, + { + "@type": "Review", + "datePublished": "2012-10-19T23:53:05.35Z", + "reviewBody": "Never had Gazpacho. Didn't think I would like a cold soup. I was surprised to find this is absolutely delicious. I didn't have farm tomatoes, so I used on the vine ones from the supermarket and added 1\/4 of a mango for sweetness. So good, savory, and lite. Will eat again.", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "REE28AM", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/1365464\/" + } + }, + { + "@type": "Review", + "datePublished": "2012-08-03T23:06:44.48Z", + "reviewBody": "This was amazing- the time was worth it. I gave up on the straining and put all the \"chunks\" of the cherry tomato pur\u00e9e in with the rest of the soup but I don't see a problem at all with the texture. I also used a lemon instead of a lime. Other than that I followed all the directions and the video! And here's my secret: I used supermarket tomatoes. Who knows it might taste better with real vine ripened tomatoes but it still tastes great either way!", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "The Purple Baker", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/6449783\/" + } + }, + { + "@type": "Review", + "datePublished": "2013-07-23T00:30:18.06Z", + "reviewBody": "Made this with fresh veg from my garden. Left out the cayenne and the jalapeno so my young son could eat it. Also left out the lime as our tomatoes were bright enough without. My son didn't care for the raw onion and my husband and I decided I should dice the onion a lot smaller next time (I used my vitamix to chop the veg). I was however very pleased with the flavor. I think I might go heavier on the cumin and oregano next time just to play up the Spanish influence. I made some biscuits to go with (didn't have time to make bread) and that was dinner. It was delicious. Our cherry tomatoes are candy-sweet and the big yellow tomatoes were very mild and relatively low acid. So this ended up on the sweet end of the spectrum which really suited me very well. I think it will be even better tomorrow.", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "shris", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/2606463\/" + } + }, + { + "@type": "Review", + "datePublished": "2013-11-12T00:35:55.42Z", + "reviewBody": "This certainly wasn't a Gazpacho recipe that I enjoyed. Perhaps the tomatoes weren't ripe enough, I don't know. Either way, it wasn't bursting with flavor. I also couldn't get past the blended\/pureed tomatoes, it didn't look appealing at all. My kids and wife tried it and didn't like it either. I was a bit disappointed, perhaps I should be more disappointed with the lack of fresh\/flavorful produce in my area.", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 2 + }, + "author": { + "@type": "Person", + "name": "RSFORBES", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/1155228\/" + } + } + ], + "video": { + "@context": "http:\/\/schema.org", + "@type": "VideoObject", + "name": "Chef John's Gazpacho", + "description": "See how to make this classic cold Spanish soup.", + "uploadDate": "2012-04-21T02:08:33.432Z", + "duration": "PT5M2.875S", + "thumbnailUrl": "https:\/\/imagesvc.meredithcorp.io\/v3\/mm\/image?url=https%3A%2F%2Fcf-images.us-east-1.prod.boltdns.net%2Fv1%2Fstatic%2F1033249144001%2F478b6c41-77cd-49c8-9ded-c008d033f0fd%2F69627980-14b0-49c7-8f89-d162e1d277da%2F160x90%2Fmatch%2Fimage.jpg", + "publisher": { + "@type": "Organization", + "name": "Allrecipes", + "url": "https:\/\/www.allrecipes.com", + "logo": { + "@type": "ImageObject", + "url": "https:\/\/www.allrecipes.com\/img\/logo.png", + "width": 209, + "height": 60 + }, + "sameAs": [ + "https:\/\/www.facebook.com\/allrecipes", + "https:\/\/twitter.com\/Allrecipes", + "https:\/\/www.pinterest.com\/allrecipes\/", + "https:\/\/www.instagram.com\/allrecipes\/" + ] + }, + "embedUrl": "https:\/\/players.brightcove.net\/1033249144001\/default_default\/index.html?videoId=1574176958001" + }, + "dateCreated": "2021-01-30T14:58:28+0000", + "printImage": false, + "id": 908724, + "name": "Chef John's Gazpacho", + "imageUrl": "\/apps\/cookbook\/recipes\/908724\/image?size=full", + "recipeCategory": "Soup", + "description": "Only try this recipe if you're going to use some killer, end-of-summer, super-sweet tomatoes. There just isn't any substitute, so happy hunting, and I hope you find some so you give this a try.", + "recipeIngredient": [ + "4 large fresh tomatoes, peeled and diced", + "\u00bd English cucumber, peeled and finely diced", + "\u00bd cup finely diced red bell pepper", + "\u00bc cup minced green onion", + "1 large jalapeno pepper, seeded and minced", + "2 cloves garlic, minced", + "1 teaspoon salt", + "\u00bd teaspoon ground cumin", + "1 pinch dried oregano", + "1 pinch cayenne pepper, or to taste", + "freshly ground black pepper to taste", + "1 pint cherry tomatoes", + "\u00bc cup extra-virgin olive oil", + "1 lime, juiced", + "1 tablespoon balsamic vinegar", + "1 teaspoon Worcestershire sauce", + "salt and ground black pepper to taste", + "2 tablespoons thinly sliced fresh basil" + ], + "recipeInstructions": [ + "Combine diced tomatoes, cucumber, bell pepper, green onion, jalapeno, and garlic in a large bowl. Stir in salt, cumin, oregano, cayenne pepper, and black pepper.\n", + "Place cherry tomatoes, olive oil, lime juice, balsamic vinegar, and Worcestershire sauce in a blender. Cover and puree until smooth. Pour pureed mixture through a strainer into the tomato-cucumber mixture; stir to combine.\n", + "Place 1\/3 of the tomato mixture into the blender. Cover, turn blender on, and puree until smooth. Return pureed mixture to the remaining tomato-cucumber mixture. Stir to combine. Cover and chill in refrigerator for 2 hours.\n", + "Season cold soup with salt and black pepper to taste. Ladle into bowls and top with basil.\n" + ], + "tool": [], + "recipeYield": 6, + "prepTime": "PT0H45M", + "cookTime": "PT0H2M", + "totalTime": "PT2H45M", + "keywords": "", + "image": "https:\/\/imagesvc.meredithcorp.io\/v3\/mm\/image?url=https%3A%2F%2Fimages.media-allrecipes.com%2Fuserphotos%2F842477.jpg", + "url": "https:\/\/www.allrecipes.com\/recipe\/222331\/chef-johns-gazpacho\/", + "dateModified": "2021-09-27T21:55:46+0000" +} diff --git a/packages/nextcloud_test/docker/assets/Recipes/Chili sin Carne mit Jackfruit/recipe.json b/packages/nextcloud_test/docker/assets/Recipes/Chili sin Carne mit Jackfruit/recipe.json new file mode 100644 index 00000000000..ed965ded856 --- /dev/null +++ b/packages/nextcloud_test/docker/assets/Recipes/Chili sin Carne mit Jackfruit/recipe.json @@ -0,0 +1,38 @@ +{ + "name": "Chili sin Carne mit Jackfruit", + "image": "https:\/\/recipecontent.fooby.ch\/20246_3-2_480-320.jpg", + "recipeYield": 4, + "keywords": "Hauptgericht,Suppen und Eintopf,Fr\u00fchling", + "recipeIngredient": [ + " 1 EL Raps\u00f6l", + " 1 TL getrockneter Oregano", + " 1 TL Kreuzk\u00fcmmel", + " 2 TL Paprika", + " \u00bc TL Chiliflocken", + " 2 Knoblauchzehen, fein gehackt", + " 1 rote Zwiebel, fein gehackt", + " \u00bd rote Peperoni, in W\u00fcrfeli", + " 1 Dose Jackfruit (ca. 400 g), abgetropft", + " 1 Dose gehackte Tomaten (ca. 400 g)", + " 1 Dose Red Kidney Bohnen (ca. 250 g), abgesp\u00fclt, abgetropft", + " 1 Dose Maisk\u00f6rner (ca. 140 g), abgetropft", + " 1 EL Kakaopulver", + " 2 \u00bc dl Wasser", + " 1 TL Salz", + " 1 Limette, nur Saft", + " 100 g Kokosnussmilch-Jogurt", + " \u00bd Bund Koriander, zerzupft" + ], + "recipeInstructions": [ + "\n \n Gew\u00fcrze r\u00f6sten\n \n \u00d6l in einer Bratpfanne erhitzen. Oregano, Kreuzk\u00fcmmel, Paprika und Chiliflocken beigeben, unter R\u00fchren ca. 1 Min. r\u00f6sten, Hitze reduzieren.\n \n \n Chili\n \n Knoblauch und Zwiebel zu den Gew\u00fcrzen geben, kurz and\u00e4mpfen. Peperoni und Jackfruit beigeben, ca. 5 Min. mitd\u00e4mpfen. Tomaten, Bohnen, Mais und Kakao beigeben, Wasser dazugiessen, aufkochen, salzen. Hitze reduzieren, zugedeckt ca. 30 Min. k\u00f6cheln.\n \n \n Anrichten\n \n Limettensaft daruntermischen. Chili anrichten, mit Jogurt und Koriander garnieren.\n \n \n " + ], + "@context": "http:\/\/schema.org", + "@type": "Recipe", + "recipeCategory": "", + "tool": [], + "description": "", + "url": "https:\/\/fooby.ch\/de\/rezepte\/20246\/chili-sin-carne-mit-jackfruit?startAuto1=0", + "nutrition": [], + "dateModified": "2021-04-17T12:55:55+0000", + "dateCreated": "2021-04-17T12:55:55+0000" +} diff --git a/packages/nextcloud_test/docker/assets/Recipes/Easy Heart-Shaped Cake/recipe.json b/packages/nextcloud_test/docker/assets/Recipes/Easy Heart-Shaped Cake/recipe.json new file mode 100644 index 00000000000..c9a26ead7e9 --- /dev/null +++ b/packages/nextcloud_test/docker/assets/Recipes/Easy Heart-Shaped Cake/recipe.json @@ -0,0 +1,78 @@ +{ + "@context": "http:\/\/schema.org", + "@type": "Recipe", + "mainEntityOfPage": "https:\/\/www.allrecipes.com\/recipe\/283074\/easy-heart-shaped-cake\/", + "name": "Easy Heart-Shaped Cake", + "image": "https:\/\/imagesvc.meredithcorp.io\/v3\/mm\/image?url=https%3A%2F%2Fimages.media-allrecipes.com%2Fuserphotos%2F8979442.jpg", + "datePublished": "2021-01-20T00:41:46.000Z", + "description": "This heart-shaped cake combines Ann McGavin Stout's Homemade Vanilla Cake recipe and QueenCook's Easy Valentine's Day Cake frosting recipe. The result is a supremely tasty, no-fail heart cake.", + "prepTime": "PT1H0M", + "cookTime": "PT0H45M", + "totalTime": "PT2H25M", + "recipeYield": 1, + "recipeIngredient": [ + "2 cups white sugar", + "1 cup unsalted butter, softened", + "2 teaspoons vanilla extract", + "2 teaspoons almond extract", + "4 large eggs", + "3 cups all-purpose flour", + "\u2153 cup cornstarch", + "1 tablespoon baking powder", + "\u00be teaspoon salt", + "1\u2009\u00bd cups milk", + "2 cups unsalted butter, softened", + "4 teaspoons vanilla extract", + "8 cups powdered sugar", + "2 tablespoons whole milk, or more as needed", + "2 drops red food coloring, or as desired", + "2 drops yellow food coloring, or as desired", + "sprinkles as needed" + ], + "recipeInstructions": [ + "Preheat the oven to 350 degrees F (175 degrees C). Grease an 8-inch square pan and an 8-inch round pan. Line bottoms with parchment or wax paper. Grease paper and dust lightly with flour.\n", + "Beat white sugar, butter, vanilla, and almond extract in a large bowl with an electric mixer on high speed until light and fluffy. Beat in eggs, 1 at a time, until well combined.\n", + "Stir flour, cornstarch, baking powder, and salt together in another bowl.\n", + "Beat 1 cup dry ingredients into wet ingredients until just combined. Add 1\/2 cup milk; beat until combined. Continue adding 1 cup dry ingredients and 1\/2 cup milk, beating after each addition, until all are used and batter is smooth. Divide evenly between the prepared pans.\n", + "Bake in the preheated oven until a toothpick inserted in the center of each cake comes out clean, 45 to 50 minutes. Cool in pans on wire racks for 10 minutes. Remove from pans and cool completely on racks.\n", + "Beat butter and vanilla together in a large bowl with an electric mixer on medium speed until combined, about 30 seconds. Gradually add powdered sugar, beating after each addition and adding milk as needed, until frosting is fluffy, smooth, and spreadable.\n", + "Remove 1\/3 cup frosting and divide between 2 small bowls. Tint 1 dark pink with red food coloring. Tint the other orange-pink with red and yellow food coloring. Tint remaining frosting light pink with red food coloring.\n", + "Set square cake on a work surface and rotate 45 degrees so that it resembles a diamond. Spread a little light pink frosting on left and right top sides of the diamond. Cut round cake in half crosswise to make 2 half-moons. Attach half-moons to top left and top right sides of diamond, gently pressing cake pieces together to adhere. Spread remaining light pink frosting over the assembled cake. Drop spoonfuls of dark pink and pink-orange frosting onto cake. Drag an offset spatula through frosting to create a marbled look.\n", + "Pat sprinkles onto the sides of the cake. Chill, covered, for up to 3 days. Let stand at room temperature 30 minutes before slicing into 16 pieces.\n" + ], + "recipeCategory": "Dessert", + "recipeCuisine": [], + "author": [ + { + "@type": "Person", + "name": "thehungryscientist" + } + ], + "aggregateRating": { + "@type": "AggregateRating", + "itemReviewed": "Easy Heart-Shaped Cake", + "bestRating": "5", + "worstRating": "1" + }, + "nutrition": { + "@type": "NutritionInformation", + "calories": "778.3 calories", + "carbohydrateContent": "109.4 g", + "cholesterolContent": "140 mg", + "fatContent": "36.6 g", + "fiberContent": "0.7 g", + "proteinContent": "5.2 g", + "saturatedFatContent": "22.6 g", + "sodiumContent": "205.8 mg", + "sugarContent": "87.9 g" + }, + "review": [], + "keywords": "", + "tool": [], + "url": "https:\/\/www.allrecipes.com\/recipe\/283074\/easy-heart-shaped-cake\/", + "dateModified": "2021-01-30T15:02:50+0000", + "dateCreated": "2021-01-30T14:57:15+0000", + "id": 908706, + "printImage": false, + "imageUrl": "\/apps\/cookbook\/recipes\/908706\/image?size=full" +} diff --git "a/packages/nextcloud_test/docker/assets/Recipes/Fr\303\203\302\274hlingsfladen mit Rindfleisch/recipe.json" "b/packages/nextcloud_test/docker/assets/Recipes/Fr\303\203\302\274hlingsfladen mit Rindfleisch/recipe.json" new file mode 100644 index 00000000000..9c5203e9284 --- /dev/null +++ "b/packages/nextcloud_test/docker/assets/Recipes/Fr\303\203\302\274hlingsfladen mit Rindfleisch/recipe.json" @@ -0,0 +1,42 @@ +{ + "name": "Fr\u00c3\u00bchlingsfladen mit Rindfleisch", + "image": "https:\/\/recipecontent.fooby.ch\/17431_3-2_480-320.jpg", + "recipeYield": 4, + "keywords": "Hauptgericht,Sommer,Fr\u00c3\u00bchling", + "recipeIngredient": [ + " 350 g Halbweissmehl", + " \u00c2\u00be TL Salz", + " \u00c2\u00bc W\u00c3\u00bcrfel Hefe (ca. 10 g), zerbr\u00c3\u00b6ckelt", + " \u00c2\u00bc TL Zucker", + " 1 Bund Koriander", + " 3 EL \u00c3\u0096l", + " 2 dl Wasser", + " \u00c2\u00bd Bund Koriander, grob geschnitten", + " 200 g saurer Halbrahm", + " 250 g d\u00c3\u00bcnne gr\u00c3\u00bcne Spargeln", + " 2 Bundzwiebeln mit dem Gr\u00c3\u00bcn, halbiert, l\u00c3\u00a4ngs in feinen Streifen", + " 1 EL Oliven\u00c3\u00b6l zum Braten", + " 250 g Hohr\u00c3\u00bcckensteaks", + " \u00c2\u00bc TL orientalische Gew\u00c3\u00bcrzmischung (z.B. Smokey Beef)", + " 100 g Edamame, ausgel\u00c3\u00b6st", + " 30 g Micro Greens ", + " \u00c2\u00bd Bund Koriander, Bl\u00c3\u00a4tter abgezupft", + " 2 Prisen Salz", + " 150 g Burratas, in St\u00c3\u00bccken", + " 2 EL Oliven\u00c3\u00b6l", + " 2 EL Zitronensaft", + " \u00c2\u00bc TL Salz" + ], + "recipeInstructions": [ + "\n \n Gr\u00c3\u00bcner Pizzateig\n \n Mehl, Salz, Zucker und Hefe in einer Sch\u00c3\u00bcssel mischen Koriander mit \u00c3\u0096l und Wasser p\u00c3\u00bcrieren, dazugiessen, mischen, zu einem glatten Teig kneten. Zugedeckt bei Raumtemperatur ca. 1\u00c2\u00bd Std. aufs Doppelte aufgehen lassen.\n \n \n Belag\n \n Teig etwas flach dr\u00c3\u00bccken, auf wenig Mehl auswallen (ca. 30 cm \u00c3\u0098), auf ein Backpapier legen. Koriander mit dem sauren Halbrahm p\u00c3\u00bcrieren, auf dem Teigboden verteilen, dabei rundum einen ca. 2 cm breiten Rand frei lassen. Spargeln und Bundzwiebeln darauf verteilen. \n \n \n Backen\n \n Blech im auf 240 \u00c2\u00b0C vorgeheizten Ofen vorheizen. Herausnehmen, Fladen darauf ziehen, ca. 25 Min. auf der untersten Rille des auf 240 \u00c2\u00b0C vorgeheizten Ofens backen. \n \n \n Fr\u00c3\u00bchlings-Belag\n \n \u00c3\u0096l in einer Bratpfanne erhitzen. Hohr\u00c3\u00bcckensteak w\u00c3\u00bcrzen, beidseitig je ca. 2 Min. braten, herausnehmen, ca. 5 Min. ziehen lassen, in Tranchen schneiden. Edamame, Micro Greens und Koriander mischen, salzen, mit dem Fleisch auf dem Fladen verteilen. Burrata auf dem Fladen verteilen. \u00c3\u0096l und Zitronensaft verr\u00c3\u00bchren, salzen, dar\u00c3\u00bcbertr\u00c3\u00a4ufeln.\n \n \n " + ], + "@context": "http:\/\/schema.org", + "@type": "Recipe", + "recipeCategory": "", + "tool": [], + "description": "", + "url": "https:\/\/fooby.ch\/de\/rezepte\/17431\/fruehlingsfladen-mit-rindfleisch?startAuto1=0", + "nutrition": [], + "dateModified": "2021-04-17T13:04:16+0000", + "dateCreated": "2021-04-17T13:04:16+0000" +} diff --git a/packages/nextcloud_test/docker/assets/Recipes/Gelber Smoothie/recipe.json b/packages/nextcloud_test/docker/assets/Recipes/Gelber Smoothie/recipe.json new file mode 100644 index 00000000000..376e6bff051 --- /dev/null +++ b/packages/nextcloud_test/docker/assets/Recipes/Gelber Smoothie/recipe.json @@ -0,0 +1,32 @@ +{ + "@context": "http:\/\/schema.org", + "@type": "Recipe", + "nutrition": [], + "dateCreated": "2021-04-11T14:23:36+0000", + "printImage": false, + "id": 922169, + "name": "Gelber Smoothie ", + "imageUrl": "\/apps\/cookbook\/recipes\/922169\/image?size=full", + "recipeCategory": "", + "description": "", + "recipeIngredient": [ + " 1 Mango, in St\u00fccken", + " \u00bd Ananas, in St\u00fccken", + " \u00bd TL Kurkuma", + " \u00bd EL Limettensaft", + " 1 dl Wasser", + " 1 dl Kokosmilch" + ], + "recipeInstructions": [ + "\n \n Smoothie\n \n Mango mit allen Zutaten bis und mit Kokosmilch p\u00fcrieren, in die Gl\u00e4ser verteilen. \n \n \n " + ], + "tool": [], + "recipeYield": 5, + "prepTime": "", + "cookTime": "", + "totalTime": "", + "keywords": "Vegan,Vegetarisch,Schnelle K\u00fcche", + "image": "https:\/\/recipecontent.fooby.ch\/12744_3-2_480-320.jpg", + "url": "https:\/\/fooby.ch\/de\/rezepte\/12744\/gelber-smoothie-?startAuto1=0", + "dateModified": "2021-04-17T12:45:04+0000" +} diff --git a/packages/nextcloud_test/docker/assets/Recipes/Grandma's Sour Cream Pound Cake/recipe.json b/packages/nextcloud_test/docker/assets/Recipes/Grandma's Sour Cream Pound Cake/recipe.json new file mode 100644 index 00000000000..f7653711974 --- /dev/null +++ b/packages/nextcloud_test/docker/assets/Recipes/Grandma's Sour Cream Pound Cake/recipe.json @@ -0,0 +1,222 @@ +{ + "@context": "http:\/\/schema.org", + "@type": "Recipe", + "mainEntityOfPage": "https:\/\/www.allrecipes.com\/recipe\/84042\/grandmas-sour-cream-pound-cake\/", + "name": "Grandma's Sour Cream Pound Cake", + "image": "\/photo_2021-06-02_22-03-08.jpg", + "datePublished": "2020-06-19T03:11:57.000Z", + "description": "This is a recipe the whole family loves. It's always a hit!", + "prepTime": "PT0H30M", + "cookTime": "PT1H20M", + "totalTime": "PT2H0M", + "recipeYield": 1, + "recipeIngredient": [ + "2 cups butter, softened", + "3 cups white sugar", + "6 eggs, room temperature", + "1 teaspoon vanilla extract", + "3 cups all-purpose flour", + "\u00bc teaspoon baking soda", + "\u00bd teaspoon salt", + "1 pinch ground mace", + "1 cup sour cream", + "1 tablespoon confectioners' sugar, or as needed" + ], + "recipeInstructions": [ + "Preheat the oven to 350 degrees F (175 degrees C). Grease and flour a 9- or 10-inch fluted tube pan (such as Bundt\u00ae.\n", + "Beat butter and sugar with an electric mixer in a large bowl until light and fluffy and noticeably lighter in color. Add room-temperature eggs 1 at a time, allowing each egg to blend into the butter mixture before adding the next. Beat in vanilla with the last egg.\n", + "Mix together flour, baking soda, salt, and mace in a bowl. Add flour mixture to the butter-egg mixture alternately with sour cream, mixing until just incorporated. Transfer batter to the prepared pan and spread to smooth top.\n", + "Bake in the preheated oven until a toothpick inserted in the cake comes out clean, about 1 hour and 20 minutes. Cool for at least 10 minutes before inverting pan onto a cooling rack, and tapping out the cake. Dust with confectioners' sugar before serving.\n" + ], + "recipeCategory": "Dessert", + "recipeCuisine": [], + "author": [ + { + "@type": "Person", + "name": "LVJOANNE" + } + ], + "aggregateRating": { + "@type": "AggregateRating", + "ratingValue": 4.578231292517007, + "ratingCount": 294, + "itemReviewed": "Grandma's Sour Cream Pound Cake", + "bestRating": "5", + "worstRating": "1" + }, + "nutrition": { + "@type": "NutritionInformation", + "calories": "494.3 calories", + "carbohydrateContent": "56.7 g", + "cholesterolContent": "137.1 mg", + "fatContent": "28.1 g", + "fiberContent": "0.6 g", + "proteinContent": "5.5 g", + "saturatedFatContent": "17.1 g", + "sodiumContent": "290.2 mg", + "sugarContent": "38.2 g" + }, + "review": [ + { + "@type": "Review", + "datePublished": "2007-05-12T15:37:04.577Z", + "reviewBody": "Excellent!! This is the 4th pound cake I've tried from this site and I've finally found a keeper. It's exactly what a pound cake should be in flavor and texture: dense, moist and rich. I did increase the vanilla to 1.5 tablespoons, used the mace (it gives a nice sublte aroma, but taste wise, you can't tell it's there), and when I don't have sour cream, I've subsituted it with plain yogurt (both the lowfat or whole milk works) and decrease the temp to 325. Like other posters, mine baked perfectly at 1 hour 10 min. too. This cake holds up very well, and as long as you keep it covered, it's stays moist for a good 3 days. Good old fashion ingredients that gives you a classic pound cake. TIP - whip the heck out of the butter\/sugar (until very pale and fluffy) and whip even more when combining the eggs. But once you add the flour, fold it in BY HAND ONLY or else you'll get a tough cake. Also, if your cake is browning too quickly half way through, just lightly cover it with foil. This will be my master pound cake recip.", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "MommyFromSeattle", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/857169\/" + } + }, + { + "@type": "Review", + "datePublished": "2008-08-18T01:55:19.92Z", + "reviewBody": "To say this is a \"moist\" pound cake is a misnomer. It is a \"butter saturated\" pound cake. To discuss using lemon versus mace, no mace, more vanilla, less sugar, more sugar, adding baking powder, etc., isn't even important. None of it matters unless you reduce the butter in this recipe to 1-1\/2 cups. Only then can variations be relevant. Even tho' as an experienced baker I knew better when I saw 2 cups of butter in this recipe (when most others would call for half that) I foolishly went ahead with this as written anyway, mistakenly assuming 100+ glowing reviews couldn't be wrong. Live and learn--they were wrong. Before making this, please do check out other pound cake recipes and compare the ratio of butter to flour--you will find this is an extraordinary amount of butter for the amount of flour which will NOT result in the dense, moist, fine crumb so prized in a good pound cake. ", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 2 + }, + "author": { + "@type": "Person", + "name": "naples34102", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/naples34102\/" + } + }, + { + "@type": "Review", + "datePublished": "2007-08-20T13:41:10.877Z", + "reviewBody": "I already have a good pound cake recipe but wanted to try this one because of the sour cream addition - wanted a nice variation. I used the existing reviews as guides and my recipe as a point of comparison.\n\nI used the modifications others made, namely: added 1\/4 tsp of baking powder; reduced sugar to 2&1\/4 cups; increase vanilla to 1&1\/2 tsp; reduced oven temp to 325 and baked for 1hr & 20 min.\n\nThe resulting cake is moister but a little denser than my standard recipe. Regarding the mace - it was a mixed bag. I did not care for the flavor; others liked it. If I'd make this again, I'd skip the mace and add the grated rind of 1 lemon (I do the same in my standard recipe).\n\nRegarding quatities and reducing sugar: it's called a \"pound cake\" because it's supposed to contain a pound of butter (4 sticks\/2 cups), sugar (2 cups) and flour (approx. 3 cups). Most standard recipes use these proportions. I used 2&1\/4 cups of sugar because of the sour cream; next time, I'd use just 2 cups. I can imagine that 3 cups is way too sweet.\n\nFor those who had problems, I'll echo what others have said: cream the sugar and butter very well (at least 5 minutes) and beat for 1 min. after the addition of each egg. For the flour, use a machine to quickly fold it in and then finish by hand OR fold it in all by hand. Don't overwork the flour!!\n\nI gave this recipe 4 stars because of the need for modifications. With the mods, the cake is very good, although I prefer lemon instead of the mace.", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 4 + }, + "author": { + "@type": "Person", + "name": "MuscleMan", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/muscleman\/" + } + }, + { + "@type": "Review", + "datePublished": "2006-06-08T19:30:52.077Z", + "reviewBody": "I've been looking for a moist heavy poundcake and this is it. I did make two small changes. I omitted the mace. I wanted a rich buttery stand alone cake that would marry with berries. Removing the mace gave me what I wanted. I also added a 1\/4 tsp of baking powder. The result is a silky cake that's heavy but has some air in it. Just perfection.", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "Nancy Lindquist Liedel", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/1283134\/" + } + }, + { + "@type": "Review", + "datePublished": "2007-09-21T01:28:41.657Z", + "reviewBody": "This cake is the bomb,this is my second time making this cake,I didn't have any mace so i just add 2 Tsp of vanilla extract and 1 Tsp Of lemon extract and a half of Tsp of almond extract.,And i did blend the butter and sugar for about 6-7 minutes.I love this cake it's my favorite sour cream cake.Thanks a million grandma.", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "Miami Nell", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/2182737\/" + } + }, + { + "@type": "Review", + "datePublished": "2008-01-21T02:32:33.09Z", + "reviewBody": "I was very pleased with this recipe. It gave me a cake that had a good texture and taste. I did make two technical adjustments and one based on personal preference. I added the 1\/4 tsp. baking powder mentioned by other reviewers and I added 3 Tbsp vanilla because mine is weak (if you have stronger extracts this would probably be too much. I like a more pronounced vanilla flavor). After reading how quickly this cake browned at 350 I decided to try starting it in a cold oven. I set it to 325 after the pan was in place and did not open the door for 60 minutes. It rose well and browned golden not dark with a nice crust taking a total of 70 minutes. The recipe didn't specify type of butter so I used 2 sticks salted and 2 sticks unsalted; the full 3 cups of sugar; and 1\/4 teaspoon mace. I use Baker's Joy Spray in my pan and it popped out easily and intact. After it was cool I brushed it with a glaze made of softened cream cheese unsalted butter half and half glazing sugar and vanilla and lemon extracts. This does make a large amount of thick batter so make sure you have a true 12 cup Bundt pan use a larger Angel-food type pan or plan on making a second smaller cake that will have to come out of the oven sooner. I will definitely make this recipe again.", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "MAS13", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/1304373\/" + } + }, + { + "@type": "Review", + "datePublished": "2007-10-14T17:19:22.547Z", + "reviewBody": "Great recipe! Great cake! It was dense as pound cake should be, but not heavy at all. This was my first attempt at making a pound cake and it came out perfect! I used three sticks of butter, egg substitute, fat free sour cream, omitted the mace, used the zest and juice of one lemon, 1 3\/4 tsp. vanilla extract, and 1\/4 tsp. of almond extract. I followed the advice of other viewers and beat the sugar and butter for seven minutes. I mixed for one minute after the addition of each egg. I folded in the flour mixture and sour cream and I was very careful not to over work the batter, so that the cake would not be tough. This is a definite keeper! Thanks for sharing.", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "Gilda George", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/ebony3\/" + } + }, + { + "@type": "Review", + "datePublished": "2006-12-30T19:43:56.627Z", + "reviewBody": "Wow...what a moist and flavorful cake. I've been searching for a sour cream bundt cake recipe like my mom used to make and this is it. I made the following modifications after reading the reviews: Omitted the mace added 1\/4 teaspoon baking powder and increased vanilla to 2 teaspoons. Baked at 325 degrees on middle rack in my oven. Cake was done after 1 hr and 10 minutes. This is delicious plain or drizzled with vanilla glaze. I plan to use this for strawberry shortcakes in the spring and for trifle.", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "CLANCYSMOM", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/943965\/" + } + }, + { + "@type": "Review", + "datePublished": "2005-05-13T01:57:00.107Z", + "reviewBody": "I had a lot of eggs and wanted to bake a cake to get rid of them. This one (with 6 eggs) turned out great. Very moist very tasty. Tips: use a little more than a pinch of ground mace (up to 1\/4 teaspoon) and watch the cake closely for the final 15 minutes (I almost left it in the oven too long...next time I'll bake it at 325 degrees). This one is a keeper!", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "Brown Sugar Girl", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/204291\/" + } + } + ], + "keywords": "", + "tool": [], + "url": "https:\/\/www.allrecipes.com\/recipe\/84042\/grandmas-sour-cream-pound-cake\/", + "dateModified": "2021-06-02T20:34:41+0000", + "dateCreated": "2021-01-30T14:57:34+0000", + "id": 908712, + "printImage": false, + "imageUrl": "\/apps\/cookbook\/recipes\/908712\/image?size=full" +} diff --git "a/packages/nextcloud_test/docker/assets/Recipes/Lachs auf Fr\303\203\302\274hlingssalat/recipe.json" "b/packages/nextcloud_test/docker/assets/Recipes/Lachs auf Fr\303\203\302\274hlingssalat/recipe.json" new file mode 100644 index 00000000000..02831039acc --- /dev/null +++ "b/packages/nextcloud_test/docker/assets/Recipes/Lachs auf Fr\303\203\302\274hlingssalat/recipe.json" @@ -0,0 +1,36 @@ +{ + "name": "Lachs auf Fr\u00c3\u00bchlingssalat ", + "image": "https:\/\/recipecontent.fooby.ch\/19134_3-2_480-320.jpg", + "recipeYield": 4, + "keywords": "Hauptgericht,Salate,Sommer", + "recipeIngredient": [ + " 100 g schwarze Linsen (Beluga)", + " Wasser, siedend", + " \u00c2\u00bc TL Salz", + " 1 Bio-Zitrone, abgeriebene Schale und 2 EL Saft", + " 3 EL Haselnuss\u00c3\u00b6l", + " \u00c2\u00bd TL Salz", + " wenig Pfeffer", + " 1 Bund Kerbel, fein geschnitten", + " 1 Bund Radiesli mit dem Gr\u00c3\u00bcn, Radiesli geviertelt, 10 g Gr\u00c3\u00bcn fein geschnitten", + " 300 g R\u00c3\u00bcebli, mit dem Sparsch\u00c3\u00a4ler in d\u00c3\u00bcnne Streifen geschnitten", + " \u00c2\u00bd EL Oliven\u00c3\u00b6l", + " 250 g Rhabarber, in ca. 6 cm langen St\u00c3\u00bccken, halbiert", + " 2 EL Yaconsirup", + " \u00c2\u00bd EL Oliven\u00c3\u00b6l", + " 400 g Lachsr\u00c3\u00bcckenfilet" + ], + "recipeInstructions": [ + "\n \n Linsen \n \n Linsen im siedenden Wasser bei mittlerer Hitze ca. 20 Min. k\u00c3\u00b6cheln, abtropfen, salzen, beiseite stellen.\n \n \n Salat \n \n Zitronenschale und -saft mit dem \u00c3\u0096l in einer Sch\u00c3\u00bcssel verr\u00c3\u00bchren, w\u00c3\u00bcrzen, Kerbel und Radiesligr\u00c3\u00bcn daruntermischen. Radiesli, R\u00c3\u00bcebli und beiseite gestellte Linsen beigeben, mischen. \n \n \n Lachs\n \n \u00c3\u0096l in einer beschichteten Bratpfanne erhitzen. Rhabarber beigeben, ca. 2 Min. r\u00c3\u00bchrbraten. Yaconsirup beigeben, ca. 2 Min. k\u00c3\u00b6cheln, mit der entstandenen Fl\u00c3\u00bcssigkeit unter den Salat mischen. \u00c3\u0096l in derselben Pfanne erhitzen. Lachs beidseitig je ca. 3 Min. braten, auf dem Salat anrichten. \n \n \n " + ], + "@context": "http:\/\/schema.org", + "@type": "Recipe", + "recipeCategory": "", + "tool": [], + "description": "", + "url": "https:\/\/fooby.ch\/de\/rezepte\/19134\/lachs-auf-fruehlingssalat-", + "nutrition": [], + "dateModified": "2021-04-17T12:59:22+0000", + "dateCreated": "2021-04-17T12:59:22+0000", + "id": 3 +} diff --git a/packages/nextcloud_test/docker/assets/Recipes/Readme.md b/packages/nextcloud_test/docker/assets/Recipes/Readme.md new file mode 100644 index 00000000000..2027829dcae --- /dev/null +++ b/packages/nextcloud_test/docker/assets/Recipes/Readme.md @@ -0,0 +1,2 @@ +Recipes in this directory are taken from the [nextcloud-cookbook-flutter](https://github.com/Teifun2/nextcloud-cookbook-flutter/) project. +The recipes contain some nasty formatting and both test parsing of the recipe respnse and the server cookbook app to apply correcting filters. diff --git a/packages/nextcloud_test/docker/assets/Recipes/Recipe Without an image/recipe.json b/packages/nextcloud_test/docker/assets/Recipes/Recipe Without an image/recipe.json new file mode 100644 index 00000000000..b840efd7ca8 --- /dev/null +++ b/packages/nextcloud_test/docker/assets/Recipes/Recipe Without an image/recipe.json @@ -0,0 +1,21 @@ +{ + "id": 0, + "name": "Recipe Without an image", + "description": "", + "url": "", + "image": "", + "prepTime": "", + "cookTime": "", + "totalTime": "", + "recipeCategory": "", + "keywords": "", + "recipeYield": 1, + "tool": [], + "recipeIngredient": [], + "recipeInstructions": [], + "nutrition": [], + "@context": "http:\/\/schema.org", + "@type": "Recipe", + "dateModified": "2021-12-18T16:30:25+0000", + "dateCreated": "2021-12-18T16:30:25+0000" +} diff --git a/packages/nextcloud_test/docker/assets/Recipes/Reines Roggenbrot aus Sauerteig/recipe.json b/packages/nextcloud_test/docker/assets/Recipes/Reines Roggenbrot aus Sauerteig/recipe.json new file mode 100644 index 00000000000..cf99d80daac --- /dev/null +++ b/packages/nextcloud_test/docker/assets/Recipes/Reines Roggenbrot aus Sauerteig/recipe.json @@ -0,0 +1,125 @@ +{ + "@context": "http:\/\/schema.org", + "@type": "Recipe", + "image": "https:\/\/img.chefkoch-cdn.de\/rezepte\/2949131447162709\/bilder\/1362373\/crop-960x540\/reines-roggenbrot-aus-sauerteig.jpg", + "recipeCategory": "Backen", + "recipeIngredient": [ + "210 g Roggenvollkornmehl", + "230 g Wasser", + "4 g Salz", + "40 g Anstellgut", + "60 g Altbrot", + "240 g Wasser", + "8 g Salz", + "370 g Roggenmehl Type 1370", + "120 g Wasser Wasser" + ], + "name": "Reines Roggenbrot aus Sauerteig", + "description": "Reines Roggenbrot aus Sauerteig - Roggenbrot aus Sauerteig mit Br\u00fchst\u00fcck und Anstellgut. \u00dcber 28 Bewertungen und f\u00fcr sehr lecker befunden. Mit \u25ba Portionsrechner \u25ba Kochbuch \u25ba Video-Tipps!", + "recipeInstructions": [ + "Sauerteig", + "Die Zutaten f\u00fcr den Sauerteig (210 g Roggenvollkornmehl, 230 g Wasser (45 Grad Celsius), 4 g Salz und 40 g Anstellgut) verr\u00fchren und 12-16 Stunden bei Raumtemperatur reifen lassen.", + "Br\u00fchst\u00fcck", + "F\u00fcr das Br\u00fchst\u00fcck kochendes Wasser (240 g) mit dem Salz und dem Altbrot verr\u00fchren und abgedeckt auf Raumtemperatur ausk\u00fchlen lassen. Lagerf\u00e4hig bis zu 12 Stunden.", + "Hauptteig", + "F\u00fcr den Hauptteig den gesamten Sauerteig, das Br\u00fchst\u00fcck, 370 g Roggenmehl (Type 1370) und 120 g Wasser (70 Grad Celsius) von Hand oder auf niedrigster Stufe 5-8 Minuten mischen bis eine glatte, geschmeidige Masse entstanden ist (Teigtemperatur zirka 28 Grad Celsius). Bei Bedarf noch Wasser nachsch\u00fctten.", + "Den Teig 30 Minuten bei Raumtemperatur ruhen lassen.", + "Den Teig rundwirken und mit Schluss nach unten in den bemehlten G\u00e4rkorb setzen.", + "80 Minuten bei Raumtemperatur reifen lassen.", + "Brot backen", + "Mit knapper Gare und Schluss nach oben bei 250 Grad Celsius fallend auf 200 Grad Celsius 50 Minuten ohne Dampf backen." + ], + "author": { + "@type": "Person", + "name": "Gel\u00f6schter Benutzer" + }, + "publisher": { + "@type": "Organization", + "name": "Chefkoch.de" + }, + "datePublished": "2016-10-05", + "prepTime": "PT1H0M", + "cookTime": "PT0H50M", + "totalTime": "PT15H50M", + "recipeYield": 4, + "aggregateRating": { + "@type": "AggregateRating", + "ratingCount": 28, + "ratingValue": 4.57, + "reviewCount": 21, + "worstRating": 0, + "bestRating": 5 + }, + "video": [ + { + "@type": "VideoObject", + "name": "Video zu Reines Roggenbrot aus Sauerteig", + "description": "Video zu Reines Roggenbrot aus Sauerteig", + "thumbnailUrl": "https:\/\/api.chefkoch.de\/v2\/images\/crop-960x540\/videos\/1071\/preview\/org", + "contentUrl": "https:\/\/www.chefkoch.de\/rezepte\/2949131447162709\/Reines-Roggenbrot-aus-Sauerteig.html", + "embedUrl": "https:\/\/video.chefkoch-cdn.de\/ck.de\/videos\/1071-video.mp4", + "uploadDate": "2016-10-05" + } + ], + "nutrition": { + "@type": "NutritionInformation", + "servingSize": "1", + "calories": "511 kcal", + "proteinContent": "12,49g", + "fatContent": "2,07g", + "carbohydrateContent": "107,77g" + }, + "keywords": "Backen,Vegetarisch,Vegan,Backen oder S\u00fc\u00dfspeise,Brot oder Br\u00f6tchen", + "reviews": [ + { + "@type": "Review", + "reviewBody": "Das Brot ist der Hammer!!! Wie soll ich je wieder Brot vom Discounter essen k\u00f6nnen, jetzt wo ich wei\u00df, wie es schmecken muss? :)", + "datePublished": "2021-08-16", + "author": { + "@type": "Person", + "name": "juli481" + } + }, + { + "@type": "Review", + "reviewBody": "Was macht man denn, wenn man noch nie ein Brot gebacken hat und kein Anstellgut hat?! WIe macht man Anstellgut?", + "datePublished": "2021-06-17", + "author": { + "@type": "Person", + "name": "mettkoenig" + } + }, + { + "@type": "Review", + "reviewBody": "Hallo!\r\n\r\nDie Kommentare hatten mich etwas verwirrt, ebenso der Hinweis auf ein Video(?).\r\nIch habe unsere zwei Brote trotzdem nach diesem Rezept fabriziert. Gr\u00f6\u00dfere Probleme gab es nicht, nur die Gare dauerte wesentlich l\u00e4nger als angegeben. Das passiert mir allerdings \u00f6fter beim Ausprobieren neuer Rezepte. Geschmacklich gef\u00e4llt das Brot sehr gut.\r\n\r\nVG Tiiine", + "datePublished": "2021-06-14", + "author": { + "@type": "Person", + "name": "gourmettine" + } + }, + { + "@type": "Review", + "reviewBody": "Und wenn man kein 1370 Mehl hat???", + "datePublished": "2019-09-28", + "author": { + "@type": "Person", + "name": "hobbykochgeselle" + } + }, + { + "@type": "Review", + "reviewBody": "Super tolles Rezept! Ist mir gut gelungen, auch wegen dem hervorragenden Video! Danke!!", + "datePublished": "2017-11-17", + "author": { + "@type": "Person", + "name": "MariSaKi" + } + } + ], + "tool": [], + "url": "https:\/\/www.chefkoch.de\/rezepte\/2949131447162709\/Reines-Roggenbrot-aus-Sauerteig.html", + "dateModified": "2021-12-19T01:18:11+0000", + "dateCreated": "2021-12-19T01:18:11+0000", + "id": 3 +} diff --git a/packages/nextcloud_test/docker/assets/Recipes/Restaurant-Style Zuppa Toscana/recipe.json b/packages/nextcloud_test/docker/assets/Recipes/Restaurant-Style Zuppa Toscana/recipe.json new file mode 100644 index 00000000000..35fadacc61e --- /dev/null +++ b/packages/nextcloud_test/docker/assets/Recipes/Restaurant-Style Zuppa Toscana/recipe.json @@ -0,0 +1,266 @@ +{ + "@context": "http:\/\/schema.org", + "@type": "Recipe", + "mainEntityOfPage": "https:\/\/www.allrecipes.com\/recipe\/13183\/restaurant-style-zuppa-toscana\/", + "datePublished": "1999-03-14T09:49:38.000Z", + "recipeCuisine": [], + "author": [ + { + "@type": "Person", + "name": "Nancy" + } + ], + "aggregateRating": { + "@type": "AggregateRating", + "ratingValue": 4.717329545454546, + "ratingCount": 704, + "itemReviewed": "Restaurant-Style Zuppa Toscana", + "bestRating": "5", + "worstRating": "1" + }, + "nutrition": { + "@type": "NutritionInformation", + "calories": "380.4 calories", + "carbohydrateContent": "21.1 g", + "cholesterolContent": "77.9 mg", + "fatContent": "25.4 g", + "fiberContent": "2.4 g", + "proteinContent": "17.3 g", + "saturatedFatContent": "10.3 g", + "sodiumContent": "1904 mg", + "sugarContent": "4.2 g" + }, + "review": [ + { + "@type": "Review", + "datePublished": "2003-12-17T16:27:24.043Z", + "reviewBody": "As a retired test kitchen chef, I am bound to dabble. So after reading all the reviews, I set to work to make a lower fat version and still maintain taste. I had researched the Top Secret version and felt I could even drop fat content on that one too.\r\n\r\n1. I used hot italian turkey sausage. Yes it came in links, but I squeezed out the meat and cooked it. Then roll in paper towels to get out any remaining fat. \r\n\r\n2. Bacon and Onion should be cooked separately, then blended in at the last minute to meld flavors.\r\n3. I dropped the water content, got rid of the cream and used entirely fat free half and half from the dairy section. Brilliant stuff and works well in this recipe. Smooth, rich, not too thin consistency\r\n\r\n4. Some brave souls prefer to add pepper at this point, but I say \"to taste\"\r\n\r\n5. I prefer the texture of Youkon Gold potatoes, but any young new potato with the skins on is great. If you like earthy, you can use russets. I have never been a fan of dirt so I stick with thin skins.\r\n\r\nSo play, enjoy! And don't forget the Romano!", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 4 + }, + "author": { + "@type": "Person", + "name": "SUDIEMARIE", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/888457\/" + } + }, + { + "@type": "Review", + "datePublished": "2005-10-10T01:59:17.907Z", + "reviewBody": "Excellent recipe. I have made this so many times here is what I have changed:\r\n\r\nCook the bacon separately from the onions to avoid burning. Use six chicken bullion cubes. Use 1\/2 cup of cream. Increase the water to 1 1\/2 quarts. Use 1\/2 pound of mild ground italian sausage and 1\/2 pound of spicy ground sausage instead of the sausage links.", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 4 + }, + "author": { + "@type": "Person", + "name": "RogueOnion8", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/185024\/" + } + }, + { + "@type": "Review", + "datePublished": "2003-12-17T16:29:28.043Z", + "reviewBody": "This is a fantastic recipe...and it's even tastier and easier made in a crock-pot! Thought I would share with you haw I did it. I baked 4 Italian Sausages in the oven until the were done. Meanwhile, I cooked the bacon pieces and removed them from the skillet along with most of the grease. I sauteed the onion and garlic in the remaining Tbs or so of bacon fat. I also added one carrot, diced. I added the sauteed vegetables along with the diced potatoes to a 3 and 1\/2 quart crock-pot and covered with two cans of chicken broth and one can of beef broth, some of which I used to deglaze the skillet. When the sausages were done, I sliced them and added them to the pot. I let the pot simmer on low for about 6 hours. When we got home, I turned the pot to high and added the chopped kale and cooked bacon and let them cook for about 15 minutes while I made some garlic bread. When we were ready to serve, I poured a Tbs or so of cream into each bowl and ladled in the soup. Fantastic and so easy!", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "OMAHA", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/45814\/" + } + }, + { + "@type": "Review", + "datePublished": "2003-09-10T23:56:51.543Z", + "reviewBody": "When I make this soup I have my hubby in mind. He loves the Zuppa Toscana soup at a popular italian restaurant..(yeah..I'm sure you know which one I'm talking about). I like to use the \"hot\" italian sausage and fresh spinach instead of kale. I cut my bacon with scissors and fry it by itself. Then I use the bacon grease to saute the onions. There have been occasions when I didn't have any cream on hand and so I used either half and half or whole milk with a little butter. I also have replaced half of the water called for with chicken broth..and it's great. Thanks Nancy.", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "JOSIE", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/15350275\/" + } + }, + { + "@type": "Review", + "datePublished": "2003-01-26T14:53:38.593Z", + "reviewBody": "i used to work for the olive garden and i thought their soup was good. but i have been proven wrong. this is AMAZING. i LOVE IT!!! i will make this again and again.", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "WNORTH", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/719269\/" + } + }, + { + "@type": "Review", + "datePublished": "2004-02-02T13:39:49.513Z", + "reviewBody": "I make this soup often & my children LOVE it! I use ground Italian sausage (so that there is no need to deal with the casing) and I just brown it along with some cayenne pepper (for a kick) and then drain it. I also drain all but 1 tbsp. of the bacon grease and add a pinch of crushed red pepper. I used to frequent Olive Garden to get this soup but it is just so much better homemade not to mention fresher (you know how sometimes you get that bad waiter\/waitress that gives you a bowl of kale)! YUM!! Thanks Nancy!", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "I'm nuts too", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/610376\/" + } + }, + { + "@type": "Review", + "datePublished": "2002-11-01T08:09:57.28Z", + "reviewBody": "I love this soup! I make it every year upon request from the family. I would suggest cooking the bacon first remove then cook chopped onions in bacon grease. Otherwise onions burn before bacon is cooked. Great recipe!!", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "BILLIAME", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/648398\/" + } + }, + { + "@type": "Review", + "datePublished": "2002-10-19T22:52:59.233Z", + "reviewBody": "Okay I had to rate this recipe again just to say that I had to give the recipe to my son-in-law who went nuts over this soup after I sent home with him and my daughter. Any time I offer a frozen container he is thrilled. I do find I like the texture better after the soup is cooled and then reheated. Also I always use the entire bunch of kale and mild italian sausage which I think is wonderful. Family or entertaining this is fabulous!", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "DIANEM527", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/52535\/" + } + }, + { + "@type": "Review", + "datePublished": "2003-01-30T06:25:32.293Z", + "reviewBody": "DELISH! I was so excited to try this soup and it exceeded all my expectations! It is a wonderful copy of the restaurant soup which is one of my all time faves! I omitted the sausage since i'm not a sausage fan and increased the bacon. I also used spinach instead of kale since for some odd reason my grocery store doesn't carry kale but it didn't really change the taste at all. I highly recommend this soup it was wonderful!", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "RENA21", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/156307\/" + } + }, + { + "@type": "Review", + "datePublished": "2008-06-16T12:49:28.3Z", + "reviewBody": "My family weren't fans but it had good flavor. I don't discourage people from trying it. I just think that it didn't meet my family's taste.", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 3 + }, + "author": { + "@type": "Person", + "name": "Bakingdom", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/2534652\/" + } + } + ], + "video": { + "@context": "http:\/\/schema.org", + "@type": "VideoObject", + "name": "Restaurant-Style Zuppa Toscana", + "description": "See how to make a healthy Tuscan-style soup.", + "uploadDate": "2013-01-04T22:32:45.295Z", + "duration": "PT4M34.691S", + "thumbnailUrl": "https:\/\/imagesvc.meredithcorp.io\/v3\/mm\/image?url=https%3A%2F%2Fcf-images.us-east-1.prod.boltdns.net%2Fv1%2Fstatic%2F1033249144001%2Fa665f26e-0c96-49dc-81d9-6de80f92349f%2F8f5e9839-8e88-4525-88e1-8b4cb8a66bc9%2F160x90%2Fmatch%2Fimage.jpg", + "publisher": { + "@type": "Organization", + "name": "Allrecipes", + "url": "https:\/\/www.allrecipes.com", + "logo": { + "@type": "ImageObject", + "url": "https:\/\/www.allrecipes.com\/img\/logo.png", + "width": 209, + "height": 60 + }, + "sameAs": [ + "https:\/\/www.facebook.com\/allrecipes", + "https:\/\/twitter.com\/Allrecipes", + "https:\/\/www.pinterest.com\/allrecipes\/", + "https:\/\/www.instagram.com\/allrecipes\/" + ] + }, + "embedUrl": "https:\/\/players.brightcove.net\/1033249144001\/default_default\/index.html?videoId=2073395161001" + }, + "dateCreated": "2021-01-30T14:58:40+0000", + "printImage": false, + "id": 908730, + "name": "Restaurant-Style Zuppa Toscana", + "imageUrl": "\/apps\/cookbook\/recipes\/908730\/image?size=full", + "recipeCategory": "Soup", + "description": "Creamy sausage and potato soup. This recipe is very similar to the one served in a well known restaurant.", + "recipeIngredient": [ + "1 (16 ounce) package smoked sausage", + "2 potatoes, cut into 1\/4-inch slices", + "\u00be cup chopped onion", + "6 slices bacon", + "1\u2009\u00bd teaspoons minced garlic", + "2 cups kale - washed, dried, and shredded", + "2 tablespoons chicken soup base", + "1 quart water", + "\u2153 cup heavy whipping cream" + ], + "recipeInstructions": [ + "Preheat oven to 300 degrees F (150 degrees C).\n", + "Place sausage links onto a sheet pan and bake for 25 minutes, or until done. Cut links in half lengthwise, then cut at an angle into 1\/2-inch slices.\n", + "Place onions and bacon slices in a large saucepan and cook over medium heat until onions are almost clear. Remove bacon and crumble. Set aside.\n", + "Add garlic to the onions and cook an additional 1 minute. Add chicken soup base, water, and potatoes, simmer 15 minutes.\n", + "Add crumbled bacon, sausage, kale, and cream. Simmer 4 minutes and serve.\n" + ], + "tool": [], + "recipeYield": 6, + "prepTime": "PT0H15M", + "cookTime": "PT0H2M", + "totalTime": "PT1H5M", + "keywords": "", + "image": "https:\/\/imagesvc.meredithcorp.io\/v3\/mm\/image?url=https%3A%2F%2Fimages.media-allrecipes.com%2Fuserphotos%2F1515920.jpg", + "url": "https:\/\/www.allrecipes.com\/recipe\/13183\/restaurant-style-zuppa-toscana\/", + "dateModified": "2021-06-18T12:31:58+0000" +} diff --git "a/packages/nextcloud_test/docker/assets/Recipes/Sellerie-Rucola-Suppe mit Zitronen\303\203\302\266l/recipe.json" "b/packages/nextcloud_test/docker/assets/Recipes/Sellerie-Rucola-Suppe mit Zitronen\303\203\302\266l/recipe.json" new file mode 100644 index 00000000000..9ff240c0bdd --- /dev/null +++ "b/packages/nextcloud_test/docker/assets/Recipes/Sellerie-Rucola-Suppe mit Zitronen\303\203\302\266l/recipe.json" @@ -0,0 +1,38 @@ +{ + "@context": "http:\/\/schema.org", + "@type": "Recipe", + "nutrition": [], + "dateCreated": "2021-04-17T12:41:40+0000", + "printImage": false, + "id": 922659, + "name": "Sellerie-Rucola-Suppe mit Zitronen\u00c3\u00b6l", + "imageUrl": "\/apps\/cookbook\/recipes\/922659\/image?size=full", + "recipeCategory": "", + "description": "", + "recipeIngredient": [ + " 1 dl Oliven\u00c3\u00b6l", + " 2 Bio-Zitronen, nur abgeriebene Schale", + " 1 EL Oliven\u00c3\u00b6l", + " 1 Zwiebel, grob gehackt", + " 1 Knoblauchzehe, grob gehackt", + " 800 g Knollensellerie, in St\u00c3\u00bccken", + " 1 Liter Wasser", + " 2 TL Salz", + " 100 g Rucola, grob geschnitten", + " 1 EL Zitronensaft", + " Salz, Pfeffer, nach Bedarf", + " 50 g Rucola" + ], + "recipeInstructions": [ + "\n \n Schnelles Zitronen\u00c3\u00b6l\n \n \u00c3\u0096l in einer kleinen Pfanne erw\u00c3\u00a4rmen. Zitronenschale beigeben, in eine kleine, saubere Flasche umf\u00c3\u00bcllen.\n \n \n Suppe\n \n \u00c3\u0096l in einer Pfanne erw\u00c3\u00a4rmen. Zwiebel und Knoblauch and\u00c3\u00a4mpfen. Sellerie beigeben, ca. 3 Min. mitd\u00c3\u00a4mpfen. Wasser dazugiessen, aufkochen, salzen. Suppe ca. 25 Min. k\u00c3\u00b6cheln. Rucola beigeben, ca. 5 Min. mitk\u00c3\u00b6cheln, fein p\u00c3\u00bcrieren. \n \n \n Anrichten\n \n Zitronensaft unter die Suppe r\u00c3\u00bchren, w\u00c3\u00bcrzen. Suppe anrichten, Rucola mit wenig Zitronen\u00c3\u00b6l auf der Suppe verteilen. \n \n \n " + ], + "tool": [], + "recipeYield": 4, + "prepTime": "", + "cookTime": "PT0H2M", + "totalTime": "", + "keywords": "Winter,Suppen und Eintopf", + "image": "https:\/\/recipecontent.fooby.ch\/18757_3-2_480-320.jpg", + "url": "https:\/\/fooby.ch\/de\/rezepte\/18757\/sellerie-rucola-suppe-mit-zitronenoel", + "dateModified": "2021-07-05T14:57:07+0000" +} diff --git a/packages/nextcloud_test/docker/assets/Recipes/Sommerlicher Himbeerkuchen/recipe.json b/packages/nextcloud_test/docker/assets/Recipes/Sommerlicher Himbeerkuchen/recipe.json new file mode 100644 index 00000000000..59cb35240e8 --- /dev/null +++ b/packages/nextcloud_test/docker/assets/Recipes/Sommerlicher Himbeerkuchen/recipe.json @@ -0,0 +1,34 @@ +{ + "name": "Sommerlicher Himbeerkuchen", + "image": "https:\/\/recipecontent.fooby.ch\/18323_3-2_480-320.jpg", + "recipeYield": 8, + "keywords": "Desserts,Sommer,Herbst", + "recipeIngredient": [ + " 200 g Kokosraspel", + " 180 g Datteln, entsteint", + " 1 EL Ahornsirup", + " 5 EL Kokos\u00f6l", + " 1 Prise Salz", + " 1 Dose Kokosmilch (ca. 4 dl), \u00fcber Nacht in den K\u00fchlschrank gestellt", + " 100 g vegane, weisse Schokolade, in St\u00fccken", + " 2 EL Kokos\u00f6l", + " 1 dl Mandeldrink", + " 80 g Kokosbl\u00fctenzucker", + " 10 g Agar-Agar (Morga)", + " 1 TL Vanillepaste", + " 250 g Himbeeren" + ], + "recipeInstructions": [ + "\n \n Boden\n \n Alle Zutaten im Cutter oder Mixglas p\u00fcrieren, bis eine klebrige Masse entsteht. Die Masse in die vorbereitete Springform geben und mit den H\u00e4nden flachdr\u00fccken, dabei einen ca. 2 cm hohen Rand formen.\n \n \n F\u00fcllung\n \n Den hart gewordenen Teil der Kokosmilch (Kokoscreme) absch\u00f6pfen. Schokolade mit dem Kokos\u00f6l im Wasserbad schmelzen, gut verr\u00fchren. Mandeldrink mit Zucker und Agar-Agar unter R\u00fchren aufkochen, mit der Kokoscreme, der Schokolade und der Vanillepaste gut verr\u00fchren. F\u00fcllung auf den Kuchenboden giessen. Kuchen zugedeckt ca. 4 Std. k\u00fchl stellen.\n \n \n Beeren\n \n Den Kuchen vor dem Servieren mit den Himbeeren verzieren.\n \n \n " + ], + "@context": "http:\/\/schema.org", + "@type": "Recipe", + "recipeCategory": "", + "tool": [], + "description": "", + "url": "https:\/\/fooby.ch\/de\/rezepte\/18323\/sommerlicher-himbeerkuchen", + "nutrition": [], + "dateModified": "2021-04-17T13:02:08+0000", + "dateCreated": "2021-04-17T13:02:08+0000", + "id": 9 +} diff --git a/packages/nextcloud_test/docker/assets/Recipes/Sweet and Spicy Baked Keto Chicken WingsNEW/recipe.json b/packages/nextcloud_test/docker/assets/Recipes/Sweet and Spicy Baked Keto Chicken WingsNEW/recipe.json new file mode 100644 index 00000000000..293128aeb07 --- /dev/null +++ b/packages/nextcloud_test/docker/assets/Recipes/Sweet and Spicy Baked Keto Chicken WingsNEW/recipe.json @@ -0,0 +1,104 @@ +{ + "@context": "http:\/\/schema.org", + "@type": "Recipe", + "mainEntityOfPage": "https:\/\/www.allrecipes.com\/recipe\/276110\/sweet-and-spicy-baked-keto-chicken-wings\/", + "datePublished": "2019-10-16T23:43:05.000Z", + "recipeCuisine": [], + "author": [ + { + "@type": "Person", + "name": "SunnyDaysNora" + } + ], + "aggregateRating": { + "@type": "AggregateRating", + "ratingValue": 5, + "ratingCount": 3, + "itemReviewed": "Sweet and Spicy Baked Keto Chicken Wings", + "bestRating": "5", + "worstRating": "1" + }, + "nutrition": { + "@type": "NutritionInformation", + "calories": "670.1 calories", + "carbohydrateContent": "15.1 g", + "cholesterolContent": "137.6 mg", + "fatContent": "55.8 g", + "fiberContent": "0.1 g", + "proteinContent": "24.8 g", + "saturatedFatContent": "22.3 g", + "sodiumContent": "1822.2 mg", + "sugarContent": "13.4 g" + }, + "review": [ + { + "@type": "Review", + "datePublished": "2020-09-26T13:05:32.147Z", + "reviewBody": "Delicious! I used Erythritol Sweetener, Frank's Hot Sauce and unsalted butter.", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "jalbanese", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/10729683\/" + } + }, + { + "@type": "Review", + "datePublished": "2020-02-02T03:48:54.84Z", + "reviewBody": "This was so easy and I loved it. Unfortunately I am not Keto so I did not have Splenda; I used sugar. I will need to try Splenda the next. I used Frank Original Red Hot Sauce.", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "Sydney", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/8837556\/" + } + } + ], + "dateCreated": "2021-01-30T14:58:58+0000", + "printImage": false, + "id": 908736, + "name": "Sweet and Spicy Baked Keto Chicken WingsNEW", + "imageUrl": "\/apps\/cookbook\/recipes\/908736\/image?size=full", + "recipeCategory": "Appetizer", + "description": "My family loves these low-carb and keto-friendly baked chicken wings! They're a staple around our house during football season. I love to serve them with blue cheese dressing for dipping. Updated! AGAINN!! And again!", + "recipeIngredient": [ + "aluminum foilll", + "cooking spray", + "\u00bd cup butter", + "\u00be cup hot pepper sauce (such as Valentina\u00ae)", + "\u00bc cup sucralose sugar substitute (such as Splenda\u00ae)", + "\u00bc teaspoon salt", + "\u00bc teaspoon garlic powder", + "3 pounds chicken wing pieces, drumettes and flats", + "\u00bd cup blue cheese salad dressing" + ], + "recipeInstructions": [ + "Melt TO MUCH butter in a small saucepan. Mix in hot sauce, sucralose, salt, and garlic powder. Remove from heat and set sauce aside.\n", + "Bake in the preheated oven for 15 minutes. Remove from the oven, pour off any juices accumulated in the bottom of the pan, and turn chicken pieces over. Bake for an additional 15 minutes.\n", + "Preheat the oven to 425 degrees F (220 degrees C). \n\nLine a rimmed baking pan with foil. Spray a wire rack with cooking spray and set inside the baking pan.", + "Remove chicken from the oven and transfer to a large bowl. Cover with sauce and toss to coat. Return chicken to the rack on the baking pan and bake until no longer pink at the bone and the juices run clear, 15 to 30 minutes. An instant-read thermometer inserted near the bone should read 165 degrees F (74 degrees C).\n", + "Don't Worry be Happy :D", + "Don't forget to fart! Much" + ], + "tool": [], + "recipeYield": 4, + "prepTime": "PT0H5M", + "cookTime": "PT0H45M", + "totalTime": "PT1H50M", + "keywords": "", + "image": "https:\/\/imagesvc.meredithcorp.io\/v3\/mm\/image?url=https%3A%2F%2Fimages.media-allrecipes.com%2Fuserphotos%2F7067746.jpg", + "url": "https:\/\/www.allrecipes.com\/recipe\/276110\/sweet-and-spicy-baked-keto-chicken-wings\/", + "dateModified": "2021-05-24T15:12:32+0000" +} diff --git a/packages/nextcloud_test/docker/assets/Recipes/The Best Baked Ziti/recipe.json b/packages/nextcloud_test/docker/assets/Recipes/The Best Baked Ziti/recipe.json new file mode 100644 index 00000000000..9ef5cd23e32 --- /dev/null +++ b/packages/nextcloud_test/docker/assets/Recipes/The Best Baked Ziti/recipe.json @@ -0,0 +1,257 @@ +{ + "@context": "http:\/\/schema.org", + "@type": "Recipe", + "mainEntityOfPage": "https:\/\/www.allrecipes.com\/recipe\/281646\/the-best-baked-ziti\/", + "name": "The Best Baked Ziti", + "image": "https:\/\/imagesvc.meredithcorp.io\/v3\/mm\/image?url=https%3A%2F%2Fimages.media-allrecipes.com%2Fuserphotos%2F8564993.jpg", + "datePublished": "2020-09-21T20:08:38.000Z", + "description": "I am half Italian, was raised eating the finest Italian-American cuisine, and have filmed almost 2000 recipe videos, so when you consider all of those facts, it seems incredible that I have never posted a video for baked ziti. Hopefully I make up for that long wait by posting what I think is the best version of it.", + "prepTime": "PT0H20M", + "cookTime": "PT1H45M", + "totalTime": "PT2H20M", + "recipeYield": 10, + "recipeIngredient": [ + "\u00be pound hot Italian sausage", + "\u00be pound sweet Italian sausage", + "2 tablespoons olive oil", + "1 large yellow onion, diced", + "\u00bd teaspoon dried oregano", + "\u00bc teaspoon dried thyme", + "\u00bc teaspoon dried rosemary", + "2 (24 ounce) jars prepared marinara sauce", + "2 cups water", + "1 (16 ounce) package ziti pasta", + "1 drizzle olive oil", + "1\u2009\u00bd cups whole-milk ricotta cheese", + "8 ounces mozzarella cheese, cut into small cubes", + "1 cup grated Pecorino Romano cheese", + "1 teaspoon chopped flat-leaf (Italian) parsley, or to taste" + ], + "recipeInstructions": [ + "Cut down the length of each sausage with a sharp knife. Remove and discard casings.\n", + "Heat olive oil in a large saucepan set over high heat. Add sausages and onion. Cook, stirring occasionally and breaking up with a spatula, until the sausage begins to brown, and the onion turns translucent, 5 to 7 minutes. Add oregano, thyme, and rosemary and cook for 1 minute more. Pour in marinara sauce. Pour 1 cup water into each jar to rinse out remaining sauce; add to the saucepan. Stir together and bring sauce to a simmer.\n", + "Reduce the heat to medium-low, and let simmer, stirring occasionally, for 1 hour. Taste for seasoning and adjust if needed. Turn off heat and reserve until needed. Before using, skim any excess fat that rises to the surface.\n", + "While sauce simmers, bring a large pot of generously salted water to a boil. Add ziti and cook, stirring occasionally, for 1 or 2 minutes less than the directions on the package call for, about 8 minutes. Drain well and transfer into a large mixing bowl.\n", + "Carefully add the meat sauce and stir until thoroughly combined. Let rest for 5 minutes.\n", + "Meanwhile, preheat the oven to 375 degrees F (190 degrees C). Grease a large 9x15-inch or 9x13-inch casserole dish with a drizzle of olive oil.\n", + "Use a slotted spoon to transfer half of the pasta and sauce mixture to the prepared dish, then use a spatula to even out into a uniform layer. Top with 1\/2 of the ricotta cheese, 1\/2 of the mozzarella cheese, and then 1\/2 of the grated Pecorino Romano cheese, being sure to distribute evenly. Top with the rest of the pasta and sauce mixture and give the pan a little shake to settle the sauce. Repeat the cheese application.\n", + "Bake in the center of the preheated oven until the cheese is melted and the casserole is piping hot, 30 to 35 minutes. Remove from the oven and let cool 10 to 15 minutes before serving. Top with parsley.\n" + ], + "recipeCategory": "Dinner", + "recipeCuisine": [], + "author": [ + { + "@type": "Person", + "name": "Chef John" + } + ], + "aggregateRating": { + "@type": "AggregateRating", + "ratingValue": 4.96078431372549, + "ratingCount": 51, + "itemReviewed": "The Best Baked Ziti", + "bestRating": "5", + "worstRating": "1" + }, + "nutrition": { + "@type": "NutritionInformation", + "calories": "627.1 calories", + "carbohydrateContent": "58.1 g", + "cholesterolContent": "71.8 mg", + "fatContent": "29.5 g", + "fiberContent": "5.3 g", + "proteinContent": "30.8 g", + "saturatedFatContent": "11.9 g", + "sodiumContent": "1380.1 mg", + "sugarContent": "14.4 g" + }, + "review": [ + { + "@type": "Review", + "datePublished": "2020-09-24T08:36:16.643Z", + "reviewBody": "Absolutely delicious! Used chicken sausage instead, this will be added to my meal plan!!! Thank you Chef John!!", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "Ziggy", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/28105440\/" + } + }, + { + "@type": "Review", + "datePublished": "2020-10-02T04:51:12.22Z", + "reviewBody": "Made the recipe exactly as Chef John. Turned out fantastic! I've had baked Ziti before, and he's right, most of the time it's too dry. This one had enough sauce to keep it moist.", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "George Carlton", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/17057648\/" + } + }, + { + "@type": "Review", + "datePublished": "2020-10-06T03:20:16.077Z", + "reviewBody": "somehow it wasn't as saucy but next time I'll add more water even though I followed instruction on that part.", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "Lee", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/10718800\/" + } + }, + { + "@type": "Review", + "datePublished": "2020-10-03T03:38:14.137Z", + "reviewBody": "I just made this for dinner and it definitely is the best baked Ziti I've ever had. I used Rao's Marinara Sauce since I think that's what Chef John used in the video based on part of the label I could see (I paused and zoomed in). I followed the recipe exactly and didn't even need to add more salt and pepper. It was perfect and will be making this again.", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "Joyce Cordova", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/24703506\/" + } + }, + { + "@type": "Review", + "datePublished": "2020-10-05T19:10:01.707Z", + "reviewBody": "Amazing. Made it exactly like Chef John did except that I made my own marinara sauce for it. It was perfect \n\nDefinitely do skim off the grease from the sauce before tossing in the pasta.", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "Milton Figures", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/28134556\/" + } + }, + { + "@type": "Review", + "datePublished": "2020-11-02T02:26:45.9Z", + "reviewBody": "It was lovely!!", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "Patricia Early", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/7126777\/" + } + }, + { + "@type": "Review", + "datePublished": "2020-09-27T04:16:39.35Z", + "reviewBody": "Followed Chef John's recipe and it came out perfect. Rave reviews. Thanks again Chef John for convincing me cooking is as easy as you make it look.", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "Vee", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/14707542\/" + } + }, + { + "@type": "Review", + "datePublished": "2020-10-02T23:21:28.723Z", + "reviewBody": "Delicious", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "Jewell", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/28123910\/" + } + }, + { + "@type": "Review", + "datePublished": "2020-10-02T01:55:11.56Z", + "reviewBody": "Excellent!", + "reviewRating": { + "@type": "Rating", + "worstRating": "1", + "bestRating": "5", + "ratingValue": 5 + }, + "author": { + "@type": "Person", + "name": "Philip Staff", + "image": null, + "sameAs": "https:\/\/www.allrecipes.com\/cook\/27614221\/" + } + } + ], + "video": { + "@context": "http:\/\/schema.org", + "@type": "VideoObject", + "name": "The Best Baked Ziti", + "uploadDate": "2020-09-21T14:51:05.091Z", + "duration": "PT8M51.947S", + "thumbnailUrl": "https:\/\/imagesvc.meredithcorp.io\/v3\/mm\/image?url=https%3A%2F%2Fcf-images.us-east-1.prod.boltdns.net%2Fv1%2Fstatic%2F1033249144001%2Fe88e4686-2359-4cb5-8ec7-3b5ff73e8312%2Fd6468130-7f14-46da-88f5-13889f4d7796%2F160x90%2Fmatch%2Fimage.jpg", + "publisher": { + "@type": "Organization", + "name": "Allrecipes", + "url": "https:\/\/www.allrecipes.com", + "logo": { + "@type": "ImageObject", + "url": "https:\/\/www.allrecipes.com\/img\/logo.png", + "width": 209, + "height": 60 + }, + "sameAs": [ + "https:\/\/www.facebook.com\/allrecipes", + "https:\/\/twitter.com\/Allrecipes", + "https:\/\/www.pinterest.com\/allrecipes\/", + "https:\/\/www.instagram.com\/allrecipes\/" + ] + }, + "embedUrl": "https:\/\/players.brightcove.net\/1033249144001\/default_default\/index.html?videoId=6193079583001" + }, + "keywords": "", + "tool": [], + "url": "https:\/\/www.allrecipes.com\/recipe\/281646\/the-best-baked-ziti\/", + "dateModified": "2021-01-30T15:00:09+0000", + "dateCreated": "2021-01-30T14:56:44+0000", + "id": 908700, + "printImage": false, + "imageUrl": "\/apps\/cookbook\/recipes\/908700\/image?size=full" +} diff --git a/packages/nextcloud_test/docker/assets/Recipes/Vegi-Tortillas/recipe.json b/packages/nextcloud_test/docker/assets/Recipes/Vegi-Tortillas/recipe.json new file mode 100644 index 00000000000..ccc712ad077 --- /dev/null +++ b/packages/nextcloud_test/docker/assets/Recipes/Vegi-Tortillas/recipe.json @@ -0,0 +1,35 @@ +{ + "name": "Vegi-Tortillas", + "image": "https:\/\/recipecontent.fooby.ch\/14222_3-2_480-320.jpg", + "recipeYield": 8, + "keywords": "Vorspeise", + "recipeIngredient": [ + " 400 g Rotkabis, fein gehobelt", + " 1 Limette, nur Saft", + " 1 EL Rohzucker", + " 2 TL Sambal Oelek", + " \u00bd TL Salz", + " 16 Mini-Tortillas", + " 8 EL Guacamole ", + " 1 Dose rote Indianerbohnen (ca. 290 g), abgesp\u00fclt, abgetropft", + " 60 g eingelegte Jalape\u00f1os in Scheiben", + " 200 g Manchego, grob gerieben", + " 200 g Cr\u00e8me fra\u00eeche", + " 1 Limette, heiss abgesp\u00fclt, trocken getupft, in Schnitzen", + " wenig Pfeffer", + " wenig Fleur de Sel" + ], + "recipeInstructions": [ + "\n \n Rotkabis\n \n Kabis mit Limettensaft, Rohzucker, Sambal Oelek und Salz mischen., zugedeckt ca. 30 Min. ziehen lassen.\n \n \n Tortillas\n \n Tortillas mit je \u00bd EL Guacamole bestreichen, auf zwei mit Backpapier belegte Bleche legen. Bohnen, Jalape\u00f1os und K\u00e4se darauf verteilen.\n \n \n Backen\n \n Pro Blech ca. 3 Min. in der oberen H\u00e4lfte des auf 220 \u00b0C vorgeheizten Ofens. Rotkabis und Cr\u00e8me fra\u00eeche darauf verteilen, mit Limettensaft betr\u00e4ufeln, w\u00fcrzen und umschlagen. \n \n \n " + ], + "@context": "http:\/\/schema.org", + "@type": "Recipe", + "recipeCategory": "", + "tool": [], + "description": "", + "url": "https:\/\/fooby.ch\/de\/rezepte\/14222\/vegi-tortillas?startAuto1=0", + "nutrition": [], + "dateModified": "2021-04-17T12:25:01+0000", + "dateCreated": "2021-04-17T12:25:01+0000", + "id": 12 +} diff --git a/packages/nextcloud_test/docker/assets/Recipes/problem/recipe.json b/packages/nextcloud_test/docker/assets/Recipes/problem/recipe.json new file mode 100644 index 00000000000..7334fcd43d5 --- /dev/null +++ b/packages/nextcloud_test/docker/assets/Recipes/problem/recipe.json @@ -0,0 +1,31 @@ +{ + "id": 128051, + "name": "Test-Recipe", + "description": "", + "url": "", + "image": "", + "prepTime": "", + "cookTime": "", + "totalTime": "", + "recipeCategory": "", + "keywords": "", + "recipeYield": 1, + "tool": [], + "recipeIngredient": [ + "Ingredient 1", + "", + "Ingredient 3" + ], + "recipeInstructions": [ + "Step 1", + "", + "Step 3" + ], + "nutrition": [], + "@context": "http:\/\/schema.org", + "@type": "Recipe", + "dateModified": "2021-10-30T16:02:47+0000", + "dateCreated": "2021-10-30T16:02:22+0000", + "printImage": false, + "imageUrl": "\/index.php\/apps\/cookbook\/recipes\/128051\/image?size=full" +} diff --git a/packages/nextcloud_test/docker/presets/cookbook/0.11 b/packages/nextcloud_test/docker/presets/cookbook/0.11 new file mode 100644 index 00000000000..cf14822f6dc --- /dev/null +++ b/packages/nextcloud_test/docker/presets/cookbook/0.11 @@ -0,0 +1,7 @@ +SERVER_VERSION=29.0.3 +COOKBOOK_URL=https://github.com/christianlupus-nextcloud/cookbook-releases/releases/download/v0.11.1/cookbook-0.11.1.tar.gz +DROP_ACCOUNT_URL=https://packages.framasoft.org/projects/nextcloud-apps/drop-account/drop_account-2.5.0.tar.gz +NEWS_URL=https://github.com/nextcloud/news/releases/download/25.0.0-alpha7/news.tar.gz +NOTES_URL=https://github.com/nextcloud-releases/notes/releases/download/v4.10.0/notes.tar.gz +SPREED_URL=https://github.com/nextcloud-releases/spreed/releases/download/v19.0.4/spreed-v19.0.4.tar.gz +UPPUSH_URL=https://codeberg.org/NextPush/uppush/archive/1.4.3.tar.gz diff --git a/packages/nextcloud_test/docker/presets/drop_account/2.4 b/packages/nextcloud_test/docker/presets/drop_account/2.4 index ee7420b0bee..0a5422ba4ff 100644 --- a/packages/nextcloud_test/docker/presets/drop_account/2.4 +++ b/packages/nextcloud_test/docker/presets/drop_account/2.4 @@ -1,4 +1,5 @@ SERVER_VERSION=28.0.7 +COOKBOOK_URL=https://github.com/christianlupus-nextcloud/cookbook-releases/releases/download/v0.11.1/cookbook-0.11.1.tar.gz DROP_ACCOUNT_URL=https://packages.framasoft.org/projects/nextcloud-apps/drop-account/drop_account-2.4.0.tar.gz NEWS_URL=https://github.com/nextcloud/news/releases/download/25.0.0-alpha8/news.tar.gz NOTES_URL=https://github.com/nextcloud-releases/notes/releases/download/v4.10.0/notes.tar.gz diff --git a/packages/nextcloud_test/docker/presets/drop_account/2.5 b/packages/nextcloud_test/docker/presets/drop_account/2.5 index 14800a49a27..4f36ad1c211 100644 --- a/packages/nextcloud_test/docker/presets/drop_account/2.5 +++ b/packages/nextcloud_test/docker/presets/drop_account/2.5 @@ -1,4 +1,5 @@ SERVER_VERSION=29.0.3 +COOKBOOK_URL=https://github.com/christianlupus-nextcloud/cookbook-releases/releases/download/v0.11.1/cookbook-0.11.1.tar.gz DROP_ACCOUNT_URL=https://packages.framasoft.org/projects/nextcloud-apps/drop-account/drop_account-2.5.0.tar.gz NEWS_URL=https://github.com/nextcloud/news/releases/download/25.0.0-alpha8/news.tar.gz NOTES_URL=https://github.com/nextcloud-releases/notes/releases/download/v4.10.0/notes.tar.gz diff --git a/packages/nextcloud_test/docker/presets/news/25.0 b/packages/nextcloud_test/docker/presets/news/25.0 index 14800a49a27..4f36ad1c211 100644 --- a/packages/nextcloud_test/docker/presets/news/25.0 +++ b/packages/nextcloud_test/docker/presets/news/25.0 @@ -1,4 +1,5 @@ SERVER_VERSION=29.0.3 +COOKBOOK_URL=https://github.com/christianlupus-nextcloud/cookbook-releases/releases/download/v0.11.1/cookbook-0.11.1.tar.gz DROP_ACCOUNT_URL=https://packages.framasoft.org/projects/nextcloud-apps/drop-account/drop_account-2.5.0.tar.gz NEWS_URL=https://github.com/nextcloud/news/releases/download/25.0.0-alpha8/news.tar.gz NOTES_URL=https://github.com/nextcloud-releases/notes/releases/download/v4.10.0/notes.tar.gz diff --git a/packages/nextcloud_test/docker/presets/notes/4.10 b/packages/nextcloud_test/docker/presets/notes/4.10 index 14800a49a27..4f36ad1c211 100644 --- a/packages/nextcloud_test/docker/presets/notes/4.10 +++ b/packages/nextcloud_test/docker/presets/notes/4.10 @@ -1,4 +1,5 @@ SERVER_VERSION=29.0.3 +COOKBOOK_URL=https://github.com/christianlupus-nextcloud/cookbook-releases/releases/download/v0.11.1/cookbook-0.11.1.tar.gz DROP_ACCOUNT_URL=https://packages.framasoft.org/projects/nextcloud-apps/drop-account/drop_account-2.5.0.tar.gz NEWS_URL=https://github.com/nextcloud/news/releases/download/25.0.0-alpha8/news.tar.gz NOTES_URL=https://github.com/nextcloud-releases/notes/releases/download/v4.10.0/notes.tar.gz diff --git a/packages/nextcloud_test/docker/presets/notes/4.8 b/packages/nextcloud_test/docker/presets/notes/4.8 index 646a884d460..d50e4956f5d 100644 --- a/packages/nextcloud_test/docker/presets/notes/4.8 +++ b/packages/nextcloud_test/docker/presets/notes/4.8 @@ -1,4 +1,5 @@ SERVER_VERSION=28.0.7 +COOKBOOK_URL=https://github.com/christianlupus-nextcloud/cookbook-releases/releases/download/v0.11.1/cookbook-0.11.1.tar.gz DROP_ACCOUNT_URL=https://packages.framasoft.org/projects/nextcloud-apps/drop-account/drop_account-2.5.0.tar.gz NEWS_URL=https://github.com/nextcloud/news/releases/download/25.0.0-alpha8/news.tar.gz NOTES_URL=https://github.com/nextcloud-releases/notes/releases/download/v4.8.1/notes.tar.gz diff --git a/packages/nextcloud_test/docker/presets/notes/4.9 b/packages/nextcloud_test/docker/presets/notes/4.9 index 19ccdeaf4ab..ea3f9309e81 100644 --- a/packages/nextcloud_test/docker/presets/notes/4.9 +++ b/packages/nextcloud_test/docker/presets/notes/4.9 @@ -1,4 +1,5 @@ SERVER_VERSION=29.0.3 +COOKBOOK_URL=https://github.com/christianlupus-nextcloud/cookbook-releases/releases/download/v0.11.1/cookbook-0.11.1.tar.gz DROP_ACCOUNT_URL=https://packages.framasoft.org/projects/nextcloud-apps/drop-account/drop_account-2.5.0.tar.gz NEWS_URL=https://github.com/nextcloud/news/releases/download/25.0.0-alpha8/news.tar.gz NOTES_URL=https://github.com/nextcloud-releases/notes/releases/download/v4.9.4/notes-v4.9.4.tar.gz diff --git a/packages/nextcloud_test/docker/presets/server/28.0 b/packages/nextcloud_test/docker/presets/server/28.0 index 291d258445d..5d2d6e4a1d8 100644 --- a/packages/nextcloud_test/docker/presets/server/28.0 +++ b/packages/nextcloud_test/docker/presets/server/28.0 @@ -1,4 +1,5 @@ SERVER_VERSION=28.0.7 +COOKBOOK_URL=https://github.com/christianlupus-nextcloud/cookbook-releases/releases/download/v0.11.1/cookbook-0.11.1.tar.gz DROP_ACCOUNT_URL=https://packages.framasoft.org/projects/nextcloud-apps/drop-account/drop_account-2.5.0.tar.gz NEWS_URL=https://github.com/nextcloud/news/releases/download/25.0.0-alpha8/news.tar.gz NOTES_URL=https://github.com/nextcloud-releases/notes/releases/download/v4.10.0/notes.tar.gz diff --git a/packages/nextcloud_test/docker/presets/server/29.0 b/packages/nextcloud_test/docker/presets/server/29.0 index 14800a49a27..4f36ad1c211 100644 --- a/packages/nextcloud_test/docker/presets/server/29.0 +++ b/packages/nextcloud_test/docker/presets/server/29.0 @@ -1,4 +1,5 @@ SERVER_VERSION=29.0.3 +COOKBOOK_URL=https://github.com/christianlupus-nextcloud/cookbook-releases/releases/download/v0.11.1/cookbook-0.11.1.tar.gz DROP_ACCOUNT_URL=https://packages.framasoft.org/projects/nextcloud-apps/drop-account/drop_account-2.5.0.tar.gz NEWS_URL=https://github.com/nextcloud/news/releases/download/25.0.0-alpha8/news.tar.gz NOTES_URL=https://github.com/nextcloud-releases/notes/releases/download/v4.10.0/notes.tar.gz diff --git a/packages/nextcloud_test/docker/presets/spreed/18.0 b/packages/nextcloud_test/docker/presets/spreed/18.0 index 291d258445d..5d2d6e4a1d8 100644 --- a/packages/nextcloud_test/docker/presets/spreed/18.0 +++ b/packages/nextcloud_test/docker/presets/spreed/18.0 @@ -1,4 +1,5 @@ SERVER_VERSION=28.0.7 +COOKBOOK_URL=https://github.com/christianlupus-nextcloud/cookbook-releases/releases/download/v0.11.1/cookbook-0.11.1.tar.gz DROP_ACCOUNT_URL=https://packages.framasoft.org/projects/nextcloud-apps/drop-account/drop_account-2.5.0.tar.gz NEWS_URL=https://github.com/nextcloud/news/releases/download/25.0.0-alpha8/news.tar.gz NOTES_URL=https://github.com/nextcloud-releases/notes/releases/download/v4.10.0/notes.tar.gz diff --git a/packages/nextcloud_test/docker/presets/spreed/19.0 b/packages/nextcloud_test/docker/presets/spreed/19.0 index 14800a49a27..4f36ad1c211 100644 --- a/packages/nextcloud_test/docker/presets/spreed/19.0 +++ b/packages/nextcloud_test/docker/presets/spreed/19.0 @@ -1,4 +1,5 @@ SERVER_VERSION=29.0.3 +COOKBOOK_URL=https://github.com/christianlupus-nextcloud/cookbook-releases/releases/download/v0.11.1/cookbook-0.11.1.tar.gz DROP_ACCOUNT_URL=https://packages.framasoft.org/projects/nextcloud-apps/drop-account/drop_account-2.5.0.tar.gz NEWS_URL=https://github.com/nextcloud/news/releases/download/25.0.0-alpha8/news.tar.gz NOTES_URL=https://github.com/nextcloud-releases/notes/releases/download/v4.10.0/notes.tar.gz diff --git a/packages/nextcloud_test/docker/presets/uppush/1.4 b/packages/nextcloud_test/docker/presets/uppush/1.4 index 14800a49a27..4f36ad1c211 100644 --- a/packages/nextcloud_test/docker/presets/uppush/1.4 +++ b/packages/nextcloud_test/docker/presets/uppush/1.4 @@ -1,4 +1,5 @@ SERVER_VERSION=29.0.3 +COOKBOOK_URL=https://github.com/christianlupus-nextcloud/cookbook-releases/releases/download/v0.11.1/cookbook-0.11.1.tar.gz DROP_ACCOUNT_URL=https://packages.framasoft.org/projects/nextcloud-apps/drop-account/drop_account-2.5.0.tar.gz NEWS_URL=https://github.com/nextcloud/news/releases/download/25.0.0-alpha8/news.tar.gz NOTES_URL=https://github.com/nextcloud-releases/notes/releases/download/v4.10.0/notes.tar.gz diff --git a/packages/nextcloud_test/docker/static/recipe.html b/packages/nextcloud_test/docker/static/recipe.html new file mode 100644 index 00000000000..541dce04f8b --- /dev/null +++ b/packages/nextcloud_test/docker/static/recipe.html @@ -0,0 +1,97 @@ + + + + + + Non-Alcoholic Piña Colada + + + + + + + diff --git a/tool/generate-specs.sh b/tool/generate-specs.sh index 7a6ce14d44d..8c6077d3e55 100755 --- a/tool/generate-specs.sh +++ b/tool/generate-specs.sh @@ -50,6 +50,12 @@ function generate_spec() { cd external/nextcloud-drop_account generate_spec "." "drop_account" ) +( + yq -s '.[0]."components"."schemas" = .[1] | .[0] | walk(if type == "object" then with_entries( if (.key == "$ref" and (.value | test("#\/components\/schemas\/") | not) ) then .value |= sub("#\/"; "#/components/schemas/") else . end ) else . end) | .paths |= with_entries(.key = "/index.php/apps/cookbook\(.key)")' \ + external/nextcloud-cookbook/docs/dev/api/0.1.2/openapi-cookbook.yaml \ + external/nextcloud-cookbook/docs/dev/api/0.1.2/objects.yaml \ + > /tmp/nextcloud-neon/cookbook.openapi.json +) for spec in /tmp/nextcloud-neon/*.openapi.json; do name="$(basename "$spec" | cut -d "." -f 1)"