diff --git a/packages/app/integration_test/screenshot_test.dart b/packages/app/integration_test/screenshot_test.dart index 50973fea..86f83251 100644 --- a/packages/app/integration_test/screenshot_test.dart +++ b/packages/app/integration_test/screenshot_test.dart @@ -53,6 +53,7 @@ Future getAccount(final String username) async { loginName: username, password: username, ).core.appPassword.getAppPassword()) + .body .ocs .data .apppassword; @@ -149,7 +150,7 @@ Future main() async { final folder = await account.client.news.createFolder(name: 'test'); await account.client.news.addFeed( url: nasaFeedURL, - folderId: folder.folders.single.id, + folderId: folder.body.folders.single.id, ); await runTestApp( diff --git a/packages/dynamite/dynamite/lib/src/builder/client.dart b/packages/dynamite/dynamite/lib/src/builder/client.dart index 3bb46694..a5d6b3db 100644 --- a/packages/dynamite/dynamite/lib/src/builder/client.dart +++ b/packages/dynamite/dynamite/lib/src/builder/client.dart @@ -1,121 +1,21 @@ import 'package:built_collection/built_collection.dart'; import 'package:code_builder/code_builder.dart'; import 'package:collection/collection.dart'; +import 'package:dynamite/src/builder/resolve_mime_type.dart'; import 'package:dynamite/src/builder/resolve_object.dart'; import 'package:dynamite/src/builder/resolve_type.dart'; import 'package:dynamite/src/builder/state.dart'; import 'package:dynamite/src/helpers/dart_helpers.dart'; import 'package:dynamite/src/helpers/dynamite.dart'; import 'package:dynamite/src/helpers/type_result.dart'; -import 'package:dynamite/src/models/open_api.dart'; -import 'package:dynamite/src/models/path_item.dart'; -import 'package:dynamite/src/models/response.dart'; -import 'package:dynamite/src/models/schema.dart'; -import 'package:dynamite/src/type_result/type_result.dart'; - -List generateDynamiteOverrides(final State state) => [ - Class( - (final b) => b - ..name = '${state.classPrefix}Response' - ..types.addAll([ - refer('T'), - refer('U'), - ]) - ..extend = refer('DynamiteResponse') - ..constructors.add( - Constructor( - (final b) => b - ..requiredParameters.addAll( - ['data', 'headers'].map( - (final name) => Parameter( - (final b) => b - ..name = name - ..toSuper = true, - ), - ), - ), - ), - ) - ..methods.add( - Method( - (final b) => b - ..name = 'toString' - ..returns = refer('String') - ..annotations.add(refer('override')) - ..lambda = true - ..body = Code( - "'${state.classPrefix}Response(data: \$data, headers: \$headers)'", - ), - ), - ), - ), - Class( - (final b) => b - ..name = '${state.classPrefix}ApiException' - ..extend = refer('DynamiteApiException') - ..constructors.add( - Constructor( - (final b) => b - ..requiredParameters.addAll( - ['statusCode', 'headers', 'body'].map( - (final name) => Parameter( - (final b) => b - ..name = name - ..toSuper = true, - ), - ), - ), - ), - ) - ..methods.addAll([ - Method( - (final b) => b - ..name = 'fromResponse' - ..returns = refer('Future<${state.classPrefix}ApiException>') - ..static = true - ..modifier = MethodModifier.async - ..requiredParameters.add( - Parameter( - (final b) => b - ..name = 'response' - ..type = refer('HttpClientResponse'), - ), - ) - ..body = Code(''' -String body; -try { - body = await response.body; -} on FormatException { - body = 'binary'; -} - -return ${state.classPrefix}ApiException( - response.statusCode, - response.responseHeaders, - body, -); -'''), - ), - Method( - (final b) => b - ..name = 'toString' - ..returns = refer('String') - ..annotations.add(refer('override')) - ..lambda = true - ..body = Code( - "'${state.classPrefix}ApiException(statusCode: \$statusCode, headers: \$headers, body: \$body)'", - ), - ), - ]), - ), - ]; +import 'package:dynamite/src/models/openapi.dart' as openapi; +import 'package:dynamite/src/models/type_result.dart'; +import 'package:intersperse/intersperse.dart'; Iterable generateClients( - final OpenAPI spec, + final openapi.OpenAPI spec, final State state, ) sync* { - yield* generateDynamiteOverrides(state); - final tags = generateTags(spec); yield buildRootClient(spec, state, tags); @@ -125,7 +25,7 @@ Iterable generateClients( } Class buildRootClient( - final OpenAPI spec, + final openapi.OpenAPI spec, final State state, final List tags, ) => @@ -219,12 +119,12 @@ super( ); } - b.methods.addAll(buildTags(spec, state, tags, null)); + b.methods.addAll(buildTags(spec, state, null)); }, ); Class buildClient( - final OpenAPI spec, + final openapi.OpenAPI spec, final State state, final List tags, final String tag, @@ -267,366 +167,343 @@ Class buildClient( ); } - b.methods.addAll(buildTags(spec, state, tags, tag)); + b.methods.addAll(buildTags(spec, state, tag)); }, ); Iterable buildTags( - final OpenAPI spec, + final openapi.OpenAPI spec, final State state, - final List tags, final String? tag, ) sync* { - final isRootClient = tag == null; + final client = tag == null ? 'this' : '_rootClient'; final paths = generatePaths(spec, tag); for (final pathEntry in paths.entries) { for (final operationEntry in pathEntry.value.operations.entries) { - yield Method( - (final b) { - final httpMethod = operationEntry.key.name; - final operation = operationEntry.value; - final operationId = operation.operationId ?? toDartName('$httpMethod-${pathEntry.key}'); - final parameters = [ - ...?pathEntry.value.parameters, - ...?operation.parameters, - ]..sort(sortRequiredParameters); - b - ..name = toDartName(filterMethodName(operationId, tag ?? '')) - ..modifier = MethodModifier.async - ..docs.addAll(operation.formattedDescription); - if (operation.deprecated ?? false) { - b.annotations.add(refer('Deprecated').call([refer("''")])); - } + final httpMethod = operationEntry.key.name; + final operation = operationEntry.value; + final operationId = operation.operationId ?? toDartName('$httpMethod-${pathEntry.key}'); + final parameters = [ + ...?pathEntry.value.parameters, + ...?operation.parameters, + ]..sort(sortRequiredParameters); + final name = toDartName(filterMethodName(operationId, tag ?? '')); + + var responses = >{}; + if (operation.responses != null) { + for (final responseEntry in operation.responses!.entries) { + final statusCode = int.parse(responseEntry.key); + final response = responseEntry.value; + + responses[response] ??= []; + responses[response]!.add(statusCode); + } - var responses = >{}; - if (operation.responses != null) { - for (final responseEntry in operation.responses!.entries) { - final statusCode = int.parse(responseEntry.key); - final response = responseEntry.value; + if (responses.length > 1) { + print('$operationId uses more than one response schema but we only generate the first one'); + responses = Map.fromEntries([responses.entries.first]); + } + } - responses[response] ??= []; - responses[response]!.add(statusCode); - } + final code = StringBuffer(); + final acceptHeader = responses.keys + .map((final response) => response.content?.keys) + .whereNotNull() + .expand((final element) => element) + .toSet() + .join(','); + + code.writeln(''' + var _path = '${pathEntry.key}'; + final _queryParameters = {}; + final _headers = {${acceptHeader.isNotEmpty ? "'Accept': '$acceptHeader'," : ''}}; + Uint8List? _body; + '''); + + buildAuthCheck( + responses, + pathEntry, + operation, + spec, + client, + ).forEach(code.writeln); + + final operationParameters = ListBuilder(); + final annotations = operation.deprecated ?? false ? refer('Deprecated').call([refer("''")]) : null; + var returnDataType = 'void'; + var returnHeadersType = 'void'; + + for (final parameter in parameters) { + final dartParameterNullable = isDartParameterNullable( + parameter.required, + parameter.schema, + ); + + final result = resolveType( + spec, + state, + toDartName( + '$operationId-${parameter.name}', + uppercaseFirstCharacter: true, + ), + parameter.schema!, + nullable: dartParameterNullable, + ).dartType; + + buildPatternCheck(result, parameter).forEach(code.writeln); + + final defaultValueCode = parameter.schema?.$default != null + ? valueToEscapedValue(result, parameter.schema!.$default.toString()) + : null; + + operationParameters.add( + Parameter( + (final b) { + b + ..named = true + ..name = toDartName(parameter.name) + ..required = parameter.isDartRequired; + if (parameter.schema != null) { + b.type = refer(result.nullableName); + } + if (defaultValueCode != null) { + b.defaultTo = Code(defaultValueCode); + } + }, + ), + ); - if (responses.length > 1) { - print('$operationId uses more than one response schema but we only generate the first one'); - responses = Map.fromEntries([responses.entries.first]); - } - } + if (dartParameterNullable) { + code.writeln('if (${toDartName(parameter.name)} != null) {'); + } + final value = result.encode( + toDartName(parameter.name), + onlyChildren: result is TypeResultList && parameter.$in == 'query', + ); + if (defaultValueCode != null && parameter.$in == 'query') { + code.writeln('if (${toDartName(parameter.name)} != $defaultValueCode) {'); + } + switch (parameter.$in) { + case 'path': + code.writeln( + "_path = _path.replaceAll('{${parameter.name}}', Uri.encodeQueryComponent($value));", + ); + case 'query': + code.writeln( + "_queryParameters['${parameter.name}'] = $value;", + ); + case 'header': + code.writeln( + "_headers['${parameter.name}'] = $value;", + ); + default: + throw Exception('Can not work with parameter in "${parameter.$in}"'); + } + if (defaultValueCode != null && parameter.$in == 'query') { + code.writeln('}'); + } + if (dartParameterNullable) { + code.writeln('}'); + } + } + resolveMimeTypeEncode(operation, spec, state, operationId, operationParameters).forEach(code.writeln); + + for (final responseEntry in responses.entries) { + final response = responseEntry.key; + final statusCodes = responseEntry.value; + + TypeResult? headersType; + if (response.headers != null) { + final identifier = + '${tag != null ? toDartName(tag, uppercaseFirstCharacter: true) : null}${toDartName(operationId, uppercaseFirstCharacter: true)}Headers'; + headersType = resolveObject( + spec, + state, + identifier, + openapi.Schema( + (final b) => b + ..properties.replace( + response.headers!.map( + (final headerName, final value) => MapEntry( + headerName.toLowerCase(), + value.schema!, + ), + ), + ), + ), + isHeader: true, + ); + } - final acceptHeader = responses.keys - .map((final response) => response.content?.keys) - .whereNotNull() - .expand((final element) => element) - .toSet() - .join(','); - final code = StringBuffer(''' -var _path = '${pathEntry.key}'; -final _queryParameters = {}; -final _headers = {${acceptHeader.isNotEmpty ? "'Accept': '$acceptHeader'," : ''}}; -Uint8List? _body; -'''); + final dataType = resolveMimeTypeDecode( + response, + spec, + state, + toDartName( + '$operationId-response${responses.entries.length > 1 ? '-${responses.entries.toList().indexOf(responseEntry)}' : ''}', + uppercaseFirstCharacter: true, + ), + ); - final security = operation.security ?? spec.security ?? BuiltList(); - final securityRequirements = security.where((final requirement) => requirement.isNotEmpty); - final isOptionalSecurity = securityRequirements.length != security.length; - code.write(' // coverage:ignore-start\n'); - for (final requirement in securityRequirements) { - final securityScheme = spec.components!.securitySchemes![requirement.keys.single]!; - code.write(''' -if (${isRootClient ? 'this' : '_rootClient'}.authentications.where((final a) => a.type == '${securityScheme.type}' && a.scheme == '${securityScheme.scheme}').isNotEmpty) { - _headers.addAll(${isRootClient ? 'this' : '_rootClient'}.authentications.singleWhere((final a) => a.type == '${securityScheme.type}' && a.scheme == '${securityScheme.scheme}').headers); -} -'''); - if (securityRequirements.last != requirement) { - code.write('else '); - } - } - if (securityRequirements.isNotEmpty && !isOptionalSecurity) { - code.write(''' -else { - throw Exception('Missing authentication for ${securityRequirements.map((final r) => r.keys.single).join(' or ')}'); -} -'''); - } - code.write(' // coverage:ignore-end\n'); + code.writeln( + 'final _uri = Uri(path: _path, queryParameters: _queryParameters.isNotEmpty ? _queryParameters : null);', + ); - for (final parameter in parameters) { - final dartParameterNullable = isDartParameterNullable( - parameter.required, - parameter.schema, - ); + if (dataType != null) { + returnDataType = dataType.name; + } + if (headersType != null) { + returnHeadersType = headersType.name; + } - final result = resolveType( - spec, - state, - toDartName( - '$operationId-${parameter.name}', - uppercaseFirstCharacter: true, - ), - parameter.schema!, - nullable: dartParameterNullable, - ).dartType; - - if (result.name == 'String') { - if (parameter.schema?.pattern != null) { - code.write(''' -if (!RegExp(r'${parameter.schema!.pattern!}').hasMatch(${toDartName(parameter.name)})) { - throw Exception('Invalid value "\$${toDartName(parameter.name)}" for parameter "${toDartName(parameter.name)}" with pattern "\${r'${parameter.schema!.pattern!}'}"'); // coverage:ignore-line -} + code.writeln(''' + return DynamiteRawResponse<$returnDataType, $returnHeadersType>( + response: $client.doRequest( + '$httpMethod', + _uri, + _headers, + _body, '''); - } - if (parameter.schema?.minLength != null) { - code.write(''' -if (${toDartName(parameter.name)}.length < ${parameter.schema!.minLength!}) { - throw Exception('Parameter "${toDartName(parameter.name)}" has to be at least ${parameter.schema!.minLength!} characters long'); // coverage:ignore-line -} -'''); - } - if (parameter.schema?.maxLength != null) { - code.write(''' -if (${toDartName(parameter.name)}.length > ${parameter.schema!.maxLength!}) { - throw Exception('Parameter "${toDartName(parameter.name)}" has to be at most ${parameter.schema!.maxLength!} characters long'); // coverage:ignore-line -} -'''); - } - } - final defaultValueCode = parameter.schema?.$default != null - ? valueToEscapedValue(result, parameter.schema!.$default.toString()) - : null; - - b.optionalParameters.add( - Parameter( - (final b) { - b - ..named = true - ..name = toDartName(parameter.name) - ..required = parameter.isDartRequired; - if (parameter.schema != null) { - b.type = refer(result.nullableName); - } - if (defaultValueCode != null) { - b.defaultTo = Code(defaultValueCode); - } - }, - ), - ); + if (responses.values.isNotEmpty) { + final codes = statusCodes.join(','); + code.writeln('const {$codes},'); + } - if (dartParameterNullable) { - code.write('if (${toDartName(parameter.name)} != null) {'); - } - final value = result.encode( - toDartName(parameter.name), - onlyChildren: result is TypeResultList && parameter.$in == 'query', - ); - if (defaultValueCode != null && parameter.$in == 'query') { - code.write('if (${toDartName(parameter.name)} != $defaultValueCode) {'); - } - switch (parameter.$in) { - case 'path': - code.write( - "_path = _path.replaceAll('{${parameter.name}}', Uri.encodeQueryComponent($value));", - ); - case 'query': - code.write( - "_queryParameters['${parameter.name}'] = $value;", - ); - case 'header': - code.write( - "_headers['${parameter.name}'] = $value;", - ); - default: - throw Exception('Can not work with parameter in "${parameter.$in}"'); - } - if (defaultValueCode != null && parameter.$in == 'query') { - code.write('}'); - } - if (dartParameterNullable) { - code.write('}'); - } - } + code.writeln(''' + ), + bodyType: ${dataType?.fullType}, + headersType: ${headersType?.fullType}, + serializers: _jsonSerializers, + ); +'''); + } - if (operation.requestBody != null) { - if (operation.requestBody!.content!.length > 1) { - throw Exception('Can not work with multiple mime types right now'); - } - for (final content in operation.requestBody!.content!.entries) { - final mimeType = content.key; - final mediaType = content.value; - - code.write("_headers['Content-Type'] = '$mimeType';"); - - final dartParameterNullable = isDartParameterNullable( - operation.requestBody!.required, - mediaType.schema, - ); - - final result = resolveType( - spec, - state, - toDartName('$operationId-request-$mimeType', uppercaseFirstCharacter: true), - mediaType.schema!, - nullable: dartParameterNullable, - ); - final parameterName = toDartName(result.name.replaceFirst(state.classPrefix, '')); - switch (mimeType) { - case 'application/json': - case 'application/x-www-form-urlencoded': - final dartParameterRequired = isRequired( - operation.requestBody!.required, - mediaType.schema?.$default, - ); - b.optionalParameters.add( - Parameter( - (final b) => b - ..name = parameterName - ..type = refer(result.nullableName) - ..named = true - ..required = dartParameterRequired, - ), - ); - - if (dartParameterNullable) { - code.write('if ($parameterName != null) {'); - } - code.write( - '_body = utf8.encode(${result.encode(parameterName, mimeType: mimeType)}) as Uint8List;', - ); - if (dartParameterNullable) { - code.write('}'); - } - default: - throw Exception('Can not parse mime type "$mimeType"'); - } - } - } + yield Method((final b) { + b + ..name = name + ..modifier = MethodModifier.async + ..docs.addAll(operation.formattedDescription(name)); - code.write( - ''' -final _response = await ${isRootClient ? 'this' : '_rootClient'}.doRequest( - '$httpMethod', - Uri(path: _path, queryParameters: _queryParameters.isNotEmpty ? _queryParameters : null), - _headers, - _body, -); -''', - ); + if (annotations != null) { + b.annotations.add(annotations); + } - for (final responseEntry in responses.entries) { - final response = responseEntry.key; - final statusCodes = responseEntry.value; - code.write( - 'if (${statusCodes.map((final statusCode) => '_response.statusCode == $statusCode').join(' || ')}) {', - ); + final parameters = operationParameters.build(); + final rawParameters = parameters.map((final p) => '${p.name}: ${p.name},').join('\n'); - String? headersType; - String? headersValue; - if (response.headers != null) { - final identifier = - '${tag != null ? toDartName(tag, uppercaseFirstCharacter: true) : null}${toDartName(operationId, uppercaseFirstCharacter: true)}Headers'; - final result = resolveObject( - spec, - state, - identifier, - Schema( - (final b) => b - ..properties.replace( - response.headers!.map( - (final headerName, final value) => MapEntry( - headerName.toLowerCase(), - value.schema!, - ), - ), - ), - ), - isHeader: true, - ); - headersType = result.name; - headersValue = result.deserialize('_response.responseHeaders'); - } + b + ..optionalParameters.addAll(parameters) + ..returns = refer('Future>') + ..body = Code(''' +final rawResponse = ${name}Raw( + $rawParameters +); - String? dataType; - String? dataValue; - bool? dataNeedsAwait; - if (response.content != null) { - if (response.content!.length > 1) { - throw Exception('Can not work with multiple mime types right now'); - } - for (final content in response.content!.entries) { - final mimeType = content.key; - final mediaType = content.value; - - final result = resolveType( - spec, - state, - toDartName( - '$operationId-response${responses.entries.length > 1 ? '-${responses.entries.toList().indexOf(responseEntry)}' : ''}-$mimeType', - uppercaseFirstCharacter: true, - ), - mediaType.schema!, - ); - - if (mimeType == '*/*' || mimeType == 'application/octet-stream' || mimeType.startsWith('image/')) { - dataType = 'Uint8List'; - dataValue = '_response.bodyBytes'; - dataNeedsAwait = true; - } else if (mimeType.startsWith('text/') || mimeType == 'application/javascript') { - dataType = 'String'; - dataValue = '_response.body'; - dataNeedsAwait = true; - } else if (mimeType == 'application/json') { - dataType = result.name; - if (result.name == 'dynamic') { - dataValue = ''; - } else if (result.name == 'String') { - dataValue = '_response.body'; - dataNeedsAwait = true; - } else if (result is TypeResultEnum || result is TypeResultBase) { - dataValue = result.deserialize(result.decode('await _response.body')); - dataNeedsAwait = false; - } else { - dataValue = result.deserialize('await _response.jsonBody'); - dataNeedsAwait = false; - } - } else { - throw Exception('Can not parse mime type "$mimeType"'); - } - } - } +return rawResponse.future; +'''); + }); - if (headersType != null && dataType != null) { - b.returns = refer('Future<${state.classPrefix}Response<$dataType, $headersType>>'); - code.write( - 'return ${state.classPrefix}Response<$dataType, $headersType>(${dataNeedsAwait ?? false ? 'await ' : ''}$dataValue, $headersValue,);', - ); - } else if (headersType != null) { - b.returns = refer('Future<$headersType>'); - code.write('return $headersValue;'); - } else if (dataType != null) { - b.returns = refer('Future<$dataType>'); - code.write('return $dataValue;'); - } else { - b.returns = refer('Future'); - code.write('return;'); - } + yield Method( + (final b) { + b + ..name = '${name}Raw' + ..docs.addAll(operation.formattedDescription(name, isRawRequest: true)) + ..annotations.add(refer('experimental')); - code.write('}'); + if (annotations != null) { + b.annotations.add(annotations); } - code.write( - 'throw await ${state.classPrefix}ApiException.fromResponse(_response); // coverage:ignore-line\n', - ); - b.body = Code(code.toString()); + b + ..optionalParameters.addAll(operationParameters.build()) + ..returns = refer('DynamiteRawResponse<$returnDataType, $returnHeadersType>') + ..body = Code(code.toString()); }, ); } } } -Map generatePaths(final OpenAPI spec, final String? tag) { - final paths = {}; +Iterable buildPatternCheck( + final TypeResult result, + final openapi.Parameter parameter, +) sync* { + final value = toDartName(parameter.name); + final name = "'$value'"; + + final schema = parameter.schema; + if (result.name == 'String' && schema != null) { + if (schema.pattern != null) { + yield "checkPattern($value, RegExp(r'${schema.pattern!}'), $name); // coverage:ignore-line"; + } + if (schema.minLength != null) { + yield 'checkMinLength($value, ${schema.minLength}, $name); // coverage:ignore-line'; + } + if (schema.maxLength != null) { + yield 'checkMaxLength($value, ${schema.maxLength}, $name); // coverage:ignore-line'; + } + } +} + +Iterable buildAuthCheck( + final Map> responses, + final MapEntry pathEntry, + final openapi.Operation operation, + final openapi.OpenAPI spec, + final String client, +) sync* { + final security = operation.security ?? spec.security ?? BuiltList(); + final securityRequirements = security.where((final requirement) => requirement.isNotEmpty); + final isOptionalSecurity = securityRequirements.length != security.length; + + if (securityRequirements.isEmpty) { + return; + } + + yield ''' +// coverage:ignore-start +final authentication = $client.authentications.firstWhereOrNull( + (final auth) => switch (auth) { +'''; + + yield* securityRequirements.map((final requirement) { + final securityScheme = spec.components!.securitySchemes![requirement.keys.single]!; + final dynamiteAuth = toDartName( + 'Dynamite-${securityScheme.type}-${securityScheme.scheme}-Authentication', + uppercaseFirstCharacter: true, + ); + return '$dynamiteAuth()'; + }).intersperse(' || '); + + yield ''' + => true, + _ => false, + }, + ); +'''; + + yield ''' +if(authentication != null) { + _headers.addAll( + authentication.headers, + ); +} +'''; + + if (!isOptionalSecurity) { + yield ''' +else { + throw Exception('Missing authentication for ${securityRequirements.map((final r) => r.keys.single).join(' or ')}'); +} +'''; + } + yield '// coverage:ignore-end'; +} + +Map generatePaths(final openapi.OpenAPI spec, final String? tag) { + final paths = {}; if (spec.paths != null) { for (final path in spec.paths!.entries) { @@ -637,21 +514,21 @@ Map generatePaths(final OpenAPI spec, final String? tag) { paths[path.key] ??= path.value; paths[path.key]!.rebuild((final b) { switch (operationEntry.key) { - case PathItemOperation.get: + case openapi.PathItemOperation.get: b.get.replace(operation); - case PathItemOperation.put: + case openapi.PathItemOperation.put: b.put.replace(operation); - case PathItemOperation.post: + case openapi.PathItemOperation.post: b.post.replace(operation); - case PathItemOperation.delete: + case openapi.PathItemOperation.delete: b.delete.replace(operation); - case PathItemOperation.options: + case openapi.PathItemOperation.options: b.options.replace(operation); - case PathItemOperation.head: + case openapi.PathItemOperation.head: b.head.replace(operation); - case PathItemOperation.patch: + case openapi.PathItemOperation.patch: b.patch.replace(operation); - case PathItemOperation.trace: + case openapi.PathItemOperation.trace: b.trace.replace(operation); } }); @@ -663,7 +540,7 @@ Map generatePaths(final OpenAPI spec, final String? tag) { return paths; } -List generateTags(final OpenAPI spec) { +List generateTags(final openapi.OpenAPI spec) { final tags = []; if (spec.paths != null) { diff --git a/packages/dynamite/dynamite/lib/src/builder/header_serializer.dart b/packages/dynamite/dynamite/lib/src/builder/header_serializer.dart index 0a6f519b..2e9121d2 100644 --- a/packages/dynamite/dynamite/lib/src/builder/header_serializer.dart +++ b/packages/dynamite/dynamite/lib/src/builder/header_serializer.dart @@ -3,11 +3,15 @@ import 'package:dynamite/src/builder/resolve_type.dart'; import 'package:dynamite/src/builder/state.dart'; import 'package:dynamite/src/helpers/dart_helpers.dart'; import 'package:dynamite/src/helpers/dynamite.dart'; -import 'package:dynamite/src/models/open_api.dart'; -import 'package:dynamite/src/models/schema.dart'; -import 'package:dynamite/src/type_result/type_result.dart'; +import 'package:dynamite/src/models/openapi.dart' as openapi; +import 'package:dynamite/src/models/type_result.dart'; -Spec buildHeaderSerializer(final State state, final String identifier, final OpenAPI spec, final Schema schema) => +Spec buildHeaderSerializer( + final State state, + final String identifier, + final openapi.OpenAPI spec, + final openapi.Schema schema, +) => Class( (final b) => b ..name = '_\$${state.classPrefix}${identifier}Serializer' @@ -107,8 +111,8 @@ return result.build(); Iterable deserializeProperty( final State state, final String identifier, - final OpenAPI spec, - final Schema schema, + final openapi.OpenAPI spec, + final openapi.Schema schema, ) sync* { for (final property in schema.properties!.entries) { final propertyName = property.key; diff --git a/packages/dynamite/dynamite/lib/src/builder/imports.dart b/packages/dynamite/dynamite/lib/src/builder/imports.dart index c847f0d2..236fedfc 100644 --- a/packages/dynamite/dynamite/lib/src/builder/imports.dart +++ b/packages/dynamite/dynamite/lib/src/builder/imports.dart @@ -4,7 +4,9 @@ import 'package:path/path.dart' as p; List generateImports(final AssetId outputId) => [ const Code('// ignore_for_file: camel_case_types'), + const Code('// ignore_for_file: discarded_futures'), const Code('// ignore_for_file: public_member_api_docs'), + const Code('// ignore_for_file: unreachable_switch_case'), Directive.import('dart:convert'), Directive.import('dart:typed_data'), const Code(''), @@ -13,8 +15,11 @@ List generateImports(final AssetId outputId) => [ Directive.import('package:built_value/json_object.dart'), Directive.import('package:built_value/serializer.dart'), Directive.import('package:built_value/standard_json_plugin.dart'), + Directive.import('package:collection/collection.dart'), Directive.import('package:dynamite_runtime/content_string.dart'), Directive.import('package:dynamite_runtime/http_client.dart'), + Directive.import('package:dynamite_runtime/utils.dart'), + Directive.import('package:meta/meta.dart'), Directive.import('package:universal_io/io.dart'), const Code(''), Directive.export('package:dynamite_runtime/http_client.dart'), diff --git a/packages/dynamite/dynamite/lib/src/builder/ofs_builder.dart b/packages/dynamite/dynamite/lib/src/builder/ofs_builder.dart index 04583373..5d8fe5ea 100644 --- a/packages/dynamite/dynamite/lib/src/builder/ofs_builder.dart +++ b/packages/dynamite/dynamite/lib/src/builder/ofs_builder.dart @@ -5,15 +5,14 @@ import 'package:dynamite/src/builder/resolve_type.dart'; import 'package:dynamite/src/builder/state.dart'; import 'package:dynamite/src/helpers/built_value.dart'; import 'package:dynamite/src/helpers/dart_helpers.dart'; -import 'package:dynamite/src/models/open_api.dart'; -import 'package:dynamite/src/models/schema.dart'; -import 'package:dynamite/src/type_result/type_result.dart'; +import 'package:dynamite/src/models/openapi.dart' as openapi; +import 'package:dynamite/src/models/type_result.dart'; TypeResult resolveAllOf( - final OpenAPI spec, + final openapi.OpenAPI spec, final State state, final String identifier, - final Schema schema, { + final openapi.Schema schema, { final bool nullable = false, }) { final result = TypeResultObject( @@ -65,10 +64,10 @@ TypeResult resolveAllOf( } TypeResult resolveOfs( - final OpenAPI spec, + final openapi.OpenAPI spec, final State state, final String identifier, - final Schema schema, { + final openapi.Schema schema, { final bool nullable = false, }) { if (schema.allOf != null) { diff --git a/packages/dynamite/dynamite/lib/src/builder/resolve_enum.dart b/packages/dynamite/dynamite/lib/src/builder/resolve_enum.dart index 1c986ca1..df8199ab 100644 --- a/packages/dynamite/dynamite/lib/src/builder/resolve_enum.dart +++ b/packages/dynamite/dynamite/lib/src/builder/resolve_enum.dart @@ -4,15 +4,14 @@ import 'package:dynamite/src/builder/state.dart'; import 'package:dynamite/src/helpers/built_value.dart'; import 'package:dynamite/src/helpers/dart_helpers.dart'; import 'package:dynamite/src/helpers/type_result.dart'; -import 'package:dynamite/src/models/open_api.dart'; -import 'package:dynamite/src/models/schema.dart'; -import 'package:dynamite/src/type_result/type_result.dart'; +import 'package:dynamite/src/models/openapi.dart' as openapi; +import 'package:dynamite/src/models/type_result.dart'; TypeResult resolveEnum( - final OpenAPI spec, + final openapi.OpenAPI spec, final State state, final String identifier, - final Schema schema, + final openapi.Schema schema, final TypeResult subResult, { final bool nullable = false, }) { diff --git a/packages/dynamite/dynamite/lib/src/builder/resolve_interface.dart b/packages/dynamite/dynamite/lib/src/builder/resolve_interface.dart index d20f472f..6f93512e 100644 --- a/packages/dynamite/dynamite/lib/src/builder/resolve_interface.dart +++ b/packages/dynamite/dynamite/lib/src/builder/resolve_interface.dart @@ -4,15 +4,14 @@ import 'package:dynamite/src/builder/state.dart'; import 'package:dynamite/src/helpers/built_value.dart'; import 'package:dynamite/src/helpers/dart_helpers.dart'; import 'package:dynamite/src/helpers/dynamite.dart'; -import 'package:dynamite/src/models/open_api.dart'; -import 'package:dynamite/src/models/schema.dart'; -import 'package:dynamite/src/type_result/type_result.dart'; +import 'package:dynamite/src/models/openapi.dart' as openapi; +import 'package:dynamite/src/models/type_result.dart'; TypeResultObject resolveInterface( - final OpenAPI spec, + final openapi.OpenAPI spec, final State state, final String identifier, - final Schema schema, + final openapi.Schema schema, ) { final result = TypeResultObject( '${state.classPrefix}$identifier', diff --git a/packages/dynamite/dynamite/lib/src/builder/resolve_mime_type.dart b/packages/dynamite/dynamite/lib/src/builder/resolve_mime_type.dart new file mode 100644 index 00000000..36d38222 --- /dev/null +++ b/packages/dynamite/dynamite/lib/src/builder/resolve_mime_type.dart @@ -0,0 +1,129 @@ +import 'package:built_collection/built_collection.dart'; +import 'package:code_builder/code_builder.dart'; +import 'package:dynamite/src/builder/resolve_type.dart'; +import 'package:dynamite/src/builder/state.dart'; +import 'package:dynamite/src/helpers/dart_helpers.dart'; +import 'package:dynamite/src/helpers/dynamite.dart'; +import 'package:dynamite/src/models/openapi.dart' as openapi; +import 'package:dynamite/src/models/type_result.dart'; + +TypeResult? resolveMimeTypeDecode( + final openapi.Response response, + final openapi.OpenAPI spec, + final State state, + final String identifier, +) { + if (response.content != null) { + if (response.content!.length > 1) { + throw Exception('Can not work with multiple mime types right now'); + } + + for (final content in response.content!.entries) { + final mimeType = content.key; + final mediaType = content.value; + + final result = resolveType( + spec, + state, + toDartName('$identifier-$mimeType', uppercaseFirstCharacter: true), + mediaType.schema!, + ); + + if (mimeType == '*/*' || mimeType == 'application/octet-stream' || mimeType.startsWith('image/')) { + return TypeResultObject('Uint8List'); + } else if (mimeType.startsWith('text/') || mimeType == 'application/javascript') { + return TypeResultBase('String'); + } else if (mimeType == 'application/json') { + return result; + } else { + throw Exception('Can not parse mime type "$mimeType"'); + } + } + } + return null; +} + +Iterable resolveMimeTypeEncode( + final openapi.Operation operation, + final openapi.OpenAPI spec, + final State state, + final String identifier, + final ListBuilder b, +) sync* { + if (operation.requestBody != null) { + if (operation.requestBody!.content!.length > 1) { + throw Exception('Can not work with multiple mime types right now'); + } + for (final content in operation.requestBody!.content!.entries) { + final mimeType = content.key; + final mediaType = content.value; + + yield "_headers['Content-Type'] = '$mimeType';"; + + final dartParameterNullable = isDartParameterNullable( + operation.requestBody!.required, + mediaType.schema, + ); + + final result = resolveType( + spec, + state, + toDartName('$identifier-request-$mimeType', uppercaseFirstCharacter: true), + mediaType.schema!, + nullable: dartParameterNullable, + ); + final parameterName = toDartName(result.name.replaceFirst(state.classPrefix, '')); + switch (mimeType) { + case 'application/json': + case 'application/x-www-form-urlencoded': + final dartParameterRequired = isRequired( + operation.requestBody!.required, + mediaType.schema?.$default, + ); + b.add( + Parameter( + (final b) => b + ..name = parameterName + ..type = refer(result.nullableName) + ..named = true + ..required = dartParameterRequired, + ), + ); + + if (dartParameterNullable) { + yield 'if ($parameterName != null) {'; + } + yield '_body = utf8.encode(${result.encode(parameterName, mimeType: mimeType)}) as Uint8List;'; + if (dartParameterNullable) { + yield '}'; + } + return; + case 'application/octet-stream': + final dartParameterRequired = isRequired( + operation.requestBody!.required, + mediaType.schema?.$default, + ); + b.add( + Parameter( + (final b) => b + ..name = parameterName + ..type = refer(result.nullableName) + ..named = true + ..required = dartParameterRequired, + ), + ); + + if (dartParameterNullable) { + yield 'if ($parameterName != null) {'; + } + yield '_body = ${result.encode(parameterName, mimeType: mimeType)};'; + if (dartParameterNullable) { + yield '}'; + } + return; + default: + throw Exception('Can not parse mime type "$mimeType"'); + } + } + } +} diff --git a/packages/dynamite/dynamite/lib/src/builder/resolve_object.dart b/packages/dynamite/dynamite/lib/src/builder/resolve_object.dart index d33d81e4..6ad891d2 100644 --- a/packages/dynamite/dynamite/lib/src/builder/resolve_object.dart +++ b/packages/dynamite/dynamite/lib/src/builder/resolve_object.dart @@ -5,15 +5,14 @@ import 'package:dynamite/src/builder/state.dart'; import 'package:dynamite/src/helpers/built_value.dart'; import 'package:dynamite/src/helpers/dart_helpers.dart'; import 'package:dynamite/src/helpers/type_result.dart'; -import 'package:dynamite/src/models/open_api.dart'; -import 'package:dynamite/src/models/schema.dart'; -import 'package:dynamite/src/type_result/type_result.dart'; +import 'package:dynamite/src/models/openapi.dart' as openapi; +import 'package:dynamite/src/models/type_result.dart'; TypeResultObject resolveObject( - final OpenAPI spec, + final openapi.OpenAPI spec, final State state, final String identifier, - final Schema schema, { + final openapi.Schema schema, { final bool nullable = false, final bool isHeader = false, }) { diff --git a/packages/dynamite/dynamite/lib/src/builder/resolve_type.dart b/packages/dynamite/dynamite/lib/src/builder/resolve_type.dart index 99e61ccc..e96363ec 100644 --- a/packages/dynamite/dynamite/lib/src/builder/resolve_type.dart +++ b/packages/dynamite/dynamite/lib/src/builder/resolve_type.dart @@ -2,15 +2,14 @@ import 'package:dynamite/src/builder/ofs_builder.dart'; import 'package:dynamite/src/builder/resolve_enum.dart'; import 'package:dynamite/src/builder/resolve_object.dart'; import 'package:dynamite/src/builder/state.dart'; -import 'package:dynamite/src/models/open_api.dart'; -import 'package:dynamite/src/models/schema.dart'; -import 'package:dynamite/src/type_result/type_result.dart'; +import 'package:dynamite/src/models/openapi.dart' as openapi; +import 'package:dynamite/src/models/type_result.dart'; TypeResult resolveType( - final OpenAPI spec, + final openapi.OpenAPI spec, final State state, final String identifier, - final Schema schema, { + final openapi.Schema schema, { final bool ignoreEnum = false, final bool nullable = false, }) { diff --git a/packages/dynamite/dynamite/lib/src/builder/serializer.dart b/packages/dynamite/dynamite/lib/src/builder/serializer.dart index bbd4d7ed..97e8b49e 100644 --- a/packages/dynamite/dynamite/lib/src/builder/serializer.dart +++ b/packages/dynamite/dynamite/lib/src/builder/serializer.dart @@ -13,19 +13,9 @@ List buildSerializer(final State state) { .map(Code.new), const Code(').build();'), const Code(''), - Code('Serializers get ${state.variablePrefix}Serializers => _serializers;'), - const Code(''), const Code( 'final Serializers _jsonSerializers = (_serializers.toBuilder()..addPlugin(StandardJsonPlugin())..addPlugin(const ContentStringPlugin())).build();', ), - const Code(''), - Code( - 'T deserialize${state.classPrefix}(final Object data) => _serializers.deserialize(data, specifiedType: FullType(T))! as T;', - ), - const Code(''), - Code( - 'Object? serialize${state.classPrefix}(final T data) => _serializers.serialize(data, specifiedType: FullType(T));', - ), const Code('// coverage:ignore-end'), ]; } diff --git a/packages/dynamite/dynamite/lib/src/builder/state.dart b/packages/dynamite/dynamite/lib/src/builder/state.dart index c9d66d20..b4ebac49 100644 --- a/packages/dynamite/dynamite/lib/src/builder/state.dart +++ b/packages/dynamite/dynamite/lib/src/builder/state.dart @@ -1,6 +1,6 @@ import 'package:code_builder/code_builder.dart'; import 'package:dynamite/src/helpers/dart_helpers.dart'; -import 'package:dynamite/src/type_result/type_result.dart'; +import 'package:dynamite/src/models/type_result.dart'; class State { State(final String prefix) diff --git a/packages/dynamite/dynamite/lib/src/helpers/built_value.dart b/packages/dynamite/dynamite/lib/src/helpers/built_value.dart index bf58c9c0..013b0945 100644 --- a/packages/dynamite/dynamite/lib/src/helpers/built_value.dart +++ b/packages/dynamite/dynamite/lib/src/helpers/built_value.dart @@ -1,7 +1,7 @@ import 'package:built_collection/built_collection.dart'; import 'package:code_builder/code_builder.dart'; import 'package:dynamite/src/helpers/dart_helpers.dart'; -import 'package:dynamite/src/type_result/type_result.dart'; +import 'package:dynamite/src/models/type_result.dart'; const interfaceSuffix = 'Interface'; diff --git a/packages/dynamite/dynamite/lib/src/helpers/docs.dart b/packages/dynamite/dynamite/lib/src/helpers/docs.dart index 87b2501b..450b0516 100644 --- a/packages/dynamite/dynamite/lib/src/helpers/docs.dart +++ b/packages/dynamite/dynamite/lib/src/helpers/docs.dart @@ -3,7 +3,13 @@ const docsSeparator = '///'; Iterable descriptionToDocs(final String? description) sync* { if (description != null && description.isNotEmpty) { for (final line in description.split('\n')) { - yield '$docsSeparator $line'; + final buffer = StringBuffer('$docsSeparator ')..write(line); + + if (!line.endsWith('.')) { + buffer.write('.'); + } + + yield buffer.toString(); } } } diff --git a/packages/dynamite/dynamite/lib/src/helpers/dynamite.dart b/packages/dynamite/dynamite/lib/src/helpers/dynamite.dart index ae15d5ba..8df4768b 100644 --- a/packages/dynamite/dynamite/lib/src/helpers/dynamite.dart +++ b/packages/dynamite/dynamite/lib/src/helpers/dynamite.dart @@ -1,8 +1,7 @@ // ignore_for_file: avoid_positional_boolean_parameters import 'package:dynamite/src/helpers/dart_helpers.dart'; -import 'package:dynamite/src/models/parameter.dart'; -import 'package:dynamite/src/models/schema.dart'; +import 'package:dynamite/src/models/openapi.dart' as openapi; String filterMethodName(final String operationId, final String tag) { final expandedTag = tag.split('/').toList(); @@ -20,7 +19,7 @@ String clientName(final String tag) => '${toDartName(tag, uppercaseFirstCharacte bool isDartParameterNullable( final bool? required, - final Schema? schema, + final openapi.Schema? schema, ) => (!(required ?? false) && schema?.$default == null) || (schema?.nullable ?? false); @@ -30,7 +29,7 @@ bool isRequired( ) => (required ?? false) && default_ == null; -int sortRequiredParameters(final Parameter a, final Parameter b) { +int sortRequiredParameters(final openapi.Parameter a, final openapi.Parameter b) { if (a.isDartRequired != b.isDartRequired) { if (a.isDartRequired && !b.isDartRequired) { return -1; diff --git a/packages/dynamite/dynamite/lib/src/helpers/type_result.dart b/packages/dynamite/dynamite/lib/src/helpers/type_result.dart index 3bc8f104..1a57a799 100644 --- a/packages/dynamite/dynamite/lib/src/helpers/type_result.dart +++ b/packages/dynamite/dynamite/lib/src/helpers/type_result.dart @@ -1,5 +1,5 @@ import 'package:dynamite/src/helpers/dart_helpers.dart'; -import 'package:dynamite/src/type_result/type_result.dart'; +import 'package:dynamite/src/models/type_result.dart'; String valueToEscapedValue(final TypeResult result, final String value) { if (result is TypeResultBase && result.name == 'String') { diff --git a/packages/dynamite/dynamite/lib/src/models/openapi.dart b/packages/dynamite/dynamite/lib/src/models/openapi.dart new file mode 100644 index 00000000..f4fac433 --- /dev/null +++ b/packages/dynamite/dynamite/lib/src/models/openapi.dart @@ -0,0 +1,70 @@ +import 'package:built_collection/built_collection.dart'; +import 'package:built_value/serializer.dart'; +import 'package:built_value/standard_json_plugin.dart'; +import 'package:dynamite/src/models/openapi/components.dart'; +import 'package:dynamite/src/models/openapi/discriminator.dart'; +import 'package:dynamite/src/models/openapi/header.dart'; +import 'package:dynamite/src/models/openapi/info.dart'; +import 'package:dynamite/src/models/openapi/license.dart'; +import 'package:dynamite/src/models/openapi/media_type.dart'; +import 'package:dynamite/src/models/openapi/open_api.dart'; +import 'package:dynamite/src/models/openapi/operation.dart'; +import 'package:dynamite/src/models/openapi/parameter.dart'; +import 'package:dynamite/src/models/openapi/path_item.dart'; +import 'package:dynamite/src/models/openapi/request_body.dart'; +import 'package:dynamite/src/models/openapi/response.dart'; +import 'package:dynamite/src/models/openapi/schema.dart'; +import 'package:dynamite/src/models/openapi/security_scheme.dart'; +import 'package:dynamite/src/models/openapi/server.dart'; +import 'package:dynamite/src/models/openapi/server_variable.dart'; +import 'package:dynamite/src/models/openapi/tag.dart'; + +export 'openapi/components.dart'; +export 'openapi/discriminator.dart'; +export 'openapi/header.dart'; +export 'openapi/info.dart'; +export 'openapi/license.dart'; +export 'openapi/media_type.dart'; +export 'openapi/open_api.dart'; +export 'openapi/operation.dart'; +export 'openapi/parameter.dart'; +export 'openapi/path_item.dart'; +export 'openapi/request_body.dart'; +export 'openapi/response.dart'; +export 'openapi/schema.dart'; +export 'openapi/security_scheme.dart'; +export 'openapi/server.dart'; +export 'openapi/server_variable.dart'; +export 'openapi/tag.dart'; + +part 'openapi.g.dart'; + +@SerializersFor([ + Components, + Discriminator, + Header, + Info, + License, + MediaType, + OpenAPI, + Operation, + Parameter, + PathItem, + RequestBody, + Response, + Schema, + SecurityScheme, + Server, + ServerVariable, + Tag, +]) +final Serializers serializers = (_$serializers.toBuilder() + ..addBuilderFactory( + const FullType(BuiltMap, [ + FullType(String), + FullType(BuiltList, [FullType(String)]), + ]), + MapBuilder>.new, + ) + ..addPlugin(StandardJsonPlugin())) + .build(); diff --git a/packages/dynamite/dynamite/lib/src/models/serializers.g.dart b/packages/dynamite/dynamite/lib/src/models/openapi.g.dart similarity index 99% rename from packages/dynamite/dynamite/lib/src/models/serializers.g.dart rename to packages/dynamite/dynamite/lib/src/models/openapi.g.dart index b39aa85b..574ace87 100644 --- a/packages/dynamite/dynamite/lib/src/models/serializers.g.dart +++ b/packages/dynamite/dynamite/lib/src/models/openapi.g.dart @@ -1,6 +1,6 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -part of 'serializers.dart'; +part of 'openapi.dart'; // ************************************************************************** // BuiltValueGenerator diff --git a/packages/dynamite/dynamite/lib/src/models/components.dart b/packages/dynamite/dynamite/lib/src/models/openapi/components.dart similarity index 81% rename from packages/dynamite/dynamite/lib/src/models/components.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/components.dart index 3d4e0f61..4ce32ae4 100644 --- a/packages/dynamite/dynamite/lib/src/models/components.dart +++ b/packages/dynamite/dynamite/lib/src/models/openapi/components.dart @@ -1,8 +1,8 @@ import 'package:built_collection/built_collection.dart'; import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.dart'; -import 'package:dynamite/src/models/schema.dart'; -import 'package:dynamite/src/models/security_scheme.dart'; +import 'package:dynamite/src/models/openapi/schema.dart'; +import 'package:dynamite/src/models/openapi/security_scheme.dart'; part 'components.g.dart'; diff --git a/packages/dynamite/dynamite/lib/src/models/components.g.dart b/packages/dynamite/dynamite/lib/src/models/openapi/components.g.dart similarity index 100% rename from packages/dynamite/dynamite/lib/src/models/components.g.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/components.g.dart diff --git a/packages/dynamite/dynamite/lib/src/models/discriminator.dart b/packages/dynamite/dynamite/lib/src/models/openapi/discriminator.dart similarity index 100% rename from packages/dynamite/dynamite/lib/src/models/discriminator.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/discriminator.dart diff --git a/packages/dynamite/dynamite/lib/src/models/discriminator.g.dart b/packages/dynamite/dynamite/lib/src/models/openapi/discriminator.g.dart similarity index 100% rename from packages/dynamite/dynamite/lib/src/models/discriminator.g.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/discriminator.g.dart diff --git a/packages/dynamite/dynamite/lib/src/models/header.dart b/packages/dynamite/dynamite/lib/src/models/openapi/header.dart similarity index 88% rename from packages/dynamite/dynamite/lib/src/models/header.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/header.dart index 41155bb8..a9623417 100644 --- a/packages/dynamite/dynamite/lib/src/models/header.dart +++ b/packages/dynamite/dynamite/lib/src/models/openapi/header.dart @@ -1,6 +1,6 @@ import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.dart'; -import 'package:dynamite/src/models/schema.dart'; +import 'package:dynamite/src/models/openapi/schema.dart'; part 'header.g.dart'; diff --git a/packages/dynamite/dynamite/lib/src/models/header.g.dart b/packages/dynamite/dynamite/lib/src/models/openapi/header.g.dart similarity index 100% rename from packages/dynamite/dynamite/lib/src/models/header.g.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/header.g.dart diff --git a/packages/dynamite/dynamite/lib/src/models/info.dart b/packages/dynamite/dynamite/lib/src/models/openapi/info.dart similarity index 89% rename from packages/dynamite/dynamite/lib/src/models/info.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/info.dart index 3f14c893..1e7d346f 100644 --- a/packages/dynamite/dynamite/lib/src/models/info.dart +++ b/packages/dynamite/dynamite/lib/src/models/openapi/info.dart @@ -1,6 +1,6 @@ import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.dart'; -import 'package:dynamite/src/models/license.dart'; +import 'package:dynamite/src/models/openapi/license.dart'; part 'info.g.dart'; diff --git a/packages/dynamite/dynamite/lib/src/models/info.g.dart b/packages/dynamite/dynamite/lib/src/models/openapi/info.g.dart similarity index 100% rename from packages/dynamite/dynamite/lib/src/models/info.g.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/info.g.dart diff --git a/packages/dynamite/dynamite/lib/src/models/license.dart b/packages/dynamite/dynamite/lib/src/models/openapi/license.dart similarity index 100% rename from packages/dynamite/dynamite/lib/src/models/license.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/license.dart diff --git a/packages/dynamite/dynamite/lib/src/models/license.g.dart b/packages/dynamite/dynamite/lib/src/models/openapi/license.g.dart similarity index 100% rename from packages/dynamite/dynamite/lib/src/models/license.g.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/license.g.dart diff --git a/packages/dynamite/dynamite/lib/src/models/media_type.dart b/packages/dynamite/dynamite/lib/src/models/openapi/media_type.dart similarity index 87% rename from packages/dynamite/dynamite/lib/src/models/media_type.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/media_type.dart index 71363871..9a4b1cc2 100644 --- a/packages/dynamite/dynamite/lib/src/models/media_type.dart +++ b/packages/dynamite/dynamite/lib/src/models/openapi/media_type.dart @@ -1,6 +1,6 @@ import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.dart'; -import 'package:dynamite/src/models/schema.dart'; +import 'package:dynamite/src/models/openapi/schema.dart'; part 'media_type.g.dart'; diff --git a/packages/dynamite/dynamite/lib/src/models/media_type.g.dart b/packages/dynamite/dynamite/lib/src/models/openapi/media_type.g.dart similarity index 100% rename from packages/dynamite/dynamite/lib/src/models/media_type.g.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/media_type.g.dart diff --git a/packages/dynamite/dynamite/lib/src/models/open_api.dart b/packages/dynamite/dynamite/lib/src/models/openapi/open_api.dart similarity index 77% rename from packages/dynamite/dynamite/lib/src/models/open_api.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/open_api.dart index a6bd891e..0f33dba2 100644 --- a/packages/dynamite/dynamite/lib/src/models/open_api.dart +++ b/packages/dynamite/dynamite/lib/src/models/openapi/open_api.dart @@ -1,11 +1,11 @@ import 'package:built_collection/built_collection.dart'; import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.dart'; -import 'package:dynamite/src/models/components.dart'; -import 'package:dynamite/src/models/info.dart'; -import 'package:dynamite/src/models/path_item.dart'; -import 'package:dynamite/src/models/server.dart'; -import 'package:dynamite/src/models/tag.dart'; +import 'package:dynamite/src/models/openapi/components.dart'; +import 'package:dynamite/src/models/openapi/info.dart'; +import 'package:dynamite/src/models/openapi/path_item.dart'; +import 'package:dynamite/src/models/openapi/server.dart'; +import 'package:dynamite/src/models/openapi/tag.dart'; part 'open_api.g.dart'; diff --git a/packages/dynamite/dynamite/lib/src/models/open_api.g.dart b/packages/dynamite/dynamite/lib/src/models/openapi/open_api.g.dart similarity index 100% rename from packages/dynamite/dynamite/lib/src/models/open_api.g.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/open_api.g.dart diff --git a/packages/dynamite/dynamite/lib/src/models/openapi/operation.dart b/packages/dynamite/dynamite/lib/src/models/openapi/operation.dart new file mode 100644 index 00000000..bd431f39 --- /dev/null +++ b/packages/dynamite/dynamite/lib/src/models/openapi/operation.dart @@ -0,0 +1,100 @@ +import 'package:built_collection/built_collection.dart'; +import 'package:built_value/built_value.dart'; +import 'package:built_value/serializer.dart'; +import 'package:dynamite/src/helpers/docs.dart'; +import 'package:dynamite/src/models/openapi/parameter.dart'; +import 'package:dynamite/src/models/openapi/request_body.dart'; +import 'package:dynamite/src/models/openapi/response.dart'; + +part 'operation.g.dart'; + +abstract class Operation implements Built { + factory Operation([final void Function(OperationBuilder) updates]) = _$Operation; + + const Operation._(); + + static Serializer get serializer => _$operationSerializer; + + String? get operationId; + + @BuiltValueField(compare: false) + String? get summary; + + @BuiltValueField(compare: false) + String? get description; + + bool? get deprecated; + + BuiltList? get tags; + + BuiltList? get parameters; + + RequestBody? get requestBody; + + BuiltMap? get responses; + + BuiltList>>? get security; + + Iterable formattedDescription( + final String methodName, { + final bool isRawRequest = false, + final bool requiresAuth = false, + }) sync* { + if (summary != null && summary!.isNotEmpty) { + yield* descriptionToDocs(summary); + yield docsSeparator; + } + + if (description != null && description!.isNotEmpty) { + yield* descriptionToDocs(description); + yield docsSeparator; + } + + if (isRawRequest) { + yield ''' +$docsSeparator This method and the response it returns is experimental. The API might change without a major version bump. +$docsSeparator +$docsSeparator Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers.'''; + } else { + yield '$docsSeparator Returns a [Future] containing a [DynamiteResponse] with the status code, deserialized body and headers.'; + } + yield '$docsSeparator Throws a [DynamiteApiException] if the API call does not return an expected status code.'; + yield docsSeparator; + + if (parameters != null && parameters!.isNotEmpty) { + yield '$docsSeparator Parameters:'; + for (final parameter in parameters!) { + yield parameter.formattedDescription; + } + yield docsSeparator; + } + + if (responses != null && responses!.isNotEmpty) { + yield '$docsSeparator Status codes:'; + for (final response in responses!.entries) { + final statusCode = response.key; + final description = response.value.description; + + final buffer = StringBuffer() + ..write('$docsSeparator ') + ..write(' * $statusCode'); + + if (description.isNotEmpty) { + buffer + ..write(': ') + ..write(description); + } + + yield buffer.toString(); + } + yield docsSeparator; + } + + yield '$docsSeparator See:'; + if (isRawRequest) { + yield '$docsSeparator * [$methodName] for an operation that returns a [DynamiteResponse] with a stable API.'; + } else { + yield '$docsSeparator * [${methodName}Raw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized.'; + } + } +} diff --git a/packages/dynamite/dynamite/lib/src/models/operation.g.dart b/packages/dynamite/dynamite/lib/src/models/openapi/operation.g.dart similarity index 100% rename from packages/dynamite/dynamite/lib/src/models/operation.g.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/operation.g.dart diff --git a/packages/dynamite/dynamite/lib/src/models/parameter.dart b/packages/dynamite/dynamite/lib/src/models/openapi/parameter.dart similarity index 60% rename from packages/dynamite/dynamite/lib/src/models/parameter.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/parameter.dart index 575fcdb8..d23147f6 100644 --- a/packages/dynamite/dynamite/lib/src/models/parameter.dart +++ b/packages/dynamite/dynamite/lib/src/models/openapi/parameter.dart @@ -1,7 +1,9 @@ import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.dart'; +import 'package:dynamite/src/helpers/dart_helpers.dart'; +import 'package:dynamite/src/helpers/docs.dart'; import 'package:dynamite/src/helpers/dynamite.dart'; -import 'package:dynamite/src/models/schema.dart'; +import 'package:dynamite/src/models/openapi/schema.dart'; part 'parameter.g.dart'; @@ -25,4 +27,18 @@ abstract class Parameter implements Built { Schema? get schema; bool get isDartRequired => isRequired(required, schema?.$default); + + String get formattedDescription { + final name = toDartName(this.name); + + final buffer = StringBuffer() + ..write('$docsSeparator * ') + ..write('[$name]'); + + if (description != null) { + buffer.write(' $description'); + } + + return buffer.toString(); + } } diff --git a/packages/dynamite/dynamite/lib/src/models/parameter.g.dart b/packages/dynamite/dynamite/lib/src/models/openapi/parameter.g.dart similarity index 100% rename from packages/dynamite/dynamite/lib/src/models/parameter.g.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/parameter.g.dart diff --git a/packages/dynamite/dynamite/lib/src/models/path_item.dart b/packages/dynamite/dynamite/lib/src/models/openapi/path_item.dart similarity index 91% rename from packages/dynamite/dynamite/lib/src/models/path_item.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/path_item.dart index 121f3eb6..a5cf539b 100644 --- a/packages/dynamite/dynamite/lib/src/models/path_item.dart +++ b/packages/dynamite/dynamite/lib/src/models/openapi/path_item.dart @@ -1,8 +1,8 @@ import 'package:built_collection/built_collection.dart'; import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.dart'; -import 'package:dynamite/src/models/operation.dart'; -import 'package:dynamite/src/models/parameter.dart'; +import 'package:dynamite/src/models/openapi/operation.dart'; +import 'package:dynamite/src/models/openapi/parameter.dart'; part 'path_item.g.dart'; diff --git a/packages/dynamite/dynamite/lib/src/models/path_item.g.dart b/packages/dynamite/dynamite/lib/src/models/openapi/path_item.g.dart similarity index 100% rename from packages/dynamite/dynamite/lib/src/models/path_item.g.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/path_item.g.dart diff --git a/packages/dynamite/dynamite/lib/src/models/request_body.dart b/packages/dynamite/dynamite/lib/src/models/openapi/request_body.dart similarity index 90% rename from packages/dynamite/dynamite/lib/src/models/request_body.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/request_body.dart index 9f7417dd..f89d5310 100644 --- a/packages/dynamite/dynamite/lib/src/models/request_body.dart +++ b/packages/dynamite/dynamite/lib/src/models/openapi/request_body.dart @@ -1,7 +1,7 @@ import 'package:built_collection/built_collection.dart'; import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.dart'; -import 'package:dynamite/src/models/media_type.dart'; +import 'package:dynamite/src/models/openapi/media_type.dart'; part 'request_body.g.dart'; diff --git a/packages/dynamite/dynamite/lib/src/models/request_body.g.dart b/packages/dynamite/dynamite/lib/src/models/openapi/request_body.g.dart similarity index 100% rename from packages/dynamite/dynamite/lib/src/models/request_body.g.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/request_body.g.dart diff --git a/packages/dynamite/dynamite/lib/src/models/response.dart b/packages/dynamite/dynamite/lib/src/models/openapi/response.dart similarity index 82% rename from packages/dynamite/dynamite/lib/src/models/response.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/response.dart index 872b6a6f..aedfccca 100644 --- a/packages/dynamite/dynamite/lib/src/models/response.dart +++ b/packages/dynamite/dynamite/lib/src/models/openapi/response.dart @@ -1,8 +1,8 @@ import 'package:built_collection/built_collection.dart'; import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.dart'; -import 'package:dynamite/src/models/header.dart'; -import 'package:dynamite/src/models/media_type.dart'; +import 'package:dynamite/src/models/openapi/header.dart'; +import 'package:dynamite/src/models/openapi/media_type.dart'; part 'response.g.dart'; diff --git a/packages/dynamite/dynamite/lib/src/models/response.g.dart b/packages/dynamite/dynamite/lib/src/models/openapi/response.g.dart similarity index 100% rename from packages/dynamite/dynamite/lib/src/models/response.g.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/response.g.dart diff --git a/packages/dynamite/dynamite/lib/src/models/schema.dart b/packages/dynamite/dynamite/lib/src/models/openapi/schema.dart similarity index 95% rename from packages/dynamite/dynamite/lib/src/models/schema.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/schema.dart index 76030ecd..145e59e6 100644 --- a/packages/dynamite/dynamite/lib/src/models/schema.dart +++ b/packages/dynamite/dynamite/lib/src/models/openapi/schema.dart @@ -3,7 +3,7 @@ import 'package:built_value/built_value.dart'; import 'package:built_value/json_object.dart'; import 'package:built_value/serializer.dart'; import 'package:dynamite/src/helpers/docs.dart'; -import 'package:dynamite/src/models/discriminator.dart'; +import 'package:dynamite/src/models/openapi/discriminator.dart'; part 'schema.g.dart'; diff --git a/packages/dynamite/dynamite/lib/src/models/schema.g.dart b/packages/dynamite/dynamite/lib/src/models/openapi/schema.g.dart similarity index 100% rename from packages/dynamite/dynamite/lib/src/models/schema.g.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/schema.g.dart diff --git a/packages/dynamite/dynamite/lib/src/models/security_scheme.dart b/packages/dynamite/dynamite/lib/src/models/openapi/security_scheme.dart similarity index 100% rename from packages/dynamite/dynamite/lib/src/models/security_scheme.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/security_scheme.dart diff --git a/packages/dynamite/dynamite/lib/src/models/security_scheme.g.dart b/packages/dynamite/dynamite/lib/src/models/openapi/security_scheme.g.dart similarity index 100% rename from packages/dynamite/dynamite/lib/src/models/security_scheme.g.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/security_scheme.g.dart diff --git a/packages/dynamite/dynamite/lib/src/models/server.dart b/packages/dynamite/dynamite/lib/src/models/openapi/server.dart similarity index 87% rename from packages/dynamite/dynamite/lib/src/models/server.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/server.dart index af4a364d..c2928115 100644 --- a/packages/dynamite/dynamite/lib/src/models/server.dart +++ b/packages/dynamite/dynamite/lib/src/models/openapi/server.dart @@ -1,7 +1,7 @@ import 'package:built_collection/built_collection.dart'; import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.dart'; -import 'package:dynamite/src/models/server_variable.dart'; +import 'package:dynamite/src/models/openapi/server_variable.dart'; part 'server.g.dart'; diff --git a/packages/dynamite/dynamite/lib/src/models/server.g.dart b/packages/dynamite/dynamite/lib/src/models/openapi/server.g.dart similarity index 100% rename from packages/dynamite/dynamite/lib/src/models/server.g.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/server.g.dart diff --git a/packages/dynamite/dynamite/lib/src/models/server_variable.dart b/packages/dynamite/dynamite/lib/src/models/openapi/server_variable.dart similarity index 100% rename from packages/dynamite/dynamite/lib/src/models/server_variable.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/server_variable.dart diff --git a/packages/dynamite/dynamite/lib/src/models/server_variable.g.dart b/packages/dynamite/dynamite/lib/src/models/openapi/server_variable.g.dart similarity index 100% rename from packages/dynamite/dynamite/lib/src/models/server_variable.g.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/server_variable.g.dart diff --git a/packages/dynamite/dynamite/lib/src/models/tag.dart b/packages/dynamite/dynamite/lib/src/models/openapi/tag.dart similarity index 100% rename from packages/dynamite/dynamite/lib/src/models/tag.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/tag.dart diff --git a/packages/dynamite/dynamite/lib/src/models/tag.g.dart b/packages/dynamite/dynamite/lib/src/models/openapi/tag.g.dart similarity index 100% rename from packages/dynamite/dynamite/lib/src/models/tag.g.dart rename to packages/dynamite/dynamite/lib/src/models/openapi/tag.g.dart diff --git a/packages/dynamite/dynamite/lib/src/models/operation.dart b/packages/dynamite/dynamite/lib/src/models/operation.dart deleted file mode 100644 index ace1970c..00000000 --- a/packages/dynamite/dynamite/lib/src/models/operation.dart +++ /dev/null @@ -1,47 +0,0 @@ -import 'package:built_collection/built_collection.dart'; -import 'package:built_value/built_value.dart'; -import 'package:built_value/serializer.dart'; -import 'package:dynamite/src/helpers/docs.dart'; -import 'package:dynamite/src/models/parameter.dart'; -import 'package:dynamite/src/models/request_body.dart'; -import 'package:dynamite/src/models/response.dart'; - -part 'operation.g.dart'; - -abstract class Operation implements Built { - factory Operation([final void Function(OperationBuilder) updates]) = _$Operation; - - const Operation._(); - - static Serializer get serializer => _$operationSerializer; - - String? get operationId; - - @BuiltValueField(compare: false) - String? get summary; - - @BuiltValueField(compare: false) - String? get description; - - bool? get deprecated; - - BuiltList? get tags; - - BuiltList? get parameters; - - RequestBody? get requestBody; - - BuiltMap? get responses; - - BuiltList>>? get security; - - Iterable get formattedDescription sync* { - yield* descriptionToDocs(summary); - - if (summary != null && description != null) { - yield docsSeparator; - } - - yield* descriptionToDocs(description); - } -} diff --git a/packages/dynamite/dynamite/lib/src/models/serializers.dart b/packages/dynamite/dynamite/lib/src/models/serializers.dart deleted file mode 100644 index b4a8ce1a..00000000 --- a/packages/dynamite/dynamite/lib/src/models/serializers.dart +++ /dev/null @@ -1,52 +0,0 @@ -import 'package:built_collection/built_collection.dart'; -import 'package:built_value/serializer.dart'; -import 'package:built_value/standard_json_plugin.dart'; -import 'package:dynamite/src/models/components.dart'; -import 'package:dynamite/src/models/discriminator.dart'; -import 'package:dynamite/src/models/header.dart'; -import 'package:dynamite/src/models/info.dart'; -import 'package:dynamite/src/models/license.dart'; -import 'package:dynamite/src/models/media_type.dart'; -import 'package:dynamite/src/models/open_api.dart'; -import 'package:dynamite/src/models/operation.dart'; -import 'package:dynamite/src/models/parameter.dart'; -import 'package:dynamite/src/models/path_item.dart'; -import 'package:dynamite/src/models/request_body.dart'; -import 'package:dynamite/src/models/response.dart'; -import 'package:dynamite/src/models/schema.dart'; -import 'package:dynamite/src/models/security_scheme.dart'; -import 'package:dynamite/src/models/server.dart'; -import 'package:dynamite/src/models/server_variable.dart'; -import 'package:dynamite/src/models/tag.dart'; - -part 'serializers.g.dart'; - -@SerializersFor([ - Components, - Discriminator, - Header, - Info, - License, - MediaType, - OpenAPI, - Operation, - Parameter, - PathItem, - RequestBody, - Response, - Schema, - SecurityScheme, - Server, - ServerVariable, - Tag, -]) -final Serializers serializers = (_$serializers.toBuilder() - ..addBuilderFactory( - const FullType(BuiltMap, [ - FullType(String), - FullType(BuiltList, [FullType(String)]), - ]), - MapBuilder>.new, - ) - ..addPlugin(StandardJsonPlugin())) - .build(); diff --git a/packages/dynamite/dynamite/lib/src/models/type_result.dart b/packages/dynamite/dynamite/lib/src/models/type_result.dart new file mode 100644 index 00000000..aa13439d --- /dev/null +++ b/packages/dynamite/dynamite/lib/src/models/type_result.dart @@ -0,0 +1 @@ +export 'type_result/type_result.dart'; diff --git a/packages/dynamite/dynamite/lib/src/models/type_result/base.dart b/packages/dynamite/dynamite/lib/src/models/type_result/base.dart new file mode 100644 index 00000000..aa58e38c --- /dev/null +++ b/packages/dynamite/dynamite/lib/src/models/type_result/base.dart @@ -0,0 +1,50 @@ +part of 'type_result.dart'; + +@immutable +class TypeResultBase extends TypeResult { + TypeResultBase( + super.className, { + super.nullable, + }); + + @override + String? get _builderFactory => null; + + @override + String? get _serializer => null; + + @override + String serialize(final String object) => object; + + @override + String encode( + final String object, { + final bool onlyChildren = false, + final String? mimeType, + }) { + switch (mimeType) { + case null: + case 'application/json': + case 'application/x-www-form-urlencoded': + if (className == 'String') { + return object; + } else { + return '$object.toString()'; + } + case 'application/octet-stream': + return 'utf8.encode($object) as Uint8List'; + default: + throw Exception('Can not encode mime type "$mimeType"'); + } + } + + @override + TypeResultBase get dartType { + final dartName = switch (name) { + 'JsonObject' => 'dynamic', + _ => name, + }; + + return TypeResultBase(dartName, nullable: nullable); + } +} diff --git a/packages/dynamite/dynamite/lib/src/type_result/enum.dart b/packages/dynamite/dynamite/lib/src/models/type_result/enum.dart similarity index 100% rename from packages/dynamite/dynamite/lib/src/type_result/enum.dart rename to packages/dynamite/dynamite/lib/src/models/type_result/enum.dart diff --git a/packages/dynamite/dynamite/lib/src/type_result/list.dart b/packages/dynamite/dynamite/lib/src/models/type_result/list.dart similarity index 100% rename from packages/dynamite/dynamite/lib/src/type_result/list.dart rename to packages/dynamite/dynamite/lib/src/models/type_result/list.dart diff --git a/packages/dynamite/dynamite/lib/src/type_result/map.dart b/packages/dynamite/dynamite/lib/src/models/type_result/map.dart similarity index 100% rename from packages/dynamite/dynamite/lib/src/type_result/map.dart rename to packages/dynamite/dynamite/lib/src/models/type_result/map.dart diff --git a/packages/dynamite/dynamite/lib/src/type_result/object.dart b/packages/dynamite/dynamite/lib/src/models/type_result/object.dart similarity index 100% rename from packages/dynamite/dynamite/lib/src/type_result/object.dart rename to packages/dynamite/dynamite/lib/src/models/type_result/object.dart diff --git a/packages/dynamite/dynamite/lib/src/type_result/type_result.dart b/packages/dynamite/dynamite/lib/src/models/type_result/type_result.dart similarity index 99% rename from packages/dynamite/dynamite/lib/src/type_result/type_result.dart rename to packages/dynamite/dynamite/lib/src/models/type_result/type_result.dart index 7067ddfc..db2c66ef 100644 --- a/packages/dynamite/dynamite/lib/src/type_result/type_result.dart +++ b/packages/dynamite/dynamite/lib/src/models/type_result/type_result.dart @@ -8,7 +8,7 @@ part 'map.dart'; part 'object.dart'; @immutable -abstract class TypeResult { +sealed class TypeResult { TypeResult( this.className, { this.generics = const [], diff --git a/packages/dynamite/dynamite/lib/src/openapi_builder.dart b/packages/dynamite/dynamite/lib/src/openapi_builder.dart index c675c6b2..3eaad791 100644 --- a/packages/dynamite/dynamite/lib/src/openapi_builder.dart +++ b/packages/dynamite/dynamite/lib/src/openapi_builder.dart @@ -11,9 +11,8 @@ import 'package:dynamite/src/builder/resolve_type.dart'; import 'package:dynamite/src/builder/serializer.dart'; import 'package:dynamite/src/builder/state.dart'; import 'package:dynamite/src/helpers/dart_helpers.dart'; -import 'package:dynamite/src/models/open_api.dart'; -import 'package:dynamite/src/models/serializers.dart'; -import 'package:dynamite/src/type_result/type_result.dart'; +import 'package:dynamite/src/models/openapi.dart' as openapi; +import 'package:dynamite/src/models/type_result.dart'; class OpenAPIBuilder implements Builder { @override @@ -34,13 +33,13 @@ class OpenAPIBuilder implements Builder { ); final spec = switch (inputId.extension) { - '.json' => serializers.deserializeWith( - OpenAPI.serializer, + '.json' => openapi.serializers.deserializeWith( + openapi.OpenAPI.serializer, json.decode(await buildStep.readAsString(inputId)), )!, '.yaml' => checkedYamlDecode( await buildStep.readAsString(inputId), - (final m) => serializers.deserializeWith(OpenAPI.serializer, m)!, + (final m) => openapi.serializers.deserializeWith(openapi.OpenAPI.serializer, m)!, ), _ => throw StateError('Openapi specs can only be yaml or json.'), }; diff --git a/packages/dynamite/dynamite/lib/src/type_result/base.dart b/packages/dynamite/dynamite/lib/src/type_result/base.dart deleted file mode 100644 index fe9df7f2..00000000 --- a/packages/dynamite/dynamite/lib/src/type_result/base.dart +++ /dev/null @@ -1,58 +0,0 @@ -part of 'type_result.dart'; - -@immutable -class TypeResultBase extends TypeResult { - TypeResultBase( - super.className, { - super.nullable, - }); - - @override - String? get _builderFactory => null; - - @override - String? get _serializer => null; - - @override - String serialize(final String object) => object; - - @override - String encode( - final String object, { - final bool onlyChildren = false, - final String? mimeType, - }) => - name == 'String' ? object : '$object.toString()'; - - @override - String deserialize(final String object, {final bool toBuilder = false}) => '($object as $nullableName)'; - - @override - String decode(final String object) { - switch (name) { - case 'String': - return '($object as String)'; - case 'int': - return 'int.parse($object as String)'; - case 'bool': - return "($object as String == 'true')"; - case 'JsonObject': - return 'JsonObject($object)'; - default: - throw Exception('Can not decode "$name" from String'); - } - } - - @override - TypeResultBase get dartType { - final String dartName; - switch (name) { - case 'JsonObject': - dartName = 'dynamic'; - default: - dartName = name; - } - - return TypeResultBase(dartName, nullable: nullable); - } -} diff --git a/packages/dynamite/dynamite/test/type_result_test.dart b/packages/dynamite/dynamite/test/type_result_test.dart index 903475f3..e8147142 100644 --- a/packages/dynamite/dynamite/test/type_result_test.dart +++ b/packages/dynamite/dynamite/test/type_result_test.dart @@ -1,4 +1,4 @@ -import 'package:dynamite/src/type_result/type_result.dart'; +import 'package:dynamite/src/models/type_result.dart'; import 'package:test/test.dart'; void main() { diff --git a/packages/dynamite/dynamite_runtime/analysis_options.yaml b/packages/dynamite/dynamite_runtime/analysis_options.yaml index 80216cb3..447af2a6 100644 --- a/packages/dynamite/dynamite_runtime/analysis_options.yaml +++ b/packages/dynamite/dynamite_runtime/analysis_options.yaml @@ -1,9 +1,5 @@ include: package:neon_lints/dart.yaml -linter: - rules: - public_member_api_docs: false - analyzer: exclude: - '**.g.dart' diff --git a/packages/dynamite/dynamite_runtime/lib/http_client.dart b/packages/dynamite/dynamite_runtime/lib/http_client.dart index 1550b0eb..13962b5d 100644 --- a/packages/dynamite/dynamite_runtime/lib/http_client.dart +++ b/packages/dynamite/dynamite_runtime/lib/http_client.dart @@ -1 +1,3 @@ -export 'src/http_client.dart'; +export 'package:cookie_jar/cookie_jar.dart'; +export 'src/dynamite_client.dart'; +export 'src/http_extensions.dart'; diff --git a/packages/dynamite/dynamite_runtime/lib/src/dynamite_client.dart b/packages/dynamite/dynamite_runtime/lib/src/dynamite_client.dart new file mode 100644 index 00000000..b241426a --- /dev/null +++ b/packages/dynamite/dynamite_runtime/lib/src/dynamite_client.dart @@ -0,0 +1,445 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:built_value/serializer.dart'; +import 'package:cookie_jar/cookie_jar.dart'; +import 'package:dynamite_runtime/src/http_extensions.dart'; +import 'package:dynamite_runtime/src/uri.dart'; +import 'package:meta/meta.dart'; +import 'package:universal_io/io.dart'; + +/// Response returned by operations of a [DynamiteClient]. +/// +/// See: +/// * [DynamiteRawResponse] for an experimental implementation that can be serialized. +/// * [DynamiteApiException] as the exception that can be thrown in operations +/// * [DynamiteAuthentication] for providing authentication methods. +/// * [DynamiteClient] for the client providing operations. +@immutable +class DynamiteResponse { + /// Creates a new dynamite response. + const DynamiteResponse( + this.statusCode, + this._body, + this._headers, + ); + + /// The status code of the response. + final int statusCode; + + final B? _body; + + final H? _headers; + + /// The decoded body of the response. + B get body => _body!; + + /// The decoded headers of the response. + H get headers => _headers!; + + @override + String toString() => 'DynamiteResponse(data: $body, headers: $headers, statusCode: $statusCode)'; +} + +/// Raw response returned by operations of a [DynamiteClient]. +/// +/// This type itself is serializable. +/// +/// The api of this type might change without a major bump. +/// Use methods that return a [DynamiteResponse] instead. +/// +/// See: +/// * [DynamiteResponse] as the response returned by an operation. +/// * [DynamiteApiException] as the exception that can be thrown in operations +/// * [DynamiteAuthentication] for providing authentication methods. +/// * [DynamiteClient] for the client providing operations. +@experimental +class DynamiteRawResponse { + /// Creates a new raw dynamite response. + /// + /// The [response] will be awaited and deserialized. + /// After [future] completes the deserialized response can be accessed + /// through [response]. + DynamiteRawResponse({ + required final Future response, + required this.bodyType, + required this.headersType, + required this.serializers, + }) { + final completer = Completer>(); + future = completer.future; + + // ignore: discarded_futures + response.then( + (final response) async { + _rawBody = switch (bodyType) { + const FullType(Uint8List) => await response.bytes, + const FullType(String) => await response.string, + _ => await response.json, + }; + _rawHeaders = response.responseHeaders; + + final body = deserializeBody(_rawBody, serializers, bodyType); + final headers = deserializeHeaders(_rawHeaders, serializers, headersType); + + _response = DynamiteResponse( + response.statusCode, + body, + headers, + ); + + completer.complete(_response); + }, + onError: completer.completeError, + ); + } + + /// Decodes a raw dynamite response from json data. + /// + /// The [future] must not be awaited and the deserialized response can be + /// accessed immediately through [response]. + factory DynamiteRawResponse.fromJson( + final Map json, { + required final Serializers serializers, + final FullType? bodyType, + final FullType? headersType, + }) { + final statusCode = json['statusCode']! as int; + final body = deserializeBody(json['body'], serializers, bodyType); + final headers = deserializeHeaders(json['headers'], serializers, headersType); + + final response = DynamiteResponse( + statusCode, + body, + headers, + ); + + return DynamiteRawResponse._fromJson( + response, + bodyType: bodyType, + headersType: headersType, + serializers: serializers, + ); + } + + DynamiteRawResponse._fromJson( + this._response, { + required this.bodyType, + required this.headersType, + required this.serializers, + }) : future = Future.value(_response); + + /// The serializers for the header and body. + final Serializers serializers; + + /// The full type of the body. + /// + /// This is `null` if the body type is void. + final FullType? bodyType; + + /// The full type of the headers. + /// + /// This is `null` if the headers type is void. + final FullType? headersType; + + /// Future of the deserialized response. + /// + /// After this future completes the response can be accessed synchronously + /// through [response]. + late final Future> future; + + /// Caches the serialized response body for later serialization in [toJson]. + /// + /// Responses revived with [DynamiteRawResponse.fromJson] are not cached as + /// they are not expected to be serialized again. + Object? _rawBody; + + /// Caches the serialized response headers for later serialization in [toJson]. + /// + /// Responses revived with [DynamiteRawResponse.fromJson] are not cached as + /// they are not expected to be serialized again. + Map? _rawHeaders; + + DynamiteResponse? _response; + + /// Returns the deserialized response synchronously. + /// + /// Throws a `StateError` if [future] has not completed yet and `this` has + /// not been instantiated through [DynamiteRawResponse.fromJson]. + DynamiteResponse get response { + final response = _response; + + if (response == null) { + throw StateError('The response did not finish yet. Make sure to await `this.future`.'); + } + + return response; + } + + /// Deserializes the body. + /// + /// Most efficient if the [serialized] value is already the correct type. + /// The [bodyType] should represent the return type [B]. + static B? deserializeBody(final Object? serialized, final Serializers serializers, final FullType? bodyType) { + // If we use the more efficient helpers from BytesStreamExtension the serialized value can already be correct. + if (serialized is B) { + return serialized; + } + + if (bodyType != null) { + return serializers.deserialize(serialized, specifiedType: bodyType) as B?; + } + + return null; + } + + /// Serializes the body. + Object? serializeBody(final B? object) { + if (bodyType != null && object != null) { + return serializers.serialize(object, specifiedType: bodyType!); + } + + return null; + } + + /// Deserializes the headers. + /// + /// Most efficient if the [serialized] value is already the correct type. + /// The [headersType] should represent the return type [H]. + static H? deserializeHeaders( + final Object? serialized, + final Serializers serializers, + final FullType? headersType, + ) { + // If we use the more efficient helpers from BytesStreamExtension the serialized value can already be correct. + if (serialized is H) { + return serialized; + } + + if (headersType != null) { + return serializers.deserialize(serialized, specifiedType: headersType) as H?; + } + + return null; + } + + /// Serializes the headers. + Object? serializeHeaders(final H? object) { + if (headersType != null && object != null) { + return serializers.serialize(object, specifiedType: headersType!); + } + + return null; + } + + /// Serializes this response into json. + /// + /// To revive it again use [DynamiteRawResponse.fromJson] with the same + /// serializer and `FullType`s as this. + Map toJson() => { + 'statusCode': response.statusCode, + 'body': _rawBody ?? serializeBody(response._body), + 'headers': _rawHeaders ?? serializeHeaders(response._headers), + }; + + @override + String toString() => 'DynamiteResponse(${toJson()})'; +} + +/// The exception thrown by operations of a [DynamiteClient]. +/// +/// +/// See: +/// * [DynamiteResponse] as the response returned by an operation. +/// * [DynamiteRawResponse] as the raw response that can be serialized. +/// * [DynamiteAuthentication] for providing authentication methods. +/// * [DynamiteClient] for the client providing operations. +@immutable +class DynamiteApiException implements Exception { + /// Creates a new dynamite exception with the given information. + const DynamiteApiException( + this.statusCode, + this.headers, + this.body, + ); + + /// Creates a new Exception from the given [response]. + /// + /// Tries to decode the `response` into a string. + static Future fromResponse(final HttpClientResponse response) async { + String body; + try { + body = await response.string; + } on FormatException { + body = 'binary'; + } + + return DynamiteApiException( + response.statusCode, + response.responseHeaders, + body, + ); + } + + /// The returned status code when the exception was thrown. + final int statusCode; + + /// The returned headers when the exception was thrown. + final Map headers; + + /// The returned body code when the exception was thrown. + final String body; + + @override + String toString() => 'DynamiteApiException(statusCode: $statusCode, headers: $headers, body: $body)'; +} + +/// Base dynamite authentication. +/// +/// See: +/// * [DynamiteResponse] as the response returned by an operation. +/// * [DynamiteRawResponse] as the raw response that can be serialized. +/// * [DynamiteApiException] as the exception that can be thrown in operations +/// * [DynamiteClient] for the client providing operations. +@immutable +sealed class DynamiteAuthentication { + /// Creates a new authentication. + const DynamiteAuthentication({ + required this.type, + required this.scheme, + }); + + /// The base type of the authentication. + final String type; + + /// The used authentication scheme. + final String scheme; + + /// The authentication headers added to a request. + Map get headers; +} + +/// Basic http authentication with username and password. +class DynamiteHttpBasicAuthentication extends DynamiteAuthentication { + /// Creates a new http basic authentication. + const DynamiteHttpBasicAuthentication({ + required this.username, + required this.password, + }) : super( + type: 'http', + scheme: 'basic', + ); + + /// The username. + final String username; + + /// The password. + final String password; + + @override + Map get headers => { + 'Authorization': 'Basic ${base64.encode(utf8.encode('$username:$password'))}', + }; +} + +/// Http bearer authentication with a token. +class DynamiteHttpBearerAuthentication extends DynamiteAuthentication { + /// Creates a new http bearer authentication. + const DynamiteHttpBearerAuthentication({ + required this.token, + }) : super( + type: 'http', + scheme: 'bearer', + ); + + /// The authentication token. + final String token; + + @override + Map get headers => { + 'Authorization': 'Bearer $token', + }; +} + +/// A client for making network requests. +/// +/// See: +/// * [DynamiteResponse] as the response returned by an operation. +/// * [DynamiteRawResponse] as the raw response that can be serialized. +/// * [DynamiteApiException] as the exception that can be thrown in operations +/// * [DynamiteAuthentication] for providing authentication methods. +class DynamiteClient { + /// Creates a new dynamite network client. + /// + /// If [httpClient] is not provided a default one will be created. + /// The [baseURL] will be normalized, removing any trailing `/`. + DynamiteClient( + final Uri baseURL, { + this.baseHeaders, + final String? userAgent, + final HttpClient? httpClient, + this.cookieJar, + this.authentications = const [], + }) : httpClient = (httpClient ?? HttpClient())..userAgent = userAgent, + baseURL = baseURL.normalizeEmptyPath(); + + /// The base server url used to build the request uri. + /// + /// See `https://swagger.io/docs/specification/api-host-and-base-path` for + /// further information. + final Uri baseURL; + + /// The base headers added to each request. + final Map? baseHeaders; + + /// The base http client. + final HttpClient httpClient; + + /// The optional cookie jar to persist the response cookies. + final CookieJar? cookieJar; + + /// The available authentications for this client. + /// + /// The first one matching the required authentication type will be used. + final List authentications; + + /// Makes a request against a given [path]. + Future doRequest( + final String method, + final Uri path, + final Map headers, + final Uint8List? body, + final Set? validStatuses, + ) async { + final uri = baseURL.replace( + path: '${baseURL.path}${path.path}', + queryParameters: { + ...baseURL.queryParameters, + ...path.queryParameters, + }, + ); + + final request = await httpClient.openUrl(method, uri); + for (final header in {...?baseHeaders, ...headers}.entries) { + request.headers.add(header.key, header.value); + } + if (body != null) { + request.add(body); + } + if (cookieJar != null) { + request.cookies.addAll(await cookieJar!.loadForRequest(uri)); + } + + final response = await request.close(); + if (cookieJar != null) { + await cookieJar!.saveFromResponse(uri, response.cookies); + } + + if (validStatuses?.contains(response.statusCode) ?? true) { + return response; + } else { + throw await DynamiteApiException.fromResponse(response); + } + } +} diff --git a/packages/dynamite/dynamite_runtime/lib/src/http_client.dart b/packages/dynamite/dynamite_runtime/lib/src/http_client.dart deleted file mode 100644 index 52366962..00000000 --- a/packages/dynamite/dynamite_runtime/lib/src/http_client.dart +++ /dev/null @@ -1,165 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; -import 'dart:typed_data'; - -import 'package:cookie_jar/cookie_jar.dart'; -import 'package:dynamite_runtime/src/uri.dart'; -import 'package:universal_io/io.dart'; - -export 'package:cookie_jar/cookie_jar.dart'; - -extension DynamiteHttpClientResponseBody on HttpClientResponse { - Future get bodyBytes async { - final buffer = BytesBuilder(); - - await forEach(buffer.add); - - return buffer.toBytes(); - } - - Future get body => transform(utf8.decoder).join(); - - Future get jsonBody => transform(utf8.decoder).transform(json.decoder).first; - - Map get responseHeaders { - final responseHeaders = {}; - headers.forEach((final name, final values) { - responseHeaders[name] = values.last; - }); - - return responseHeaders; - } -} - -class DynamiteResponse { - DynamiteResponse( - this.data, - this.headers, - ); - - final T data; - - final U headers; - - @override - String toString() => 'DynamiteResponse(data: $data, headers: $headers)'; -} - -class DynamiteApiException implements Exception { - DynamiteApiException( - this.statusCode, - this.headers, - this.body, - ); - - final int statusCode; - - final Map headers; - - final String body; - - @override - String toString() => 'DynamiteApiException(statusCode: $statusCode, headers: $headers, body: $body)'; -} - -abstract class DynamiteAuthentication { - String get type; - String get scheme; - Map get headers; -} - -class DynamiteHttpBasicAuthentication extends DynamiteAuthentication { - DynamiteHttpBasicAuthentication({ - required this.username, - required this.password, - }); - - final String username; - - final String password; - - @override - String type = 'http'; - - @override - String scheme = 'basic'; - - @override - Map get headers => { - 'Authorization': 'Basic ${base64.encode(utf8.encode('$username:$password'))}', - }; -} - -class DynamiteHttpBearerAuthentication extends DynamiteAuthentication { - DynamiteHttpBearerAuthentication({ - required this.token, - }); - - final String token; - - @override - String type = 'http'; - - @override - String scheme = 'bearer'; - - @override - Map get headers => { - 'Authorization': 'Bearer $token', - }; -} - -class DynamiteClient { - DynamiteClient( - final Uri baseURL, { - this.baseHeaders, - final String? userAgent, - final HttpClient? httpClient, - this.cookieJar, - this.authentications = const [], - }) : httpClient = (httpClient ?? HttpClient())..userAgent = userAgent, - baseURL = baseURL.normalizeEmptyPath(); - - final Uri baseURL; - - final Map? baseHeaders; - - final HttpClient httpClient; - - final CookieJar? cookieJar; - - final List authentications; - - Future doRequest( - final String method, - final Uri path, - final Map headers, - final Uint8List? body, - ) async { - final uri = baseURL.replace( - path: '${baseURL.path}${path.path}', - queryParameters: { - ...baseURL.queryParameters, - ...path.queryParameters, - }, - ); - - final request = await httpClient.openUrl(method, uri); - for (final header in {...?baseHeaders, ...headers}.entries) { - request.headers.add(header.key, header.value); - } - if (body != null) { - request.add(body); - } - if (cookieJar != null) { - request.cookies.addAll(await cookieJar!.loadForRequest(uri)); - } - - final response = await request.close(); - if (cookieJar != null) { - await cookieJar!.saveFromResponse(uri, response.cookies); - } - - return response; - } -} diff --git a/packages/dynamite/dynamite_runtime/lib/src/http_extensions.dart b/packages/dynamite/dynamite_runtime/lib/src/http_extensions.dart new file mode 100644 index 00000000..005a80aa --- /dev/null +++ b/packages/dynamite/dynamite_runtime/lib/src/http_extensions.dart @@ -0,0 +1,43 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:universal_io/io.dart'; + +/// A stream of bytes. +/// +/// Usually a `Stream`. +typedef BytesStream = Stream>; + +final _utf8JsonDecoder = utf8.decoder.fuse(json.decoder); + +/// Extension on byte streams that enable efficient transformations. +extension BytesStreamExtension on BytesStream { + /// Returns the all bytes of the stream. + Future get bytes async { + final buffer = BytesBuilder(); + + await forEach(buffer.add); + + return buffer.toBytes(); + } + + /// Converts the stream into a `String` using the [utf8] encoding. + Future get string => transform(utf8.decoder).join(); + + /// Converts the stream into a JSON using the [utf8] encoding. + Future get json => transform(_utf8JsonDecoder).first; +} + +/// Extension on a http responses. +extension HttpClientResponseExtension on HttpClientResponse { + /// Returns a map of headers. + Map get responseHeaders { + final responseHeaders = {}; + headers.forEach((final name, final values) { + responseHeaders[name] = values.last; + }); + + return responseHeaders; + } +} diff --git a/packages/dynamite/dynamite_runtime/lib/src/string_checker.dart b/packages/dynamite/dynamite_runtime/lib/src/string_checker.dart new file mode 100644 index 00000000..accfb49f --- /dev/null +++ b/packages/dynamite/dynamite_runtime/lib/src/string_checker.dart @@ -0,0 +1,26 @@ +/// Checks the [input] against [pattern]. +/// +/// Throws an `Exception` containing the [parameterName] if the `pattern` does not match. +void checkPattern(final String input, final RegExp pattern, final String parameterName) { + if (!pattern.hasMatch(input)) { + throw Exception('Invalid value "$input" for parameter "$parameterName" with pattern "${pattern.pattern}"'); + } +} + +/// Checks the [input] length against [minLength]. +/// +/// Throws an `Exception` containing the [parameterName] if the `input` is to short. +void checkMinLength(final String input, final int minLength, final String parameterName) { + if (input.length < minLength) { + throw Exception('Parameter "$input" has to be at least $minLength characters long'); + } +} + +/// Checks the [input] length against [maxLength]. +/// +/// Throws an `Exception` containing the [parameterName] if the `input` is to long. +void checkMaxLength(final String input, final int maxLength, final String parameterName) { + if (input.length > maxLength) { + throw Exception('Parameter "$input" has to be at most $maxLength characters long'); + } +} diff --git a/packages/dynamite/dynamite_runtime/lib/utils.dart b/packages/dynamite/dynamite_runtime/lib/utils.dart index 30f229d5..c8d7b711 100644 --- a/packages/dynamite/dynamite_runtime/lib/utils.dart +++ b/packages/dynamite/dynamite_runtime/lib/utils.dart @@ -1 +1,2 @@ +export 'src/string_checker.dart'; export 'src/uri.dart'; diff --git a/packages/dynamite/dynamite_runtime/pubspec.yaml b/packages/dynamite/dynamite_runtime/pubspec.yaml index c0c34740..5de176e5 100644 --- a/packages/dynamite/dynamite_runtime/pubspec.yaml +++ b/packages/dynamite/dynamite_runtime/pubspec.yaml @@ -8,6 +8,7 @@ environment: dependencies: built_value: ^8.6.3 cookie_jar: ^4.0.8 + meta: ^1.9.1 universal_io: ^2.2.2 dev_dependencies: diff --git a/packages/neon/neon/lib/src/bloc/result.dart b/packages/neon/neon/lib/src/bloc/result.dart index d652fbbf..66240ccd 100644 --- a/packages/neon/neon/lib/src/bloc/result.dart +++ b/packages/neon/neon/lib/src/bloc/result.dart @@ -42,11 +42,19 @@ class Result { isCached: isCached, ); - Result asLoading() => Result( - data, - error, - isLoading: true, - isCached: isCached, + Result asLoading() => copyWith(isLoading: true); + + Result copyWith({ + final T? data, + final Object? error, + final bool? isLoading, + final bool? isCached, + }) => + Result( + data ?? this.data, + error ?? this.error, + isLoading: isLoading ?? this.isLoading, + isCached: isCached ?? this.isCached, ); bool get hasError => error != null; diff --git a/packages/neon/neon/lib/src/blocs/apps.dart b/packages/neon/neon/lib/src/blocs/apps.dart index 54fd9fa7..9733e0f6 100644 --- a/packages/neon/neon/lib/src/blocs/apps.dart +++ b/packages/neon/neon/lib/src/blocs/apps.dart @@ -199,12 +199,12 @@ class AppsBloc extends InteractiveBloc implements AppsBlocEvents, AppsBlocStates @override Future refresh() async { await RequestManager.instance - .wrapNextcloud, CoreNavigationGetAppsNavigationResponseApplicationJson>( + .wrapNextcloud, CoreNavigationGetAppsNavigationResponseApplicationJson, void>( _account.id, 'apps-apps', apps, - () async => _account.client.core.navigation.getAppsNavigation(), - (final response) => response.ocs.data.toList(), + _account.client.core.navigation.getAppsNavigationRaw(), + (final response) => response.body.ocs.data.toList(), ); } diff --git a/packages/neon/neon/lib/src/blocs/capabilities.dart b/packages/neon/neon/lib/src/blocs/capabilities.dart index a2f91e95..f67a1d43 100644 --- a/packages/neon/neon/lib/src/blocs/capabilities.dart +++ b/packages/neon/neon/lib/src/blocs/capabilities.dart @@ -39,12 +39,12 @@ class CapabilitiesBloc extends InteractiveBloc implements CapabilitiesBlocEvents @override Future refresh() async { await RequestManager.instance.wrapNextcloud( + CoreOcsGetCapabilitiesResponseApplicationJson, void>( _account.id, 'capabilities', capabilities, - () async => _account.client.core.ocs.getCapabilities(), - (final response) => response.ocs.data, + _account.client.core.ocs.getCapabilitiesRaw(), + (final response) => response.body.ocs.data, ); } } diff --git a/packages/neon/neon/lib/src/blocs/login_check_account.dart b/packages/neon/neon/lib/src/blocs/login_check_account.dart index 337b3e56..1d1b7bf0 100644 --- a/packages/neon/neon/lib/src/blocs/login_check_account.dart +++ b/packages/neon/neon/lib/src/blocs/login_check_account.dart @@ -59,7 +59,7 @@ class LoginCheckAccountBloc extends InteractiveBloc final account = Account( serverURL: serverURL, - username: response.ocs.data.id, + username: response.body.ocs.data.id, password: password, userAgent: neonUserAgent, ); diff --git a/packages/neon/neon/lib/src/blocs/login_check_server_status.dart b/packages/neon/neon/lib/src/blocs/login_check_server_status.dart index 1f7eeb4d..73a42f57 100644 --- a/packages/neon/neon/lib/src/blocs/login_check_server_status.dart +++ b/packages/neon/neon/lib/src/blocs/login_check_server_status.dart @@ -47,7 +47,7 @@ class LoginCheckServerStatusBloc extends InteractiveBloc ); final status = await client.core.getStatus(); - state.add(Result.success(status)); + state.add(Result.success(status.body)); } catch (e, s) { debugPrint(e.toString()); debugPrint(s.toString()); diff --git a/packages/neon/neon/lib/src/blocs/login_flow.dart b/packages/neon/neon/lib/src/blocs/login_flow.dart index a0d3e892..2f640bdd 100644 --- a/packages/neon/neon/lib/src/blocs/login_flow.dart +++ b/packages/neon/neon/lib/src/blocs/login_flow.dart @@ -54,14 +54,14 @@ class LoginFlowBloc extends InteractiveBloc implements LoginFlowBlocEvents, Logi init.add(Result.loading()); final initResponse = await _client.core.clientFlowLoginV2.init(); - init.add(Result.success(initResponse)); + init.add(Result.success(initResponse.body)); _cancelPollTimer(); _pollTimer = Timer.periodic(const Duration(seconds: 1), (final _) async { try { - final resultResponse = await _client.core.clientFlowLoginV2.poll(token: initResponse.poll.token); + final resultResponse = await _client.core.clientFlowLoginV2.poll(token: initResponse.body.poll.token); _cancelPollTimer(); - _resultController.add(resultResponse); + _resultController.add(resultResponse.body); } catch (e, s) { debugPrint(e.toString()); debugPrint(s.toString()); diff --git a/packages/neon/neon/lib/src/blocs/next_push.dart b/packages/neon/neon/lib/src/blocs/next_push.dart index 0e9184f1..79ad6e62 100644 --- a/packages/neon/neon/lib/src/blocs/next_push.dart +++ b/packages/neon/neon/lib/src/blocs/next_push.dart @@ -46,7 +46,8 @@ class NextPushBloc extends Bloc implements NextPushBlocEvents, NextPushBlocState for (final account in _accountsBloc.accounts.value) { if (!_supported.containsKey(account)) { try { - _supported[account] = (await account.client.uppush.check()).success; + final response = await account.client.uppush.check(); + _supported[account] = response.body.success; } catch (e, s) { debugPrint(e.toString()); debugPrint(s.toString()); diff --git a/packages/neon/neon/lib/src/blocs/push_notifications.dart b/packages/neon/neon/lib/src/blocs/push_notifications.dart index bc5c7051..9571bb53 100644 --- a/packages/neon/neon/lib/src/blocs/push_notifications.dart +++ b/packages/neon/neon/lib/src/blocs/push_notifications.dart @@ -96,7 +96,7 @@ class PushNotificationsBloc extends Bloc implements PushNotificationsBlocEvents, await _storage.setString(_keyLastEndpoint(account), endpoint); debugPrint( - 'Account $instance registered for push notifications ${json.encode(subscription.ocs.data.toJson())}', + 'Account $instance registered for push notifications ${json.encode(subscription.body.ocs.data.toJson())}', ); }, onMessage: PushUtils.onMessage, diff --git a/packages/neon/neon/lib/src/blocs/unified_search.dart b/packages/neon/neon/lib/src/blocs/unified_search.dart index a20e59ad..e99933ab 100644 --- a/packages/neon/neon/lib/src/blocs/unified_search.dart +++ b/packages/neon/neon/lib/src/blocs/unified_search.dart @@ -88,7 +88,8 @@ class UnifiedSearchBloc extends InteractiveBloc implements UnifiedSearchBlocEven try { results.add(results.value.asLoading()); - final providers = (await _account.client.core.unifiedSearch.getProviders()).ocs.data; + final response = await _account.client.core.unifiedSearch.getProviders(); + final providers = response.body.ocs.data; results.add( Result.success(Map.fromEntries(_getLoadingProviders(providers))), ); @@ -117,7 +118,7 @@ class UnifiedSearchBloc extends InteractiveBloc implements UnifiedSearchBlocEven providerId: provider.id, term: _term, ); - _updateResults(provider, Result.success(response.ocs.data)); + _updateResults(provider, Result.success(response.body.ocs.data)); } catch (e, s) { debugPrint(e.toString()); debugPrint(s.toString()); diff --git a/packages/neon/neon/lib/src/blocs/user_details.dart b/packages/neon/neon/lib/src/blocs/user_details.dart index d109406b..2336ab9c 100644 --- a/packages/neon/neon/lib/src/blocs/user_details.dart +++ b/packages/neon/neon/lib/src/blocs/user_details.dart @@ -39,12 +39,12 @@ class UserDetailsBloc extends InteractiveBloc implements UserDetailsBlocEvents, @override Future refresh() async { await RequestManager.instance - .wrapNextcloud( + .wrapNextcloud( _account.id, 'user-details', userDetails, - () async => _account.client.provisioningApi.users.getCurrentUser(), - (final response) => response.ocs.data, + _account.client.provisioningApi.users.getCurrentUserRaw(), + (final response) => response.body.ocs.data, ); } } diff --git a/packages/neon/neon/lib/src/blocs/user_statuses.dart b/packages/neon/neon/lib/src/blocs/user_statuses.dart index 5cf0dd3b..eee802de 100644 --- a/packages/neon/neon/lib/src/blocs/user_statuses.dart +++ b/packages/neon/neon/lib/src/blocs/user_statuses.dart @@ -73,7 +73,7 @@ class UserStatusesBloc extends InteractiveBloc implements UserStatusesBlocEvents final response = await _account.client.userStatus.heartbeat.heartbeat( status: isAway ? 'away' : 'online', ); - data = response.ocs.data; + data = response.body.ocs.data; } catch (e) { // 204 is returned if the heartbeat failed because the current status is different. Ignore this and fetch the normal status if (e is! DynamiteApiException || e.statusCode != 204) { @@ -84,7 +84,7 @@ class UserStatusesBloc extends InteractiveBloc implements UserStatusesBlocEvents if (data == null) { final response = await _account.client.userStatus.statuses.find(userId: username); - data = response.ocs.data; + data = response.body.ocs.data; } _updateStatus(username, Result.success(data)); diff --git a/packages/neon/neon/lib/src/pages/home.dart b/packages/neon/neon/lib/src/pages/home.dart index 2ff64712..a66a881a 100644 --- a/packages/neon/neon/lib/src/pages/home.dart +++ b/packages/neon/neon/lib/src/pages/home.dart @@ -82,7 +82,7 @@ class _HomePageState extends State { Future _checkMaintenanceMode() async { try { final status = await _account.client.core.getStatus(); - if (status.maintenance && mounted) { + if (status.body.maintenance && mounted) { await _showProblem( AppLocalizations.of(context).errorServerInMaintenanceMode, ); diff --git a/packages/neon/neon/lib/src/utils/push_utils.dart b/packages/neon/neon/lib/src/utils/push_utils.dart index 0880f97c..49a99188 100644 --- a/packages/neon/neon/lib/src/utils/push_utils.dart +++ b/packages/neon/neon/lib/src/utils/push_utils.dart @@ -102,10 +102,9 @@ class PushUtils { try { account = accounts.tryFind(instance); if (account != null) { - notification = - (await account.client.notifications.endpoint.getNotification(id: pushNotification.subject.nid!)) - .ocs - .data; + final response = + await account.client.notifications.endpoint.getNotification(id: pushNotification.subject.nid!); + notification = response.body.ocs.data; if (notification.icon?.endsWith('.svg') ?? false) { // Only SVG icons are supported right now (should be most of them) diff --git a/packages/neon/neon/lib/src/utils/request_manager.dart b/packages/neon/neon/lib/src/utils/request_manager.dart index ec1b96ed..bfe5ee4e 100644 --- a/packages/neon/neon/lib/src/utils/request_manager.dart +++ b/packages/neon/neon/lib/src/utils/request_manager.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:convert'; import 'package:flutter/foundation.dart'; @@ -13,7 +14,10 @@ import 'package:xml/xml.dart' as xml; typedef UnwrapCallback = T Function(R); typedef SerializeCallback = String Function(T); typedef DeserializeCallback = T Function(String); -typedef NextcloudApiCallback = Future Function(); +typedef NextcloudApiCallback = AsyncValueGetter; + +const maxRetries = 3; +const defaultTimeout = Duration(seconds: 30); class RequestManager { RequestManager(); @@ -34,26 +38,32 @@ class RequestManager { Cache? _cache; - Future wrapNextcloud( + Future wrapNextcloud( final String clientID, final String k, final BehaviorSubject> subject, - final NextcloudApiCallback call, - final UnwrapCallback unwrap, { + final DynamiteRawResponse rawResponse, + final UnwrapCallback> unwrap, { final bool disableTimeout = false, - final bool emitEmptyCache = false, }) async => - _wrap( + _wrap>( clientID, k, subject, - call, - unwrap, - (final data) => json.encode(serializeNextcloud(data)), - (final data) => deserializeNextcloud(json.decode(data) as Object), + () async { + await rawResponse.future; + + return rawResponse; + }, + (final rawResponse) => unwrap(rawResponse.response), + (final data) => json.encode(data), + (final data) => DynamiteRawResponse.fromJson( + json.decode(data) as Map, + serializers: rawResponse.serializers, + bodyType: rawResponse.bodyType, + headersType: rawResponse.headersType, + ), disableTimeout, - emitEmptyCache, - 0, ); Future wrapWebDav( @@ -75,7 +85,6 @@ class RequestManager { (final data) => WebDavMultistatus.fromXmlElement(xml.XmlDocument.parse(data).rootElement), disableTimeout, emitEmptyCache, - 0, ); Future _wrap( @@ -85,44 +94,44 @@ class RequestManager { final NextcloudApiCallback call, final UnwrapCallback unwrap, final SerializeCallback serialize, - final DeserializeCallback deserialize, - final bool disableTimeout, - final bool emitEmptyCache, - final int retries, - ) async { - if (subject.valueOrNull?.hasData ?? false) { - subject.add( - Result( - subject.value.data, - null, - isLoading: true, - isCached: true, - ), - ); - } else { - subject.add(Result.loading()); - } + final DeserializeCallback deserialize, [ + final bool disableTimeout = false, + final bool emitEmptyCache = false, + final int retries = 0, + ]) async { + // emit loading state with the current value if present + final value = subject.valueOrNull?.copyWith(isLoading: true) ?? Result.loading(); + subject.add(value); final key = '$clientID-$k'; - await _emitCached( - key, - subject, - unwrap, - deserialize, - emitEmptyCache, - true, - null, + unawaited( + _emitCached( + key, + subject, + unwrap, + deserialize, + emitEmptyCache, + ), ); try { - final response = await (disableTimeout ? call() : timeout(call)); - await _cache?.set(key, await compute(serialize, response)); + final response = await timeout(call, disableTimeout: disableTimeout); subject.add(Result.success(unwrap(response))); + + final serialized = serialize(response); + await _cache?.set(key, serialized); + } on TimeoutException catch (e, s) { + debugPrint('Request timed out ...'); + debugPrint(e.toString()); + debugPrintStack(stackTrace: s, maxFrames: 5); + + _emitError(e, subject); } catch (e, s) { debugPrint(e.toString()); - debugPrint(s.toString()); - if (e is DynamiteApiException && e.statusCode >= 500 && retries < 3) { + debugPrintStack(stackTrace: s, maxFrames: 5); + + if (e is DynamiteApiException && e.statusCode >= 500 && retries < maxRetries) { debugPrint('Retrying...'); await _wrap( clientID, @@ -136,58 +145,79 @@ class RequestManager { emitEmptyCache, retries + 1, ); - return; - } - if (!(await _emitCached( - key, - subject, - unwrap, - deserialize, - emitEmptyCache, - false, - e, - ))) { - subject.add(Result.error(e)); + } else { + _emitError(e, subject); } } } + /// Re emits the current result with the given [error]. + /// + /// Defaults to a [Result.error] if none has been emitted yet. + void _emitError( + final Object error, + final BehaviorSubject> subject, + ) { + final value = subject.valueOrNull?.copyWith(error: error, isLoading: false) ?? Result.error(error); + subject.add(value); + } + Future _emitCached( final String key, final BehaviorSubject> subject, final UnwrapCallback unwrap, final DeserializeCallback deserialize, final bool emitEmptyCache, - final bool loading, - final Object? error, ) async { - T? cached; - try { - if (_cache != null && await _cache!.has(key)) { - cached = unwrap(await compute(deserialize, (await _cache!.get(key))!)); + if (_cache != null && await _cache!.has(key)) { + try { + final cacheValue = await _cache!.get(key); + final cached = unwrap(deserialize(cacheValue!)); + + // If the network fetch is faster than fetching the cached value the + // subject can be closed before emitting. + if (subject.value.hasUncachedData) { + return true; + } + + subject.add( + subject.value.copyWith( + data: cached, + isCached: true, + ), + ); + + return true; + } catch (e, s) { + debugPrint(e.toString()); + debugPrintStack(stackTrace: s, maxFrames: 5); } - } catch (e, s) { - debugPrint(e.toString()); - debugPrint(s.toString()); } - if (cached != null || emitEmptyCache) { + + if (emitEmptyCache && !subject.value.hasUncachedData) { subject.add( - Result( - cached, - error, - isLoading: loading, + subject.value.copyWith( isCached: true, ), ); + return true; } + return false; } Future timeout( - final NextcloudApiCallback call, - ) => - call().timeout(const Duration(seconds: 30)); + final NextcloudApiCallback call, { + final bool disableTimeout = false, + final Duration timeout = const Duration(seconds: 30), + }) { + if (disableTimeout) { + return call(); + } + + return call().timeout(timeout); + } } @internal diff --git a/packages/neon/neon/lib/src/widgets/cached_image.dart b/packages/neon/neon/lib/src/widgets/cached_image.dart index 4f393d73..08a58bb6 100644 --- a/packages/neon/neon/lib/src/widgets/cached_image.dart +++ b/packages/neon/neon/lib/src/widgets/cached_image.dart @@ -17,7 +17,7 @@ typedef ImageDownloader = FutureOr Function(); typedef CacheWriter = Future Function(CacheManager cacheManager, Uint8List image); typedef ErrorWidgetBuilder = Widget? Function(BuildContext, dynamic); -typedef ApiImageDownloader = FutureOr Function(NextcloudClient client); +typedef ApiImageDownloader = FutureOr> Function(NextcloudClient client); class NeonCachedImage extends StatefulWidget { const NeonCachedImage({ @@ -223,7 +223,10 @@ class NeonApiImage extends StatelessWidget { final account = NeonProvider.of(context).activeAccount.value!; return NeonCachedImage.custom( - getImage: () async => getImage(account.client), + getImage: () async { + final response = await getImage(account.client); + return response.body; + }, cacheKey: '${account.id}-$cacheKey', ); } diff --git a/packages/neon/neon/lib/src/widgets/user_avatar.dart b/packages/neon/neon/lib/src/widgets/user_avatar.dart index f4277785..76c7c391 100644 --- a/packages/neon/neon/lib/src/widgets/user_avatar.dart +++ b/packages/neon/neon/lib/src/widgets/user_avatar.dart @@ -64,19 +64,17 @@ class _UserAvatarState extends State { child: NeonCachedImage.custom( cacheKey: '${widget.account.id}-avatar-${widget.username}-$brightness$pixelSize', getImage: () async { - if (brightness == Brightness.dark) { - return (await widget.account.client.core.avatar.getAvatarDark( - userId: widget.username, - size: pixelSize, - )) - .data; - } else { - return (await widget.account.client.core.avatar.getAvatar( - userId: widget.username, - size: pixelSize, - )) - .data; - } + final response = switch (brightness) { + Brightness.dark => await widget.account.client.core.avatar.getAvatarDark( + userId: widget.username, + size: pixelSize, + ), + Brightness.light => await widget.account.client.core.avatar.getAvatar( + userId: widget.username, + size: pixelSize, + ), + }; + return response.body; }, ), ), diff --git a/packages/neon/neon_files/lib/blocs/browser.dart b/packages/neon/neon_files/lib/blocs/browser.dart index b644e9a7..80c97062 100644 --- a/packages/neon/neon_files/lib/blocs/browser.dart +++ b/packages/neon/neon_files/lib/blocs/browser.dart @@ -47,7 +47,7 @@ class FilesBrowserBloc extends InteractiveBloc implements FilesBrowserBlocEvents account.id, 'files-${path.value.join('/')}', files, - () async => account.client.webdav.propfind( + () => account.client.webdav.propfind( Uri(pathSegments: path.value), prop: WebDavPropWithoutValues.fromBools( davgetcontenttype: true, diff --git a/packages/neon/neon_news/lib/blocs/articles.dart b/packages/neon/neon_news/lib/blocs/articles.dart index c8ae115f..45b2c287 100644 --- a/packages/neon/neon_news/lib/blocs/articles.dart +++ b/packages/neon/neon_news/lib/blocs/articles.dart @@ -115,16 +115,16 @@ class NewsArticlesBloc extends InteractiveBloc implements NewsArticlesBlocEvents } } - await RequestManager.instance.wrapNextcloud, NewsListArticles>( + await RequestManager.instance.wrapNextcloud, NewsListArticles, void>( account.id, 'news-articles-${type.index}-$id-$getRead', articles, - () async => account.client.news.listArticles( + account.client.news.listArticlesRaw( type: type.index, id: id ?? 0, getRead: getRead ?? true ? 1 : 0, ), - (final response) => response.items.toList(), + (final response) => response.body.items.toList(), ); } diff --git a/packages/neon/neon_news/lib/blocs/news.dart b/packages/neon/neon_news/lib/blocs/news.dart index 224fec85..1f7033de 100644 --- a/packages/neon/neon_news/lib/blocs/news.dart +++ b/packages/neon/neon_news/lib/blocs/news.dart @@ -92,23 +92,23 @@ class NewsBloc extends InteractiveBloc implements NewsBlocEvents, NewsBlocStates @override Future refresh() async { await Future.wait([ - RequestManager.instance.wrapNextcloud, NewsListFolders>( + RequestManager.instance.wrapNextcloud, NewsListFolders, void>( account.id, 'news-folders', folders, - () async => account.client.news.listFolders(), - (final response) => response.folders.toList(), + account.client.news.listFoldersRaw(), + (final response) => response.body.folders.toList(), ), - RequestManager.instance.wrapNextcloud, NewsListFeeds>( + RequestManager.instance.wrapNextcloud, NewsListFeeds, void>( account.id, 'news-feeds', feeds, - () async => account.client.news.listFeeds(), + account.client.news.listFeedsRaw(), (final response) { - if (response.newestItemId != null) { - _newestItemId = response.newestItemId!; + if (response.body.newestItemId != null) { + _newestItemId = response.body.newestItemId!; } - return response.feeds.toList(); + return response.body.feeds.toList(); }, ), mainArticlesBloc.reload(), diff --git a/packages/neon/neon_notes/lib/blocs/note.dart b/packages/neon/neon_notes/lib/blocs/note.dart index de552b54..02e8b9aa 100644 --- a/packages/neon/neon_notes/lib/blocs/note.dart +++ b/packages/neon/neon_notes/lib/blocs/note.dart @@ -29,11 +29,11 @@ class NotesNoteBloc extends InteractiveBloc implements NotesNoteBlocEvents, Note } // ignore: avoid_void_async - void _wrapAction(final Future Function(String etag) call) async { + void _wrapAction(final Future> Function(String etag) call) async { await _updateQueue.add(() async { try { - final data = await call(_etag); - _emitNote(data); + final response = await call(_etag); + _emitNote(response.body); await _notesBloc.refresh(); } catch (e, s) { debugPrint(e.toString()); diff --git a/packages/neon/neon_notes/lib/blocs/notes.dart b/packages/neon/neon_notes/lib/blocs/notes.dart index 2f24714b..64e3a38f 100644 --- a/packages/neon/neon_notes/lib/blocs/notes.dart +++ b/packages/neon/neon_notes/lib/blocs/notes.dart @@ -44,12 +44,12 @@ class NotesBloc extends InteractiveBloc implements NotesBlocEvents, NotesBlocSta @override Future refresh() async { - await RequestManager.instance.wrapNextcloud, BuiltList>( + await RequestManager.instance.wrapNextcloud, BuiltList, void>( account.id, 'notes-notes', notes, - () async => account.client.notes.getNotes(), - List.from, + account.client.notes.getNotesRaw(), + (final response) => List.from(response.body), ); } diff --git a/packages/neon/neon_notifications/lib/blocs/notifications.dart b/packages/neon/neon_notifications/lib/blocs/notifications.dart index e0da4a9f..6ea611e0 100644 --- a/packages/neon/neon_notifications/lib/blocs/notifications.dart +++ b/packages/neon/neon_notifications/lib/blocs/notifications.dart @@ -50,16 +50,13 @@ class NotificationsBloc extends InteractiveBloc @override Future refresh() async { - await RequestManager.instance - .wrapNextcloud, NotificationsEndpointListNotificationsResponseApplicationJson>( + await RequestManager.instance.wrapNextcloud, + NotificationsEndpointListNotificationsResponseApplicationJson, void>( _account.id, 'notifications-notifications', notifications, - () async { - final response = await _account.client.notifications.endpoint.listNotifications(); - return response.data; - }, - (final response) => response.ocs.data.toList(), + _account.client.notifications.endpoint.listNotificationsRaw(), + (final response) => response.body.ocs.data.toList(), ); } diff --git a/packages/nextcloud/lib/src/api/comments.openapi.dart b/packages/nextcloud/lib/src/api/comments.openapi.dart index a8576d69..5200840f 100644 --- a/packages/nextcloud/lib/src/api/comments.openapi.dart +++ b/packages/nextcloud/lib/src/api/comments.openapi.dart @@ -1,53 +1,18 @@ // ignore_for_file: camel_case_types +// ignore_for_file: discarded_futures // ignore_for_file: public_member_api_docs +// ignore_for_file: unreachable_switch_case import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.dart'; import 'package:built_value/standard_json_plugin.dart'; import 'package:dynamite_runtime/content_string.dart'; import 'package:dynamite_runtime/http_client.dart'; -import 'package:universal_io/io.dart'; export 'package:dynamite_runtime/http_client.dart'; part 'comments.openapi.g.dart'; -class CommentsResponse extends DynamiteResponse { - CommentsResponse( - super.data, - super.headers, - ); - - @override - String toString() => 'CommentsResponse(data: $data, headers: $headers)'; -} - -class CommentsApiException extends DynamiteApiException { - CommentsApiException( - super.statusCode, - super.headers, - super.body, - ); - - static Future fromResponse(final HttpClientResponse response) async { - String body; - try { - body = await response.body; - } on FormatException { - body = 'binary'; - } - - return CommentsApiException( - response.statusCode, - response.responseHeaders, - body, - ); - } - - @override - String toString() => 'CommentsApiException(statusCode: $statusCode, headers: $headers, body: $body)'; -} - class CommentsClient extends DynamiteClient { CommentsClient( super.baseURL, { @@ -133,14 +98,8 @@ final Serializers _serializers = (Serializers().toBuilder() ..add(CommentsCapabilities_Files.serializer)) .build(); -Serializers get commentsSerializers => _serializers; - final Serializers _jsonSerializers = (_serializers.toBuilder() ..addPlugin(StandardJsonPlugin()) ..addPlugin(const ContentStringPlugin())) .build(); - -T deserializeComments(final Object data) => _serializers.deserialize(data, specifiedType: FullType(T))! as T; - -Object? serializeComments(final T data) => _serializers.serialize(data, specifiedType: FullType(T)); // coverage:ignore-end diff --git a/packages/nextcloud/lib/src/api/core.openapi.dart b/packages/nextcloud/lib/src/api/core.openapi.dart index 8b2086fd..317a6241 100644 --- a/packages/nextcloud/lib/src/api/core.openapi.dart +++ b/packages/nextcloud/lib/src/api/core.openapi.dart @@ -1,5 +1,8 @@ // ignore_for_file: camel_case_types +// ignore_for_file: discarded_futures // ignore_for_file: public_member_api_docs +// ignore_for_file: unreachable_switch_case +import 'dart:convert'; import 'dart:typed_data'; import 'package:built_collection/built_collection.dart'; @@ -7,50 +10,16 @@ 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'; +import 'package:collection/collection.dart'; import 'package:dynamite_runtime/content_string.dart'; import 'package:dynamite_runtime/http_client.dart'; +import 'package:meta/meta.dart'; import 'package:universal_io/io.dart'; export 'package:dynamite_runtime/http_client.dart'; part 'core.openapi.g.dart'; -class CoreResponse extends DynamiteResponse { - CoreResponse( - super.data, - super.headers, - ); - - @override - String toString() => 'CoreResponse(data: $data, headers: $headers)'; -} - -class CoreApiException extends DynamiteApiException { - CoreApiException( - super.statusCode, - super.headers, - super.body, - ); - - static Future fromResponse(final HttpClientResponse response) async { - String body; - try { - body = await response.body; - } on FormatException { - body = 'binary'; - } - - return CoreApiException( - response.statusCode, - response.responseHeaders, - body, - ); - } - - @override - String toString() => 'CoreApiException(statusCode: $statusCode, headers: $headers, body: $body)'; -} - class CoreClient extends DynamiteClient { CoreClient( super.baseURL, { @@ -108,26 +77,52 @@ class CoreClient extends DynamiteClient { CoreWipeClient get wipe => CoreWipeClient(this); - Future getStatus() async { + /// 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: Status returned + /// + /// See: + /// * [getStatusRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getStatus() async { + final rawResponse = getStatusRaw(); + + return rawResponse.future; + } + + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: Status returned + /// + /// See: + /// * [getStatus] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getStatusRaw() { const path = '/status.php'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - // coverage:ignore-end - final response = await doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize(await response.jsonBody, specifiedType: const FullType(CoreStatus))! - as CoreStatus; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreStatus), + headersType: null, + serializers: _jsonSerializers, + ); } } @@ -136,119 +131,256 @@ class CoreAppPasswordClient { final CoreClient _rootClient; - /// Create app password - Future getAppPassword({final bool oCSAPIRequest = true}) async { + /// Create app password. + /// + /// 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: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: App password returned + /// * 403: Creating app password is not allowed + /// + /// See: + /// * [getAppPasswordRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getAppPassword({ + final bool oCSAPIRequest = true, + }) async { + final rawResponse = getAppPasswordRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Create app password. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: App password returned + /// * 403: Creating app password is not allowed + /// + /// See: + /// * [getAppPassword] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getAppPasswordRaw({ + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/core/getapppassword'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreAppPasswordGetAppPasswordResponseApplicationJson), - )! as CoreAppPasswordGetAppPasswordResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreAppPasswordGetAppPasswordResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Rotate app password - Future rotateAppPassword({ + /// Rotate app password. + /// + /// 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: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: App password returned + /// * 403: Rotating app password is not allowed + /// + /// See: + /// * [rotateAppPasswordRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> rotateAppPassword({ final bool oCSAPIRequest = true, }) async { + final rawResponse = rotateAppPasswordRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Rotate app password. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: App password returned + /// * 403: Rotating app password is not allowed + /// + /// See: + /// * [rotateAppPassword] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse rotateAppPasswordRaw({ + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/core/apppassword/rotate'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreAppPasswordRotateAppPasswordResponseApplicationJson), - )! as CoreAppPasswordRotateAppPasswordResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreAppPasswordRotateAppPasswordResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Delete app password - Future deleteAppPassword({ + /// Delete app password. + /// + /// 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: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: App password deleted successfully + /// * 403: Deleting app password is not allowed + /// + /// See: + /// * [deleteAppPasswordRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> deleteAppPassword({ final bool oCSAPIRequest = true, }) async { + final rawResponse = deleteAppPasswordRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Delete app password. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: App password deleted successfully + /// * 403: Deleting app password is not allowed + /// + /// See: + /// * [deleteAppPassword] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse deleteAppPasswordRaw({ + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/core/apppassword'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreAppPasswordDeleteAppPasswordResponseApplicationJson), - )! as CoreAppPasswordDeleteAppPasswordResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'delete', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreAppPasswordDeleteAppPasswordResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } } @@ -257,8 +389,26 @@ class CoreAutoCompleteClient { final CoreClient _rootClient; - /// Autocomplete a query - Future $get({ + /// Autocomplete a query. + /// + /// 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: + /// * [search] Text to search for + /// * [itemType] Type of the items to search for + /// * [itemId] ID of the items to search for + /// * [sorter] can be piped, top prio first, e.g.: "commenters|share-recipients" + /// * [shareTypes] Types of shares to search for + /// * [limit] Maximum number of results to return + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Autocomplete results returned + /// + /// See: + /// * [$getRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> $get({ required final String search, final String? itemType, final String? itemId, @@ -267,25 +417,74 @@ class CoreAutoCompleteClient { final int limit = 10, final bool oCSAPIRequest = true, }) async { + final rawResponse = $getRaw( + search: search, + itemType: itemType, + itemId: itemId, + sorter: sorter, + shareTypes: shareTypes, + limit: limit, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Autocomplete a query. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [search] Text to search for + /// * [itemType] Type of the items to search for + /// * [itemId] ID of the items to search for + /// * [sorter] can be piped, top prio first, e.g.: "commenters|share-recipients" + /// * [shareTypes] Types of shares to search for + /// * [limit] Maximum number of results to return + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Autocomplete results returned + /// + /// See: + /// * [$get] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse $getRaw({ + required final String search, + final String? itemType, + final String? itemId, + final String? sorter, + final List? shareTypes, + final int limit = 10, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/core/autocomplete/get'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['search'] = search; if (itemType != null) { queryParameters['itemType'] = itemType; @@ -303,110 +502,202 @@ class CoreAutoCompleteClient { queryParameters['limit'] = limit.toString(); } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreAutoCompleteGetResponseApplicationJson), - )! as CoreAutoCompleteGetResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreAutoCompleteGetResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } } -/// Class AvatarController +/// Class AvatarController. class CoreAvatarClient { CoreAvatarClient(this._rootClient); final CoreClient _rootClient; - /// Get the dark avatar - Future> getAvatarDark({ + /// Get the dark avatar. + /// + /// 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: + /// * [userId] ID of the user + /// * [size] Size of the avatar + /// + /// Status codes: + /// * 200: Avatar returned + /// * 404: Avatar not found + /// + /// See: + /// * [getAvatarDarkRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getAvatarDark({ required final String userId, required final int size, }) async { + final rawResponse = getAvatarDarkRaw( + userId: userId, + size: size, + ); + + return rawResponse.future; + } + + /// Get the dark avatar. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [userId] ID of the user + /// * [size] Size of the avatar + /// + /// Status codes: + /// * 200: Avatar returned + /// * 404: Avatar not found + /// + /// See: + /// * [getAvatarDark] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getAvatarDarkRaw({ + required final String userId, + required final int size, + }) { var path = '/index.php/avatar/{userId}/{size}/dark'; final queryParameters = {}; final headers = { 'Accept': '*/*', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{userId}', Uri.encodeQueryComponent(userId)); path = path.replaceAll('{size}', Uri.encodeQueryComponent(size.toString())); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return CoreResponse( - await response.bodyBytes, - _jsonSerializers.deserialize( - response.responseHeaders, - specifiedType: const FullType(CoreAvatarAvatarGetAvatarDarkHeaders), - )! as CoreAvatarAvatarGetAvatarDarkHeaders, - ); - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(Uint8List), + headersType: const FullType(CoreAvatarAvatarGetAvatarDarkHeaders), + serializers: _jsonSerializers, + ); } - /// Get the avatar - Future> getAvatar({ + /// Get the avatar. + /// + /// 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: + /// * [userId] ID of the user + /// * [size] Size of the avatar + /// + /// Status codes: + /// * 200: Avatar returned + /// * 404: Avatar not found + /// + /// See: + /// * [getAvatarRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getAvatar({ required final String userId, required final int size, }) async { + final rawResponse = getAvatarRaw( + userId: userId, + size: size, + ); + + return rawResponse.future; + } + + /// Get the avatar. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [userId] ID of the user + /// * [size] Size of the avatar + /// + /// Status codes: + /// * 200: Avatar returned + /// * 404: Avatar not found + /// + /// See: + /// * [getAvatar] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getAvatarRaw({ + required final String userId, + required final int size, + }) { var path = '/index.php/avatar/{userId}/{size}'; final queryParameters = {}; final headers = { 'Accept': '*/*', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{userId}', Uri.encodeQueryComponent(userId)); path = path.replaceAll('{size}', Uri.encodeQueryComponent(size.toString())); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return CoreResponse( - await response.bodyBytes, - _jsonSerializers.deserialize( - response.responseHeaders, - specifiedType: const FullType(CoreAvatarAvatarGetAvatarHeaders), - )! as CoreAvatarAvatarGetAvatarHeaders, - ); - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(Uint8List), + headersType: const FullType(CoreAvatarAvatarGetAvatarHeaders), + serializers: _jsonSerializers, + ); } } @@ -415,71 +706,149 @@ class CoreClientFlowLoginV2Client { final CoreClient _rootClient; - /// Poll the login flow credentials - Future poll({required final String token}) async { + /// Poll the login flow credentials. + /// + /// 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: + /// * [token] Token of the flow + /// + /// Status codes: + /// * 200: Login flow credentials returned + /// * 404: Login flow not found or completed + /// + /// See: + /// * [pollRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> poll({required final String token}) async { + final rawResponse = pollRaw( + token: token, + ); + + return rawResponse.future; + } + + /// Poll the login flow credentials. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [token] Token of the flow + /// + /// Status codes: + /// * 200: Login flow credentials returned + /// * 404: Login flow not found or completed + /// + /// See: + /// * [poll] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse pollRaw({required final String token}) { const path = '/index.php/login/v2/poll'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['token'] = token; - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreLoginFlowV2Credentials), - )! as CoreLoginFlowV2Credentials; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreLoginFlowV2Credentials), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Init a login flow - Future init() async { + /// Init a login flow. + /// + /// 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: Login flow init returned + /// + /// See: + /// * [initRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> init() async { + final rawResponse = initRaw(); + + return rawResponse.future; + } + + /// Init a login flow. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: Login flow init returned + /// + /// See: + /// * [init] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse initRaw() { const path = '/index.php/login/v2'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } - // coverage:ignore-end - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize(await response.jsonBody, specifiedType: const FullType(CoreLoginFlowV2))! - as CoreLoginFlowV2; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + +// coverage:ignore-end + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreLoginFlowV2), + headersType: null, + serializers: _jsonSerializers, + ); } } @@ -488,307 +857,698 @@ class CoreCollaborationResourcesClient { final CoreClient _rootClient; - /// Search for collections - Future searchCollections({ + /// Search for collections. + /// + /// 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: + /// * [filter] Filter collections + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Collections returned + /// * 404: Collection not found + /// + /// See: + /// * [searchCollectionsRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> searchCollections({ required final String filter, final bool oCSAPIRequest = true, }) async { + final rawResponse = searchCollectionsRaw( + filter: filter, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Search for collections. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [filter] Filter collections + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Collections returned + /// * 404: Collection not found + /// + /// See: + /// * [searchCollections] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse searchCollectionsRaw({ + required final String filter, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/collaboration/resources/collections/search/{filter}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{filter}', Uri.encodeQueryComponent(filter)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreCollaborationResourcesSearchCollectionsResponseApplicationJson), - )! as CoreCollaborationResourcesSearchCollectionsResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreCollaborationResourcesSearchCollectionsResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Get a collection - Future listCollection({ + /// Get a collection. + /// + /// 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: + /// * [collectionId] ID of the collection + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Collection returned + /// * 404: Collection not found + /// * 500 + /// + /// See: + /// * [listCollectionRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> listCollection({ required final int collectionId, final bool oCSAPIRequest = true, }) async { + final rawResponse = listCollectionRaw( + collectionId: collectionId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get a collection. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [collectionId] ID of the collection + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Collection returned + /// * 404: Collection not found + /// * 500 + /// + /// See: + /// * [listCollection] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse listCollectionRaw({ + required final int collectionId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/collaboration/resources/collections/{collectionId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{collectionId}', Uri.encodeQueryComponent(collectionId.toString())); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreCollaborationResourcesListCollectionResponseApplicationJson), - )! as CoreCollaborationResourcesListCollectionResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreCollaborationResourcesListCollectionResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Rename a collection - Future renameCollection({ + /// Rename a collection. + /// + /// 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: + /// * [collectionName] New name + /// * [collectionId] ID of the collection + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Collection returned + /// * 404: Collection not found + /// * 500 + /// + /// See: + /// * [renameCollectionRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> renameCollection({ required final String collectionName, required final int collectionId, final bool oCSAPIRequest = true, }) async { + final rawResponse = renameCollectionRaw( + collectionName: collectionName, + collectionId: collectionId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Rename a collection. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [collectionName] New name + /// * [collectionId] ID of the collection + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Collection returned + /// * 404: Collection not found + /// * 500 + /// + /// See: + /// * [renameCollection] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse renameCollectionRaw({ + required final String collectionName, + required final int collectionId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/collaboration/resources/collections/{collectionId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['collectionName'] = collectionName; path = path.replaceAll('{collectionId}', Uri.encodeQueryComponent(collectionId.toString())); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'put', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreCollaborationResourcesRenameCollectionResponseApplicationJson), - )! as CoreCollaborationResourcesRenameCollectionResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'put', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreCollaborationResourcesRenameCollectionResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Add a resource to a collection - Future addResource({ + /// Add a resource to a collection. + /// + /// 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: + /// * [resourceType] Name of the resource + /// * [resourceId] ID of the resource + /// * [collectionId] ID of the collection + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Collection returned + /// * 404: Collection not found or resource inaccessible + /// * 500 + /// + /// See: + /// * [addResourceRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> addResource({ required final String resourceType, required final String resourceId, required final int collectionId, final bool oCSAPIRequest = true, }) async { + final rawResponse = addResourceRaw( + resourceType: resourceType, + resourceId: resourceId, + collectionId: collectionId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Add a resource to a collection. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [resourceType] Name of the resource + /// * [resourceId] ID of the resource + /// * [collectionId] ID of the collection + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Collection returned + /// * 404: Collection not found or resource inaccessible + /// * 500 + /// + /// See: + /// * [addResource] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse addResourceRaw({ + required final String resourceType, + required final String resourceId, + required final int collectionId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/collaboration/resources/collections/{collectionId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['resourceType'] = resourceType; queryParameters['resourceId'] = resourceId; path = path.replaceAll('{collectionId}', Uri.encodeQueryComponent(collectionId.toString())); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreCollaborationResourcesAddResourceResponseApplicationJson), - )! as CoreCollaborationResourcesAddResourceResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreCollaborationResourcesAddResourceResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Remove a resource from a collection - Future removeResource({ + /// Remove a resource from a collection. + /// + /// 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: + /// * [resourceType] Name of the resource + /// * [resourceId] ID of the resource + /// * [collectionId] ID of the collection + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Collection returned + /// * 404: Collection or resource not found + /// * 500 + /// + /// See: + /// * [removeResourceRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> removeResource({ required final String resourceType, required final String resourceId, required final int collectionId, final bool oCSAPIRequest = true, }) async { + final rawResponse = removeResourceRaw( + resourceType: resourceType, + resourceId: resourceId, + collectionId: collectionId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Remove a resource from a collection. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [resourceType] Name of the resource + /// * [resourceId] ID of the resource + /// * [collectionId] ID of the collection + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Collection returned + /// * 404: Collection or resource not found + /// * 500 + /// + /// See: + /// * [removeResource] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse removeResourceRaw({ + required final String resourceType, + required final String resourceId, + required final int collectionId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/collaboration/resources/collections/{collectionId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['resourceType'] = resourceType; queryParameters['resourceId'] = resourceId; path = path.replaceAll('{collectionId}', Uri.encodeQueryComponent(collectionId.toString())); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreCollaborationResourcesRemoveResourceResponseApplicationJson), - )! as CoreCollaborationResourcesRemoveResourceResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'delete', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreCollaborationResourcesRemoveResourceResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Get collections by resource - Future getCollectionsByResource({ + /// Get collections by resource. + /// + /// 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: + /// * [resourceType] Type of the resource + /// * [resourceId] ID of the resource + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Collections returned + /// * 404: Resource not accessible + /// + /// See: + /// * [getCollectionsByResourceRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> + getCollectionsByResource({ required final String resourceType, required final String resourceId, final bool oCSAPIRequest = true, }) async { + final rawResponse = getCollectionsByResourceRaw( + resourceType: resourceType, + resourceId: resourceId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get collections by resource. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [resourceType] Type of the resource + /// * [resourceId] ID of the resource + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Collections returned + /// * 404: Resource not accessible + /// + /// See: + /// * [getCollectionsByResource] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse + getCollectionsByResourceRaw({ + required final String resourceType, + required final String resourceId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/collaboration/resources/{resourceType}/{resourceId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{resourceType}', Uri.encodeQueryComponent(resourceType)); path = path.replaceAll('{resourceId}', Uri.encodeQueryComponent(resourceId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreCollaborationResourcesGetCollectionsByResourceResponseApplicationJson), - )! as CoreCollaborationResourcesGetCollectionsByResourceResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreCollaborationResourcesGetCollectionsByResourceResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Create a collection for a resource - Future createCollectionOnResource({ + /// Create a collection for a resource. + /// + /// 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: + /// * [name] Name of the collection + /// * [baseResourceType] Type of the base resource + /// * [baseResourceId] ID of the base resource + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Collection returned + /// * 400: Creating collection is not possible + /// * 404: Resource inaccessible + /// * 500 + /// + /// See: + /// * [createCollectionOnResourceRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> + createCollectionOnResource({ required final String name, required final String baseResourceType, required final String baseResourceId, final bool oCSAPIRequest = true, }) async { + final rawResponse = createCollectionOnResourceRaw( + name: name, + baseResourceType: baseResourceType, + baseResourceId: baseResourceId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Create a collection for a resource. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [name] Name of the collection + /// * [baseResourceType] Type of the base resource + /// * [baseResourceId] ID of the base resource + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Collection returned + /// * 400: Creating collection is not possible + /// * 404: Resource inaccessible + /// * 500 + /// + /// See: + /// * [createCollectionOnResource] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse + createCollectionOnResourceRaw({ + required final String name, + required final String baseResourceType, + required final String baseResourceId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/collaboration/resources/{baseResourceType}/{baseResourceId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['name'] = name; path = path.replaceAll('{baseResourceType}', Uri.encodeQueryComponent(baseResourceType)); path = path.replaceAll('{baseResourceId}', Uri.encodeQueryComponent(baseResourceId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreCollaborationResourcesCreateCollectionOnResourceResponseApplicationJson), - )! as CoreCollaborationResourcesCreateCollectionOnResourceResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreCollaborationResourcesCreateCollectionOnResourceResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } } @@ -798,65 +1558,174 @@ class CoreGuestAvatarClient { final CoreClient _rootClient; - /// Returns a dark guest avatar image response - Future getAvatarDark({ + /// Returns a dark guest avatar image response. + /// + /// 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: + /// * [guestName] The guest name, e.g. "Albert" + /// * [size] The desired avatar size, e.g. 64 for 64x64px + /// + /// Status codes: + /// * 200: Custom avatar returned + /// * 201: Avatar returned + /// * 500 + /// + /// See: + /// * [getAvatarDarkRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getAvatarDark({ required final String guestName, required final String size, }) async { + final rawResponse = getAvatarDarkRaw( + guestName: guestName, + size: size, + ); + + return rawResponse.future; + } + + /// Returns a dark guest avatar image response. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [guestName] The guest name, e.g. "Albert" + /// * [size] The desired avatar size, e.g. 64 for 64x64px + /// + /// Status codes: + /// * 200: Custom avatar returned + /// * 201: Avatar returned + /// * 500 + /// + /// See: + /// * [getAvatarDark] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getAvatarDarkRaw({ + required final String guestName, + required final String size, + }) { var path = '/index.php/avatar/guest/{guestName}/{size}/dark'; final queryParameters = {}; final headers = { 'Accept': '*/*', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{guestName}', Uri.encodeQueryComponent(guestName)); path = path.replaceAll('{size}', Uri.encodeQueryComponent(size)); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200 || response.statusCode == 201) { - return response.bodyBytes; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200, 201}, + ), + bodyType: const FullType(Uint8List), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Returns a guest avatar image response - Future getAvatar({ + /// Returns a guest avatar image response. + /// + /// 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: + /// * [darkTheme] Return dark avatar + /// * [guestName] The guest name, e.g. "Albert" + /// * [size] The desired avatar size, e.g. 64 for 64x64px + /// + /// Status codes: + /// * 200: Custom avatar returned + /// * 201: Avatar returned + /// * 500 + /// + /// See: + /// * [getAvatarRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getAvatar({ required final String guestName, required final String size, final int? darkTheme = 0, }) async { + final rawResponse = getAvatarRaw( + guestName: guestName, + size: size, + darkTheme: darkTheme, + ); + + return rawResponse.future; + } + + /// Returns a guest avatar image response. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [darkTheme] Return dark avatar + /// * [guestName] The guest name, e.g. "Albert" + /// * [size] The desired avatar size, e.g. 64 for 64x64px + /// + /// Status codes: + /// * 200: Custom avatar returned + /// * 201: Avatar returned + /// * 500 + /// + /// See: + /// * [getAvatar] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getAvatarRaw({ + required final String guestName, + required final String size, + final int? darkTheme = 0, + }) { var path = '/index.php/avatar/guest/{guestName}/{size}'; final queryParameters = {}; final headers = { 'Accept': '*/*', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{guestName}', Uri.encodeQueryComponent(guestName)); path = path.replaceAll('{size}', Uri.encodeQueryComponent(size)); if (darkTheme != null) { @@ -864,16 +1733,19 @@ class CoreGuestAvatarClient { queryParameters['darkTheme'] = darkTheme.toString(); } } - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200 || response.statusCode == 201) { - return response.bodyBytes; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200, 201}, + ), + bodyType: const FullType(Uint8List), + headersType: null, + serializers: _jsonSerializers, + ); } } @@ -882,45 +1754,94 @@ class CoreHoverCardClient { final CoreClient _rootClient; - /// Get the user details for a hovercard - Future getUser({ + /// Get the user details for a hovercard. + /// + /// 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: + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User details returned + /// * 404: User not found + /// + /// See: + /// * [getUserRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getUser({ required final String userId, final bool oCSAPIRequest = true, }) async { + final rawResponse = getUserRaw( + userId: userId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get the user details for a hovercard. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User details returned + /// * 404: User not found + /// + /// See: + /// * [getUser] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getUserRaw({ + required final String userId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/hovercard/v1/{userId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{userId}', Uri.encodeQueryComponent(userId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreHoverCardGetUserResponseApplicationJson), - )! as CoreHoverCardGetUserResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreHoverCardGetUserResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } } @@ -929,137 +1850,264 @@ class CoreNavigationClient { final CoreClient _rootClient; - /// Get the apps navigation - Future getAppsNavigation({ + /// Get the apps navigation. + /// + /// 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: + /// * [absolute] Rewrite URLs to absolute ones + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Apps navigation returned + /// * 304: No apps navigation changed + /// + /// See: + /// * [getAppsNavigationRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getAppsNavigation({ final int absolute = 0, final bool oCSAPIRequest = true, }) async { + final rawResponse = getAppsNavigationRaw( + absolute: absolute, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get the apps navigation. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [absolute] Rewrite URLs to absolute ones + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Apps navigation returned + /// * 304: No apps navigation changed + /// + /// See: + /// * [getAppsNavigation] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getAppsNavigationRaw({ + final int absolute = 0, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/core/navigation/apps'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end if (absolute != 0) { queryParameters['absolute'] = absolute.toString(); } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreNavigationGetAppsNavigationResponseApplicationJson), - )! as CoreNavigationGetAppsNavigationResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreNavigationGetAppsNavigationResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Get the settings navigation - Future getSettingsNavigation({ + /// Get the settings navigation. + /// + /// 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: + /// * [absolute] Rewrite URLs to absolute ones + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Apps navigation returned + /// * 304: No apps navigation changed + /// + /// See: + /// * [getSettingsNavigationRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getSettingsNavigation({ final int absolute = 0, final bool oCSAPIRequest = true, }) async { + final rawResponse = getSettingsNavigationRaw( + absolute: absolute, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get the settings navigation. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [absolute] Rewrite URLs to absolute ones + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Apps navigation returned + /// * 304: No apps navigation changed + /// + /// See: + /// * [getSettingsNavigation] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getSettingsNavigationRaw({ + final int absolute = 0, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/core/navigation/settings'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end if (absolute != 0) { queryParameters['absolute'] = absolute.toString(); } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreNavigationGetSettingsNavigationResponseApplicationJson), - )! as CoreNavigationGetSettingsNavigationResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreNavigationGetSettingsNavigationResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } } -/// Controller about the endpoint /ocm-provider/ +/// Controller about the endpoint /ocm-provider/. class CoreOcmClient { CoreOcmClient(this._rootClient); final CoreClient _rootClient; - /// generate a OCMProvider with local data and send it as DataResponse. This replaces the old PHP file ocm-provider/index.php - Future> discovery() async { + /// generate a OCMProvider with local data and send it as DataResponse. This replaces the old PHP file ocm-provider/index.php. + /// + /// 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: OCM Provider details returned + /// * 500: OCM not supported + /// + /// See: + /// * [discoveryRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> discovery() async { + final rawResponse = discoveryRaw(); + + return rawResponse.future; + } + + /// generate a OCMProvider with local data and send it as DataResponse. This replaces the old PHP file ocm-provider/index.php. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: OCM Provider details returned + /// * 500: OCM not supported + /// + /// See: + /// * [discovery] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse discoveryRaw() { const path = '/index.php/ocm-provider'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, - ); - } - // coverage:ignore-end - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return CoreResponse( - _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreOcmDiscoveryResponseApplicationJson), - )! as CoreOcmDiscoveryResponseApplicationJson, - _jsonSerializers.deserialize( - response.responseHeaders, - specifiedType: const FullType(CoreOcmOcmDiscoveryHeaders), - )! as CoreOcmOcmDiscoveryHeaders, + authentication.headers, ); } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + +// coverage:ignore-end + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreOcmDiscoveryResponseApplicationJson), + headersType: const FullType(CoreOcmOcmDiscoveryHeaders), + serializers: _jsonSerializers, + ); } } @@ -1068,39 +2116,84 @@ class CoreOcsClient { final CoreClient _rootClient; - /// Get the capabilities - Future getCapabilities({final bool oCSAPIRequest = true}) async { + /// Get the capabilities. + /// + /// 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: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Capabilities returned + /// + /// See: + /// * [getCapabilitiesRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getCapabilities({ + final bool oCSAPIRequest = true, + }) async { + final rawResponse = getCapabilitiesRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get the capabilities. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Capabilities returned + /// + /// See: + /// * [getCapabilities] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getCapabilitiesRaw({ + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/cloud/capabilities'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreOcsGetCapabilitiesResponseApplicationJson), - )! as CoreOcsGetCapabilitiesResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreOcsGetCapabilitiesResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } } @@ -1109,8 +2202,30 @@ class CorePreviewClient { final CoreClient _rootClient; - /// Get a preview by file ID - Future getPreviewByFileId({ + /// Get a preview by file ID. + /// + /// 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: + /// * [fileId] ID of the file + /// * [x] Width of the preview + /// * [y] Height of the preview + /// * [a] Whether to not crop the preview + /// * [forceIcon] Force returning an icon + /// * [mode] How to crop the image + /// * [mimeFallback] Whether to fallback to the mime icon if no preview is available + /// + /// Status codes: + /// * 200: Preview returned + /// * 400: Getting preview is not possible + /// * 403: Getting preview is not allowed + /// * 404: Preview not found + /// * 303: Redirect to the mime icon url if mimeFallback is true + /// + /// See: + /// * [getPreviewByFileIdRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getPreviewByFileId({ final int fileId = -1, final int x = 32, final int y = 32, @@ -1119,25 +2234,78 @@ class CorePreviewClient { final String mode = 'fill', final int mimeFallback = 0, }) async { + final rawResponse = getPreviewByFileIdRaw( + fileId: fileId, + x: x, + y: y, + a: a, + forceIcon: forceIcon, + mode: mode, + mimeFallback: mimeFallback, + ); + + return rawResponse.future; + } + + /// Get a preview by file ID. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [fileId] ID of the file + /// * [x] Width of the preview + /// * [y] Height of the preview + /// * [a] Whether to not crop the preview + /// * [forceIcon] Force returning an icon + /// * [mode] How to crop the image + /// * [mimeFallback] Whether to fallback to the mime icon if no preview is available + /// + /// Status codes: + /// * 200: Preview returned + /// * 400: Getting preview is not possible + /// * 403: Getting preview is not allowed + /// * 404: Preview not found + /// * 303: Redirect to the mime icon url if mimeFallback is true + /// + /// See: + /// * [getPreviewByFileId] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getPreviewByFileIdRaw({ + final int fileId = -1, + final int x = 32, + final int y = 32, + final int a = 0, + final int forceIcon = 1, + final String mode = 'fill', + final int mimeFallback = 0, + }) { const path = '/index.php/core/preview'; final queryParameters = {}; final headers = { 'Accept': '*/*', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end if (fileId != -1) { queryParameters['fileId'] = fileId.toString(); } @@ -1159,20 +2327,45 @@ class CorePreviewClient { if (mimeFallback != 0) { queryParameters['mimeFallback'] = mimeFallback.toString(); } - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return response.bodyBytes; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(Uint8List), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Get a preview by file path - Future getPreview({ + /// Get a preview by file path. + /// + /// 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: + /// * [file] Path of the file + /// * [x] Width of the preview + /// * [y] Height of the preview + /// * [a] Whether to not crop the preview + /// * [forceIcon] Force returning an icon + /// * [mode] How to crop the image + /// * [mimeFallback] Whether to fallback to the mime icon if no preview is available + /// + /// Status codes: + /// * 200: Preview returned + /// * 400: Getting preview is not possible + /// * 403: Getting preview is not allowed + /// * 404: Preview not found + /// * 303: Redirect to the mime icon url if mimeFallback is true + /// + /// See: + /// * [getPreviewRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getPreview({ final String file = '', final int x = 32, final int y = 32, @@ -1181,25 +2374,78 @@ class CorePreviewClient { final String mode = 'fill', final int mimeFallback = 0, }) async { + final rawResponse = getPreviewRaw( + file: file, + x: x, + y: y, + a: a, + forceIcon: forceIcon, + mode: mode, + mimeFallback: mimeFallback, + ); + + return rawResponse.future; + } + + /// Get a preview by file path. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [file] Path of the file + /// * [x] Width of the preview + /// * [y] Height of the preview + /// * [a] Whether to not crop the preview + /// * [forceIcon] Force returning an icon + /// * [mode] How to crop the image + /// * [mimeFallback] Whether to fallback to the mime icon if no preview is available + /// + /// Status codes: + /// * 200: Preview returned + /// * 400: Getting preview is not possible + /// * 403: Getting preview is not allowed + /// * 404: Preview not found + /// * 303: Redirect to the mime icon url if mimeFallback is true + /// + /// See: + /// * [getPreview] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getPreviewRaw({ + final String file = '', + final int x = 32, + final int y = 32, + final int a = 0, + final int forceIcon = 1, + final String mode = 'fill', + final int mimeFallback = 0, + }) { const path = '/index.php/core/preview.png'; final queryParameters = {}; final headers = { 'Accept': '*/*', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end if (file != '') { queryParameters['file'] = file; } @@ -1221,16 +2467,19 @@ class CorePreviewClient { if (mimeFallback != 0) { queryParameters['mimeFallback'] = mimeFallback.toString(); } - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return response.bodyBytes; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(Uint8List), + headersType: null, + serializers: _jsonSerializers, + ); } } @@ -1239,49 +2488,110 @@ class CoreProfileApiClient { final CoreClient _rootClient; - /// Update the visibility of a parameter - Future setVisibility({ + /// Update the visibility of a parameter. + /// + /// 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: + /// * [paramId] ID of the parameter + /// * [visibility] New visibility + /// * [targetUserId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Visibility updated successfully + /// * 400: Updating visibility is not possible + /// * 403: Not allowed to edit other users visibility + /// * 404: User not found + /// + /// See: + /// * [setVisibilityRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> setVisibility({ required final String paramId, required final String visibility, required final String targetUserId, final bool oCSAPIRequest = true, }) async { + final rawResponse = setVisibilityRaw( + paramId: paramId, + visibility: visibility, + targetUserId: targetUserId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Update the visibility of a parameter. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [paramId] ID of the parameter + /// * [visibility] New visibility + /// * [targetUserId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Visibility updated successfully + /// * 400: Updating visibility is not possible + /// * 403: Not allowed to edit other users visibility + /// * 404: User not found + /// + /// See: + /// * [setVisibility] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse setVisibilityRaw({ + required final String paramId, + required final String visibility, + required final String targetUserId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/profile/{targetUserId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['paramId'] = paramId; queryParameters['visibility'] = visibility; path = path.replaceAll('{targetUserId}', Uri.encodeQueryComponent(targetUserId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'put', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreProfileApiSetVisibilityResponseApplicationJson), - )! as CoreProfileApiSetVisibilityResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'put', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreProfileApiSetVisibilityResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } } @@ -1290,36 +2600,82 @@ class CoreReferenceClient { final CoreClient _rootClient; - /// Get a preview for a reference - Future preview({required final String referenceId}) async { + /// Get a preview for a reference. + /// + /// 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: + /// * [referenceId] the reference cache key + /// + /// Status codes: + /// * 200: Preview returned + /// * 404: Reference not found + /// + /// See: + /// * [previewRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> preview({required final String referenceId}) async { + final rawResponse = previewRaw( + referenceId: referenceId, + ); + + return rawResponse.future; + } + + /// Get a preview for a reference. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [referenceId] the reference cache key + /// + /// Status codes: + /// * 200: Preview returned + /// * 404: Reference not found + /// + /// See: + /// * [preview] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse previewRaw({required final String referenceId}) { var path = '/index.php/core/references/preview/{referenceId}'; final queryParameters = {}; final headers = { 'Accept': '*/*', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{referenceId}', Uri.encodeQueryComponent(referenceId)); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return response.bodyBytes; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(Uint8List), + headersType: null, + serializers: _jsonSerializers, + ); } } @@ -1328,118 +2684,271 @@ class CoreReferenceApiClient { final CoreClient _rootClient; - /// Resolve a reference - Future resolveOne({ + /// Resolve a reference. + /// + /// 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: + /// * [reference] Reference to resolve + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Reference returned + /// + /// See: + /// * [resolveOneRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> resolveOne({ required final String reference, final bool oCSAPIRequest = true, }) async { + final rawResponse = resolveOneRaw( + reference: reference, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Resolve a reference. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [reference] Reference to resolve + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Reference returned + /// + /// See: + /// * [resolveOne] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse resolveOneRaw({ + required final String reference, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/references/resolve'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['reference'] = reference; headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreReferenceApiResolveOneResponseApplicationJson), - )! as CoreReferenceApiResolveOneResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreReferenceApiResolveOneResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Resolve multiple references - Future resolve({ + /// Resolve multiple references. + /// + /// 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: + /// * [references] References to resolve + /// * [limit] Maximum amount of references to resolve + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: References returned + /// + /// See: + /// * [resolveRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> resolve({ required final List references, final int limit = 1, final bool oCSAPIRequest = true, }) async { + final rawResponse = resolveRaw( + references: references, + limit: limit, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Resolve multiple references. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [references] References to resolve + /// * [limit] Maximum amount of references to resolve + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: References returned + /// + /// See: + /// * [resolve] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse resolveRaw({ + required final List references, + final int limit = 1, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/references/resolve'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['references[]'] = references.map((final e) => e); if (limit != 1) { queryParameters['limit'] = limit.toString(); } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreReferenceApiResolveResponseApplicationJson), - )! as CoreReferenceApiResolveResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreReferenceApiResolveResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Extract references from a text - Future extract({ + /// Extract references from a text. + /// + /// 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: + /// * [text] Text to extract from + /// * [resolve] Resolve the references + /// * [limit] Maximum amount of references to extract + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: References returned + /// + /// See: + /// * [extractRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> extract({ required final String text, final int resolve = 0, final int limit = 1, final bool oCSAPIRequest = true, }) async { + final rawResponse = extractRaw( + text: text, + resolve: resolve, + limit: limit, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Extract references from a text. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [text] Text to extract from + /// * [resolve] Resolve the references + /// * [limit] Maximum amount of references to extract + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: References returned + /// + /// See: + /// * [extract] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse extractRaw({ + required final String text, + final int resolve = 0, + final int limit = 1, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/references/extract'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['text'] = text; if (resolve != 0) { queryParameters['resolve'] = resolve.toString(); @@ -1448,103 +2957,197 @@ class CoreReferenceApiClient { queryParameters['limit'] = limit.toString(); } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreReferenceApiExtractResponseApplicationJson), - )! as CoreReferenceApiExtractResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreReferenceApiExtractResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Get the providers - Future getProvidersInfo({ + /// Get the providers. + /// + /// 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: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Providers returned + /// + /// See: + /// * [getProvidersInfoRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getProvidersInfo({ final bool oCSAPIRequest = true, }) async { + final rawResponse = getProvidersInfoRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get the providers. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Providers returned + /// + /// See: + /// * [getProvidersInfo] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getProvidersInfoRaw({ + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/references/providers'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreReferenceApiGetProvidersInfoResponseApplicationJson), - )! as CoreReferenceApiGetProvidersInfoResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreReferenceApiGetProvidersInfoResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Touch a provider - Future touchProvider({ + /// Touch a provider. + /// + /// 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: + /// * [timestamp] Timestamp of the last usage + /// * [providerId] ID of the provider + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Provider touched + /// + /// See: + /// * [touchProviderRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> touchProvider({ required final String providerId, final int? timestamp, final bool oCSAPIRequest = true, }) async { + final rawResponse = touchProviderRaw( + providerId: providerId, + timestamp: timestamp, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Touch a provider. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [timestamp] Timestamp of the last usage + /// * [providerId] ID of the provider + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Provider touched + /// + /// See: + /// * [touchProvider] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse touchProviderRaw({ + required final String providerId, + final int? timestamp, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/references/provider/{providerId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{providerId}', Uri.encodeQueryComponent(providerId)); if (timestamp != null) { queryParameters['timestamp'] = timestamp.toString(); } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'put', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreReferenceApiTouchProviderResponseApplicationJson), - )! as CoreReferenceApiTouchProviderResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'put', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreReferenceApiTouchProviderResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } } @@ -1553,66 +3156,174 @@ class CoreTextProcessingApiClient { final CoreClient _rootClient; - /// This endpoint returns all available LanguageModel task types - Future taskTypes({final bool oCSAPIRequest = true}) async { + /// This endpoint returns all available LanguageModel task types. + /// + /// 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: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Task types returned + /// + /// See: + /// * [taskTypesRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> taskTypes({ + final bool oCSAPIRequest = true, + }) async { + final rawResponse = taskTypesRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// This endpoint returns all available LanguageModel task types. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Task types returned + /// + /// See: + /// * [taskTypes] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse taskTypesRaw({ + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/textprocessing/tasktypes'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreTextProcessingApiTaskTypesResponseApplicationJson), - )! as CoreTextProcessingApiTaskTypesResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreTextProcessingApiTaskTypesResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// This endpoint allows scheduling a language model task - Future schedule({ + /// This endpoint allows scheduling a language model task. + /// + /// 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: + /// * [input] Input text + /// * [type] Type of the task + /// * [appId] ID of the app that will execute the task + /// * [identifier] An arbitrary identifier for the task + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Task scheduled successfully + /// * 400: Scheduling task is not possible + /// * 412: Scheduling task is not possible + /// + /// See: + /// * [scheduleRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> schedule({ required final String input, required final String type, required final String appId, final String identifier = '', final bool oCSAPIRequest = true, }) async { + final rawResponse = scheduleRaw( + input: input, + type: type, + appId: appId, + identifier: identifier, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// This endpoint allows scheduling a language model task. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [input] Input text + /// * [type] Type of the task + /// * [appId] ID of the app that will execute the task + /// * [identifier] An arbitrary identifier for the task + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Task scheduled successfully + /// * 400: Scheduling task is not possible + /// * 412: Scheduling task is not possible + /// + /// See: + /// * [schedule] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse scheduleRaw({ + required final String input, + required final String type, + required final String appId, + final String identifier = '', + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/textprocessing/schedule'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['input'] = input; queryParameters['type'] = type; queryParameters['appId'] = appId; @@ -1620,144 +3331,299 @@ class CoreTextProcessingApiClient { queryParameters['identifier'] = identifier; } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreTextProcessingApiScheduleResponseApplicationJson), - )! as CoreTextProcessingApiScheduleResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreTextProcessingApiScheduleResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } /// This endpoint allows checking the status and results of a task. Tasks are removed 1 week after receiving their last update. - Future getTask({ + /// + /// 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 task + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Task returned + /// * 404: Task not found + /// * 500 + /// + /// See: + /// * [getTaskRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getTask({ required final int id, final bool oCSAPIRequest = true, }) async { + final rawResponse = getTaskRaw( + id: id, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// This endpoint allows checking the status and results of a task. Tasks are removed 1 week after receiving their last update. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [id] The id of the task + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Task returned + /// * 404: Task not found + /// * 500 + /// + /// See: + /// * [getTask] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getTaskRaw({ + required final int id, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/textprocessing/task/{id}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{id}', Uri.encodeQueryComponent(id.toString())); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreTextProcessingApiGetTaskResponseApplicationJson), - )! as CoreTextProcessingApiGetTaskResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreTextProcessingApiGetTaskResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// This endpoint allows to delete a scheduled task for a user - Future deleteTask({ + /// This endpoint allows to delete a scheduled task for a 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. + /// + /// Parameters: + /// * [id] The id of the task + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Task returned + /// * 404: Task not found + /// * 500 + /// + /// See: + /// * [deleteTaskRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> deleteTask({ required final int id, final bool oCSAPIRequest = true, }) async { + final rawResponse = deleteTaskRaw( + id: id, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// This endpoint allows to delete a scheduled task for a user. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [id] The id of the task + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Task returned + /// * 404: Task not found + /// * 500 + /// + /// See: + /// * [deleteTask] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse deleteTaskRaw({ + required final int id, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/textprocessing/task/{id}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{id}', Uri.encodeQueryComponent(id.toString())); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreTextProcessingApiDeleteTaskResponseApplicationJson), - )! as CoreTextProcessingApiDeleteTaskResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'delete', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreTextProcessingApiDeleteTaskResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// This endpoint returns a list of tasks of a user that are related with a specific appId and optionally with an identifier - Future listTasksByApp({ + /// This endpoint returns a list of tasks of a user that are related with a specific appId and optionally with an identifier. + /// + /// 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: + /// * [identifier] An arbitrary identifier for the task + /// * [appId] ID of the app + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Task list returned + /// * 500 + /// + /// See: + /// * [listTasksByAppRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> listTasksByApp({ required final String appId, final String? identifier, final bool oCSAPIRequest = true, }) async { + final rawResponse = listTasksByAppRaw( + appId: appId, + identifier: identifier, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// This endpoint returns a list of tasks of a user that are related with a specific appId and optionally with an identifier. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [identifier] An arbitrary identifier for the task + /// * [appId] ID of the app + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Task list returned + /// * 500 + /// + /// See: + /// * [listTasksByApp] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse listTasksByAppRaw({ + required final String appId, + final String? identifier, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/textprocessing/tasks/app/{appId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{appId}', Uri.encodeQueryComponent(appId)); if (identifier != null) { queryParameters['identifier'] = identifier; } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreTextProcessingApiListTasksByAppResponseApplicationJson), - )! as CoreTextProcessingApiListTasksByAppResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreTextProcessingApiListTasksByAppResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } } @@ -1766,84 +3632,190 @@ class CoreTranslationApiClient { final CoreClient _rootClient; - /// Get the list of supported languages - Future languages({final bool oCSAPIRequest = true}) async { + /// Get the list of supported languages. + /// + /// 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: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Supported languages returned + /// + /// See: + /// * [languagesRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> languages({ + final bool oCSAPIRequest = true, + }) async { + final rawResponse = languagesRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get the list of supported languages. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Supported languages returned + /// + /// See: + /// * [languages] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse languagesRaw({ + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/translation/languages'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreTranslationApiLanguagesResponseApplicationJson), - )! as CoreTranslationApiLanguagesResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreTranslationApiLanguagesResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Translate a text - Future translate({ + /// Translate a text. + /// + /// 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: + /// * [text] Text to be translated + /// * [fromLanguage] Language to translate from + /// * [toLanguage] Language to translate to + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Translated text returned + /// * 400: Language not detected or unable to translate + /// * 412: Translating is not possible + /// * 500 + /// + /// See: + /// * [translateRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> translate({ required final String text, required final String toLanguage, final String? fromLanguage, final bool oCSAPIRequest = true, }) async { + final rawResponse = translateRaw( + text: text, + toLanguage: toLanguage, + fromLanguage: fromLanguage, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Translate a text. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [text] Text to be translated + /// * [fromLanguage] Language to translate from + /// * [toLanguage] Language to translate to + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Translated text returned + /// * 400: Language not detected or unable to translate + /// * 412: Translating is not possible + /// * 500 + /// + /// See: + /// * [translate] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse translateRaw({ + required final String text, + required final String toLanguage, + final String? fromLanguage, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/translation/translate'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['text'] = text; queryParameters['toLanguage'] = toLanguage; if (fromLanguage != null) { queryParameters['fromLanguage'] = fromLanguage; } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreTranslationApiTranslateResponseApplicationJson), - )! as CoreTranslationApiTranslateResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreTranslationApiTranslateResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } } @@ -1852,51 +3824,117 @@ class CoreUnifiedSearchClient { final CoreClient _rootClient; - /// Get the providers for unified search - Future getProviders({ + /// Get the providers for unified search. + /// + /// 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: + /// * [from] the url the user is currently at + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Providers returned + /// + /// See: + /// * [getProvidersRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getProviders({ final String from = '', final bool oCSAPIRequest = true, }) async { + final rawResponse = getProvidersRaw( + from: from, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get the providers for unified search. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [from] the url the user is currently at + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Providers returned + /// + /// See: + /// * [getProviders] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getProvidersRaw({ + final String from = '', + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/search/providers'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end if (from != '') { queryParameters['from'] = from; } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreUnifiedSearchGetProvidersResponseApplicationJson), - )! as CoreUnifiedSearchGetProvidersResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreUnifiedSearchGetProvidersResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Search - Future search({ + /// Search. + /// + /// 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: + /// * [term] Term to search + /// * [sortOrder] Order of entries + /// * [limit] Maximum amount of entries + /// * [cursor] Offset for searching + /// * [from] The current user URL + /// * [providerId] ID of the provider + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Search entries returned + /// * 400: Searching is not possible + /// + /// See: + /// * [searchRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> search({ required final String providerId, final String term = '', final int? sortOrder, @@ -1905,25 +3943,75 @@ class CoreUnifiedSearchClient { final String from = '', final bool oCSAPIRequest = true, }) async { + final rawResponse = searchRaw( + providerId: providerId, + term: term, + sortOrder: sortOrder, + limit: limit, + cursor: cursor, + from: from, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Search. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [term] Term to search + /// * [sortOrder] Order of entries + /// * [limit] Maximum amount of entries + /// * [cursor] Offset for searching + /// * [from] The current user URL + /// * [providerId] ID of the provider + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Search entries returned + /// * 400: Searching is not possible + /// + /// See: + /// * [search] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse searchRaw({ + required final String providerId, + final String term = '', + final int? sortOrder, + final int? limit, + final ContentString? cursor, + final String from = '', + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/search/providers/{providerId}/search'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{providerId}', Uri.encodeQueryComponent(providerId)); if (term != '') { queryParameters['term'] = term; @@ -1944,19 +4032,19 @@ class CoreUnifiedSearchClient { queryParameters['from'] = from; } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreUnifiedSearchSearchResponseApplicationJson), - )! as CoreUnifiedSearchSearchResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreUnifiedSearchSearchResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } } @@ -1965,82 +4053,174 @@ class CoreWhatsNewClient { final CoreClient _rootClient; - /// Get the changes - Future $get({final bool oCSAPIRequest = true}) async { + /// Get the changes. + /// + /// 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: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Changes returned + /// * 204: No changes + /// + /// See: + /// * [$getRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> $get({final bool oCSAPIRequest = true}) async { + final rawResponse = $getRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get the changes. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Changes returned + /// * 204: No changes + /// + /// See: + /// * [$get] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse $getRaw({final bool oCSAPIRequest = true}) { const path = '/ocs/v2.php/core/whatsnew'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreWhatsNewGetResponseApplicationJson), - )! as CoreWhatsNewGetResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreWhatsNewGetResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Dismiss the changes - Future dismiss({ + /// Dismiss the changes. + /// + /// 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: + /// * [version] Version to dismiss the changes for + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Changes dismissed + /// * 500 + /// + /// See: + /// * [dismissRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> dismiss({ required final String version, final bool oCSAPIRequest = true, }) async { + final rawResponse = dismissRaw( + version: version, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Dismiss the changes. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [version] Version to dismiss the changes for + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Changes dismissed + /// * 500 + /// + /// See: + /// * [dismiss] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse dismissRaw({ + required final String version, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/core/whatsnew'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['version'] = version; headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreWhatsNewDismissResponseApplicationJson), - )! as CoreWhatsNewDismissResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreWhatsNewDismissResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } } @@ -2049,71 +4229,162 @@ class CoreWipeClient { final CoreClient _rootClient; - /// Check if the device should be wiped - Future checkWipe({required final String token}) async { + /// Check if the device should be wiped. + /// + /// 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: + /// * [token] App password + /// + /// Status codes: + /// * 200: Device should be wiped + /// * 404: Device should not be wiped + /// + /// See: + /// * [checkWipeRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> checkWipe({ + required final String token, + }) async { + final rawResponse = checkWipeRaw( + token: token, + ); + + return rawResponse.future; + } + + /// Check if the device should be wiped. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [token] App password + /// + /// Status codes: + /// * 200: Device should be wiped + /// * 404: Device should not be wiped + /// + /// See: + /// * [checkWipe] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse checkWipeRaw({required final String token}) { const path = '/index.php/core/wipe/check'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['token'] = token; - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(CoreWipeCheckWipeResponseApplicationJson), - )! as CoreWipeCheckWipeResponseApplicationJson; - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(CoreWipeCheckWipeResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); + } + + /// Finish the wipe. + /// + /// 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: + /// * [token] App password + /// + /// Status codes: + /// * 200: Wipe finished successfully + /// * 404: Device should not be wiped + /// + /// See: + /// * [wipeDoneRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> wipeDone({required final String token}) async { + final rawResponse = wipeDoneRaw( + token: token, + ); + + return rawResponse.future; } - /// Finish the wipe - Future wipeDone({required final String token}) async { + /// Finish the wipe. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [token] App password + /// + /// Status codes: + /// * 200: Wipe finished successfully + /// * 404: Device should not be wiped + /// + /// See: + /// * [wipeDone] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse wipeDoneRaw({required final String token}) { const path = '/index.php/core/wipe/success'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['token'] = token; - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200 || response.statusCode == 404) { - return JsonObject(await response.body); - } - throw await CoreApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200, 404}, + ), + bodyType: const FullType(JsonObject), + headersType: null, + serializers: _jsonSerializers, + ); } } @@ -2630,7 +4901,8 @@ class _$CoreAvatarAvatarGetAvatarDarkHeadersSerializer final value = iterator.current! as String; switch (key) { case 'x-nc-iscustomavatar': - result.xNcIscustomavatar = int.parse(value); + result.xNcIscustomavatar = + _jsonSerializers.deserialize(json.decode(value), specifiedType: const FullType(int))! as int; } } @@ -2703,7 +4975,8 @@ class _$CoreAvatarAvatarGetAvatarHeadersSerializer implements StructuredSerializ final value = iterator.current! as String; switch (key) { case 'x-nc-iscustomavatar': - result.xNcIscustomavatar = int.parse(value); + result.xNcIscustomavatar = + _jsonSerializers.deserialize(json.decode(value), specifiedType: const FullType(int))! as int; } } @@ -3587,10 +5860,10 @@ class _$CoreNavigationEntry_OrderSerializer implements PrimitiveSerializer x != null).isNotEmpty, 'Need oneOf for ${result._data}'); return result.build(); @@ -3837,7 +6110,10 @@ class _$CoreOcmOcmDiscoveryHeadersSerializer implements StructuredSerializer x != null).isNotEmpty, 'Need oneOf for ${result._data}'); return result.build(); @@ -7569,10 +9845,10 @@ class _$CoreUnifiedSearchResult_CursorSerializer implements PrimitiveSerializer< }) { final result = CoreUnifiedSearchResult_CursorBuilder()..data = JsonObject(data); try { - result._$int = data as int?; + result._$int = _jsonSerializers.deserialize(data, specifiedType: const FullType(int))! as int; } catch (_) {} try { - result._string = data as String?; + result._string = _jsonSerializers.deserialize(data, specifiedType: const FullType(String))! as String; } catch (_) {} assert([result._$int, result._string].where((final x) => x != null).isNotEmpty, 'Need oneOf for ${result._data}'); return result.build(); @@ -8643,14 +10919,8 @@ final Serializers _serializers = (Serializers().toBuilder() ..add(CoreWipeCheckWipeResponseApplicationJson.serializer)) .build(); -Serializers get coreSerializers => _serializers; - final Serializers _jsonSerializers = (_serializers.toBuilder() ..addPlugin(StandardJsonPlugin()) ..addPlugin(const ContentStringPlugin())) .build(); - -T deserializeCore(final Object data) => _serializers.deserialize(data, specifiedType: FullType(T))! as T; - -Object? serializeCore(final T data) => _serializers.serialize(data, specifiedType: FullType(T)); // coverage:ignore-end diff --git a/packages/nextcloud/lib/src/api/dashboard.openapi.dart b/packages/nextcloud/lib/src/api/dashboard.openapi.dart index 126c77d2..0c5b2abd 100644 --- a/packages/nextcloud/lib/src/api/dashboard.openapi.dart +++ b/packages/nextcloud/lib/src/api/dashboard.openapi.dart @@ -1,55 +1,23 @@ // ignore_for_file: camel_case_types +// ignore_for_file: discarded_futures // ignore_for_file: public_member_api_docs +// ignore_for_file: unreachable_switch_case import 'dart:typed_data'; import 'package:built_collection/built_collection.dart'; import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.dart'; import 'package:built_value/standard_json_plugin.dart'; +import 'package:collection/collection.dart'; import 'package:dynamite_runtime/content_string.dart'; import 'package:dynamite_runtime/http_client.dart'; +import 'package:meta/meta.dart'; import 'package:universal_io/io.dart'; export 'package:dynamite_runtime/http_client.dart'; part 'dashboard.openapi.g.dart'; -class DashboardResponse extends DynamiteResponse { - DashboardResponse( - super.data, - super.headers, - ); - - @override - String toString() => 'DashboardResponse(data: $data, headers: $headers)'; -} - -class DashboardApiException extends DynamiteApiException { - DashboardApiException( - super.statusCode, - super.headers, - super.body, - ); - - static Future fromResponse(final HttpClientResponse response) async { - String body; - try { - body = await response.body; - } on FormatException { - body = 'binary'; - } - - return DashboardApiException( - response.statusCode, - response.responseHeaders, - body, - ); - } - - @override - String toString() => 'DashboardApiException(statusCode: $statusCode, headers: $headers, body: $body)'; -} - class DashboardClient extends DynamiteClient { DashboardClient( super.baseURL, { @@ -77,69 +45,169 @@ class DashboardDashboardApiClient { final DashboardClient _rootClient; - /// Get the widgets - Future getWidgets({final bool oCSAPIRequest = true}) async { + /// Get the widgets. + /// + /// 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: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Widgets returned + /// + /// See: + /// * [getWidgetsRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getWidgets({ + final bool oCSAPIRequest = true, + }) async { + final rawResponse = getWidgetsRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get the widgets. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Widgets returned + /// + /// See: + /// * [getWidgets] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getWidgetsRaw({ + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/dashboard/api/v1/widgets'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(DashboardDashboardApiGetWidgetsResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(DashboardDashboardApiGetWidgetsResponseApplicationJson), - )! as DashboardDashboardApiGetWidgetsResponseApplicationJson; - } - throw await DashboardApiException.fromResponse(response); // coverage:ignore-line } - /// Get the items for the widgets - Future getWidgetItems({ + /// Get the items for the widgets. + /// + /// 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: + /// * [sinceIds] Array indexed by widget Ids, contains date/id from which we want the new items + /// * [limit] Limit number of result items per widget + /// * [widgets] Limit results to specific widgets + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Widget items returned + /// + /// See: + /// * [getWidgetItemsRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getWidgetItems({ final ContentString>? sinceIds, final int limit = 7, final List widgets = const [], final bool oCSAPIRequest = true, }) async { + final rawResponse = getWidgetItemsRaw( + sinceIds: sinceIds, + limit: limit, + widgets: widgets, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get the items for the widgets. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [sinceIds] Array indexed by widget Ids, contains date/id from which we want the new items + /// * [limit] Limit number of result items per widget + /// * [widgets] Limit results to specific widgets + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Widget items returned + /// + /// See: + /// * [getWidgetItems] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getWidgetItemsRaw({ + final ContentString>? sinceIds, + final int limit = 7, + final List widgets = const [], + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/dashboard/api/v1/widget-items'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end if (sinceIds != null) { queryParameters['sinceIds'] = _jsonSerializers.serialize( sinceIds, @@ -155,47 +223,102 @@ class DashboardDashboardApiClient { queryParameters['widgets[]'] = widgets.map((final e) => e); } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(DashboardDashboardApiGetWidgetItemsResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(DashboardDashboardApiGetWidgetItemsResponseApplicationJson), - )! as DashboardDashboardApiGetWidgetItemsResponseApplicationJson; - } - throw await DashboardApiException.fromResponse(response); // coverage:ignore-line } - /// Get the items for the widgets - Future getWidgetItemsV2({ + /// Get the items for the widgets. + /// + /// 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: + /// * [sinceIds] Array indexed by widget Ids, contains date/id from which we want the new items + /// * [limit] Limit number of result items per widget + /// * [widgets] Limit results to specific widgets + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Widget items returned + /// + /// See: + /// * [getWidgetItemsV2Raw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getWidgetItemsV2({ final ContentString>? sinceIds, final int limit = 7, final List widgets = const [], final bool oCSAPIRequest = true, }) async { + final rawResponse = getWidgetItemsV2Raw( + sinceIds: sinceIds, + limit: limit, + widgets: widgets, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get the items for the widgets. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [sinceIds] Array indexed by widget Ids, contains date/id from which we want the new items + /// * [limit] Limit number of result items per widget + /// * [widgets] Limit results to specific widgets + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Widget items returned + /// + /// See: + /// * [getWidgetItemsV2] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getWidgetItemsV2Raw({ + final ContentString>? sinceIds, + final int limit = 7, + final List widgets = const [], + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/dashboard/api/v2/widget-items'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end if (sinceIds != null) { queryParameters['sinceIds'] = _jsonSerializers.serialize( sinceIds, @@ -211,19 +334,19 @@ class DashboardDashboardApiClient { queryParameters['widgets[]'] = widgets.map((final e) => e); } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(DashboardDashboardApiGetWidgetItemsV2ResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(DashboardDashboardApiGetWidgetItemsV2ResponseApplicationJson), - )! as DashboardDashboardApiGetWidgetItemsV2ResponseApplicationJson; - } - throw await DashboardApiException.fromResponse(response); // coverage:ignore-line } } @@ -681,14 +804,8 @@ final Serializers _serializers = (Serializers().toBuilder() )) .build(); -Serializers get dashboardSerializers => _serializers; - final Serializers _jsonSerializers = (_serializers.toBuilder() ..addPlugin(StandardJsonPlugin()) ..addPlugin(const ContentStringPlugin())) .build(); - -T deserializeDashboard(final Object data) => _serializers.deserialize(data, specifiedType: FullType(T))! as T; - -Object? serializeDashboard(final T data) => _serializers.serialize(data, specifiedType: FullType(T)); // coverage:ignore-end diff --git a/packages/nextcloud/lib/src/api/dav.openapi.dart b/packages/nextcloud/lib/src/api/dav.openapi.dart index 0660ed34..e8b25221 100644 --- a/packages/nextcloud/lib/src/api/dav.openapi.dart +++ b/packages/nextcloud/lib/src/api/dav.openapi.dart @@ -1,54 +1,22 @@ // ignore_for_file: camel_case_types +// ignore_for_file: discarded_futures // ignore_for_file: public_member_api_docs +// ignore_for_file: unreachable_switch_case import 'dart:typed_data'; import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.dart'; import 'package:built_value/standard_json_plugin.dart'; +import 'package:collection/collection.dart'; import 'package:dynamite_runtime/content_string.dart'; import 'package:dynamite_runtime/http_client.dart'; +import 'package:meta/meta.dart'; import 'package:universal_io/io.dart'; export 'package:dynamite_runtime/http_client.dart'; part 'dav.openapi.g.dart'; -class DavResponse extends DynamiteResponse { - DavResponse( - super.data, - super.headers, - ); - - @override - String toString() => 'DavResponse(data: $data, headers: $headers)'; -} - -class DavApiException extends DynamiteApiException { - DavApiException( - super.statusCode, - super.headers, - super.body, - ); - - static Future fromResponse(final HttpClientResponse response) async { - String body; - try { - body = await response.body; - } on FormatException { - body = 'binary'; - } - - return DavApiException( - response.statusCode, - response.responseHeaders, - body, - ); - } - - @override - String toString() => 'DavApiException(statusCode: $statusCode, headers: $headers, body: $body)'; -} - class DavClient extends DynamiteClient { DavClient( super.baseURL, { @@ -76,49 +44,106 @@ class DavDirectClient { final DavClient _rootClient; - /// Get a direct link to a file - Future getUrl({ + /// Get a direct link to a file. + /// + /// 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: + /// * [fileId] ID of the file + /// * [expirationTime] Duration until the link expires + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Direct link returned + /// * 404: File not found + /// * 400: Getting direct link is not possible + /// * 403: Missing permissions to get direct link + /// + /// See: + /// * [getUrlRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getUrl({ required final int fileId, final int? expirationTime, final bool oCSAPIRequest = true, }) async { + final rawResponse = getUrlRaw( + fileId: fileId, + expirationTime: expirationTime, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get a direct link to a file. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [fileId] ID of the file + /// * [expirationTime] Duration until the link expires + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Direct link returned + /// * 404: File not found + /// * 400: Getting direct link is not possible + /// * 403: Missing permissions to get direct link + /// + /// See: + /// * [getUrl] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getUrlRaw({ + required final int fileId, + final int? expirationTime, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/dav/api/v1/direct'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['fileId'] = fileId.toString(); if (expirationTime != null) { queryParameters['expirationTime'] = expirationTime.toString(); } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(DavDirectGetUrlResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(DavDirectGetUrlResponseApplicationJson), - )! as DavDirectGetUrlResponseApplicationJson; - } - throw await DavApiException.fromResponse(response); // coverage:ignore-line } } @@ -333,14 +358,8 @@ final Serializers _serializers = (Serializers().toBuilder() ..add(DavCapabilities_Dav.serializer)) .build(); -Serializers get davSerializers => _serializers; - final Serializers _jsonSerializers = (_serializers.toBuilder() ..addPlugin(StandardJsonPlugin()) ..addPlugin(const ContentStringPlugin())) .build(); - -T deserializeDav(final Object data) => _serializers.deserialize(data, specifiedType: FullType(T))! as T; - -Object? serializeDav(final T data) => _serializers.serialize(data, specifiedType: FullType(T)); // coverage:ignore-end diff --git a/packages/nextcloud/lib/src/api/files.openapi.dart b/packages/nextcloud/lib/src/api/files.openapi.dart index 71785dd1..5950e6e4 100644 --- a/packages/nextcloud/lib/src/api/files.openapi.dart +++ b/packages/nextcloud/lib/src/api/files.openapi.dart @@ -1,5 +1,7 @@ // ignore_for_file: camel_case_types +// ignore_for_file: discarded_futures // ignore_for_file: public_member_api_docs +// ignore_for_file: unreachable_switch_case import 'dart:typed_data'; import 'package:built_collection/built_collection.dart'; @@ -7,50 +9,17 @@ 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'; +import 'package:collection/collection.dart'; import 'package:dynamite_runtime/content_string.dart'; import 'package:dynamite_runtime/http_client.dart'; +import 'package:dynamite_runtime/utils.dart'; +import 'package:meta/meta.dart'; import 'package:universal_io/io.dart'; export 'package:dynamite_runtime/http_client.dart'; part 'files.openapi.g.dart'; -class FilesResponse extends DynamiteResponse { - FilesResponse( - super.data, - super.headers, - ); - - @override - String toString() => 'FilesResponse(data: $data, headers: $headers)'; -} - -class FilesApiException extends DynamiteApiException { - FilesApiException( - super.statusCode, - super.headers, - super.body, - ); - - static Future fromResponse(final HttpClientResponse response) async { - String body; - try { - body = await response.body; - } on FormatException { - body = 'binary'; - } - - return FilesApiException( - response.statusCode, - response.responseHeaders, - body, - ); - } - - @override - String toString() => 'FilesApiException(statusCode: $statusCode, headers: $headers, body: $body)'; -} - class FilesClient extends DynamiteClient { FilesClient( super.baseURL, { @@ -86,47 +55,103 @@ class FilesApiClient { final FilesClient _rootClient; - /// Gets a thumbnail of the specified file - Future getThumbnail({ + /// Gets a thumbnail of the specified file. + /// + /// 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: + /// * [x] Width of the thumbnail + /// * [y] Height of the thumbnail + /// * [file] URL-encoded filename + /// + /// Status codes: + /// * 200: Thumbnail returned + /// * 400: Getting thumbnail is not possible + /// * 404: File not found + /// + /// See: + /// * [getThumbnailRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getThumbnail({ required final int x, required final int y, required final String file, }) async { + final rawResponse = getThumbnailRaw( + x: x, + y: y, + file: file, + ); + + return rawResponse.future; + } + + /// Gets a thumbnail of the specified file. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [x] Width of the thumbnail + /// * [y] Height of the thumbnail + /// * [file] URL-encoded filename + /// + /// Status codes: + /// * 200: Thumbnail returned + /// * 400: Getting thumbnail is not possible + /// * 404: File not found + /// + /// See: + /// * [getThumbnail] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getThumbnailRaw({ + required final int x, + required final int y, + required final String file, + }) { var path = '/index.php/apps/files/api/v1/thumbnail/{x}/{y}/{file}'; final queryParameters = {}; final headers = { 'Accept': '*/*', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{x}', Uri.encodeQueryComponent(x.toString())); path = path.replaceAll('{y}', Uri.encodeQueryComponent(y.toString())); - if (!RegExp(r'^.+$').hasMatch(file)) { - throw Exception('Invalid value "$file" for parameter "file" with pattern "${r'^.+$'}"'); // coverage:ignore-line - } + checkPattern(file, RegExp(r'^.+$'), 'file'); // coverage:ignore-line path = path.replaceAll('{file}', Uri.encodeQueryComponent(file)); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(Uint8List), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return response.bodyBytes; - } - throw await FilesApiException.fromResponse(response); // coverage:ignore-line } } @@ -135,112 +160,267 @@ class FilesDirectEditingClient { final FilesClient _rootClient; - /// Get the direct editing capabilities - Future info({final bool oCSAPIRequest = true}) async { + /// Get the direct editing capabilities. + /// + /// 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: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Direct editing capabilities returned + /// + /// See: + /// * [infoRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> info({ + final bool oCSAPIRequest = true, + }) async { + final rawResponse = infoRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get the direct editing capabilities. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Direct editing capabilities returned + /// + /// See: + /// * [info] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse infoRaw({final bool oCSAPIRequest = true}) { const path = '/ocs/v2.php/apps/files/api/v1/directEditing'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesDirectEditingInfoResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesDirectEditingInfoResponseApplicationJson), - )! as FilesDirectEditingInfoResponseApplicationJson; - } - throw await FilesApiException.fromResponse(response); // coverage:ignore-line } - /// Get the templates for direct editing - Future templates({ + /// Get the templates for direct editing. + /// + /// 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: + /// * [editorId] ID of the editor + /// * [creatorId] ID of the creator + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Templates returned + /// * 500 + /// + /// See: + /// * [templatesRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> templates({ required final String editorId, required final String creatorId, final bool oCSAPIRequest = true, }) async { + final rawResponse = templatesRaw( + editorId: editorId, + creatorId: creatorId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get the templates for direct editing. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [editorId] ID of the editor + /// * [creatorId] ID of the creator + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Templates returned + /// * 500 + /// + /// See: + /// * [templates] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse templatesRaw({ + required final String editorId, + required final String creatorId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/files/api/v1/directEditing/templates/{editorId}/{creatorId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{editorId}', Uri.encodeQueryComponent(editorId)); path = path.replaceAll('{creatorId}', Uri.encodeQueryComponent(creatorId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesDirectEditingTemplatesResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesDirectEditingTemplatesResponseApplicationJson), - )! as FilesDirectEditingTemplatesResponseApplicationJson; - } - throw await FilesApiException.fromResponse(response); // coverage:ignore-line } - /// Open a file for direct editing - Future open({ + /// Open a file for direct editing. + /// + /// 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: + /// * [path] Path of the file + /// * [editorId] ID of the editor + /// * [fileId] ID of the file + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: URL for direct editing returned + /// * 403: Opening file is not allowed + /// * 500 + /// + /// See: + /// * [openRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> open({ required final String path, final String? editorId, final int? fileId, final bool oCSAPIRequest = true, }) async { + final rawResponse = openRaw( + path: path, + editorId: editorId, + fileId: fileId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Open a file for direct editing. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [path] Path of the file + /// * [editorId] ID of the editor + /// * [fileId] ID of the file + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: URL for direct editing returned + /// * 403: Opening file is not allowed + /// * 500 + /// + /// See: + /// * [open] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse openRaw({ + required final String path, + final String? editorId, + final int? fileId, + final bool oCSAPIRequest = true, + }) { const path0 = '/ocs/v2.php/apps/files/api/v1/directEditing/open'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['path'] = path; if (editorId != null) { queryParameters['editorId'] = editorId; @@ -249,48 +429,111 @@ class FilesDirectEditingClient { queryParameters['fileId'] = fileId.toString(); } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path0, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path0, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesDirectEditingOpenResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesDirectEditingOpenResponseApplicationJson), - )! as FilesDirectEditingOpenResponseApplicationJson; - } - throw await FilesApiException.fromResponse(response); // coverage:ignore-line } - /// Create a file for direct editing - Future create({ + /// Create a file for direct editing. + /// + /// 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: + /// * [path] Path of the file + /// * [editorId] ID of the editor + /// * [creatorId] ID of the creator + /// * [templateId] ID of the template + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: URL for direct editing returned + /// * 403: Opening file is not allowed + /// * 500 + /// + /// See: + /// * [createRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> create({ required final String path, required final String editorId, required final String creatorId, final String? templateId, final bool oCSAPIRequest = true, }) async { + final rawResponse = createRaw( + path: path, + editorId: editorId, + creatorId: creatorId, + templateId: templateId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Create a file for direct editing. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [path] Path of the file + /// * [editorId] ID of the editor + /// * [creatorId] ID of the creator + /// * [templateId] ID of the template + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: URL for direct editing returned + /// * 403: Opening file is not allowed + /// * 500 + /// + /// See: + /// * [create] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse createRaw({ + required final String path, + required final String editorId, + required final String creatorId, + final String? templateId, + final bool oCSAPIRequest = true, + }) { const path0 = '/ocs/v2.php/apps/files/api/v1/directEditing/create'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['path'] = path; queryParameters['editorId'] = editorId; queryParameters['creatorId'] = creatorId; @@ -298,19 +541,19 @@ class FilesDirectEditingClient { queryParameters['templateId'] = templateId; } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path0, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path0, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesDirectEditingCreateResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesDirectEditingCreateResponseApplicationJson), - )! as FilesDirectEditingCreateResponseApplicationJson; - } - throw await FilesApiException.fromResponse(response); // coverage:ignore-line } } @@ -319,88 +562,190 @@ class FilesOpenLocalEditorClient { final FilesClient _rootClient; - /// Create a local editor - Future create({ + /// Create a local editor. + /// + /// 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: + /// * [path] Path of the file + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Local editor returned + /// * 500 + /// + /// See: + /// * [createRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> create({ required final String path, final bool oCSAPIRequest = true, }) async { + final rawResponse = createRaw( + path: path, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Create a local editor. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [path] Path of the file + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Local editor returned + /// * 500 + /// + /// See: + /// * [create] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse createRaw({ + required final String path, + final bool oCSAPIRequest = true, + }) { const path0 = '/ocs/v2.php/apps/files/api/v1/openlocaleditor'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['path'] = path; headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path0, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path0, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesOpenLocalEditorCreateResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesOpenLocalEditorCreateResponseApplicationJson), - )! as FilesOpenLocalEditorCreateResponseApplicationJson; - } - throw await FilesApiException.fromResponse(response); // coverage:ignore-line } - /// Validate a local editor - Future validate({ + /// Validate a local editor. + /// + /// 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: + /// * [path] Path of the file + /// * [token] Token of the local editor + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Local editor validated successfully + /// * 404: Local editor not found + /// + /// See: + /// * [validateRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> validate({ required final String path, required final String token, final bool oCSAPIRequest = true, }) async { + final rawResponse = validateRaw( + path: path, + token: token, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Validate a local editor. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [path] Path of the file + /// * [token] Token of the local editor + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Local editor validated successfully + /// * 404: Local editor not found + /// + /// See: + /// * [validate] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse validateRaw({ + required final String path, + required final String token, + final bool oCSAPIRequest = true, + }) { var path0 = '/ocs/v2.php/apps/files/api/v1/openlocaleditor/{token}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['path'] = path; path0 = path0.replaceAll('{token}', Uri.encodeQueryComponent(token)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path0, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path0, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesOpenLocalEditorValidateResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesOpenLocalEditorValidateResponseApplicationJson), - )! as FilesOpenLocalEditorValidateResponseApplicationJson; - } - throw await FilesApiException.fromResponse(response); // coverage:ignore-line } } @@ -409,69 +754,169 @@ class FilesTemplateClient { final FilesClient _rootClient; - /// List the available templates - Future list({final bool oCSAPIRequest = true}) async { + /// List the available templates. + /// + /// 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: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Available templates returned + /// + /// See: + /// * [listRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> list({ + final bool oCSAPIRequest = true, + }) async { + final rawResponse = listRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// List the available templates. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Available templates returned + /// + /// See: + /// * [list] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse listRaw({final bool oCSAPIRequest = true}) { const path = '/ocs/v2.php/apps/files/api/v1/templates'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesTemplateListResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesTemplateListResponseApplicationJson), - )! as FilesTemplateListResponseApplicationJson; - } - throw await FilesApiException.fromResponse(response); // coverage:ignore-line } - /// Create a template - Future create({ + /// Create a template. + /// + /// 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: + /// * [filePath] Path of the file + /// * [templatePath] Name of the template + /// * [templateType] Type of the template + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Template created successfully + /// * 403: Creating template is not allowed + /// + /// See: + /// * [createRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> create({ required final String filePath, final String templatePath = '', final String templateType = 'user', final bool oCSAPIRequest = true, }) async { + final rawResponse = createRaw( + filePath: filePath, + templatePath: templatePath, + templateType: templateType, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Create a template. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [filePath] Path of the file + /// * [templatePath] Name of the template + /// * [templateType] Type of the template + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Template created successfully + /// * 403: Creating template is not allowed + /// + /// See: + /// * [create] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse createRaw({ + required final String filePath, + final String templatePath = '', + final String templateType = 'user', + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/files/api/v1/templates/create'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['filePath'] = filePath; if (templatePath != '') { queryParameters['templatePath'] = templatePath; @@ -480,46 +925,99 @@ class FilesTemplateClient { queryParameters['templateType'] = templateType; } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesTemplateCreateResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesTemplateCreateResponseApplicationJson), - )! as FilesTemplateCreateResponseApplicationJson; - } - throw await FilesApiException.fromResponse(response); // coverage:ignore-line } - /// Initialize the template directory - Future path({ + /// Initialize the template directory. + /// + /// 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: + /// * [templatePath] Path of the template directory + /// * [copySystemTemplates] Whether to copy the system templates to the template directory + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Template directory initialized successfully + /// * 403: Initializing the template directory is not allowed + /// + /// See: + /// * [pathRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> path({ final String templatePath = '', final int copySystemTemplates = 0, final bool oCSAPIRequest = true, }) async { + final rawResponse = pathRaw( + templatePath: templatePath, + copySystemTemplates: copySystemTemplates, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Initialize the template directory. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [templatePath] Path of the template directory + /// * [copySystemTemplates] Whether to copy the system templates to the template directory + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Template directory initialized successfully + /// * 403: Initializing the template directory is not allowed + /// + /// See: + /// * [path] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse pathRaw({ + final String templatePath = '', + final int copySystemTemplates = 0, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/files/api/v1/templates/path'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end if (templatePath != '') { queryParameters['templatePath'] = templatePath; } @@ -527,19 +1025,19 @@ class FilesTemplateClient { queryParameters['copySystemTemplates'] = copySystemTemplates.toString(); } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesTemplatePathResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesTemplatePathResponseApplicationJson), - )! as FilesTemplatePathResponseApplicationJson; - } - throw await FilesApiException.fromResponse(response); // coverage:ignore-line } } @@ -548,129 +1046,286 @@ class FilesTransferOwnershipClient { final FilesClient _rootClient; - /// Transfer the ownership to another user - Future transfer({ + /// Transfer the ownership to another 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. + /// + /// Parameters: + /// * [recipient] Username of the recipient + /// * [path] Path of the file + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Ownership transferred successfully + /// * 400: Transferring ownership is not possible + /// * 403: Transferring ownership is not allowed + /// + /// See: + /// * [transferRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> transfer({ required final String recipient, required final String path, final bool oCSAPIRequest = true, }) async { + final rawResponse = transferRaw( + recipient: recipient, + path: path, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Transfer the ownership to another user. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [recipient] Username of the recipient + /// * [path] Path of the file + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Ownership transferred successfully + /// * 400: Transferring ownership is not possible + /// * 403: Transferring ownership is not allowed + /// + /// See: + /// * [transfer] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse transferRaw({ + required final String recipient, + required final String path, + final bool oCSAPIRequest = true, + }) { const path0 = '/ocs/v2.php/apps/files/api/v1/transferownership'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['recipient'] = recipient; queryParameters['path'] = path; headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path0, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path0, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200, 400, 403}, + ), + bodyType: const FullType(FilesTransferOwnershipTransferResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200 || response.statusCode == 400 || response.statusCode == 403) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesTransferOwnershipTransferResponseApplicationJson), - )! as FilesTransferOwnershipTransferResponseApplicationJson; - } - throw await FilesApiException.fromResponse(response); // coverage:ignore-line } - /// Accept an ownership transfer - Future accept({ + /// Accept an ownership transfer. + /// + /// 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] ID of the ownership transfer + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Ownership transfer accepted successfully + /// * 403: Accepting ownership transfer is not allowed + /// * 404: Ownership transfer not found + /// + /// See: + /// * [acceptRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> accept({ required final int id, final bool oCSAPIRequest = true, }) async { + final rawResponse = acceptRaw( + id: id, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Accept an ownership transfer. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [id] ID of the ownership transfer + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Ownership transfer accepted successfully + /// * 403: Accepting ownership transfer is not allowed + /// * 404: Ownership transfer not found + /// + /// See: + /// * [accept] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse acceptRaw({ + required final int id, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/files/api/v1/transferownership/{id}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{id}', Uri.encodeQueryComponent(id.toString())); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200, 403, 404}, + ), + bodyType: const FullType(FilesTransferOwnershipAcceptResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200 || response.statusCode == 403 || response.statusCode == 404) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesTransferOwnershipAcceptResponseApplicationJson), - )! as FilesTransferOwnershipAcceptResponseApplicationJson; - } - throw await FilesApiException.fromResponse(response); // coverage:ignore-line } - /// Reject an ownership transfer - Future reject({ + /// Reject an ownership transfer. + /// + /// 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] ID of the ownership transfer + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Ownership transfer rejected successfully + /// * 403: Rejecting ownership transfer is not allowed + /// * 404: Ownership transfer not found + /// + /// See: + /// * [rejectRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> reject({ required final int id, final bool oCSAPIRequest = true, }) async { + final rawResponse = rejectRaw( + id: id, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Reject an ownership transfer. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [id] ID of the ownership transfer + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Ownership transfer rejected successfully + /// * 403: Rejecting ownership transfer is not allowed + /// * 404: Ownership transfer not found + /// + /// See: + /// * [reject] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse rejectRaw({ + required final int id, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/files/api/v1/transferownership/{id}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{id}', Uri.encodeQueryComponent(id.toString())); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'delete', + uri, + headers, + body, + const {200, 403, 404}, + ), + bodyType: const FullType(FilesTransferOwnershipRejectResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200 || response.statusCode == 403 || response.statusCode == 404) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesTransferOwnershipRejectResponseApplicationJson), - )! as FilesTransferOwnershipRejectResponseApplicationJson; - } - throw await FilesApiException.fromResponse(response); // coverage:ignore-line } } @@ -2340,14 +2995,8 @@ final Serializers _serializers = (Serializers().toBuilder() ..add(FilesTemplate.serializer)) .build(); -Serializers get filesSerializers => _serializers; - final Serializers _jsonSerializers = (_serializers.toBuilder() ..addPlugin(StandardJsonPlugin()) ..addPlugin(const ContentStringPlugin())) .build(); - -T deserializeFiles(final Object data) => _serializers.deserialize(data, specifiedType: FullType(T))! as T; - -Object? serializeFiles(final T data) => _serializers.serialize(data, specifiedType: FullType(T)); // coverage:ignore-end diff --git a/packages/nextcloud/lib/src/api/files_external.openapi.dart b/packages/nextcloud/lib/src/api/files_external.openapi.dart index 457b28c2..a77908ce 100644 --- a/packages/nextcloud/lib/src/api/files_external.openapi.dart +++ b/packages/nextcloud/lib/src/api/files_external.openapi.dart @@ -1,5 +1,7 @@ // ignore_for_file: camel_case_types +// ignore_for_file: discarded_futures // ignore_for_file: public_member_api_docs +// ignore_for_file: unreachable_switch_case import 'dart:typed_data'; import 'package:built_collection/built_collection.dart'; @@ -7,50 +9,16 @@ 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'; +import 'package:collection/collection.dart'; import 'package:dynamite_runtime/content_string.dart'; import 'package:dynamite_runtime/http_client.dart'; +import 'package:meta/meta.dart'; import 'package:universal_io/io.dart'; export 'package:dynamite_runtime/http_client.dart'; part 'files_external.openapi.g.dart'; -class FilesExternalResponse extends DynamiteResponse { - FilesExternalResponse( - super.data, - super.headers, - ); - - @override - String toString() => 'FilesExternalResponse(data: $data, headers: $headers)'; -} - -class FilesExternalApiException extends DynamiteApiException { - FilesExternalApiException( - super.statusCode, - super.headers, - super.body, - ); - - static Future fromResponse(final HttpClientResponse response) async { - String body; - try { - body = await response.body; - } on FormatException { - body = 'binary'; - } - - return FilesExternalApiException( - response.statusCode, - response.responseHeaders, - body, - ); - } - - @override - String toString() => 'FilesExternalApiException(statusCode: $statusCode, headers: $headers, body: $body)'; -} - class FilesExternalClient extends DynamiteClient { FilesExternalClient( super.baseURL, { @@ -78,41 +46,86 @@ class FilesExternalApiClient { final FilesExternalClient _rootClient; - /// Get the mount points visible for this user - Future getUserMounts({final bool oCSAPIRequest = true}) async { + /// Get the mount points visible for this 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. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User mounts returned + /// + /// See: + /// * [getUserMountsRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getUserMounts({ + final bool oCSAPIRequest = true, + }) async { + final rawResponse = getUserMountsRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get the mount points visible for this user. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User mounts returned + /// + /// See: + /// * [getUserMounts] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getUserMountsRaw({ + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/files_external/api/v1/mounts'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesExternalApiGetUserMountsResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesExternalApiGetUserMountsResponseApplicationJson), - )! as FilesExternalApiGetUserMountsResponseApplicationJson; - } - throw await FilesExternalApiException.fromResponse(response); // coverage:ignore-line } } @@ -374,14 +387,8 @@ final Serializers _serializers = (Serializers().toBuilder() )) .build(); -Serializers get filesExternalSerializers => _serializers; - final Serializers _jsonSerializers = (_serializers.toBuilder() ..addPlugin(StandardJsonPlugin()) ..addPlugin(const ContentStringPlugin())) .build(); - -T deserializeFilesExternal(final Object data) => _serializers.deserialize(data, specifiedType: FullType(T))! as T; - -Object? serializeFilesExternal(final T data) => _serializers.serialize(data, specifiedType: FullType(T)); // coverage:ignore-end diff --git a/packages/nextcloud/lib/src/api/files_reminders.openapi.dart b/packages/nextcloud/lib/src/api/files_reminders.openapi.dart index 87b28ecb..0ea53a93 100644 --- a/packages/nextcloud/lib/src/api/files_reminders.openapi.dart +++ b/packages/nextcloud/lib/src/api/files_reminders.openapi.dart @@ -1,55 +1,24 @@ // ignore_for_file: camel_case_types +// ignore_for_file: discarded_futures // ignore_for_file: public_member_api_docs +// ignore_for_file: unreachable_switch_case import 'dart:typed_data'; 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'; +import 'package:collection/collection.dart'; import 'package:dynamite_runtime/content_string.dart'; import 'package:dynamite_runtime/http_client.dart'; +import 'package:dynamite_runtime/utils.dart'; +import 'package:meta/meta.dart'; import 'package:universal_io/io.dart'; export 'package:dynamite_runtime/http_client.dart'; part 'files_reminders.openapi.g.dart'; -class FilesRemindersResponse extends DynamiteResponse { - FilesRemindersResponse( - super.data, - super.headers, - ); - - @override - String toString() => 'FilesRemindersResponse(data: $data, headers: $headers)'; -} - -class FilesRemindersApiException extends DynamiteApiException { - FilesRemindersApiException( - super.statusCode, - super.headers, - super.body, - ); - - static Future fromResponse(final HttpClientResponse response) async { - String body; - try { - body = await response.body; - } on FormatException { - body = 'binary'; - } - - return FilesRemindersApiException( - response.statusCode, - response.responseHeaders, - body, - ); - } - - @override - String toString() => 'FilesRemindersApiException(statusCode: $statusCode, headers: $headers, body: $body)'; -} - class FilesRemindersClient extends DynamiteClient { FilesRemindersClient( super.baseURL, { @@ -77,154 +46,309 @@ class FilesRemindersApiClient { final FilesRemindersClient _rootClient; - /// Get a reminder - Future $get({ + /// Get a reminder. + /// + /// 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: + /// * [version] + /// * [fileId] ID of the file + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Reminder returned + /// * 401: User not found + /// + /// See: + /// * [$getRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> $get({ required final String version, required final int fileId, final bool oCSAPIRequest = true, }) async { + final rawResponse = $getRaw( + version: version, + fileId: fileId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get a reminder. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [version] + /// * [fileId] ID of the file + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Reminder returned + /// * 401: User not found + /// + /// See: + /// * [$get] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse $getRaw({ + required final String version, + required final int fileId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/files_reminders/api/v{version}/{fileId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end - if (!RegExp(r'^1$').hasMatch(version)) { - throw Exception( - 'Invalid value "$version" for parameter "version" with pattern "${r'^1$'}"', - ); // coverage:ignore-line - } + +// coverage:ignore-end + checkPattern(version, RegExp(r'^1$'), 'version'); // coverage:ignore-line path = path.replaceAll('{version}', Uri.encodeQueryComponent(version)); path = path.replaceAll('{fileId}', Uri.encodeQueryComponent(fileId.toString())); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesRemindersApiGetResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesRemindersApiGetResponseApplicationJson), - )! as FilesRemindersApiGetResponseApplicationJson; - } - throw await FilesRemindersApiException.fromResponse(response); // coverage:ignore-line } - /// Set a reminder - Future $set({ + /// Set a reminder. + /// + /// 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: + /// * [dueDate] ISO 8601 formatted date time string + /// * [version] + /// * [fileId] ID of the file + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Reminder updated + /// * 201: Reminder created successfully + /// * 400: Creating reminder is not possible + /// * 401: User not found + /// * 404: File not found + /// + /// See: + /// * [$setRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> $set({ required final String dueDate, required final String version, required final int fileId, final bool oCSAPIRequest = true, }) async { + final rawResponse = $setRaw( + dueDate: dueDate, + version: version, + fileId: fileId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Set a reminder. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [dueDate] ISO 8601 formatted date time string + /// * [version] + /// * [fileId] ID of the file + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Reminder updated + /// * 201: Reminder created successfully + /// * 400: Creating reminder is not possible + /// * 401: User not found + /// * 404: File not found + /// + /// See: + /// * [$set] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse $setRaw({ + required final String dueDate, + required final String version, + required final int fileId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/files_reminders/api/v{version}/{fileId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['dueDate'] = dueDate; - if (!RegExp(r'^1$').hasMatch(version)) { - throw Exception( - 'Invalid value "$version" for parameter "version" with pattern "${r'^1$'}"', - ); // coverage:ignore-line - } + checkPattern(version, RegExp(r'^1$'), 'version'); // coverage:ignore-line path = path.replaceAll('{version}', Uri.encodeQueryComponent(version)); path = path.replaceAll('{fileId}', Uri.encodeQueryComponent(fileId.toString())); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'put', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'put', + uri, + headers, + body, + const {200, 201, 400, 401, 404}, + ), + bodyType: const FullType(FilesRemindersApiSetResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200 || - response.statusCode == 201 || - response.statusCode == 400 || - response.statusCode == 401 || - response.statusCode == 404) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesRemindersApiSetResponseApplicationJson), - )! as FilesRemindersApiSetResponseApplicationJson; - } - throw await FilesRemindersApiException.fromResponse(response); // coverage:ignore-line } - /// Remove a reminder - Future remove({ + /// Remove a reminder. + /// + /// 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: + /// * [version] + /// * [fileId] ID of the file + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Reminder deleted successfully + /// * 401: User not found + /// * 404: Reminder not found + /// + /// See: + /// * [removeRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> remove({ required final String version, required final int fileId, final bool oCSAPIRequest = true, }) async { + final rawResponse = removeRaw( + version: version, + fileId: fileId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Remove a reminder. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [version] + /// * [fileId] ID of the file + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Reminder deleted successfully + /// * 401: User not found + /// * 404: Reminder not found + /// + /// See: + /// * [remove] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse removeRaw({ + required final String version, + required final int fileId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/files_reminders/api/v{version}/{fileId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end - if (!RegExp(r'^1$').hasMatch(version)) { - throw Exception( - 'Invalid value "$version" for parameter "version" with pattern "${r'^1$'}"', - ); // coverage:ignore-line - } + +// coverage:ignore-end + checkPattern(version, RegExp(r'^1$'), 'version'); // coverage:ignore-line path = path.replaceAll('{version}', Uri.encodeQueryComponent(version)); path = path.replaceAll('{fileId}', Uri.encodeQueryComponent(fileId.toString())); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'delete', + uri, + headers, + body, + const {200, 401, 404}, + ), + bodyType: const FullType(FilesRemindersApiRemoveResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200 || response.statusCode == 401 || response.statusCode == 404) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesRemindersApiRemoveResponseApplicationJson), - )! as FilesRemindersApiRemoveResponseApplicationJson; - } - throw await FilesRemindersApiException.fromResponse(response); // coverage:ignore-line } } @@ -543,14 +667,8 @@ final Serializers _serializers = (Serializers().toBuilder() ..add(FilesRemindersApiRemoveResponseApplicationJson_Ocs.serializer)) .build(); -Serializers get filesRemindersSerializers => _serializers; - final Serializers _jsonSerializers = (_serializers.toBuilder() ..addPlugin(StandardJsonPlugin()) ..addPlugin(const ContentStringPlugin())) .build(); - -T deserializeFilesReminders(final Object data) => _serializers.deserialize(data, specifiedType: FullType(T))! as T; - -Object? serializeFilesReminders(final T data) => _serializers.serialize(data, specifiedType: FullType(T)); // coverage:ignore-end diff --git a/packages/nextcloud/lib/src/api/files_sharing.openapi.dart b/packages/nextcloud/lib/src/api/files_sharing.openapi.dart index e1c07dfc..7c723bdb 100644 --- a/packages/nextcloud/lib/src/api/files_sharing.openapi.dart +++ b/packages/nextcloud/lib/src/api/files_sharing.openapi.dart @@ -1,5 +1,7 @@ // ignore_for_file: camel_case_types +// ignore_for_file: discarded_futures // ignore_for_file: public_member_api_docs +// ignore_for_file: unreachable_switch_case import 'dart:typed_data'; import 'package:built_collection/built_collection.dart'; @@ -7,50 +9,16 @@ 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'; +import 'package:collection/collection.dart'; import 'package:dynamite_runtime/content_string.dart'; import 'package:dynamite_runtime/http_client.dart'; +import 'package:meta/meta.dart'; import 'package:universal_io/io.dart'; export 'package:dynamite_runtime/http_client.dart'; part 'files_sharing.openapi.g.dart'; -class FilesSharingResponse extends DynamiteResponse { - FilesSharingResponse( - super.data, - super.headers, - ); - - @override - String toString() => 'FilesSharingResponse(data: $data, headers: $headers)'; -} - -class FilesSharingApiException extends DynamiteApiException { - FilesSharingApiException( - super.statusCode, - super.headers, - super.body, - ); - - static Future fromResponse(final HttpClientResponse response) async { - String body; - try { - body = await response.body; - } on FormatException { - body = 'binary'; - } - - return FilesSharingApiException( - response.statusCode, - response.responseHeaders, - body, - ); - } - - @override - String toString() => 'FilesSharingApiException(statusCode: $statusCode, headers: $headers, body: $body)'; -} - class FilesSharingClient extends DynamiteClient { FilesSharingClient( super.baseURL, { @@ -88,82 +56,176 @@ class FilesSharingDeletedShareapiClient { final FilesSharingClient _rootClient; - /// Get a list of all deleted shares - Future list({final bool oCSAPIRequest = true}) async { + /// Get a list of all deleted shares. + /// + /// 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: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Deleted shares returned + /// + /// See: + /// * [listRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> list({ + final bool oCSAPIRequest = true, + }) async { + final rawResponse = listRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get a list of all deleted shares. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Deleted shares returned + /// + /// See: + /// * [list] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse listRaw({ + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/files_sharing/api/v1/deletedshares'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesSharingDeletedShareapiListResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesSharingDeletedShareapiListResponseApplicationJson), - )! as FilesSharingDeletedShareapiListResponseApplicationJson; - } - throw await FilesSharingApiException.fromResponse(response); // coverage:ignore-line } - /// Undelete a deleted share - Future undelete({ + /// Undelete a deleted share. + /// + /// 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] ID of the share + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Share undeleted successfully + /// * 404: Share not found + /// + /// See: + /// * [undeleteRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> undelete({ required final String id, final bool oCSAPIRequest = true, }) async { + final rawResponse = undeleteRaw( + id: id, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Undelete a deleted share. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [id] ID of the share + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Share undeleted successfully + /// * 404: Share not found + /// + /// See: + /// * [undelete] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse undeleteRaw({ + required final String id, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/files_sharing/api/v1/deletedshares/{id}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{id}', Uri.encodeQueryComponent(id)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesSharingDeletedShareapiUndeleteResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesSharingDeletedShareapiUndeleteResponseApplicationJson), - )! as FilesSharingDeletedShareapiUndeleteResponseApplicationJson; - } - throw await FilesSharingApiException.fromResponse(response); // coverage:ignore-line } } @@ -172,44 +234,120 @@ class FilesSharingPublicPreviewClient { final FilesSharingClient _rootClient; - /// Get a direct link preview for a shared file - Future directLink({ + /// Get a direct link preview for a shared file. + /// + /// 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: + /// * [token] Token of the share + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Preview returned + /// * 400: Getting preview is not possible + /// * 403: Getting preview is not allowed + /// * 404: Share or preview not found + /// + /// See: + /// * [directLinkRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> directLink({ required final String token, final bool oCSAPIRequest = true, }) async { + final rawResponse = directLinkRaw( + token: token, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get a direct link preview for a shared file. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [token] Token of the share + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Preview returned + /// * 400: Getting preview is not possible + /// * 403: Getting preview is not allowed + /// * 404: Share or preview not found + /// + /// See: + /// * [directLink] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse directLinkRaw({ + required final String token, + final bool oCSAPIRequest = true, + }) { var path = '/index.php/s/{token}/preview'; final queryParameters = {}; final headers = { 'Accept': '*/*', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{token}', Uri.encodeQueryComponent(token)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(Uint8List), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return response.bodyBytes; - } - throw await FilesSharingApiException.fromResponse(response); // coverage:ignore-line } - /// Get a preview for a shared file - Future getPreview({ + /// Get a preview for a shared file. + /// + /// 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: + /// * [file] File in the share + /// * [x] Width of the preview + /// * [y] Height of the preview + /// * [a] Whether to not crop the preview + /// * [token] Token of the share + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Preview returned + /// * 400: Getting preview is not possible + /// * 403: Getting preview is not allowed + /// * 404: Share or preview not found + /// + /// See: + /// * [getPreviewRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getPreview({ required final String token, final String file = '', final int x = 32, @@ -217,23 +355,72 @@ class FilesSharingPublicPreviewClient { final int a = 0, final bool oCSAPIRequest = true, }) async { + final rawResponse = getPreviewRaw( + token: token, + file: file, + x: x, + y: y, + a: a, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get a preview for a shared file. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [file] File in the share + /// * [x] Width of the preview + /// * [y] Height of the preview + /// * [a] Whether to not crop the preview + /// * [token] Token of the share + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Preview returned + /// * 400: Getting preview is not possible + /// * 403: Getting preview is not allowed + /// * 404: Share or preview not found + /// + /// See: + /// * [getPreview] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getPreviewRaw({ + required final String token, + final String file = '', + final int x = 32, + final int y = 32, + final int a = 0, + final bool oCSAPIRequest = true, + }) { var path = '/index.php/apps/files_sharing/publicpreview/{token}'; final queryParameters = {}; final headers = { 'Accept': '*/*', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{token}', Uri.encodeQueryComponent(token)); if (file != '') { queryParameters['file'] = file; @@ -248,16 +435,19 @@ class FilesSharingPublicPreviewClient { queryParameters['a'] = a.toString(); } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(Uint8List), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return response.bodyBytes; - } - throw await FilesSharingApiException.fromResponse(response); // coverage:ignore-line } } @@ -266,244 +456,530 @@ class FilesSharingRemoteClient { final FilesSharingClient _rootClient; - /// Get a list of accepted remote shares - Future getShares({final bool oCSAPIRequest = true}) async { + /// Get a list of accepted remote shares. + /// + /// 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: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Accepted remote shares returned + /// + /// See: + /// * [getSharesRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getShares({ + final bool oCSAPIRequest = true, + }) async { + final rawResponse = getSharesRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get a list of accepted remote shares. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Accepted remote shares returned + /// + /// See: + /// * [getShares] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getSharesRaw({ + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/files_sharing/api/v1/remote_shares'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesSharingRemoteGetSharesResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesSharingRemoteGetSharesResponseApplicationJson), - )! as FilesSharingRemoteGetSharesResponseApplicationJson; - } - throw await FilesSharingApiException.fromResponse(response); // coverage:ignore-line } - /// Get list of pending remote shares - Future getOpenShares({ + /// Get list of pending remote shares. + /// + /// 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: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Pending remote shares returned + /// + /// See: + /// * [getOpenSharesRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getOpenShares({ final bool oCSAPIRequest = true, }) async { + final rawResponse = getOpenSharesRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get list of pending remote shares. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Pending remote shares returned + /// + /// See: + /// * [getOpenShares] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getOpenSharesRaw({ + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesSharingRemoteGetOpenSharesResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesSharingRemoteGetOpenSharesResponseApplicationJson), - )! as FilesSharingRemoteGetOpenSharesResponseApplicationJson; - } - throw await FilesSharingApiException.fromResponse(response); // coverage:ignore-line } - /// Accept a remote share - Future acceptShare({ + /// Accept a remote share. + /// + /// 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] ID of the share + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Share accepted successfully + /// * 404: Share not found + /// + /// See: + /// * [acceptShareRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> acceptShare({ required final int id, final bool oCSAPIRequest = true, }) async { + final rawResponse = acceptShareRaw( + id: id, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Accept a remote share. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [id] ID of the share + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Share accepted successfully + /// * 404: Share not found + /// + /// See: + /// * [acceptShare] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse acceptShareRaw({ + required final int id, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/{id}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{id}', Uri.encodeQueryComponent(id.toString())); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesSharingRemoteAcceptShareResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesSharingRemoteAcceptShareResponseApplicationJson), - )! as FilesSharingRemoteAcceptShareResponseApplicationJson; - } - throw await FilesSharingApiException.fromResponse(response); // coverage:ignore-line } - /// Decline a remote share - Future declineShare({ + /// Decline a remote share. + /// + /// 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] ID of the share + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Share declined successfully + /// * 404: Share not found + /// + /// See: + /// * [declineShareRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> declineShare({ required final int id, final bool oCSAPIRequest = true, }) async { + final rawResponse = declineShareRaw( + id: id, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Decline a remote share. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [id] ID of the share + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Share declined successfully + /// * 404: Share not found + /// + /// See: + /// * [declineShare] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse declineShareRaw({ + required final int id, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/{id}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{id}', Uri.encodeQueryComponent(id.toString())); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'delete', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesSharingRemoteDeclineShareResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesSharingRemoteDeclineShareResponseApplicationJson), - )! as FilesSharingRemoteDeclineShareResponseApplicationJson; - } - throw await FilesSharingApiException.fromResponse(response); // coverage:ignore-line } - /// Get info of a remote share - Future getShare({ + /// Get info of a remote share. + /// + /// 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] ID of the share + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Share returned + /// * 404: Share not found + /// + /// See: + /// * [getShareRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getShare({ required final int id, final bool oCSAPIRequest = true, }) async { + final rawResponse = getShareRaw( + id: id, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get info of a remote share. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [id] ID of the share + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Share returned + /// * 404: Share not found + /// + /// See: + /// * [getShare] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getShareRaw({ + required final int id, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/files_sharing/api/v1/remote_shares/{id}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{id}', Uri.encodeQueryComponent(id.toString())); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesSharingRemoteGetShareResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesSharingRemoteGetShareResponseApplicationJson), - )! as FilesSharingRemoteGetShareResponseApplicationJson; - } - throw await FilesSharingApiException.fromResponse(response); // coverage:ignore-line } - /// Unshare a remote share - Future unshare({ + /// Unshare a remote share. + /// + /// 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] ID of the share + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Share unshared successfully + /// * 404: Share not found + /// * 403: Unsharing is not possible + /// + /// See: + /// * [unshareRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> unshare({ required final int id, final bool oCSAPIRequest = true, }) async { + final rawResponse = unshareRaw( + id: id, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Unshare a remote share. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [id] ID of the share + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Share unshared successfully + /// * 404: Share not found + /// * 403: Unsharing is not possible + /// + /// See: + /// * [unshare] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse unshareRaw({ + required final int id, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/files_sharing/api/v1/remote_shares/{id}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{id}', Uri.encodeQueryComponent(id.toString())); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'delete', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesSharingRemoteUnshareResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesSharingRemoteUnshareResponseApplicationJson), - )! as FilesSharingRemoteUnshareResponseApplicationJson; - } - throw await FilesSharingApiException.fromResponse(response); // coverage:ignore-line } } @@ -512,30 +988,89 @@ class FilesSharingShareInfoClient { final FilesSharingClient _rootClient; - /// Get the info about a share - Future info({ + /// Get the info about a share. + /// + /// 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: + /// * [t] Token of the share + /// * [password] Password of the share + /// * [dir] Subdirectory to get info about + /// * [depth] Maximum depth to get info about + /// + /// Status codes: + /// * 200: Share info returned + /// * 403: Getting share info is not allowed + /// * 404: Share not found + /// + /// See: + /// * [infoRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> info({ required final String t, final String? password, final String? dir, final int depth = -1, }) async { + final rawResponse = infoRaw( + t: t, + password: password, + dir: dir, + depth: depth, + ); + + return rawResponse.future; + } + + /// Get the info about a share. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [t] Token of the share + /// * [password] Password of the share + /// * [dir] Subdirectory to get info about + /// * [depth] Maximum depth to get info about + /// + /// Status codes: + /// * 200: Share info returned + /// * 403: Getting share info is not allowed + /// * 404: Share not found + /// + /// See: + /// * [info] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse infoRaw({ + required final String t, + final String? password, + final String? dir, + final int depth = -1, + }) { const path = '/index.php/apps/files_sharing/shareinfo'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['t'] = t; if (password != null) { queryParameters['password'] = password; @@ -546,19 +1081,19 @@ class FilesSharingShareInfoClient { if (depth != -1) { queryParameters['depth'] = depth.toString(); } - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesSharingShareInfo), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesSharingShareInfo), - )! as FilesSharingShareInfo; - } - throw await FilesSharingApiException.fromResponse(response); // coverage:ignore-line } } @@ -567,8 +1102,26 @@ class FilesSharingShareapiClient { final FilesSharingClient _rootClient; - /// Get shares of the current user - Future getShares({ + /// Get shares of 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. + /// + /// Parameters: + /// * [sharedWithMe] Only get shares with the current user + /// * [reshares] Only get shares by the current user and reshares + /// * [subfiles] Only get all shares in a folder + /// * [path] Get shares for a specific path + /// * [includeTags] Include tags in the share + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Shares returned + /// * 404: The folder was not found or is inaccessible + /// + /// See: + /// * [getSharesRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getShares({ final String sharedWithMe = 'false', final String reshares = 'false', final String subfiles = 'false', @@ -576,25 +1129,72 @@ class FilesSharingShareapiClient { final String includeTags = 'false', final bool oCSAPIRequest = true, }) async { + final rawResponse = getSharesRaw( + sharedWithMe: sharedWithMe, + reshares: reshares, + subfiles: subfiles, + path: path, + includeTags: includeTags, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get shares of the current user. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [sharedWithMe] Only get shares with the current user + /// * [reshares] Only get shares by the current user and reshares + /// * [subfiles] Only get all shares in a folder + /// * [path] Get shares for a specific path + /// * [includeTags] Include tags in the share + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Shares returned + /// * 404: The folder was not found or is inaccessible + /// + /// See: + /// * [getShares] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getSharesRaw({ + final String sharedWithMe = 'false', + final String reshares = 'false', + final String subfiles = 'false', + final String path = '', + final String includeTags = 'false', + final bool oCSAPIRequest = true, + }) { const path0 = '/ocs/v2.php/apps/files_sharing/api/v1/shares'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end if (sharedWithMe != 'false') { queryParameters['shared_with_me'] = sharedWithMe; } @@ -611,23 +1211,49 @@ class FilesSharingShareapiClient { queryParameters['include_tags'] = includeTags; } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path0, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path0, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesSharingShareapiGetSharesResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesSharingShareapiGetSharesResponseApplicationJson), - )! as FilesSharingShareapiGetSharesResponseApplicationJson; - } - throw await FilesSharingApiException.fromResponse(response); // coverage:ignore-line } - /// Create a share - Future createShare({ + /// Create a share. + /// + /// 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: + /// * [path] Path of the share + /// * [permissions] Permissions for the share + /// * [shareType] Type of the share + /// * [shareWith] The entity this should be shared with + /// * [publicUpload] If public uploading is allowed + /// * [password] Password for the share + /// * [sendPasswordByTalk] Send the password for the share over Talk + /// * [expireDate] Expiry date of the share + /// * [note] Note for the share + /// * [label] Label for the share (only used in link and email) + /// * [attributes] Additional attributes for the share + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Share created + /// * 400: Unknown share type + /// * 403: Creating the share is not allowed + /// * 404: Creating the share failed + /// + /// See: + /// * [createShareRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> createShare({ final String? path, final int? permissions, final int shareType = -1, @@ -641,25 +1267,92 @@ class FilesSharingShareapiClient { final String? attributes, final bool oCSAPIRequest = true, }) async { + final rawResponse = createShareRaw( + path: path, + permissions: permissions, + shareType: shareType, + shareWith: shareWith, + publicUpload: publicUpload, + password: password, + sendPasswordByTalk: sendPasswordByTalk, + expireDate: expireDate, + note: note, + label: label, + attributes: attributes, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Create a share. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [path] Path of the share + /// * [permissions] Permissions for the share + /// * [shareType] Type of the share + /// * [shareWith] The entity this should be shared with + /// * [publicUpload] If public uploading is allowed + /// * [password] Password for the share + /// * [sendPasswordByTalk] Send the password for the share over Talk + /// * [expireDate] Expiry date of the share + /// * [note] Note for the share + /// * [label] Label for the share (only used in link and email) + /// * [attributes] Additional attributes for the share + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Share created + /// * 400: Unknown share type + /// * 403: Creating the share is not allowed + /// * 404: Creating the share failed + /// + /// See: + /// * [createShare] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse createShareRaw({ + final String? path, + final int? permissions, + final int shareType = -1, + final String? shareWith, + final String publicUpload = 'false', + final String password = '', + final String? sendPasswordByTalk, + final String expireDate = '', + final String note = '', + final String label = '', + final String? attributes, + final bool oCSAPIRequest = true, + }) { const path0 = '/ocs/v2.php/apps/files_sharing/api/v1/shares'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end if (path != null) { queryParameters['path'] = path; } @@ -694,148 +1387,320 @@ class FilesSharingShareapiClient { queryParameters['attributes'] = attributes; } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path0, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path0, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesSharingShareapiCreateShareResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesSharingShareapiCreateShareResponseApplicationJson), - )! as FilesSharingShareapiCreateShareResponseApplicationJson; - } - throw await FilesSharingApiException.fromResponse(response); // coverage:ignore-line } - /// Get all shares relative to a file, including parent folders shares rights - Future getInheritedShares({ + /// Get all shares relative to a file, including parent folders shares rights. + /// + /// 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: + /// * [path] Path all shares will be relative to + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Shares returned + /// * 500 + /// * 404: The given path is invalid + /// + /// See: + /// * [getInheritedSharesRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getInheritedShares({ required final String path, final bool oCSAPIRequest = true, }) async { + final rawResponse = getInheritedSharesRaw( + path: path, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get all shares relative to a file, including parent folders shares rights. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [path] Path all shares will be relative to + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Shares returned + /// * 500 + /// * 404: The given path is invalid + /// + /// See: + /// * [getInheritedShares] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getInheritedSharesRaw({ + required final String path, + final bool oCSAPIRequest = true, + }) { const path0 = '/ocs/v2.php/apps/files_sharing/api/v1/shares/inherited'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['path'] = path; headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path0, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path0, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesSharingShareapiGetInheritedSharesResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesSharingShareapiGetInheritedSharesResponseApplicationJson), - )! as FilesSharingShareapiGetInheritedSharesResponseApplicationJson; - } - throw await FilesSharingApiException.fromResponse(response); // coverage:ignore-line } - /// Get all shares that are still pending - Future pendingShares({ + /// Get all shares that are still pending. + /// + /// 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: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Pending shares returned + /// + /// See: + /// * [pendingSharesRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> pendingShares({ final bool oCSAPIRequest = true, }) async { + final rawResponse = pendingSharesRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get all shares that are still pending. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Pending shares returned + /// + /// See: + /// * [pendingShares] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse pendingSharesRaw({ + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/files_sharing/api/v1/shares/pending'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesSharingShareapiPendingSharesResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesSharingShareapiPendingSharesResponseApplicationJson), - )! as FilesSharingShareapiPendingSharesResponseApplicationJson; - } - throw await FilesSharingApiException.fromResponse(response); // coverage:ignore-line } - /// Get a specific share by id - Future getShare({ + /// Get a specific share by id. + /// + /// 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: + /// * [includeTags] Include tags in the share + /// * [id] ID of the share + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Share returned + /// * 404: Share not found + /// + /// See: + /// * [getShareRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getShare({ required final String id, final int includeTags = 0, final bool oCSAPIRequest = true, }) async { + final rawResponse = getShareRaw( + id: id, + includeTags: includeTags, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get a specific share by id. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [includeTags] Include tags in the share + /// * [id] ID of the share + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Share returned + /// * 404: Share not found + /// + /// See: + /// * [getShare] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getShareRaw({ + required final String id, + final int includeTags = 0, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/files_sharing/api/v1/shares/{id}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{id}', Uri.encodeQueryComponent(id)); if (includeTags != 0) { queryParameters['include_tags'] = includeTags.toString(); } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesSharingShareapiGetShareResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesSharingShareapiGetShareResponseApplicationJson), - )! as FilesSharingShareapiGetShareResponseApplicationJson; - } - throw await FilesSharingApiException.fromResponse(response); // coverage:ignore-line } - /// Update a share - Future updateShare({ + /// Update a share. + /// + /// 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: + /// * [permissions] New permissions + /// * [password] New password + /// * [sendPasswordByTalk] New condition if the password should be send over Talk + /// * [publicUpload] New condition if public uploading is allowed + /// * [expireDate] New expiry date + /// * [note] New note + /// * [label] New label + /// * [hideDownload] New condition if the download should be hidden + /// * [attributes] New additional attributes + /// * [id] ID of the share + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Share updated successfully + /// * 400: Share could not be updated because the requested changes are invalid + /// * 403: Missing permissions to update the share + /// * 404: Share not found + /// + /// See: + /// * [updateShareRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> updateShare({ required final String id, final int? permissions, final String? password, @@ -848,25 +1713,89 @@ class FilesSharingShareapiClient { final String? attributes, final bool oCSAPIRequest = true, }) async { + final rawResponse = updateShareRaw( + id: id, + permissions: permissions, + password: password, + sendPasswordByTalk: sendPasswordByTalk, + publicUpload: publicUpload, + expireDate: expireDate, + note: note, + label: label, + hideDownload: hideDownload, + attributes: attributes, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Update a share. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [permissions] New permissions + /// * [password] New password + /// * [sendPasswordByTalk] New condition if the password should be send over Talk + /// * [publicUpload] New condition if public uploading is allowed + /// * [expireDate] New expiry date + /// * [note] New note + /// * [label] New label + /// * [hideDownload] New condition if the download should be hidden + /// * [attributes] New additional attributes + /// * [id] ID of the share + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Share updated successfully + /// * 400: Share could not be updated because the requested changes are invalid + /// * 403: Missing permissions to update the share + /// * 404: Share not found + /// + /// See: + /// * [updateShare] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse updateShareRaw({ + required final String id, + final int? permissions, + final String? password, + final String? sendPasswordByTalk, + final String? publicUpload, + final String? expireDate, + final String? note, + final String? label, + final String? hideDownload, + final String? attributes, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/files_sharing/api/v1/shares/{id}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{id}', Uri.encodeQueryComponent(id)); if (permissions != null) { queryParameters['permissions'] = permissions.toString(); @@ -896,101 +1825,203 @@ class FilesSharingShareapiClient { queryParameters['attributes'] = attributes; } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'put', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'put', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesSharingShareapiUpdateShareResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesSharingShareapiUpdateShareResponseApplicationJson), - )! as FilesSharingShareapiUpdateShareResponseApplicationJson; - } - throw await FilesSharingApiException.fromResponse(response); // coverage:ignore-line } - /// Delete a share - Future deleteShare({ + /// Delete a share. + /// + /// 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] ID of the share + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Share deleted successfully + /// * 404: Share not found + /// * 403: Missing permissions to delete the share + /// + /// See: + /// * [deleteShareRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> deleteShare({ required final String id, final bool oCSAPIRequest = true, }) async { + final rawResponse = deleteShareRaw( + id: id, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Delete a share. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [id] ID of the share + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Share deleted successfully + /// * 404: Share not found + /// * 403: Missing permissions to delete the share + /// + /// See: + /// * [deleteShare] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse deleteShareRaw({ + required final String id, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/files_sharing/api/v1/shares/{id}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{id}', Uri.encodeQueryComponent(id)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'delete', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesSharingShareapiDeleteShareResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesSharingShareapiDeleteShareResponseApplicationJson), - )! as FilesSharingShareapiDeleteShareResponseApplicationJson; - } - throw await FilesSharingApiException.fromResponse(response); // coverage:ignore-line } - /// Accept a share - Future acceptShare({ + /// Accept a share. + /// + /// 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] ID of the share + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Share accepted successfully + /// * 404: Share not found + /// * 400: Share could not be accepted + /// + /// See: + /// * [acceptShareRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> acceptShare({ required final String id, final bool oCSAPIRequest = true, }) async { + final rawResponse = acceptShareRaw( + id: id, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Accept a share. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [id] ID of the share + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Share accepted successfully + /// * 404: Share not found + /// * 400: Share could not be accepted + /// + /// See: + /// * [acceptShare] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse acceptShareRaw({ + required final String id, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/files_sharing/api/v1/shares/pending/{id}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{id}', Uri.encodeQueryComponent(id)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesSharingShareapiAcceptShareResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesSharingShareapiAcceptShareResponseApplicationJson), - )! as FilesSharingShareapiAcceptShareResponseApplicationJson; - } - throw await FilesSharingApiException.fromResponse(response); // coverage:ignore-line } } @@ -999,9 +2030,28 @@ class FilesSharingShareesapiClient { final FilesSharingClient _rootClient; - /// Search for sharees + /// Search for sharees. + /// + /// 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: + /// * [search] Text to search for + /// * [itemType] Limit to specific item types + /// * [page] Page offset for searching + /// * [perPage] Limit amount of search results per page + /// * [shareType] Limit to specific share types + /// * [lookup] If a global lookup should be performed too + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Sharees search result returned + /// * 400: Invalid search parameters + /// + /// See: + /// * [searchRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. Future< - FilesSharingResponse> search({ final String search = '', final String? itemType, @@ -1011,25 +2061,76 @@ class FilesSharingShareesapiClient { final int lookup = 0, final bool oCSAPIRequest = true, }) async { + final rawResponse = searchRaw( + search: search, + itemType: itemType, + page: page, + perPage: perPage, + shareType: shareType, + lookup: lookup, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Search for sharees. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [search] Text to search for + /// * [itemType] Limit to specific item types + /// * [page] Page offset for searching + /// * [perPage] Limit amount of search results per page + /// * [shareType] Limit to specific share types + /// * [lookup] If a global lookup should be performed too + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Sharees search result returned + /// * 400: Invalid search parameters + /// + /// See: + /// * [search] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse searchRaw({ + final String search = '', + final String? itemType, + final int page = 1, + final int perPage = 200, + final ContentString? shareType, + final int lookup = 0, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/files_sharing/api/v1/sharees'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end if (search != '') { queryParameters['search'] = search; } @@ -1052,53 +2153,98 @@ class FilesSharingShareesapiClient { queryParameters['lookup'] = lookup.toString(); } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesSharingShareesapiSearchResponseApplicationJson), + headersType: const FullType(FilesSharingShareesapiShareesapiSearchHeaders), + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return FilesSharingResponse( - _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesSharingShareesapiSearchResponseApplicationJson), - )! as FilesSharingShareesapiSearchResponseApplicationJson, - _jsonSerializers.deserialize( - response.responseHeaders, - specifiedType: const FullType(FilesSharingShareesapiShareesapiSearchHeaders), - )! as FilesSharingShareesapiShareesapiSearchHeaders, - ); - } - throw await FilesSharingApiException.fromResponse(response); // coverage:ignore-line } - /// Find recommended sharees - Future findRecommended({ + /// Find recommended sharees. + /// + /// 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: + /// * [itemType] Limit to specific item types + /// * [shareType] Limit to specific share types + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Recommended sharees returned + /// + /// See: + /// * [findRecommendedRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> findRecommended({ required final String itemType, final ContentString? shareType, final bool oCSAPIRequest = true, }) async { + final rawResponse = findRecommendedRaw( + itemType: itemType, + shareType: shareType, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Find recommended sharees. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [itemType] Limit to specific item types + /// * [shareType] Limit to specific share types + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Recommended sharees returned + /// + /// See: + /// * [findRecommended] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse findRecommendedRaw({ + required final String itemType, + final ContentString? shareType, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/files_sharing/api/v1/sharees_recommended'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['itemType'] = itemType; if (shareType != null) { queryParameters['shareType'] = _jsonSerializers.serialize( @@ -1107,19 +2253,19 @@ class FilesSharingShareesapiClient { ); } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(FilesSharingShareesapiFindRecommendedResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(FilesSharingShareesapiFindRecommendedResponseApplicationJson), - )! as FilesSharingShareesapiFindRecommendedResponseApplicationJson; - } - throw await FilesSharingApiException.fromResponse(response); // coverage:ignore-line } } @@ -1876,10 +3022,10 @@ class _$FilesSharingShareInfo_SizeSerializer implements PrimitiveSerializer x != null).isNotEmpty, 'Need oneOf for ${result._data}'); return result.build(); @@ -1970,10 +3116,10 @@ class _$FilesSharingShare_ItemSizeSerializer implements PrimitiveSerializer x != null).isNotEmpty, 'Need oneOf for ${result._data}'); return result.build(); @@ -2739,7 +3885,7 @@ class _$FilesSharingShareesapiSearchShareTypeSerializer }) { final result = FilesSharingShareesapiSearchShareTypeBuilder()..data = JsonObject(data); try { - result._$int = data as int?; + result._$int = _jsonSerializers.deserialize(data, specifiedType: const FullType(int))! as int; } catch (_) {} try { result._builtListInt = (_jsonSerializers.deserialize( @@ -3540,7 +4686,7 @@ class _$FilesSharingShareesapiFindRecommendedShareTypeSerializer }) { final result = FilesSharingShareesapiFindRecommendedShareTypeBuilder()..data = JsonObject(data); try { - result._$int = data as int?; + result._$int = _jsonSerializers.deserialize(data, specifiedType: const FullType(int))! as int; } catch (_) {} try { result._builtListInt = (_jsonSerializers.deserialize( @@ -4662,14 +5808,8 @@ final Serializers _serializers = (Serializers().toBuilder() ..add(FilesSharingCapabilities_FilesSharing_Sharee.serializer)) .build(); -Serializers get filesSharingSerializers => _serializers; - final Serializers _jsonSerializers = (_serializers.toBuilder() ..addPlugin(StandardJsonPlugin()) ..addPlugin(const ContentStringPlugin())) .build(); - -T deserializeFilesSharing(final Object data) => _serializers.deserialize(data, specifiedType: FullType(T))! as T; - -Object? serializeFilesSharing(final T data) => _serializers.serialize(data, specifiedType: FullType(T)); // coverage:ignore-end diff --git a/packages/nextcloud/lib/src/api/files_trashbin.openapi.dart b/packages/nextcloud/lib/src/api/files_trashbin.openapi.dart index 670d5527..b3b54e2d 100644 --- a/packages/nextcloud/lib/src/api/files_trashbin.openapi.dart +++ b/packages/nextcloud/lib/src/api/files_trashbin.openapi.dart @@ -1,54 +1,22 @@ // ignore_for_file: camel_case_types +// ignore_for_file: discarded_futures // ignore_for_file: public_member_api_docs +// ignore_for_file: unreachable_switch_case import 'dart:typed_data'; import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.dart'; import 'package:built_value/standard_json_plugin.dart'; +import 'package:collection/collection.dart'; import 'package:dynamite_runtime/content_string.dart'; import 'package:dynamite_runtime/http_client.dart'; +import 'package:meta/meta.dart'; import 'package:universal_io/io.dart'; export 'package:dynamite_runtime/http_client.dart'; part 'files_trashbin.openapi.g.dart'; -class FilesTrashbinResponse extends DynamiteResponse { - FilesTrashbinResponse( - super.data, - super.headers, - ); - - @override - String toString() => 'FilesTrashbinResponse(data: $data, headers: $headers)'; -} - -class FilesTrashbinApiException extends DynamiteApiException { - FilesTrashbinApiException( - super.statusCode, - super.headers, - super.body, - ); - - static Future fromResponse(final HttpClientResponse response) async { - String body; - try { - body = await response.body; - } on FormatException { - body = 'binary'; - } - - return FilesTrashbinApiException( - response.statusCode, - response.responseHeaders, - body, - ); - } - - @override - String toString() => 'FilesTrashbinApiException(statusCode: $statusCode, headers: $headers, body: $body)'; -} - class FilesTrashbinClient extends DynamiteClient { FilesTrashbinClient( super.baseURL, { @@ -76,32 +44,91 @@ class FilesTrashbinPreviewClient { final FilesTrashbinClient _rootClient; - /// Get the preview for a file - Future getPreview({ + /// Get the preview for a file. + /// + /// 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: + /// * [fileId] ID of the file + /// * [x] Width of the preview + /// * [y] Height of the preview + /// * [a] Whether to not crop the preview + /// + /// Status codes: + /// * 200: Preview returned + /// * 400: Getting preview is not possible + /// * 404: Preview not found + /// + /// See: + /// * [getPreviewRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getPreview({ final int fileId = -1, final int x = 32, final int y = 32, final int a = 0, }) async { + final rawResponse = getPreviewRaw( + fileId: fileId, + x: x, + y: y, + a: a, + ); + + return rawResponse.future; + } + + /// Get the preview for a file. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [fileId] ID of the file + /// * [x] Width of the preview + /// * [y] Height of the preview + /// * [a] Whether to not crop the preview + /// + /// Status codes: + /// * 200: Preview returned + /// * 400: Getting preview is not possible + /// * 404: Preview not found + /// + /// See: + /// * [getPreview] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getPreviewRaw({ + final int fileId = -1, + final int x = 32, + final int y = 32, + final int a = 0, + }) { const path = '/index.php/apps/files_trashbin/preview'; final queryParameters = {}; final headers = { 'Accept': '*/*', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end if (fileId != -1) { queryParameters['fileId'] = fileId.toString(); } @@ -114,16 +141,19 @@ class FilesTrashbinPreviewClient { if (a != 0) { queryParameters['a'] = a.toString(); } - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(Uint8List), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return response.bodyBytes; - } - throw await FilesTrashbinApiException.fromResponse(response); // coverage:ignore-line } } @@ -195,14 +225,8 @@ final Serializers _serializers = (Serializers().toBuilder() ..add(FilesTrashbinCapabilities_Files.serializer)) .build(); -Serializers get filesTrashbinSerializers => _serializers; - final Serializers _jsonSerializers = (_serializers.toBuilder() ..addPlugin(StandardJsonPlugin()) ..addPlugin(const ContentStringPlugin())) .build(); - -T deserializeFilesTrashbin(final Object data) => _serializers.deserialize(data, specifiedType: FullType(T))! as T; - -Object? serializeFilesTrashbin(final T data) => _serializers.serialize(data, specifiedType: FullType(T)); // coverage:ignore-end diff --git a/packages/nextcloud/lib/src/api/files_versions.openapi.dart b/packages/nextcloud/lib/src/api/files_versions.openapi.dart index 3018a2ae..2a57fa96 100644 --- a/packages/nextcloud/lib/src/api/files_versions.openapi.dart +++ b/packages/nextcloud/lib/src/api/files_versions.openapi.dart @@ -1,54 +1,22 @@ // ignore_for_file: camel_case_types +// ignore_for_file: discarded_futures // ignore_for_file: public_member_api_docs +// ignore_for_file: unreachable_switch_case import 'dart:typed_data'; import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.dart'; import 'package:built_value/standard_json_plugin.dart'; +import 'package:collection/collection.dart'; import 'package:dynamite_runtime/content_string.dart'; import 'package:dynamite_runtime/http_client.dart'; +import 'package:meta/meta.dart'; import 'package:universal_io/io.dart'; export 'package:dynamite_runtime/http_client.dart'; part 'files_versions.openapi.g.dart'; -class FilesVersionsResponse extends DynamiteResponse { - FilesVersionsResponse( - super.data, - super.headers, - ); - - @override - String toString() => 'FilesVersionsResponse(data: $data, headers: $headers)'; -} - -class FilesVersionsApiException extends DynamiteApiException { - FilesVersionsApiException( - super.statusCode, - super.headers, - super.body, - ); - - static Future fromResponse(final HttpClientResponse response) async { - String body; - try { - body = await response.body; - } on FormatException { - body = 'binary'; - } - - return FilesVersionsApiException( - response.statusCode, - response.responseHeaders, - body, - ); - } - - @override - String toString() => 'FilesVersionsApiException(statusCode: $statusCode, headers: $headers, body: $body)'; -} - class FilesVersionsClient extends DynamiteClient { FilesVersionsClient( super.baseURL, { @@ -76,32 +44,91 @@ class FilesVersionsPreviewClient { final FilesVersionsClient _rootClient; - /// Get the preview for a file version - Future getPreview({ + /// Get the preview for a file version. + /// + /// 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: + /// * [file] Path of the file + /// * [x] Width of the preview + /// * [y] Height of the preview + /// * [version] Version of the file to get the preview for + /// + /// Status codes: + /// * 200: Preview returned + /// * 400: Getting preview is not possible + /// * 404: Preview not found + /// + /// See: + /// * [getPreviewRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getPreview({ final String file = '', final int x = 44, final int y = 44, final String version = '', }) async { + final rawResponse = getPreviewRaw( + file: file, + x: x, + y: y, + version: version, + ); + + return rawResponse.future; + } + + /// Get the preview for a file version. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [file] Path of the file + /// * [x] Width of the preview + /// * [y] Height of the preview + /// * [version] Version of the file to get the preview for + /// + /// Status codes: + /// * 200: Preview returned + /// * 400: Getting preview is not possible + /// * 404: Preview not found + /// + /// See: + /// * [getPreview] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getPreviewRaw({ + final String file = '', + final int x = 44, + final int y = 44, + final String version = '', + }) { const path = '/index.php/apps/files_versions/preview'; final queryParameters = {}; final headers = { 'Accept': '*/*', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end if (file != '') { queryParameters['file'] = file; } @@ -114,16 +141,19 @@ class FilesVersionsPreviewClient { if (version != '') { queryParameters['version'] = version; } - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(Uint8List), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return response.bodyBytes; - } - throw await FilesVersionsApiException.fromResponse(response); // coverage:ignore-line } } @@ -199,14 +229,8 @@ final Serializers _serializers = (Serializers().toBuilder() ..add(FilesVersionsCapabilities_Files.serializer)) .build(); -Serializers get filesVersionsSerializers => _serializers; - final Serializers _jsonSerializers = (_serializers.toBuilder() ..addPlugin(StandardJsonPlugin()) ..addPlugin(const ContentStringPlugin())) .build(); - -T deserializeFilesVersions(final Object data) => _serializers.deserialize(data, specifiedType: FullType(T))! as T; - -Object? serializeFilesVersions(final T data) => _serializers.serialize(data, specifiedType: FullType(T)); // coverage:ignore-end diff --git a/packages/nextcloud/lib/src/api/news.openapi.dart b/packages/nextcloud/lib/src/api/news.openapi.dart index 25b0d0b9..7abfaa7a 100644 --- a/packages/nextcloud/lib/src/api/news.openapi.dart +++ b/packages/nextcloud/lib/src/api/news.openapi.dart @@ -1,5 +1,7 @@ // ignore_for_file: camel_case_types +// ignore_for_file: discarded_futures // ignore_for_file: public_member_api_docs +// ignore_for_file: unreachable_switch_case import 'dart:typed_data'; import 'package:built_collection/built_collection.dart'; @@ -7,50 +9,16 @@ 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'; +import 'package:collection/collection.dart'; import 'package:dynamite_runtime/content_string.dart'; import 'package:dynamite_runtime/http_client.dart'; +import 'package:meta/meta.dart'; import 'package:universal_io/io.dart'; export 'package:dynamite_runtime/http_client.dart'; part 'news.openapi.g.dart'; -class NewsResponse extends DynamiteResponse { - NewsResponse( - super.data, - super.headers, - ); - - @override - String toString() => 'NewsResponse(data: $data, headers: $headers)'; -} - -class NewsApiException extends DynamiteApiException { - NewsApiException( - super.statusCode, - super.headers, - super.body, - ); - - static Future fromResponse(final HttpClientResponse response) async { - String body; - try { - body = await response.body; - } on FormatException { - body = 'binary'; - } - - return NewsApiException( - response.statusCode, - response.responseHeaders, - body, - ); - } - - @override - String toString() => 'NewsApiException(statusCode: $statusCode, headers: $headers, body: $body)'; -} - class NewsClient extends DynamiteClient { NewsClient( super.baseURL, { @@ -70,349 +38,912 @@ class NewsClient extends DynamiteClient { authentications: client.authentications, ); - Future getSupportedApiVersions() async { + /// 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 + /// + /// See: + /// * [getSupportedApiVersionsRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getSupportedApiVersions() async { + final rawResponse = getSupportedApiVersionsRaw(); + + return rawResponse.future; + } + + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [getSupportedApiVersions] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getSupportedApiVersionsRaw() { const path = '/index.php/apps/news/api'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end - final response = await doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(NewsSupportedAPIVersions), - )! as NewsSupportedAPIVersions; - } - throw await NewsApiException.fromResponse(response); // coverage:ignore-line + +// coverage:ignore-end + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(NewsSupportedAPIVersions), + headersType: null, + serializers: _jsonSerializers, + ); } - Future listFolders() async { + /// 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 + /// + /// See: + /// * [listFoldersRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> listFolders() async { + final rawResponse = listFoldersRaw(); + + return rawResponse.future; + } + + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [listFolders] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse listFoldersRaw() { const path = '/index.php/apps/news/api/v1-3/folders'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end - final response = await doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize(await response.jsonBody, specifiedType: const FullType(NewsListFolders))! - as NewsListFolders; - } - throw await NewsApiException.fromResponse(response); // coverage:ignore-line + +// coverage:ignore-end + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(NewsListFolders), + headersType: null, + serializers: _jsonSerializers, + ); } - Future createFolder({required final String name}) async { + /// 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: + /// * [name] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [createFolderRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> createFolder({required final String name}) async { + final rawResponse = createFolderRaw( + name: name, + ); + + return rawResponse.future; + } + + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [name] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [createFolder] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse createFolderRaw({required final String name}) { const path = '/index.php/apps/news/api/v1-3/folders'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['name'] = name; - final response = await doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize(await response.jsonBody, specifiedType: const FullType(NewsListFolders))! - as NewsListFolders; - } - throw await NewsApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(NewsListFolders), + headersType: null, + serializers: _jsonSerializers, + ); } - Future renameFolder({ + /// 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: + /// * [name] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [renameFolderRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> renameFolder({ required final int folderId, required final String name, }) async { + final rawResponse = renameFolderRaw( + folderId: folderId, + name: name, + ); + + return rawResponse.future; + } + + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [name] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [renameFolder] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse renameFolderRaw({ + required final int folderId, + required final String name, + }) { var path = '/index.php/apps/news/api/v1-3/folders/{folderId}'; final queryParameters = {}; final headers = {}; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{folderId}', Uri.encodeQueryComponent(folderId.toString())); queryParameters['name'] = name; - final response = await doRequest( - 'put', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return; - } - throw await NewsApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'put', + uri, + headers, + body, + const {200}, + ), + bodyType: null, + headersType: null, + serializers: _jsonSerializers, + ); } - Future deleteFolder({required final int folderId}) async { + /// 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 + /// + /// See: + /// * [deleteFolderRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> deleteFolder({required final int folderId}) async { + final rawResponse = deleteFolderRaw( + folderId: folderId, + ); + + return rawResponse.future; + } + + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [deleteFolder] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse deleteFolderRaw({required final int folderId}) { var path = '/index.php/apps/news/api/v1-3/folders/{folderId}'; final queryParameters = {}; final headers = {}; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{folderId}', Uri.encodeQueryComponent(folderId.toString())); - final response = await doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return; - } - throw await NewsApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'delete', + uri, + headers, + body, + const {200}, + ), + bodyType: null, + headersType: null, + serializers: _jsonSerializers, + ); } - Future markFolderAsRead({ + /// 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: + /// * [newestItemId] The newest read item + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [markFolderAsReadRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> markFolderAsRead({ required final int folderId, required final int newestItemId, }) async { + final rawResponse = markFolderAsReadRaw( + folderId: folderId, + newestItemId: newestItemId, + ); + + return rawResponse.future; + } + + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [newestItemId] The newest read item + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [markFolderAsRead] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse markFolderAsReadRaw({ + required final int folderId, + required final int newestItemId, + }) { var path = '/index.php/apps/news/api/v1-3/folders/{folderId}/read'; final queryParameters = {}; final headers = {}; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{folderId}', Uri.encodeQueryComponent(folderId.toString())); queryParameters['newestItemId'] = newestItemId.toString(); - final response = await doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return; - } - throw await NewsApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: null, + headersType: null, + serializers: _jsonSerializers, + ); + } + + /// 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 + /// + /// See: + /// * [listFeedsRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> listFeeds() async { + final rawResponse = listFeedsRaw(); + + return rawResponse.future; } - Future listFeeds() async { + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [listFeeds] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse listFeedsRaw() { const path = '/index.php/apps/news/api/v1-3/feeds'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end - final response = await doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize(await response.jsonBody, specifiedType: const FullType(NewsListFeeds))! - as NewsListFeeds; - } - throw await NewsApiException.fromResponse(response); // coverage:ignore-line + +// coverage:ignore-end + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(NewsListFeeds), + headersType: null, + serializers: _jsonSerializers, + ); } - Future addFeed({ + /// 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: + /// * [url] + /// * [folderId] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [addFeedRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> addFeed({ required final String url, final int? folderId, }) async { + final rawResponse = addFeedRaw( + url: url, + folderId: folderId, + ); + + return rawResponse.future; + } + + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [url] + /// * [folderId] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [addFeed] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse addFeedRaw({ + required final String url, + final int? folderId, + }) { const path = '/index.php/apps/news/api/v1-3/feeds'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['url'] = url; if (folderId != null) { queryParameters['folderId'] = folderId.toString(); } - final response = await doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize(await response.jsonBody, specifiedType: const FullType(NewsListFeeds))! - as NewsListFeeds; - } - throw await NewsApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(NewsListFeeds), + headersType: null, + serializers: _jsonSerializers, + ); + } + + /// 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 + /// + /// See: + /// * [deleteFeedRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> deleteFeed({required final int feedId}) async { + final rawResponse = deleteFeedRaw( + feedId: feedId, + ); + + return rawResponse.future; } - Future deleteFeed({required final int feedId}) async { + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [deleteFeed] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse deleteFeedRaw({required final int feedId}) { var path = '/index.php/apps/news/api/v1-3/feeds/{feedId}'; final queryParameters = {}; final headers = {}; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{feedId}', Uri.encodeQueryComponent(feedId.toString())); - final response = await doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return; - } - throw await NewsApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'delete', + uri, + headers, + body, + const {200}, + ), + bodyType: null, + headersType: null, + serializers: _jsonSerializers, + ); } - Future moveFeed({ + /// 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: + /// * [folderId] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [moveFeedRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> moveFeed({ required final int feedId, final int? folderId, }) async { + final rawResponse = moveFeedRaw( + feedId: feedId, + folderId: folderId, + ); + + return rawResponse.future; + } + + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [folderId] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [moveFeed] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse moveFeedRaw({ + required final int feedId, + final int? folderId, + }) { var path = '/index.php/apps/news/api/v1-3/feeds/{feedId}/move'; final queryParameters = {}; final headers = {}; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{feedId}', Uri.encodeQueryComponent(feedId.toString())); if (folderId != null) { queryParameters['folderId'] = folderId.toString(); } - final response = await doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return; - } - throw await NewsApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: null, + headersType: null, + serializers: _jsonSerializers, + ); } - Future renameFeed({ + /// 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: + /// * [feedTitle] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [renameFeedRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> renameFeed({ required final int feedId, required final String feedTitle, }) async { + final rawResponse = renameFeedRaw( + feedId: feedId, + feedTitle: feedTitle, + ); + + return rawResponse.future; + } + + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [feedTitle] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [renameFeed] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse renameFeedRaw({ + required final int feedId, + required final String feedTitle, + }) { var path = '/index.php/apps/news/api/v1-3/feeds/{feedId}/rename'; final queryParameters = {}; final headers = {}; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{feedId}', Uri.encodeQueryComponent(feedId.toString())); queryParameters['feedTitle'] = feedTitle; - final response = await doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return; - } - throw await NewsApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: null, + headersType: null, + serializers: _jsonSerializers, + ); } - Future markFeedAsRead({ + /// 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: + /// * [newestItemId] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [markFeedAsReadRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> markFeedAsRead({ required final int feedId, required final int newestItemId, }) async { + final rawResponse = markFeedAsReadRaw( + feedId: feedId, + newestItemId: newestItemId, + ); + + return rawResponse.future; + } + + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [newestItemId] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [markFeedAsRead] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse markFeedAsReadRaw({ + required final int feedId, + required final int newestItemId, + }) { var path = '/index.php/apps/news/api/v1-3/feeds/{feedId}/read'; final queryParameters = {}; final headers = {}; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{feedId}', Uri.encodeQueryComponent(feedId.toString())); queryParameters['newestItemId'] = newestItemId.toString(); - final response = await doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return; - } - throw await NewsApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: null, + headersType: null, + serializers: _jsonSerializers, + ); } - Future listArticles({ + /// 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: + /// * [type] + /// * [id] + /// * [getRead] + /// * [batchSize] + /// * [offset] + /// * [oldestFirst] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [listArticlesRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> listArticles({ final int type = 3, final int id = 0, final int getRead = 1, @@ -420,19 +951,69 @@ class NewsClient extends DynamiteClient { final int offset = 0, final int oldestFirst = 0, }) async { + final rawResponse = listArticlesRaw( + type: type, + id: id, + getRead: getRead, + batchSize: batchSize, + offset: offset, + oldestFirst: oldestFirst, + ); + + return rawResponse.future; + } + + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [type] + /// * [id] + /// * [getRead] + /// * [batchSize] + /// * [offset] + /// * [oldestFirst] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [listArticles] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse listArticlesRaw({ + final int type = 3, + final int id = 0, + final int getRead = 1, + final int batchSize = -1, + final int offset = 0, + final int oldestFirst = 0, + }) { const path = '/index.php/apps/news/api/v1-3/items'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end if (type != 3) { queryParameters['type'] = type.toString(); } @@ -451,37 +1032,93 @@ class NewsClient extends DynamiteClient { if (oldestFirst != 0) { queryParameters['oldestFirst'] = oldestFirst.toString(); } - final response = await doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize(await response.jsonBody, specifiedType: const FullType(NewsListArticles))! - as NewsListArticles; - } - throw await NewsApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(NewsListArticles), + headersType: null, + serializers: _jsonSerializers, + ); } - Future listUpdatedArticles({ + /// 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: + /// * [type] + /// * [id] + /// * [lastModified] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [listUpdatedArticlesRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> listUpdatedArticles({ final int type = 3, final int id = 0, final int lastModified = 0, }) async { + final rawResponse = listUpdatedArticlesRaw( + type: type, + id: id, + lastModified: lastModified, + ); + + return rawResponse.future; + } + + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [type] + /// * [id] + /// * [lastModified] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [listUpdatedArticles] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse listUpdatedArticlesRaw({ + final int type = 3, + final int id = 0, + final int lastModified = 0, + }) { const path = '/index.php/apps/news/api/v1-3/items/updated'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end if (type != 3) { queryParameters['type'] = type.toString(); } @@ -491,117 +1128,283 @@ class NewsClient extends DynamiteClient { if (lastModified != 0) { queryParameters['lastModified'] = lastModified.toString(); } - final response = await doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize(await response.jsonBody, specifiedType: const FullType(NewsListArticles))! - as NewsListArticles; - } - throw await NewsApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(NewsListArticles), + headersType: null, + serializers: _jsonSerializers, + ); + } + + /// 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 + /// + /// See: + /// * [markArticleAsReadRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> markArticleAsRead({required final int itemId}) async { + final rawResponse = markArticleAsReadRaw( + itemId: itemId, + ); + + return rawResponse.future; } - Future markArticleAsRead({required final int itemId}) async { + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [markArticleAsRead] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse markArticleAsReadRaw({required final int itemId}) { var path = '/index.php/apps/news/api/v1-3/items/{itemId}/read'; final queryParameters = {}; final headers = {}; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{itemId}', Uri.encodeQueryComponent(itemId.toString())); - final response = await doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return; - } - throw await NewsApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: null, + headersType: null, + serializers: _jsonSerializers, + ); } - Future markArticleAsUnread({required final int itemId}) async { + /// 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 + /// + /// See: + /// * [markArticleAsUnreadRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> markArticleAsUnread({required final int itemId}) async { + final rawResponse = markArticleAsUnreadRaw( + itemId: itemId, + ); + + return rawResponse.future; + } + + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [markArticleAsUnread] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse markArticleAsUnreadRaw({required final int itemId}) { var path = '/index.php/apps/news/api/v1-3/items/{itemId}/unread'; final queryParameters = {}; final headers = {}; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{itemId}', Uri.encodeQueryComponent(itemId.toString())); - final response = await doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return; - } - throw await NewsApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: null, + headersType: null, + serializers: _jsonSerializers, + ); + } + + /// 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 + /// + /// See: + /// * [starArticleRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> starArticle({required final int itemId}) async { + final rawResponse = starArticleRaw( + itemId: itemId, + ); + + return rawResponse.future; } - Future starArticle({required final int itemId}) async { + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [starArticle] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse starArticleRaw({required final int itemId}) { var path = '/index.php/apps/news/api/v1-3/items/{itemId}/star'; final queryParameters = {}; final headers = {}; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{itemId}', Uri.encodeQueryComponent(itemId.toString())); - final response = await doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return; - } - throw await NewsApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: null, + headersType: null, + serializers: _jsonSerializers, + ); } - Future unstarArticle({required final int itemId}) async { + /// 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 + /// + /// See: + /// * [unstarArticleRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> unstarArticle({required final int itemId}) async { + final rawResponse = unstarArticleRaw( + itemId: itemId, + ); + + return rawResponse.future; + } + + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [unstarArticle] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse unstarArticleRaw({required final int itemId}) { var path = '/index.php/apps/news/api/v1-3/items/{itemId}/unstar'; final queryParameters = {}; final headers = {}; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{itemId}', Uri.encodeQueryComponent(itemId.toString())); - final response = await doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return; - } - throw await NewsApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: null, + headersType: null, + serializers: _jsonSerializers, + ); } } @@ -720,7 +1523,7 @@ abstract interface class NewsFolderInterface { String get name; bool get opened; - /// This seems to be broken. In testing it is always empty + /// This seems to be broken. In testing it is always empty. BuiltList get feeds; NewsFolderInterface rebuild(final void Function(NewsFolderInterfaceBuilder) updates); NewsFolderInterfaceBuilder toBuilder(); @@ -934,14 +1737,8 @@ final Serializers _serializers = (Serializers().toBuilder() ..addBuilderFactory(const FullType(BuiltList, [FullType(JsonObject)]), ListBuilder.new)) .build(); -Serializers get newsSerializers => _serializers; - final Serializers _jsonSerializers = (_serializers.toBuilder() ..addPlugin(StandardJsonPlugin()) ..addPlugin(const ContentStringPlugin())) .build(); - -T deserializeNews(final Object data) => _serializers.deserialize(data, specifiedType: FullType(T))! as T; - -Object? serializeNews(final T data) => _serializers.serialize(data, specifiedType: FullType(T)); // coverage:ignore-end diff --git a/packages/nextcloud/lib/src/api/notes.openapi.dart b/packages/nextcloud/lib/src/api/notes.openapi.dart index 3aaed16b..44f71db2 100644 --- a/packages/nextcloud/lib/src/api/notes.openapi.dart +++ b/packages/nextcloud/lib/src/api/notes.openapi.dart @@ -1,5 +1,7 @@ // ignore_for_file: camel_case_types +// ignore_for_file: discarded_futures // ignore_for_file: public_member_api_docs +// ignore_for_file: unreachable_switch_case import 'dart:convert'; import 'dart:typed_data'; @@ -8,50 +10,16 @@ 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'; +import 'package:collection/collection.dart'; import 'package:dynamite_runtime/content_string.dart'; import 'package:dynamite_runtime/http_client.dart'; +import 'package:meta/meta.dart'; import 'package:universal_io/io.dart'; export 'package:dynamite_runtime/http_client.dart'; part 'notes.openapi.g.dart'; -class NotesResponse extends DynamiteResponse { - NotesResponse( - super.data, - super.headers, - ); - - @override - String toString() => 'NotesResponse(data: $data, headers: $headers)'; -} - -class NotesApiException extends DynamiteApiException { - NotesApiException( - super.statusCode, - super.headers, - super.body, - ); - - static Future fromResponse(final HttpClientResponse response) async { - String body; - try { - body = await response.body; - } on FormatException { - body = 'binary'; - } - - return NotesApiException( - response.statusCode, - response.responseHeaders, - body, - ); - } - - @override - String toString() => 'NotesApiException(statusCode: $statusCode, headers: $headers, body: $body)'; -} - class NotesClient extends DynamiteClient { NotesClient( super.baseURL, { @@ -71,7 +39,23 @@ class NotesClient extends DynamiteClient { authentications: client.authentications, ); - Future> getNotes({ + /// 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] + /// * [exclude] + /// * [pruneBefore] + /// * [chunkSize] + /// * [chunkCursor] + /// * [ifNoneMatch] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [getNotesRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future, void>> getNotes({ final String? category, final String exclude = '', final int pruneBefore = 0, @@ -79,19 +63,69 @@ class NotesClient extends DynamiteClient { final String? chunkCursor, final String? ifNoneMatch, }) async { + final rawResponse = getNotesRaw( + category: category, + exclude: exclude, + pruneBefore: pruneBefore, + chunkSize: chunkSize, + chunkCursor: chunkCursor, + ifNoneMatch: ifNoneMatch, + ); + + return rawResponse.future; + } + + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [category] + /// * [exclude] + /// * [pruneBefore] + /// * [chunkSize] + /// * [chunkCursor] + /// * [ifNoneMatch] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [getNotes] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse, void> getNotesRaw({ + final String? category, + final String exclude = '', + final int pruneBefore = 0, + final int chunkSize = 0, + final String? chunkCursor, + final String? ifNoneMatch, + }) { const path = '/index.php/apps/notes/api/v1/notes'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end if (category != null) { queryParameters['category'] = category; } @@ -110,41 +144,103 @@ class NotesClient extends DynamiteClient { if (ifNoneMatch != null) { headers['If-None-Match'] = ifNoneMatch; } - final response = await doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse, void>( + response: doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(BuiltList, [FullType(NotesNote)]), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(BuiltList, [FullType(NotesNote)]), - )! as BuiltList; - } - throw await NotesApiException.fromResponse(response); // coverage:ignore-line } - Future createNote({ + /// 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] + /// * [title] + /// * [content] + /// * [modified] + /// * [favorite] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [createNoteRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> createNote({ final String category = '', final String title = '', final String content = '', final int modified = 0, final int favorite = 0, }) async { + final rawResponse = createNoteRaw( + category: category, + title: title, + content: content, + modified: modified, + favorite: favorite, + ); + + return rawResponse.future; + } + + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [category] + /// * [title] + /// * [content] + /// * [modified] + /// * [favorite] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [createNote] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse createNoteRaw({ + final String category = '', + final String title = '', + final String content = '', + final int modified = 0, + final int favorite = 0, + }) { const path = '/index.php/apps/notes/api/v1/notes'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end if (category != '') { queryParameters['category'] = category; } @@ -160,37 +256,91 @@ class NotesClient extends DynamiteClient { if (favorite != 0) { queryParameters['favorite'] = favorite.toString(); } - final response = await doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(NotesNote), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize(await response.jsonBody, specifiedType: const FullType(NotesNote))! - as NotesNote; - } - throw await NotesApiException.fromResponse(response); // coverage:ignore-line } - Future getNote({ + /// 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: + /// * [exclude] + /// * [ifNoneMatch] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [getNoteRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getNote({ required final int id, final String exclude = '', final String? ifNoneMatch, }) async { + final rawResponse = getNoteRaw( + id: id, + exclude: exclude, + ifNoneMatch: ifNoneMatch, + ); + + return rawResponse.future; + } + + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [exclude] + /// * [ifNoneMatch] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [getNote] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getNoteRaw({ + required final int id, + final String exclude = '', + final String? ifNoneMatch, + }) { var path = '/index.php/apps/notes/api/v1/notes/{id}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{id}', Uri.encodeQueryComponent(id.toString())); if (exclude != '') { queryParameters['exclude'] = exclude; @@ -198,20 +348,38 @@ class NotesClient extends DynamiteClient { if (ifNoneMatch != null) { headers['If-None-Match'] = ifNoneMatch; } - final response = await doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(NotesNote), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize(await response.jsonBody, specifiedType: const FullType(NotesNote))! - as NotesNote; - } - throw await NotesApiException.fromResponse(response); // coverage:ignore-line } - Future updateNote({ + /// 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: + /// * [content] + /// * [modified] + /// * [title] + /// * [category] + /// * [favorite] + /// * [ifMatch] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [updateNoteRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> updateNote({ required final int id, final String? content, final int? modified, @@ -220,19 +388,71 @@ class NotesClient extends DynamiteClient { final int? favorite, final String? ifMatch, }) async { + final rawResponse = updateNoteRaw( + id: id, + content: content, + modified: modified, + title: title, + category: category, + favorite: favorite, + ifMatch: ifMatch, + ); + + return rawResponse.future; + } + + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [content] + /// * [modified] + /// * [title] + /// * [category] + /// * [favorite] + /// * [ifMatch] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [updateNote] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse updateNoteRaw({ + required final int id, + final String? content, + final int? modified, + final String? title, + final String? category, + final int? favorite, + final String? ifMatch, + }) { var path = '/index.php/apps/notes/api/v1/notes/{id}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{id}', Uri.encodeQueryComponent(id.toString())); if (content != null) { queryParameters['content'] = content; @@ -252,101 +472,222 @@ class NotesClient extends DynamiteClient { if (ifMatch != null) { headers['If-Match'] = ifMatch; } - final response = await doRequest( - 'put', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'put', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(NotesNote), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize(await response.jsonBody, specifiedType: const FullType(NotesNote))! - as NotesNote; - } - throw await NotesApiException.fromResponse(response); // coverage:ignore-line } - Future deleteNote({required final int id}) async { + /// 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 + /// + /// See: + /// * [deleteNoteRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> deleteNote({required final int id}) async { + final rawResponse = deleteNoteRaw( + id: id, + ); + + return rawResponse.future; + } + + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [deleteNote] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse deleteNoteRaw({required final int id}) { var path = '/index.php/apps/notes/api/v1/notes/{id}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{id}', Uri.encodeQueryComponent(id.toString())); - final response = await doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'delete', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(String), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return response.body; - } - throw await NotesApiException.fromResponse(response); // coverage:ignore-line } - Future getSettings() async { + /// 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 + /// + /// See: + /// * [getSettingsRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getSettings() async { + final rawResponse = getSettingsRaw(); + + return rawResponse.future; + } + + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [getSettings] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getSettingsRaw() { const path = '/index.php/apps/notes/api/v1/settings'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end - final response = await doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + +// coverage:ignore-end + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(NotesSettings), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize(await response.jsonBody, specifiedType: const FullType(NotesSettings))! - as NotesSettings; - } - throw await NotesApiException.fromResponse(response); // coverage:ignore-line } - Future updateSettings({required final NotesSettings settings}) async { + /// 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 + /// + /// See: + /// * [updateSettingsRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> updateSettings({required final NotesSettings settings}) async { + final rawResponse = updateSettingsRaw( + settings: settings, + ); + + return rawResponse.future; + } + + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [updateSettings] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse updateSettingsRaw({required final NotesSettings settings}) { const path = '/index.php/apps/notes/api/v1/settings'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end headers['Content-Type'] = 'application/json'; body = utf8.encode(json.encode(_jsonSerializers.serialize(settings, specifiedType: const FullType(NotesSettings)))) as Uint8List; - final response = await doRequest( - 'put', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'put', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(NotesSettings), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize(await response.jsonBody, specifiedType: const FullType(NotesSettings))! - as NotesSettings; - } - throw await NotesApiException.fromResponse(response); // coverage:ignore-line } } @@ -591,14 +932,8 @@ final Serializers _serializers = (Serializers().toBuilder() ..addBuilderFactory(const FullType(BuiltList, [FullType(JsonObject)]), ListBuilder.new)) .build(); -Serializers get notesSerializers => _serializers; - final Serializers _jsonSerializers = (_serializers.toBuilder() ..addPlugin(StandardJsonPlugin()) ..addPlugin(const ContentStringPlugin())) .build(); - -T deserializeNotes(final Object data) => _serializers.deserialize(data, specifiedType: FullType(T))! as T; - -Object? serializeNotes(final T data) => _serializers.serialize(data, specifiedType: FullType(T)); // coverage:ignore-end diff --git a/packages/nextcloud/lib/src/api/notifications.openapi.dart b/packages/nextcloud/lib/src/api/notifications.openapi.dart index 1194d9b5..3cd31b00 100644 --- a/packages/nextcloud/lib/src/api/notifications.openapi.dart +++ b/packages/nextcloud/lib/src/api/notifications.openapi.dart @@ -1,5 +1,7 @@ // ignore_for_file: camel_case_types +// ignore_for_file: discarded_futures // ignore_for_file: public_member_api_docs +// ignore_for_file: unreachable_switch_case import 'dart:typed_data'; import 'package:built_collection/built_collection.dart'; @@ -7,50 +9,16 @@ 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'; +import 'package:collection/collection.dart'; import 'package:dynamite_runtime/content_string.dart'; import 'package:dynamite_runtime/http_client.dart'; +import 'package:meta/meta.dart'; import 'package:universal_io/io.dart'; export 'package:dynamite_runtime/http_client.dart'; part 'notifications.openapi.g.dart'; -class NotificationsResponse extends DynamiteResponse { - NotificationsResponse( - super.data, - super.headers, - ); - - @override - String toString() => 'NotificationsResponse(data: $data, headers: $headers)'; -} - -class NotificationsApiException extends DynamiteApiException { - NotificationsApiException( - super.statusCode, - super.headers, - super.body, - ); - - static Future fromResponse(final HttpClientResponse response) async { - String body; - try { - body = await response.body; - } on FormatException { - body = 'binary'; - } - - return NotificationsApiException( - response.statusCode, - response.responseHeaders, - body, - ); - } - - @override - String toString() => 'NotificationsApiException(statusCode: $statusCode, headers: $headers, body: $body)'; -} - class NotificationsClient extends DynamiteClient { NotificationsClient( super.baseURL, { @@ -84,35 +52,102 @@ class NotificationsApiClient { final NotificationsClient _rootClient; - /// Generate a notification for a user + /// Generate a notification for a user. + /// + /// This endpoint requires admin access. + /// + /// 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: + /// * [shortMessage] Subject of the notification + /// * [longMessage] Message of the notification + /// * [apiVersion] + /// * [userId] ID of the user + /// * [oCSAPIRequest] + /// + /// Status codes: + /// * 200: Notification generated successfully + /// * 400: Generating notification is not possible + /// * 404: User not found + /// * 500 /// - /// This endpoint requires admin access - Future generateNotification({ + /// See: + /// * [generateNotificationRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> generateNotification({ required final String shortMessage, required final String userId, final String longMessage = '', final NotificationsApiGenerateNotificationApiVersion apiVersion = NotificationsApiGenerateNotificationApiVersion.v2, final String oCSAPIRequest = 'true', }) async { + final rawResponse = generateNotificationRaw( + shortMessage: shortMessage, + userId: userId, + longMessage: longMessage, + apiVersion: apiVersion, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Generate a notification for a user. + /// + /// This endpoint requires admin access. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [shortMessage] Subject of the notification + /// * [longMessage] Message of the notification + /// * [apiVersion] + /// * [userId] ID of the user + /// * [oCSAPIRequest] + /// + /// Status codes: + /// * 200: Notification generated successfully + /// * 400: Generating notification is not possible + /// * 404: User not found + /// * 500 + /// + /// See: + /// * [generateNotification] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse generateNotificationRaw({ + required final String shortMessage, + required final String userId, + final String longMessage = '', + final NotificationsApiGenerateNotificationApiVersion apiVersion = NotificationsApiGenerateNotificationApiVersion.v2, + final String oCSAPIRequest = 'true', + }) { var path = '/ocs/v2.php/apps/notifications/api/{apiVersion}/admin_notifications/{userId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['shortMessage'] = shortMessage; path = path.replaceAll('{userId}', Uri.encodeQueryComponent(userId)); if (longMessage != '') { @@ -120,19 +155,19 @@ class NotificationsApiClient { } path = path.replaceAll('{apiVersion}', Uri.encodeQueryComponent(apiVersion.name)); headers['OCS-APIRequest'] = oCSAPIRequest; - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(NotificationsApiGenerateNotificationResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(NotificationsApiGenerateNotificationResponseApplicationJson), - )! as NotificationsApiGenerateNotificationResponseApplicationJson; - } - throw await NotificationsApiException.fromResponse(response); // coverage:ignore-line } } @@ -141,228 +176,488 @@ class NotificationsEndpointClient { final NotificationsClient _rootClient; - /// Get all notifications + /// Get all notifications. + /// + /// 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: + /// * [apiVersion] Version of the API to use + /// * [oCSAPIRequest] + /// + /// Status codes: + /// * 200: Notifications returned + /// * 204: No app uses notifications + /// + /// See: + /// * [listNotificationsRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. Future< - NotificationsResponse> listNotifications({ final NotificationsEndpointListNotificationsApiVersion apiVersion = NotificationsEndpointListNotificationsApiVersion.v2, final String oCSAPIRequest = 'true', }) async { + final rawResponse = listNotificationsRaw( + apiVersion: apiVersion, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get all notifications. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [apiVersion] Version of the API to use + /// * [oCSAPIRequest] + /// + /// Status codes: + /// * 200: Notifications returned + /// * 204: No app uses notifications + /// + /// See: + /// * [listNotifications] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse listNotificationsRaw({ + final NotificationsEndpointListNotificationsApiVersion apiVersion = + NotificationsEndpointListNotificationsApiVersion.v2, + final String oCSAPIRequest = 'true', + }) { var path = '/ocs/v2.php/apps/notifications/api/{apiVersion}/notifications'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{apiVersion}', Uri.encodeQueryComponent(apiVersion.name)); headers['OCS-APIRequest'] = oCSAPIRequest; - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(NotificationsEndpointListNotificationsResponseApplicationJson), + headersType: const FullType(NotificationsEndpointEndpointListNotificationsHeaders), + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return NotificationsResponse( - _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(NotificationsEndpointListNotificationsResponseApplicationJson), - )! as NotificationsEndpointListNotificationsResponseApplicationJson, - _jsonSerializers.deserialize( - response.responseHeaders, - specifiedType: const FullType(NotificationsEndpointEndpointListNotificationsHeaders), - )! as NotificationsEndpointEndpointListNotificationsHeaders, - ); - } - throw await NotificationsApiException.fromResponse(response); // coverage:ignore-line } - /// Delete all notifications - Future deleteAllNotifications({ + /// Delete all notifications. + /// + /// 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: + /// * [apiVersion] + /// * [oCSAPIRequest] + /// + /// Status codes: + /// * 200: All notifications deleted successfully + /// * 403: Deleting notification for impersonated user is not allowed + /// + /// See: + /// * [deleteAllNotificationsRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> + deleteAllNotifications({ final NotificationsEndpointDeleteAllNotificationsApiVersion apiVersion = NotificationsEndpointDeleteAllNotificationsApiVersion.v2, final String oCSAPIRequest = 'true', }) async { + final rawResponse = deleteAllNotificationsRaw( + apiVersion: apiVersion, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Delete all notifications. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [apiVersion] + /// * [oCSAPIRequest] + /// + /// Status codes: + /// * 200: All notifications deleted successfully + /// * 403: Deleting notification for impersonated user is not allowed + /// + /// See: + /// * [deleteAllNotifications] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse + deleteAllNotificationsRaw({ + final NotificationsEndpointDeleteAllNotificationsApiVersion apiVersion = + NotificationsEndpointDeleteAllNotificationsApiVersion.v2, + final String oCSAPIRequest = 'true', + }) { var path = '/ocs/v2.php/apps/notifications/api/{apiVersion}/notifications'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{apiVersion}', Uri.encodeQueryComponent(apiVersion.name)); headers['OCS-APIRequest'] = oCSAPIRequest; - final response = await _rootClient.doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'delete', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(NotificationsEndpointDeleteAllNotificationsResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(NotificationsEndpointDeleteAllNotificationsResponseApplicationJson), - )! as NotificationsEndpointDeleteAllNotificationsResponseApplicationJson; - } - throw await NotificationsApiException.fromResponse(response); // coverage:ignore-line } - /// Get a notification - Future getNotification({ + /// Get a notification. + /// + /// 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: + /// * [apiVersion] Version of the API to use + /// * [id] ID of the notification + /// * [oCSAPIRequest] + /// + /// Status codes: + /// * 200: Notification returned + /// * 404: Notification not found + /// + /// See: + /// * [getNotificationRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getNotification({ required final int id, final NotificationsEndpointGetNotificationApiVersion apiVersion = NotificationsEndpointGetNotificationApiVersion.v2, final String oCSAPIRequest = 'true', }) async { + final rawResponse = getNotificationRaw( + id: id, + apiVersion: apiVersion, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get a notification. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [apiVersion] Version of the API to use + /// * [id] ID of the notification + /// * [oCSAPIRequest] + /// + /// Status codes: + /// * 200: Notification returned + /// * 404: Notification not found + /// + /// See: + /// * [getNotification] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getNotificationRaw({ + required final int id, + final NotificationsEndpointGetNotificationApiVersion apiVersion = NotificationsEndpointGetNotificationApiVersion.v2, + final String oCSAPIRequest = 'true', + }) { var path = '/ocs/v2.php/apps/notifications/api/{apiVersion}/notifications/{id}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{id}', Uri.encodeQueryComponent(id.toString())); path = path.replaceAll('{apiVersion}', Uri.encodeQueryComponent(apiVersion.name)); headers['OCS-APIRequest'] = oCSAPIRequest; - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(NotificationsEndpointGetNotificationResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(NotificationsEndpointGetNotificationResponseApplicationJson), - )! as NotificationsEndpointGetNotificationResponseApplicationJson; - } - throw await NotificationsApiException.fromResponse(response); // coverage:ignore-line } - /// Delete a notification - Future deleteNotification({ + /// Delete a notification. + /// + /// 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: + /// * [apiVersion] + /// * [id] ID of the notification + /// * [oCSAPIRequest] + /// + /// Status codes: + /// * 200: Notification deleted successfully + /// * 403: Deleting notification for impersonated user is not allowed + /// * 404: Notification not found + /// + /// See: + /// * [deleteNotificationRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> deleteNotification({ required final int id, final NotificationsEndpointDeleteNotificationApiVersion apiVersion = NotificationsEndpointDeleteNotificationApiVersion.v2, final String oCSAPIRequest = 'true', }) async { + final rawResponse = deleteNotificationRaw( + id: id, + apiVersion: apiVersion, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Delete a notification. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [apiVersion] + /// * [id] ID of the notification + /// * [oCSAPIRequest] + /// + /// Status codes: + /// * 200: Notification deleted successfully + /// * 403: Deleting notification for impersonated user is not allowed + /// * 404: Notification not found + /// + /// See: + /// * [deleteNotification] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse deleteNotificationRaw({ + required final int id, + final NotificationsEndpointDeleteNotificationApiVersion apiVersion = + NotificationsEndpointDeleteNotificationApiVersion.v2, + final String oCSAPIRequest = 'true', + }) { var path = '/ocs/v2.php/apps/notifications/api/{apiVersion}/notifications/{id}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{id}', Uri.encodeQueryComponent(id.toString())); path = path.replaceAll('{apiVersion}', Uri.encodeQueryComponent(apiVersion.name)); headers['OCS-APIRequest'] = oCSAPIRequest; - final response = await _rootClient.doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'delete', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(NotificationsEndpointDeleteNotificationResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(NotificationsEndpointDeleteNotificationResponseApplicationJson), - )! as NotificationsEndpointDeleteNotificationResponseApplicationJson; - } - throw await NotificationsApiException.fromResponse(response); // coverage:ignore-line } - /// Check if notification IDs exist - Future confirmIdsForUser({ + /// Check if notification IDs exist. + /// + /// 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: + /// * [ids] IDs of the notifications to check + /// * [apiVersion] Version of the API to use + /// * [oCSAPIRequest] + /// + /// Status codes: + /// * 200: Existing notification IDs returned + /// * 400: Too many notification IDs requested + /// + /// See: + /// * [confirmIdsForUserRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> confirmIdsForUser({ required final List ids, final NotificationsEndpointConfirmIdsForUserApiVersion apiVersion = NotificationsEndpointConfirmIdsForUserApiVersion.v2, final String oCSAPIRequest = 'true', }) async { + final rawResponse = confirmIdsForUserRaw( + ids: ids, + apiVersion: apiVersion, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Check if notification IDs exist. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [ids] IDs of the notifications to check + /// * [apiVersion] Version of the API to use + /// * [oCSAPIRequest] + /// + /// Status codes: + /// * 200: Existing notification IDs returned + /// * 400: Too many notification IDs requested + /// + /// See: + /// * [confirmIdsForUser] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse confirmIdsForUserRaw({ + required final List ids, + final NotificationsEndpointConfirmIdsForUserApiVersion apiVersion = + NotificationsEndpointConfirmIdsForUserApiVersion.v2, + final String oCSAPIRequest = 'true', + }) { var path = '/ocs/v2.php/apps/notifications/api/{apiVersion}/notifications/exists'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['ids[]'] = ids.map((final e) => e.toString()); path = path.replaceAll('{apiVersion}', Uri.encodeQueryComponent(apiVersion.name)); headers['OCS-APIRequest'] = oCSAPIRequest; - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200, 400}, + ), + bodyType: const FullType(NotificationsEndpointConfirmIdsForUserResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200 || response.statusCode == 400) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(NotificationsEndpointConfirmIdsForUserResponseApplicationJson), - )! as NotificationsEndpointConfirmIdsForUserResponseApplicationJson; - } - throw await NotificationsApiException.fromResponse(response); // coverage:ignore-line } } @@ -371,92 +666,210 @@ class NotificationsPushClient { final NotificationsClient _rootClient; - /// Register device for push notifications - Future registerDevice({ + /// Register device for push notifications. + /// + /// 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: + /// * [pushTokenHash] Hash of the push token + /// * [devicePublicKey] Public key of the device + /// * [proxyServer] Proxy server to be used + /// * [apiVersion] + /// * [oCSAPIRequest] + /// + /// Status codes: + /// * 200: Device was already registered + /// * 201: Device registered successfully + /// * 400: Registering device is not possible + /// * 401: Missing permissions to register device + /// + /// See: + /// * [registerDeviceRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> registerDevice({ required final String pushTokenHash, required final String devicePublicKey, required final String proxyServer, final NotificationsPushRegisterDeviceApiVersion apiVersion = NotificationsPushRegisterDeviceApiVersion.v2, final String oCSAPIRequest = 'true', }) async { + final rawResponse = registerDeviceRaw( + pushTokenHash: pushTokenHash, + devicePublicKey: devicePublicKey, + proxyServer: proxyServer, + apiVersion: apiVersion, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Register device for push notifications. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [pushTokenHash] Hash of the push token + /// * [devicePublicKey] Public key of the device + /// * [proxyServer] Proxy server to be used + /// * [apiVersion] + /// * [oCSAPIRequest] + /// + /// Status codes: + /// * 200: Device was already registered + /// * 201: Device registered successfully + /// * 400: Registering device is not possible + /// * 401: Missing permissions to register device + /// + /// See: + /// * [registerDevice] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse registerDeviceRaw({ + required final String pushTokenHash, + required final String devicePublicKey, + required final String proxyServer, + final NotificationsPushRegisterDeviceApiVersion apiVersion = NotificationsPushRegisterDeviceApiVersion.v2, + final String oCSAPIRequest = 'true', + }) { var path = '/ocs/v2.php/apps/notifications/api/{apiVersion}/push'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['pushTokenHash'] = pushTokenHash; queryParameters['devicePublicKey'] = devicePublicKey; queryParameters['proxyServer'] = proxyServer; path = path.replaceAll('{apiVersion}', Uri.encodeQueryComponent(apiVersion.name)); headers['OCS-APIRequest'] = oCSAPIRequest; - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200, 201}, + ), + bodyType: const FullType(NotificationsPushRegisterDeviceResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200 || response.statusCode == 201) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(NotificationsPushRegisterDeviceResponseApplicationJson), - )! as NotificationsPushRegisterDeviceResponseApplicationJson; - } - throw await NotificationsApiException.fromResponse(response); // coverage:ignore-line } - /// Remove a device from push notifications - Future removeDevice({ + /// Remove a device from push notifications. + /// + /// 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: + /// * [apiVersion] + /// * [oCSAPIRequest] + /// + /// Status codes: + /// * 200: No device registered + /// * 202: Device removed successfully + /// * 401: Missing permissions to remove device + /// * 400: Removing device is not possible + /// + /// See: + /// * [removeDeviceRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> removeDevice({ final NotificationsPushRemoveDeviceApiVersion apiVersion = NotificationsPushRemoveDeviceApiVersion.v2, final String oCSAPIRequest = 'true', }) async { + final rawResponse = removeDeviceRaw( + apiVersion: apiVersion, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Remove a device from push notifications. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [apiVersion] + /// * [oCSAPIRequest] + /// + /// Status codes: + /// * 200: No device registered + /// * 202: Device removed successfully + /// * 401: Missing permissions to remove device + /// * 400: Removing device is not possible + /// + /// See: + /// * [removeDevice] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse removeDeviceRaw({ + final NotificationsPushRemoveDeviceApiVersion apiVersion = NotificationsPushRemoveDeviceApiVersion.v2, + final String oCSAPIRequest = 'true', + }) { var path = '/ocs/v2.php/apps/notifications/api/{apiVersion}/push'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{apiVersion}', Uri.encodeQueryComponent(apiVersion.name)); headers['OCS-APIRequest'] = oCSAPIRequest; - final response = await _rootClient.doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'delete', + uri, + headers, + body, + const {200, 202, 401}, + ), + bodyType: const FullType(NotificationsPushRemoveDeviceResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200 || response.statusCode == 202 || response.statusCode == 401) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(NotificationsPushRemoveDeviceResponseApplicationJson), - )! as NotificationsPushRemoveDeviceResponseApplicationJson; - } - throw await NotificationsApiException.fromResponse(response); // coverage:ignore-line } } @@ -465,100 +878,220 @@ class NotificationsSettingsClient { final NotificationsClient _rootClient; - /// Update personal notification settings - Future personal({ + /// Update personal notification settings. + /// + /// 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: + /// * [batchSetting] How often E-mails about missed notifications should be sent (hourly: 1; every three hours: 2; daily: 3; weekly: 4) + /// * [soundNotification] Enable sound for notifications ('yes' or 'no') + /// * [soundTalk] Enable sound for Talk notifications ('yes' or 'no') + /// * [apiVersion] + /// * [oCSAPIRequest] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [personalRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> personal({ required final int batchSetting, required final String soundNotification, required final String soundTalk, final NotificationsSettingsPersonalApiVersion apiVersion = NotificationsSettingsPersonalApiVersion.v2, final String oCSAPIRequest = 'true', }) async { + final rawResponse = personalRaw( + batchSetting: batchSetting, + soundNotification: soundNotification, + soundTalk: soundTalk, + apiVersion: apiVersion, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Update personal notification settings. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [batchSetting] How often E-mails about missed notifications should be sent (hourly: 1; every three hours: 2; daily: 3; weekly: 4) + /// * [soundNotification] Enable sound for notifications ('yes' or 'no') + /// * [soundTalk] Enable sound for Talk notifications ('yes' or 'no') + /// * [apiVersion] + /// * [oCSAPIRequest] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [personal] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse personalRaw({ + required final int batchSetting, + required final String soundNotification, + required final String soundTalk, + final NotificationsSettingsPersonalApiVersion apiVersion = NotificationsSettingsPersonalApiVersion.v2, + final String oCSAPIRequest = 'true', + }) { var path = '/ocs/v2.php/apps/notifications/api/{apiVersion}/settings'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['batchSetting'] = batchSetting.toString(); queryParameters['soundNotification'] = soundNotification; queryParameters['soundTalk'] = soundTalk; path = path.replaceAll('{apiVersion}', Uri.encodeQueryComponent(apiVersion.name)); headers['OCS-APIRequest'] = oCSAPIRequest; - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(NotificationsSettingsPersonalResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(NotificationsSettingsPersonalResponseApplicationJson), - )! as NotificationsSettingsPersonalResponseApplicationJson; - } - throw await NotificationsApiException.fromResponse(response); // coverage:ignore-line } - /// Update default notification settings for new users + /// Update default notification settings for new users. + /// + /// This endpoint requires admin access. /// - /// This endpoint requires admin access - Future admin({ + /// 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: + /// * [batchSetting] How often E-mails about missed notifications should be sent (hourly: 1; every three hours: 2; daily: 3; weekly: 4) + /// * [soundNotification] Enable sound for notifications ('yes' or 'no') + /// * [soundTalk] Enable sound for Talk notifications ('yes' or 'no') + /// * [apiVersion] + /// * [oCSAPIRequest] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [adminRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> admin({ required final int batchSetting, required final String soundNotification, required final String soundTalk, final NotificationsSettingsAdminApiVersion apiVersion = NotificationsSettingsAdminApiVersion.v2, final String oCSAPIRequest = 'true', }) async { + final rawResponse = adminRaw( + batchSetting: batchSetting, + soundNotification: soundNotification, + soundTalk: soundTalk, + apiVersion: apiVersion, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Update default notification settings for new users. + /// + /// This endpoint requires admin access. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [batchSetting] How often E-mails about missed notifications should be sent (hourly: 1; every three hours: 2; daily: 3; weekly: 4) + /// * [soundNotification] Enable sound for notifications ('yes' or 'no') + /// * [soundTalk] Enable sound for Talk notifications ('yes' or 'no') + /// * [apiVersion] + /// * [oCSAPIRequest] + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [admin] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse adminRaw({ + required final int batchSetting, + required final String soundNotification, + required final String soundTalk, + final NotificationsSettingsAdminApiVersion apiVersion = NotificationsSettingsAdminApiVersion.v2, + final String oCSAPIRequest = 'true', + }) { var path = '/ocs/v2.php/apps/notifications/api/{apiVersion}/settings/admin'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['batchSetting'] = batchSetting.toString(); queryParameters['soundNotification'] = soundNotification; queryParameters['soundTalk'] = soundTalk; path = path.replaceAll('{apiVersion}', Uri.encodeQueryComponent(apiVersion.name)); headers['OCS-APIRequest'] = oCSAPIRequest; - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(NotificationsSettingsAdminResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(NotificationsSettingsAdminResponseApplicationJson), - )! as NotificationsSettingsAdminResponseApplicationJson; - } - throw await NotificationsApiException.fromResponse(response); // coverage:ignore-line } } @@ -1902,14 +2435,8 @@ final Serializers _serializers = (Serializers().toBuilder() ..addBuilderFactory(const FullType(BuiltList, [FullType(String)]), ListBuilder.new)) .build(); -Serializers get notificationsSerializers => _serializers; - final Serializers _jsonSerializers = (_serializers.toBuilder() ..addPlugin(StandardJsonPlugin()) ..addPlugin(const ContentStringPlugin())) .build(); - -T deserializeNotifications(final Object data) => _serializers.deserialize(data, specifiedType: FullType(T))! as T; - -Object? serializeNotifications(final T data) => _serializers.serialize(data, specifiedType: FullType(T)); // coverage:ignore-end diff --git a/packages/nextcloud/lib/src/api/provisioning_api.openapi.dart b/packages/nextcloud/lib/src/api/provisioning_api.openapi.dart index bb60b0d7..20172d85 100644 --- a/packages/nextcloud/lib/src/api/provisioning_api.openapi.dart +++ b/packages/nextcloud/lib/src/api/provisioning_api.openapi.dart @@ -1,5 +1,7 @@ // ignore_for_file: camel_case_types +// ignore_for_file: discarded_futures // ignore_for_file: public_member_api_docs +// ignore_for_file: unreachable_switch_case import 'dart:typed_data'; import 'package:built_collection/built_collection.dart'; @@ -7,50 +9,17 @@ 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'; +import 'package:collection/collection.dart'; import 'package:dynamite_runtime/content_string.dart'; import 'package:dynamite_runtime/http_client.dart'; +import 'package:dynamite_runtime/utils.dart'; +import 'package:meta/meta.dart'; import 'package:universal_io/io.dart'; export 'package:dynamite_runtime/http_client.dart'; part 'provisioning_api.openapi.g.dart'; -class ProvisioningApiResponse extends DynamiteResponse { - ProvisioningApiResponse( - super.data, - super.headers, - ); - - @override - String toString() => 'ProvisioningApiResponse(data: $data, headers: $headers)'; -} - -class ProvisioningApiApiException extends DynamiteApiException { - ProvisioningApiApiException( - super.statusCode, - super.headers, - super.body, - ); - - static Future fromResponse(final HttpClientResponse response) async { - String body; - try { - body = await response.body; - } on FormatException { - body = 'binary'; - } - - return ProvisioningApiApiException( - response.statusCode, - response.responseHeaders, - body, - ); - } - - @override - String toString() => 'ProvisioningApiApiException(statusCode: $statusCode, headers: $headers, body: $body)'; -} - class ProvisioningApiClient extends DynamiteClient { ProvisioningApiClient( super.baseURL, { @@ -86,225 +55,494 @@ class ProvisioningApiAppConfigClient { final ProvisioningApiClient _rootClient; - /// Get a list of apps + /// Get a list of apps. + /// + /// This endpoint requires admin access. + /// + /// 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: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Apps returned + /// + /// See: + /// * [getAppsRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getApps({ + final bool oCSAPIRequest = true, + }) async { + final rawResponse = getAppsRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get a list of apps. + /// + /// This endpoint requires admin access. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Apps returned /// - /// This endpoint requires admin access - Future getApps({final bool oCSAPIRequest = true}) async { + /// See: + /// * [getApps] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getAppsRaw({ + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/provisioning_api/api/v1/config/apps'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiAppConfigGetAppsResponseApplicationJson), - )! as ProvisioningApiAppConfigGetAppsResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiAppConfigGetAppsResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Get the config keys of an app + /// Get the config keys of an app. + /// + /// This endpoint requires admin access. + /// + /// 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: + /// * [app] ID of the app + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Keys returned + /// * 403: App is not allowed /// - /// This endpoint requires admin access - Future getKeys({ + /// See: + /// * [getKeysRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getKeys({ required final String app, final bool oCSAPIRequest = true, }) async { + final rawResponse = getKeysRaw( + app: app, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get the config keys of an app. + /// + /// This endpoint requires admin access. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [app] ID of the app + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Keys returned + /// * 403: App is not allowed + /// + /// See: + /// * [getKeys] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getKeysRaw({ + required final String app, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/provisioning_api/api/v1/config/apps/{app}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{app}', Uri.encodeQueryComponent(app)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiAppConfigGetKeysResponseApplicationJson), - )! as ProvisioningApiAppConfigGetKeysResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiAppConfigGetKeysResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Get a the config value of an app + /// Get a the config value of an app. + /// + /// This endpoint requires admin access. /// - /// This endpoint requires admin access - Future getValue({ + /// 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: + /// * [defaultValue] Default returned value if the value is empty + /// * [app] ID of the app + /// * [key] Key + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Value returned + /// * 403: App is not allowed + /// + /// See: + /// * [getValueRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getValue({ required final String app, required final String key, final String defaultValue = '', final bool oCSAPIRequest = true, }) async { + final rawResponse = getValueRaw( + app: app, + key: key, + defaultValue: defaultValue, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get a the config value of an app. + /// + /// This endpoint requires admin access. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [defaultValue] Default returned value if the value is empty + /// * [app] ID of the app + /// * [key] Key + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Value returned + /// * 403: App is not allowed + /// + /// See: + /// * [getValue] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getValueRaw({ + required final String app, + required final String key, + final String defaultValue = '', + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/provisioning_api/api/v1/config/apps/{app}/{key}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{app}', Uri.encodeQueryComponent(app)); path = path.replaceAll('{key}', Uri.encodeQueryComponent(key)); if (defaultValue != '') { queryParameters['defaultValue'] = defaultValue; } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiAppConfigGetValueResponseApplicationJson), - )! as ProvisioningApiAppConfigGetValueResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiAppConfigGetValueResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Update the config value of an app - Future setValue({ + /// Update the config value of an 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. + /// + /// Parameters: + /// * [value] New value for the key + /// * [app] ID of the app + /// * [key] Key to update + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Value updated successfully + /// * 403: App or key is not allowed + /// + /// See: + /// * [setValueRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> setValue({ required final String value, required final String app, required final String key, final bool oCSAPIRequest = true, }) async { + final rawResponse = setValueRaw( + value: value, + app: app, + key: key, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Update the config value of an app. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [value] New value for the key + /// * [app] ID of the app + /// * [key] Key to update + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Value updated successfully + /// * 403: App or key is not allowed + /// + /// See: + /// * [setValue] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse setValueRaw({ + required final String value, + required final String app, + required final String key, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/provisioning_api/api/v1/config/apps/{app}/{key}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['value'] = value; path = path.replaceAll('{app}', Uri.encodeQueryComponent(app)); path = path.replaceAll('{key}', Uri.encodeQueryComponent(key)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiAppConfigSetValueResponseApplicationJson), - )! as ProvisioningApiAppConfigSetValueResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiAppConfigSetValueResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Delete a config key of an app + /// Delete a config key of an app. /// - /// This endpoint requires admin access - Future deleteKey({ + /// This endpoint requires admin access. + /// + /// 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: + /// * [app] ID of the app + /// * [key] Key to delete + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Key deleted successfully + /// * 403: App or key is not allowed + /// + /// See: + /// * [deleteKeyRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> deleteKey({ required final String app, required final String key, final bool oCSAPIRequest = true, }) async { + final rawResponse = deleteKeyRaw( + app: app, + key: key, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Delete a config key of an app. + /// + /// This endpoint requires admin access. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [app] ID of the app + /// * [key] Key to delete + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Key deleted successfully + /// * 403: App or key is not allowed + /// + /// See: + /// * [deleteKey] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse deleteKeyRaw({ + required final String app, + required final String key, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/provisioning_api/api/v1/config/apps/{app}/{key}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{app}', Uri.encodeQueryComponent(app)); path = path.replaceAll('{key}', Uri.encodeQueryComponent(key)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiAppConfigDeleteKeyResponseApplicationJson), - )! as ProvisioningApiAppConfigDeleteKeyResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'delete', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiAppConfigDeleteKeyResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } } @@ -313,178 +551,374 @@ class ProvisioningApiAppsClient { final ProvisioningApiClient _rootClient; - /// Get a list of installed apps + /// Get a list of installed apps. + /// + /// This endpoint requires admin access. + /// + /// 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: + /// * [filter] Filter for enabled or disabled apps + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Installed apps returned /// - /// This endpoint requires admin access - Future getApps({ + /// See: + /// * [getAppsRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getApps({ final String? filter, final bool oCSAPIRequest = true, }) async { + final rawResponse = getAppsRaw( + filter: filter, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get a list of installed apps. + /// + /// This endpoint requires admin access. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [filter] Filter for enabled or disabled apps + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Installed apps returned + /// + /// See: + /// * [getApps] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getAppsRaw({ + final String? filter, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/cloud/apps'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end if (filter != null) { queryParameters['filter'] = filter; } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiAppsGetAppsResponseApplicationJson), - )! as ProvisioningApiAppsGetAppsResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiAppsGetAppsResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Get the app info for an app + /// Get the app info for an app. + /// + /// This endpoint requires admin access. /// - /// This endpoint requires admin access - Future getAppInfo({ + /// 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: + /// * [app] ID of the app + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: App info returned + /// + /// See: + /// * [getAppInfoRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getAppInfo({ required final String app, final bool oCSAPIRequest = true, }) async { + final rawResponse = getAppInfoRaw( + app: app, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get the app info for an app. + /// + /// This endpoint requires admin access. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [app] ID of the app + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: App info returned + /// + /// See: + /// * [getAppInfo] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getAppInfoRaw({ + required final String app, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/cloud/apps/{app}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{app}', Uri.encodeQueryComponent(app)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiAppsGetAppInfoResponseApplicationJson), - )! as ProvisioningApiAppsGetAppInfoResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiAppsGetAppInfoResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Enable an app + /// Enable an app. + /// + /// This endpoint requires admin access. + /// + /// 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. /// - /// This endpoint requires admin access - Future enable({ + /// Parameters: + /// * [app] ID of the app + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: App enabled successfully + /// + /// See: + /// * [enableRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> enable({ required final String app, final bool oCSAPIRequest = true, }) async { + final rawResponse = enableRaw( + app: app, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Enable an app. + /// + /// This endpoint requires admin access. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [app] ID of the app + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: App enabled successfully + /// + /// See: + /// * [enable] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse enableRaw({ + required final String app, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/cloud/apps/{app}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{app}', Uri.encodeQueryComponent(app)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiAppsEnableResponseApplicationJson), - )! as ProvisioningApiAppsEnableResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiAppsEnableResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Disable an app + /// Disable an app. + /// + /// This endpoint requires admin access. + /// + /// 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: + /// * [app] ID of the app + /// * [oCSAPIRequest] Required to be true for the API request to pass /// - /// This endpoint requires admin access - Future disable({ + /// Status codes: + /// * 200: App disabled successfully + /// + /// See: + /// * [disableRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> disable({ required final String app, final bool oCSAPIRequest = true, }) async { + final rawResponse = disableRaw( + app: app, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Disable an app. + /// + /// This endpoint requires admin access. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [app] ID of the app + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: App disabled successfully + /// + /// See: + /// * [disable] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse disableRaw({ + required final String app, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/cloud/apps/{app}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{app}', Uri.encodeQueryComponent(app)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiAppsDisableResponseApplicationJson), - )! as ProvisioningApiAppsDisableResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'delete', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiAppsDisableResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } } @@ -493,32 +927,87 @@ class ProvisioningApiGroupsClient { final ProvisioningApiClient _rootClient; - /// Get a list of groups - Future getGroups({ + /// Get a list of groups. + /// + /// 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: + /// * [search] Text to search for + /// * [limit] Limit the amount of groups returned + /// * [offset] Offset for searching for groups + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Groups returned + /// + /// See: + /// * [getGroupsRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getGroups({ final String search = '', final int? limit, final int offset = 0, final bool oCSAPIRequest = true, }) async { + final rawResponse = getGroupsRaw( + search: search, + limit: limit, + offset: offset, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get a list of groups. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [search] Text to search for + /// * [limit] Limit the amount of groups returned + /// * [offset] Offset for searching for groups + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Groups returned + /// + /// See: + /// * [getGroups] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getGroupsRaw({ + final String search = '', + final int? limit, + final int offset = 0, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/cloud/groups'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end if (search != '') { queryParameters['search'] = search; } @@ -529,94 +1018,202 @@ class ProvisioningApiGroupsClient { queryParameters['offset'] = offset.toString(); } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiGroupsGetGroupsResponseApplicationJson), - )! as ProvisioningApiGroupsGetGroupsResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiGroupsGetGroupsResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Create a new group + /// Create a new group. + /// + /// This endpoint requires admin access. + /// + /// 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: + /// * [groupid] ID of the group + /// * [displayname] Display name of the group + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Group created successfully /// - /// This endpoint requires admin access - Future addGroup({ + /// See: + /// * [addGroupRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> addGroup({ required final String groupid, final String displayname = '', final bool oCSAPIRequest = true, }) async { + final rawResponse = addGroupRaw( + groupid: groupid, + displayname: displayname, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Create a new group. + /// + /// This endpoint requires admin access. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [groupid] ID of the group + /// * [displayname] Display name of the group + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Group created successfully + /// + /// See: + /// * [addGroup] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse addGroupRaw({ + required final String groupid, + final String displayname = '', + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/cloud/groups'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['groupid'] = groupid; if (displayname != '') { queryParameters['displayname'] = displayname; } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiGroupsAddGroupResponseApplicationJson), - )! as ProvisioningApiGroupsAddGroupResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiGroupsAddGroupResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Get a list of groups details - Future getGroupsDetails({ + /// Get a list of groups details. + /// + /// 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: + /// * [search] Text to search for + /// * [limit] Limit the amount of groups returned + /// * [offset] Offset for searching for groups + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Groups details returned + /// + /// See: + /// * [getGroupsDetailsRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getGroupsDetails({ final String search = '', final int? limit, final int offset = 0, final bool oCSAPIRequest = true, }) async { + final rawResponse = getGroupsDetailsRaw( + search: search, + limit: limit, + offset: offset, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get a list of groups details. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [search] Text to search for + /// * [limit] Limit the amount of groups returned + /// * [offset] Offset for searching for groups + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Groups details returned + /// + /// See: + /// * [getGroupsDetails] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getGroupsDetailsRaw({ + final String search = '', + final int? limit, + final int offset = 0, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/cloud/groups/details'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end if (search != '') { queryParameters['search'] = search; } @@ -627,99 +1224,202 @@ class ProvisioningApiGroupsClient { queryParameters['offset'] = offset.toString(); } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiGroupsGetGroupsDetailsResponseApplicationJson), - )! as ProvisioningApiGroupsGetGroupsDetailsResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiGroupsGetGroupsDetailsResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Get a list of users in the specified group - Future getGroupUsers({ + /// Get a list of users in the specified group. + /// + /// 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: + /// * [groupId] ID of the group + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User IDs returned + /// * 404: Group not found + /// * 403: Missing permissions to get users in the group + /// + /// See: + /// * [getGroupUsersRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getGroupUsers({ required final String groupId, final bool oCSAPIRequest = true, }) async { + final rawResponse = getGroupUsersRaw( + groupId: groupId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get a list of users in the specified group. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [groupId] ID of the group + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User IDs returned + /// * 404: Group not found + /// * 403: Missing permissions to get users in the group + /// + /// See: + /// * [getGroupUsers] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getGroupUsersRaw({ + required final String groupId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/cloud/groups/{groupId}/users'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end - if (!RegExp(r'^.+$').hasMatch(groupId)) { - throw Exception( - 'Invalid value "$groupId" for parameter "groupId" with pattern "${r'^.+$'}"', - ); // coverage:ignore-line - } + +// coverage:ignore-end + checkPattern(groupId, RegExp(r'^.+$'), 'groupId'); // coverage:ignore-line path = path.replaceAll('{groupId}', Uri.encodeQueryComponent(groupId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiGroupsGetGroupUsersResponseApplicationJson), - )! as ProvisioningApiGroupsGetGroupUsersResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiGroupsGetGroupUsersResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Get a list of users details in the specified group - Future getGroupUsersDetails({ + /// Get a list of users details in the specified group. + /// + /// 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: + /// * [search] Text to search for + /// * [limit] Limit the amount of groups returned + /// * [offset] Offset for searching for groups + /// * [groupId] ID of the group + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Group users details returned + /// + /// See: + /// * [getGroupUsersDetailsRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> + getGroupUsersDetails({ required final String groupId, final String search = '', final int? limit, final int offset = 0, final bool oCSAPIRequest = true, }) async { + final rawResponse = getGroupUsersDetailsRaw( + groupId: groupId, + search: search, + limit: limit, + offset: offset, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get a list of users details in the specified group. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [search] Text to search for + /// * [limit] Limit the amount of groups returned + /// * [offset] Offset for searching for groups + /// * [groupId] ID of the group + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Group users details returned + /// + /// See: + /// * [getGroupUsersDetails] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getGroupUsersDetailsRaw({ + required final String groupId, + final String search = '', + final int? limit, + final int offset = 0, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/cloud/groups/{groupId}/users/details'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end - if (!RegExp(r'^.+$').hasMatch(groupId)) { - throw Exception( - 'Invalid value "$groupId" for parameter "groupId" with pattern "${r'^.+$'}"', - ); // coverage:ignore-line - } + +// coverage:ignore-end + checkPattern(groupId, RegExp(r'^.+$'), 'groupId'); // coverage:ignore-line path = path.replaceAll('{groupId}', Uri.encodeQueryComponent(groupId)); if (search != '') { queryParameters['search'] = search; @@ -731,214 +1431,401 @@ class ProvisioningApiGroupsClient { queryParameters['offset'] = offset.toString(); } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiGroupsGetGroupUsersDetailsResponseApplicationJson), - )! as ProvisioningApiGroupsGetGroupUsersDetailsResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiGroupsGetGroupUsersDetailsResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Get the list of user IDs that are a subadmin of the group + /// Get the list of user IDs that are a subadmin of the group. + /// + /// This endpoint requires admin access. + /// + /// 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: + /// * [groupId] ID of the group + /// * [oCSAPIRequest] Required to be true for the API request to pass /// - /// This endpoint requires admin access - Future getSubAdminsOfGroup({ + /// Status codes: + /// * 200: Sub admins returned + /// + /// See: + /// * [getSubAdminsOfGroupRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getSubAdminsOfGroup({ required final String groupId, final bool oCSAPIRequest = true, }) async { + final rawResponse = getSubAdminsOfGroupRaw( + groupId: groupId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get the list of user IDs that are a subadmin of the group. + /// + /// This endpoint requires admin access. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [groupId] ID of the group + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Sub admins returned + /// + /// See: + /// * [getSubAdminsOfGroup] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getSubAdminsOfGroupRaw({ + required final String groupId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/cloud/groups/{groupId}/subadmins'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end - if (!RegExp(r'^.+$').hasMatch(groupId)) { - throw Exception( - 'Invalid value "$groupId" for parameter "groupId" with pattern "${r'^.+$'}"', - ); // coverage:ignore-line - } + +// coverage:ignore-end + checkPattern(groupId, RegExp(r'^.+$'), 'groupId'); // coverage:ignore-line path = path.replaceAll('{groupId}', Uri.encodeQueryComponent(groupId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiGroupsGetSubAdminsOfGroupResponseApplicationJson), - )! as ProvisioningApiGroupsGetSubAdminsOfGroupResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiGroupsGetSubAdminsOfGroupResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Get a list of users in the specified group + /// Get a list of users in the specified group. + /// + /// 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: + /// * [groupId] ID of the group + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Group users returned + /// + /// See: + /// * [getGroupRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. @Deprecated('') - Future getGroup({ + Future> getGroup({ required final String groupId, final bool oCSAPIRequest = true, }) async { + final rawResponse = getGroupRaw( + groupId: groupId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get a list of users in the specified group. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [groupId] ID of the group + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Group users returned + /// + /// See: + /// * [getGroup] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + @Deprecated('') + DynamiteRawResponse getGroupRaw({ + required final String groupId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/cloud/groups/{groupId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end - if (!RegExp(r'^.+$').hasMatch(groupId)) { - throw Exception( - 'Invalid value "$groupId" for parameter "groupId" with pattern "${r'^.+$'}"', - ); // coverage:ignore-line - } + +// coverage:ignore-end + checkPattern(groupId, RegExp(r'^.+$'), 'groupId'); // coverage:ignore-line path = path.replaceAll('{groupId}', Uri.encodeQueryComponent(groupId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiGroupsGetGroupResponseApplicationJson), - )! as ProvisioningApiGroupsGetGroupResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiGroupsGetGroupResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Update a group + /// Update a group. + /// + /// This endpoint requires admin access. + /// + /// 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: + /// * [key] Key to update, only 'displayname' + /// * [value] New value for the key + /// * [groupId] ID of the group + /// * [oCSAPIRequest] Required to be true for the API request to pass /// - /// This endpoint requires admin access - Future updateGroup({ + /// Status codes: + /// * 200: Group updated successfully + /// + /// See: + /// * [updateGroupRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> updateGroup({ required final String key, required final String value, required final String groupId, final bool oCSAPIRequest = true, }) async { + final rawResponse = updateGroupRaw( + key: key, + value: value, + groupId: groupId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Update a group. + /// + /// This endpoint requires admin access. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [key] Key to update, only 'displayname' + /// * [value] New value for the key + /// * [groupId] ID of the group + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Group updated successfully + /// + /// See: + /// * [updateGroup] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse updateGroupRaw({ + required final String key, + required final String value, + required final String groupId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/cloud/groups/{groupId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['key'] = key; queryParameters['value'] = value; - if (!RegExp(r'^.+$').hasMatch(groupId)) { - throw Exception( - 'Invalid value "$groupId" for parameter "groupId" with pattern "${r'^.+$'}"', - ); // coverage:ignore-line - } + checkPattern(groupId, RegExp(r'^.+$'), 'groupId'); // coverage:ignore-line path = path.replaceAll('{groupId}', Uri.encodeQueryComponent(groupId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'put', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiGroupsUpdateGroupResponseApplicationJson), - )! as ProvisioningApiGroupsUpdateGroupResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'put', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiGroupsUpdateGroupResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Delete a group + /// Delete a group. + /// + /// This endpoint requires admin access. /// - /// This endpoint requires admin access - Future deleteGroup({ + /// 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: + /// * [groupId] ID of the group + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Group deleted successfully + /// + /// See: + /// * [deleteGroupRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> deleteGroup({ required final String groupId, final bool oCSAPIRequest = true, }) async { + final rawResponse = deleteGroupRaw( + groupId: groupId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Delete a group. + /// + /// This endpoint requires admin access. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [groupId] ID of the group + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Group deleted successfully + /// + /// See: + /// * [deleteGroup] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse deleteGroupRaw({ + required final String groupId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/cloud/groups/{groupId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end - if (!RegExp(r'^.+$').hasMatch(groupId)) { - throw Exception( - 'Invalid value "$groupId" for parameter "groupId" with pattern "${r'^.+$'}"', - ); // coverage:ignore-line - } + +// coverage:ignore-end + checkPattern(groupId, RegExp(r'^.+$'), 'groupId'); // coverage:ignore-line path = path.replaceAll('{groupId}', Uri.encodeQueryComponent(groupId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiGroupsDeleteGroupResponseApplicationJson), - )! as ProvisioningApiGroupsDeleteGroupResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'delete', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiGroupsDeleteGroupResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } } @@ -947,119 +1834,284 @@ class ProvisioningApiPreferencesClient { final ProvisioningApiClient _rootClient; - /// Update a preference value of an app - Future setPreference({ + /// Update a preference value of an 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. + /// + /// Parameters: + /// * [configValue] New value + /// * [appId] ID of the app + /// * [configKey] Key of the preference + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Preference updated successfully + /// * 400: Preference invalid + /// + /// See: + /// * [setPreferenceRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> setPreference({ required final String configValue, required final String appId, required final String configKey, final bool oCSAPIRequest = true, }) async { + final rawResponse = setPreferenceRaw( + configValue: configValue, + appId: appId, + configKey: configKey, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Update a preference value of an app. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [configValue] New value + /// * [appId] ID of the app + /// * [configKey] Key of the preference + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Preference updated successfully + /// * 400: Preference invalid + /// + /// See: + /// * [setPreference] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse setPreferenceRaw({ + required final String configValue, + required final String appId, + required final String configKey, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/provisioning_api/api/v1/config/users/{appId}/{configKey}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['configValue'] = configValue; path = path.replaceAll('{appId}', Uri.encodeQueryComponent(appId)); path = path.replaceAll('{configKey}', Uri.encodeQueryComponent(configKey)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200 || response.statusCode == 400) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiPreferencesSetPreferenceResponseApplicationJson), - )! as ProvisioningApiPreferencesSetPreferenceResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200, 400}, + ), + bodyType: const FullType(ProvisioningApiPreferencesSetPreferenceResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Delete a preference for an app - Future deletePreference({ + /// Delete a preference for an 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. + /// + /// Parameters: + /// * [appId] ID of the app + /// * [configKey] Key to delete + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Preference deleted successfully + /// * 400: Preference invalid + /// + /// See: + /// * [deletePreferenceRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> deletePreference({ required final String appId, required final String configKey, final bool oCSAPIRequest = true, }) async { + final rawResponse = deletePreferenceRaw( + appId: appId, + configKey: configKey, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Delete a preference for an app. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [appId] ID of the app + /// * [configKey] Key to delete + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Preference deleted successfully + /// * 400: Preference invalid + /// + /// See: + /// * [deletePreference] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse deletePreferenceRaw({ + required final String appId, + required final String configKey, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/provisioning_api/api/v1/config/users/{appId}/{configKey}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{appId}', Uri.encodeQueryComponent(appId)); path = path.replaceAll('{configKey}', Uri.encodeQueryComponent(configKey)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200 || response.statusCode == 400) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiPreferencesDeletePreferenceResponseApplicationJson), - )! as ProvisioningApiPreferencesDeletePreferenceResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'delete', + uri, + headers, + body, + const {200, 400}, + ), + bodyType: const FullType(ProvisioningApiPreferencesDeletePreferenceResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Update multiple preference values of an app - Future setMultiplePreferences({ + /// Update multiple preference values of an 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. + /// + /// Parameters: + /// * [configs] Key-value pairs of the preferences + /// * [appId] ID of the app + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Preferences updated successfully + /// * 400: Preference invalid + /// + /// See: + /// * [setMultiplePreferencesRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> + setMultiplePreferences({ required final ContentString> configs, required final String appId, final bool oCSAPIRequest = true, }) async { + final rawResponse = setMultiplePreferencesRaw( + configs: configs, + appId: appId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Update multiple preference values of an app. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [configs] Key-value pairs of the preferences + /// * [appId] ID of the app + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Preferences updated successfully + /// * 400: Preference invalid + /// + /// See: + /// * [setMultiplePreferences] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse + setMultiplePreferencesRaw({ + required final ContentString> configs, + required final String appId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/provisioning_api/api/v1/config/users/{appId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['configs'] = _jsonSerializers.serialize( configs, specifiedType: const FullType(ContentString, [ @@ -1068,62 +2120,117 @@ class ProvisioningApiPreferencesClient { ); path = path.replaceAll('{appId}', Uri.encodeQueryComponent(appId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200 || response.statusCode == 400) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiPreferencesSetMultiplePreferencesResponseApplicationJson), - )! as ProvisioningApiPreferencesSetMultiplePreferencesResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200, 400}, + ), + bodyType: const FullType(ProvisioningApiPreferencesSetMultiplePreferencesResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Delete multiple preferences for an app - Future deleteMultiplePreference({ + /// Delete multiple preferences for an 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. + /// + /// Parameters: + /// * [configKeys] Keys to delete + /// * [appId] ID of the app + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Preferences deleted successfully + /// * 400: Preference invalid + /// + /// See: + /// * [deleteMultiplePreferenceRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> + deleteMultiplePreference({ required final List configKeys, required final String appId, final bool oCSAPIRequest = true, }) async { + final rawResponse = deleteMultiplePreferenceRaw( + configKeys: configKeys, + appId: appId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Delete multiple preferences for an app. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [configKeys] Keys to delete + /// * [appId] ID of the app + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Preferences deleted successfully + /// * 400: Preference invalid + /// + /// See: + /// * [deleteMultiplePreference] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse + deleteMultiplePreferenceRaw({ + required final List configKeys, + required final String appId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/provisioning_api/api/v1/config/users/{appId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['configKeys[]'] = configKeys.map((final e) => e); path = path.replaceAll('{appId}', Uri.encodeQueryComponent(appId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200 || response.statusCode == 400) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiPreferencesDeleteMultiplePreferenceResponseApplicationJson), - )! as ProvisioningApiPreferencesDeleteMultiplePreferenceResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'delete', + uri, + headers, + body, + const {200, 400}, + ), + bodyType: const FullType(ProvisioningApiPreferencesDeleteMultiplePreferenceResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } } @@ -1132,32 +2239,87 @@ class ProvisioningApiUsersClient { final ProvisioningApiClient _rootClient; - /// Get a list of users - Future getUsers({ + /// Get a list of users. + /// + /// 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: + /// * [search] Text to search for + /// * [limit] Limit the amount of groups returned + /// * [offset] Offset for searching for groups + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Users returned + /// + /// See: + /// * [getUsersRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getUsers({ final String search = '', final int? limit, final int offset = 0, final bool oCSAPIRequest = true, }) async { + final rawResponse = getUsersRaw( + search: search, + limit: limit, + offset: offset, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get a list of users. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [search] Text to search for + /// * [limit] Limit the amount of groups returned + /// * [offset] Offset for searching for groups + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Users returned + /// + /// See: + /// * [getUsers] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getUsersRaw({ + final String search = '', + final int? limit, + final int offset = 0, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/cloud/users'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end if (search != '') { queryParameters['search'] = search; } @@ -1168,23 +2330,45 @@ class ProvisioningApiUsersClient { queryParameters['offset'] = offset.toString(); } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiUsersGetUsersResponseApplicationJson), - )! as ProvisioningApiUsersGetUsersResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiUsersGetUsersResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Create a new user - Future addUser({ + /// Create a new 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. + /// + /// Parameters: + /// * [userid] ID of the user + /// * [password] Password of the user + /// * [displayName] Display name of the user + /// * [email] Email of the user + /// * [groups] Groups of the user + /// * [subadmin] Groups where the user is subadmin + /// * [quota] Quota of the user + /// * [language] Language of the user + /// * [manager] Manager of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User added successfully + /// * 403: Missing permissions to make user subadmin + /// + /// See: + /// * [addUserRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> addUser({ required final String userid, final String password = '', final String displayName = '', @@ -1196,25 +2380,84 @@ class ProvisioningApiUsersClient { final String? manager, final bool oCSAPIRequest = true, }) async { + final rawResponse = addUserRaw( + userid: userid, + password: password, + displayName: displayName, + email: email, + groups: groups, + subadmin: subadmin, + quota: quota, + language: language, + manager: manager, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Create a new user. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [userid] ID of the user + /// * [password] Password of the user + /// * [displayName] Display name of the user + /// * [email] Email of the user + /// * [groups] Groups of the user + /// * [subadmin] Groups where the user is subadmin + /// * [quota] Quota of the user + /// * [language] Language of the user + /// * [manager] Manager of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User added successfully + /// * 403: Missing permissions to make user subadmin + /// + /// See: + /// * [addUser] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse addUserRaw({ + required final String userid, + final String password = '', + final String displayName = '', + final String email = '', + final List groups = const [], + final List subadmin = const [], + final String quota = '', + final String language = '', + final String? manager, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/cloud/users'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['userid'] = userid; if (password != '') { queryParameters['password'] = password; @@ -1241,47 +2484,102 @@ class ProvisioningApiUsersClient { queryParameters['manager'] = manager; } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiUsersAddUserResponseApplicationJson), - )! as ProvisioningApiUsersAddUserResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiUsersAddUserResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Get a list of users and their details - Future getUsersDetails({ + /// Get a list of users and their details. + /// + /// 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: + /// * [search] Text to search for + /// * [limit] Limit the amount of groups returned + /// * [offset] Offset for searching for groups + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Users details returned + /// + /// See: + /// * [getUsersDetailsRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getUsersDetails({ final String search = '', final int? limit, final int offset = 0, final bool oCSAPIRequest = true, }) async { + final rawResponse = getUsersDetailsRaw( + search: search, + limit: limit, + offset: offset, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get a list of users and their details. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [search] Text to search for + /// * [limit] Limit the amount of groups returned + /// * [offset] Offset for searching for groups + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Users details returned + /// + /// See: + /// * [getUsersDetails] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getUsersDetailsRaw({ + final String search = '', + final int? limit, + final int offset = 0, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/cloud/users/details'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end if (search != '') { queryParameters['search'] = search; } @@ -1292,46 +2590,99 @@ class ProvisioningApiUsersClient { queryParameters['offset'] = offset.toString(); } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiUsersGetUsersDetailsResponseApplicationJson), - )! as ProvisioningApiUsersGetUsersDetailsResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiUsersGetUsersDetailsResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Search users by their phone numbers - Future searchByPhoneNumbers({ + /// Search users by their phone numbers. + /// + /// 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: + /// * [location] Location of the phone number (for country code) + /// * [search] Phone numbers to search for + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Users returned + /// * 400: Invalid location + /// + /// See: + /// * [searchByPhoneNumbersRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> searchByPhoneNumbers({ required final String location, required final ContentString>> search, final bool oCSAPIRequest = true, }) async { + final rawResponse = searchByPhoneNumbersRaw( + location: location, + search: search, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Search users by their phone numbers. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [location] Location of the phone number (for country code) + /// * [search] Phone numbers to search for + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Users returned + /// * 400: Invalid location + /// + /// See: + /// * [searchByPhoneNumbers] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse searchByPhoneNumbersRaw({ + required final String location, + required final ContentString>> search, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/cloud/users/search/by-phone'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['location'] = location; queryParameters['search'] = _jsonSerializers.serialize( search, @@ -1343,743 +2694,1579 @@ class ProvisioningApiUsersClient { ]), ); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiUsersSearchByPhoneNumbersResponseApplicationJson), - )! as ProvisioningApiUsersSearchByPhoneNumbersResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiUsersSearchByPhoneNumbersResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Get the details of a user - Future getUser({ + /// Get the details of a 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. + /// + /// Parameters: + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User returned + /// + /// See: + /// * [getUserRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getUser({ required final String userId, final bool oCSAPIRequest = true, }) async { + final rawResponse = getUserRaw( + userId: userId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get the details of a user. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User returned + /// + /// See: + /// * [getUser] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getUserRaw({ + required final String userId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/cloud/users/{userId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{userId}', Uri.encodeQueryComponent(userId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiUsersGetUserResponseApplicationJson), - )! as ProvisioningApiUsersGetUserResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiUsersGetUserResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Update a value of the user's details - Future editUser({ + /// Update a value of the user's details. + /// + /// 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: + /// * [key] Key that will be updated + /// * [value] New value for the key + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User value edited successfully + /// + /// See: + /// * [editUserRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> editUser({ required final String key, required final String value, required final String userId, final bool oCSAPIRequest = true, }) async { + final rawResponse = editUserRaw( + key: key, + value: value, + userId: userId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Update a value of the user's details. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [key] Key that will be updated + /// * [value] New value for the key + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User value edited successfully + /// + /// See: + /// * [editUser] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse editUserRaw({ + required final String key, + required final String value, + required final String userId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/cloud/users/{userId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['key'] = key; queryParameters['value'] = value; path = path.replaceAll('{userId}', Uri.encodeQueryComponent(userId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'put', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiUsersEditUserResponseApplicationJson), - )! as ProvisioningApiUsersEditUserResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'put', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiUsersEditUserResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Delete a user - Future deleteUser({ + /// Delete a 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. + /// + /// Parameters: + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User deleted successfully + /// + /// See: + /// * [deleteUserRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> deleteUser({ required final String userId, final bool oCSAPIRequest = true, }) async { + final rawResponse = deleteUserRaw( + userId: userId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Delete a user. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User deleted successfully + /// + /// See: + /// * [deleteUser] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse deleteUserRaw({ + required final String userId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/cloud/users/{userId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{userId}', Uri.encodeQueryComponent(userId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiUsersDeleteUserResponseApplicationJson), - )! as ProvisioningApiUsersDeleteUserResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'delete', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiUsersDeleteUserResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Get the details of the current user - Future getCurrentUser({ + /// Get the details of 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. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Current user returned + /// + /// See: + /// * [getCurrentUserRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getCurrentUser({ final bool oCSAPIRequest = true, }) async { + final rawResponse = getCurrentUserRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get the details of the current user. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Current user returned + /// + /// See: + /// * [getCurrentUser] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getCurrentUserRaw({ + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/cloud/user'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiUsersGetCurrentUserResponseApplicationJson), - )! as ProvisioningApiUsersGetCurrentUserResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiUsersGetCurrentUserResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Get a list of fields that are editable for the current user - Future getEditableFields({ + /// Get a list of fields that are editable 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. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Editable fields returned + /// + /// See: + /// * [getEditableFieldsRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getEditableFields({ final bool oCSAPIRequest = true, }) async { + final rawResponse = getEditableFieldsRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get a list of fields that are editable for the current user. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Editable fields returned + /// + /// See: + /// * [getEditableFields] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getEditableFieldsRaw({ + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/cloud/user/fields'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiUsersGetEditableFieldsResponseApplicationJson), - )! as ProvisioningApiUsersGetEditableFieldsResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiUsersGetEditableFieldsResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Get a list of fields that are editable for a user - Future getEditableFieldsForUser({ + /// Get a list of fields that are editable for a 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. + /// + /// Parameters: + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Editable fields for user returned + /// + /// See: + /// * [getEditableFieldsForUserRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> + getEditableFieldsForUser({ required final String userId, final bool oCSAPIRequest = true, }) async { + final rawResponse = getEditableFieldsForUserRaw( + userId: userId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get a list of fields that are editable for a user. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Editable fields for user returned + /// + /// See: + /// * [getEditableFieldsForUser] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse + getEditableFieldsForUserRaw({ + required final String userId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/cloud/user/fields/{userId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{userId}', Uri.encodeQueryComponent(userId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiUsersGetEditableFieldsForUserResponseApplicationJson), - )! as ProvisioningApiUsersGetEditableFieldsForUserResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiUsersGetEditableFieldsForUserResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Update multiple values of the user's details - Future editUserMultiValue({ + /// Update multiple values of the user's details. + /// + /// 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: + /// * [key] Key that will be updated + /// * [value] New value for the key + /// * [userId] ID of the user + /// * [collectionName] Collection to update + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User values edited successfully + /// + /// See: + /// * [editUserMultiValueRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> editUserMultiValue({ required final String key, required final String value, required final String userId, required final String collectionName, final bool oCSAPIRequest = true, }) async { + final rawResponse = editUserMultiValueRaw( + key: key, + value: value, + userId: userId, + collectionName: collectionName, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Update multiple values of the user's details. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [key] Key that will be updated + /// * [value] New value for the key + /// * [userId] ID of the user + /// * [collectionName] Collection to update + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User values edited successfully + /// + /// See: + /// * [editUserMultiValue] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse editUserMultiValueRaw({ + required final String key, + required final String value, + required final String userId, + required final String collectionName, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/cloud/users/{userId}/{collectionName}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['key'] = key; queryParameters['value'] = value; path = path.replaceAll('{userId}', Uri.encodeQueryComponent(userId)); - if (!RegExp(r'^(?!enable$|disable$)[a-zA-Z0-9_]*$').hasMatch(collectionName)) { - throw Exception( - 'Invalid value "$collectionName" for parameter "collectionName" with pattern "${r'^(?!enable$|disable$)[a-zA-Z0-9_]*$'}"', - ); // coverage:ignore-line - } + checkPattern( + collectionName, + RegExp(r'^(?!enable$|disable$)[a-zA-Z0-9_]*$'), + 'collectionName', + ); // coverage:ignore-line path = path.replaceAll('{collectionName}', Uri.encodeQueryComponent(collectionName)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'put', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiUsersEditUserMultiValueResponseApplicationJson), - )! as ProvisioningApiUsersEditUserMultiValueResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'put', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiUsersEditUserMultiValueResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Wipe all devices of a user - Future wipeUserDevices({ + /// Wipe all devices of a 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. + /// + /// Parameters: + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Wiped all user devices successfully + /// + /// See: + /// * [wipeUserDevicesRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> wipeUserDevices({ + required final String userId, + final bool oCSAPIRequest = true, + }) async { + final rawResponse = wipeUserDevicesRaw( + userId: userId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Wipe all devices of a user. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Wiped all user devices successfully + /// + /// See: + /// * [wipeUserDevices] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse wipeUserDevicesRaw({ required final String userId, final bool oCSAPIRequest = true, - }) async { + }) { var path = '/ocs/v2.php/cloud/users/{userId}/wipe'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{userId}', Uri.encodeQueryComponent(userId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiUsersWipeUserDevicesResponseApplicationJson), - )! as ProvisioningApiUsersWipeUserDevicesResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiUsersWipeUserDevicesResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Enable a user - Future enableUser({ + /// Enable a 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. + /// + /// Parameters: + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User enabled successfully + /// + /// See: + /// * [enableUserRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> enableUser({ required final String userId, final bool oCSAPIRequest = true, }) async { + final rawResponse = enableUserRaw( + userId: userId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Enable a user. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User enabled successfully + /// + /// See: + /// * [enableUser] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse enableUserRaw({ + required final String userId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/cloud/users/{userId}/enable'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{userId}', Uri.encodeQueryComponent(userId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'put', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiUsersEnableUserResponseApplicationJson), - )! as ProvisioningApiUsersEnableUserResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'put', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiUsersEnableUserResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Disable a user - Future disableUser({ + /// Disable a 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. + /// + /// Parameters: + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User disabled successfully + /// + /// See: + /// * [disableUserRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> disableUser({ required final String userId, final bool oCSAPIRequest = true, }) async { + final rawResponse = disableUserRaw( + userId: userId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Disable a user. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User disabled successfully + /// + /// See: + /// * [disableUser] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse disableUserRaw({ + required final String userId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/cloud/users/{userId}/disable'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{userId}', Uri.encodeQueryComponent(userId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'put', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiUsersDisableUserResponseApplicationJson), - )! as ProvisioningApiUsersDisableUserResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'put', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiUsersDisableUserResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Get a list of groups the user belongs to - Future getUsersGroups({ + /// Get a list of groups the user belongs to. + /// + /// 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: + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Users groups returned + /// + /// See: + /// * [getUsersGroupsRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getUsersGroups({ required final String userId, final bool oCSAPIRequest = true, }) async { + final rawResponse = getUsersGroupsRaw( + userId: userId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get a list of groups the user belongs to. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Users groups returned + /// + /// See: + /// * [getUsersGroups] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getUsersGroupsRaw({ + required final String userId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/cloud/users/{userId}/groups'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{userId}', Uri.encodeQueryComponent(userId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiUsersGetUsersGroupsResponseApplicationJson), - )! as ProvisioningApiUsersGetUsersGroupsResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiUsersGetUsersGroupsResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Add a user to a group - Future addToGroup({ + /// Add a user to a group. + /// + /// 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: + /// * [groupid] ID of the group + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User added to group successfully + /// + /// See: + /// * [addToGroupRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> addToGroup({ required final String userId, final String groupid = '', final bool oCSAPIRequest = true, }) async { + final rawResponse = addToGroupRaw( + userId: userId, + groupid: groupid, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Add a user to a group. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [groupid] ID of the group + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User added to group successfully + /// + /// See: + /// * [addToGroup] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse addToGroupRaw({ + required final String userId, + final String groupid = '', + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/cloud/users/{userId}/groups'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{userId}', Uri.encodeQueryComponent(userId)); if (groupid != '') { queryParameters['groupid'] = groupid; } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiUsersAddToGroupResponseApplicationJson), - )! as ProvisioningApiUsersAddToGroupResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiUsersAddToGroupResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Remove a user from a group - Future removeFromGroup({ + /// Remove a user from a group. + /// + /// 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: + /// * [groupid] ID of the group + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User removed from group successfully + /// + /// See: + /// * [removeFromGroupRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> removeFromGroup({ required final String groupid, required final String userId, final bool oCSAPIRequest = true, }) async { + final rawResponse = removeFromGroupRaw( + groupid: groupid, + userId: userId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Remove a user from a group. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [groupid] ID of the group + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User removed from group successfully + /// + /// See: + /// * [removeFromGroup] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse removeFromGroupRaw({ + required final String groupid, + required final String userId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/cloud/users/{userId}/groups'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['groupid'] = groupid; path = path.replaceAll('{userId}', Uri.encodeQueryComponent(userId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiUsersRemoveFromGroupResponseApplicationJson), - )! as ProvisioningApiUsersRemoveFromGroupResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'delete', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiUsersRemoveFromGroupResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Get the groups a user is a subadmin of + /// Get the groups a user is a subadmin of. /// - /// This endpoint requires admin access - Future getUserSubAdminGroups({ + /// This endpoint requires admin access. + /// + /// 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: + /// * [userId] ID if the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User subadmin groups returned + /// + /// See: + /// * [getUserSubAdminGroupsRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> + getUserSubAdminGroups({ required final String userId, final bool oCSAPIRequest = true, }) async { + final rawResponse = getUserSubAdminGroupsRaw( + userId: userId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get the groups a user is a subadmin of. + /// + /// This endpoint requires admin access. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [userId] ID if the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User subadmin groups returned + /// + /// See: + /// * [getUserSubAdminGroups] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getUserSubAdminGroupsRaw({ + required final String userId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/cloud/users/{userId}/subadmins'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{userId}', Uri.encodeQueryComponent(userId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiUsersGetUserSubAdminGroupsResponseApplicationJson), - )! as ProvisioningApiUsersGetUserSubAdminGroupsResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiUsersGetUserSubAdminGroupsResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Make a user a subadmin of a group + /// Make a user a subadmin of a group. + /// + /// This endpoint requires admin access. /// - /// This endpoint requires admin access - Future addSubAdmin({ + /// 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: + /// * [groupid] ID of the group + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User added as group subadmin successfully + /// + /// See: + /// * [addSubAdminRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> addSubAdmin({ required final String groupid, required final String userId, final bool oCSAPIRequest = true, }) async { + final rawResponse = addSubAdminRaw( + groupid: groupid, + userId: userId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Make a user a subadmin of a group. + /// + /// This endpoint requires admin access. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [groupid] ID of the group + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User added as group subadmin successfully + /// + /// See: + /// * [addSubAdmin] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse addSubAdminRaw({ + required final String groupid, + required final String userId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/cloud/users/{userId}/subadmins'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['groupid'] = groupid; path = path.replaceAll('{userId}', Uri.encodeQueryComponent(userId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiUsersAddSubAdminResponseApplicationJson), - )! as ProvisioningApiUsersAddSubAdminResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiUsersAddSubAdminResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Remove a user from the subadmins of a group + /// Remove a user from the subadmins of a group. + /// + /// This endpoint requires admin access. /// - /// This endpoint requires admin access - Future removeSubAdmin({ + /// 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: + /// * [groupid] ID of the group + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User removed as group subadmin successfully + /// + /// See: + /// * [removeSubAdminRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> removeSubAdmin({ required final String groupid, required final String userId, final bool oCSAPIRequest = true, }) async { + final rawResponse = removeSubAdminRaw( + groupid: groupid, + userId: userId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Remove a user from the subadmins of a group. + /// + /// This endpoint requires admin access. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [groupid] ID of the group + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: User removed as group subadmin successfully + /// + /// See: + /// * [removeSubAdmin] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse removeSubAdminRaw({ + required final String groupid, + required final String userId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/cloud/users/{userId}/subadmins'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['groupid'] = groupid; path = path.replaceAll('{userId}', Uri.encodeQueryComponent(userId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiUsersRemoveSubAdminResponseApplicationJson), - )! as ProvisioningApiUsersRemoveSubAdminResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'delete', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiUsersRemoveSubAdminResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Resend the welcome message - Future resendWelcomeMessage({ + /// Resend the welcome message. + /// + /// 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: + /// * [userId] ID if the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Resent welcome message successfully + /// + /// See: + /// * [resendWelcomeMessageRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> resendWelcomeMessage({ required final String userId, final bool oCSAPIRequest = true, }) async { + final rawResponse = resendWelcomeMessageRaw( + userId: userId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Resend the welcome message. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [userId] ID if the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Resent welcome message successfully + /// + /// See: + /// * [resendWelcomeMessage] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse resendWelcomeMessageRaw({ + required final String userId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/cloud/users/{userId}/welcome'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{userId}', Uri.encodeQueryComponent(userId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ProvisioningApiUsersResendWelcomeMessageResponseApplicationJson), - )! as ProvisioningApiUsersResendWelcomeMessageResponseApplicationJson; - } - throw await ProvisioningApiApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ProvisioningApiUsersResendWelcomeMessageResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } } @@ -3190,10 +5377,10 @@ class _$ProvisioningApiGroupDetails_UsercountSerializer }) { final result = ProvisioningApiGroupDetails_UsercountBuilder()..data = JsonObject(data); try { - result._$bool = data as bool?; + result._$bool = _jsonSerializers.deserialize(data, specifiedType: const FullType(bool))! as bool; } catch (_) {} try { - result._$int = data as int?; + result._$int = _jsonSerializers.deserialize(data, specifiedType: const FullType(int))! as int; } catch (_) {} assert([result._$bool, result._$int].where((final x) => x != null).isNotEmpty, 'Need oneOf for ${result._data}'); return result.build(); @@ -3250,10 +5437,10 @@ class _$ProvisioningApiGroupDetails_DisabledSerializer }) { final result = ProvisioningApiGroupDetails_DisabledBuilder()..data = JsonObject(data); try { - result._$bool = data as bool?; + result._$bool = _jsonSerializers.deserialize(data, specifiedType: const FullType(bool))! as bool; } catch (_) {} try { - result._$int = data as int?; + result._$int = _jsonSerializers.deserialize(data, specifiedType: const FullType(int))! as int; } catch (_) {} assert([result._$bool, result._$int].where((final x) => x != null).isNotEmpty, 'Need oneOf for ${result._data}'); return result.build(); @@ -3600,13 +5787,13 @@ class _$ProvisioningApiUserDetailsQuota_QuotaSerializer }) { final result = ProvisioningApiUserDetailsQuota_QuotaBuilder()..data = JsonObject(data); try { - result._$num = data as num?; + result._$num = _jsonSerializers.deserialize(data, specifiedType: const FullType(num))! as num; } catch (_) {} try { - result._$int = data as int?; + result._$int = _jsonSerializers.deserialize(data, specifiedType: const FullType(int))! as int; } catch (_) {} try { - result._string = data as String?; + result._string = _jsonSerializers.deserialize(data, specifiedType: const FullType(String))! as String; } catch (_) {} assert( [result._$num, result._$int, result._string].where((final x) => x != null).isNotEmpty, @@ -7024,14 +9211,8 @@ final Serializers _serializers = (Serializers().toBuilder() ..add(ProvisioningApiCapabilities_ProvisioningApi.serializer)) .build(); -Serializers get provisioningApiSerializers => _serializers; - final Serializers _jsonSerializers = (_serializers.toBuilder() ..addPlugin(StandardJsonPlugin()) ..addPlugin(const ContentStringPlugin())) .build(); - -T deserializeProvisioningApi(final Object data) => _serializers.deserialize(data, specifiedType: FullType(T))! as T; - -Object? serializeProvisioningApi(final T data) => _serializers.serialize(data, specifiedType: FullType(T)); // coverage:ignore-end diff --git a/packages/nextcloud/lib/src/api/settings.openapi.dart b/packages/nextcloud/lib/src/api/settings.openapi.dart index 96609560..848a2571 100644 --- a/packages/nextcloud/lib/src/api/settings.openapi.dart +++ b/packages/nextcloud/lib/src/api/settings.openapi.dart @@ -1,54 +1,22 @@ // ignore_for_file: camel_case_types +// ignore_for_file: discarded_futures // ignore_for_file: public_member_api_docs +// ignore_for_file: unreachable_switch_case import 'dart:typed_data'; import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.dart'; import 'package:built_value/standard_json_plugin.dart'; +import 'package:collection/collection.dart'; import 'package:dynamite_runtime/content_string.dart'; import 'package:dynamite_runtime/http_client.dart'; +import 'package:meta/meta.dart'; import 'package:universal_io/io.dart'; export 'package:dynamite_runtime/http_client.dart'; part 'settings.openapi.g.dart'; -class SettingsResponse extends DynamiteResponse { - SettingsResponse( - super.data, - super.headers, - ); - - @override - String toString() => 'SettingsResponse(data: $data, headers: $headers)'; -} - -class SettingsApiException extends DynamiteApiException { - SettingsApiException( - super.statusCode, - super.headers, - super.body, - ); - - static Future fromResponse(final HttpClientResponse response) async { - String body; - try { - body = await response.body; - } on FormatException { - body = 'binary'; - } - - return SettingsApiException( - response.statusCode, - response.responseHeaders, - body, - ); - } - - @override - String toString() => 'SettingsApiException(statusCode: $statusCode, headers: $headers, body: $body)'; -} - class SettingsClient extends DynamiteClient { SettingsClient( super.baseURL, { @@ -76,45 +44,77 @@ class SettingsLogSettingsClient { final SettingsClient _rootClient; - /// download logfile + /// download logfile. /// - /// This endpoint requires admin access - Future> download() async { + /// This endpoint requires admin access. + /// + /// 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: Logfile returned + /// + /// See: + /// * [downloadRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> download() async { + final rawResponse = downloadRaw(); + + return rawResponse.future; + } + + /// download logfile. + /// + /// This endpoint requires admin access. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: Logfile returned + /// + /// See: + /// * [download] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse downloadRaw() { const path = '/index.php/settings/admin/log/download'; final queryParameters = {}; final headers = { 'Accept': 'application/octet-stream', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + +// coverage:ignore-end + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(Uint8List), + headersType: const FullType(SettingsLogSettingsLogSettingsDownloadHeaders), + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return SettingsResponse( - await response.bodyBytes, - _jsonSerializers.deserialize( - response.responseHeaders, - specifiedType: const FullType(SettingsLogSettingsLogSettingsDownloadHeaders), - )! as SettingsLogSettingsLogSettingsDownloadHeaders, - ); - } - throw await SettingsApiException.fromResponse(response); // coverage:ignore-line } } @@ -206,14 +206,8 @@ final Serializers _serializers = (Serializers().toBuilder() ..add(SettingsLogSettingsLogSettingsDownloadHeaders.serializer)) .build(); -Serializers get settingsSerializers => _serializers; - final Serializers _jsonSerializers = (_serializers.toBuilder() ..addPlugin(StandardJsonPlugin()) ..addPlugin(const ContentStringPlugin())) .build(); - -T deserializeSettings(final Object data) => _serializers.deserialize(data, specifiedType: FullType(T))! as T; - -Object? serializeSettings(final T data) => _serializers.serialize(data, specifiedType: FullType(T)); // coverage:ignore-end diff --git a/packages/nextcloud/lib/src/api/sharebymail.openapi.dart b/packages/nextcloud/lib/src/api/sharebymail.openapi.dart index 7a7bbbb8..79f4a197 100644 --- a/packages/nextcloud/lib/src/api/sharebymail.openapi.dart +++ b/packages/nextcloud/lib/src/api/sharebymail.openapi.dart @@ -1,53 +1,18 @@ // ignore_for_file: camel_case_types +// ignore_for_file: discarded_futures // ignore_for_file: public_member_api_docs +// ignore_for_file: unreachable_switch_case import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.dart'; import 'package:built_value/standard_json_plugin.dart'; import 'package:dynamite_runtime/content_string.dart'; import 'package:dynamite_runtime/http_client.dart'; -import 'package:universal_io/io.dart'; export 'package:dynamite_runtime/http_client.dart'; part 'sharebymail.openapi.g.dart'; -class SharebymailResponse extends DynamiteResponse { - SharebymailResponse( - super.data, - super.headers, - ); - - @override - String toString() => 'SharebymailResponse(data: $data, headers: $headers)'; -} - -class SharebymailApiException extends DynamiteApiException { - SharebymailApiException( - super.statusCode, - super.headers, - super.body, - ); - - static Future fromResponse(final HttpClientResponse response) async { - String body; - try { - body = await response.body; - } on FormatException { - body = 'binary'; - } - - return SharebymailApiException( - response.statusCode, - response.responseHeaders, - body, - ); - } - - @override - String toString() => 'SharebymailApiException(statusCode: $statusCode, headers: $headers, body: $body)'; -} - class SharebymailClient extends DynamiteClient { SharebymailClient( super.baseURL, { @@ -309,14 +274,8 @@ final Serializers _serializers = (Serializers().toBuilder() ..add(SharebymailCapabilities_FilesSharing_Sharebymail_ExpireDate.serializer)) .build(); -Serializers get sharebymailSerializers => _serializers; - final Serializers _jsonSerializers = (_serializers.toBuilder() ..addPlugin(StandardJsonPlugin()) ..addPlugin(const ContentStringPlugin())) .build(); - -T deserializeSharebymail(final Object data) => _serializers.deserialize(data, specifiedType: FullType(T))! as T; - -Object? serializeSharebymail(final T data) => _serializers.serialize(data, specifiedType: FullType(T)); // coverage:ignore-end diff --git a/packages/nextcloud/lib/src/api/theming.openapi.dart b/packages/nextcloud/lib/src/api/theming.openapi.dart index 1ac3c481..4f47de33 100644 --- a/packages/nextcloud/lib/src/api/theming.openapi.dart +++ b/packages/nextcloud/lib/src/api/theming.openapi.dart @@ -1,5 +1,7 @@ // ignore_for_file: camel_case_types +// ignore_for_file: discarded_futures // ignore_for_file: public_member_api_docs +// ignore_for_file: unreachable_switch_case import 'dart:typed_data'; import 'package:built_collection/built_collection.dart'; @@ -7,50 +9,17 @@ 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'; +import 'package:collection/collection.dart'; import 'package:dynamite_runtime/content_string.dart'; import 'package:dynamite_runtime/http_client.dart'; +import 'package:dynamite_runtime/utils.dart'; +import 'package:meta/meta.dart'; import 'package:universal_io/io.dart'; export 'package:dynamite_runtime/http_client.dart'; part 'theming.openapi.g.dart'; -class ThemingResponse extends DynamiteResponse { - ThemingResponse( - super.data, - super.headers, - ); - - @override - String toString() => 'ThemingResponse(data: $data, headers: $headers)'; -} - -class ThemingApiException extends DynamiteApiException { - ThemingApiException( - super.statusCode, - super.headers, - super.body, - ); - - static Future fromResponse(final HttpClientResponse response) async { - String body; - try { - body = await response.body; - } on FormatException { - body = 'binary'; - } - - return ThemingApiException( - response.statusCode, - response.responseHeaders, - body, - ); - } - - @override - String toString() => 'ThemingApiException(statusCode: $statusCode, headers: $headers, body: $body)'; -} - class ThemingClient extends DynamiteClient { ThemingClient( super.baseURL, { @@ -82,140 +51,341 @@ class ThemingIconClient { final ThemingClient _rootClient; - /// Return a 32x32 favicon as png - Future getFavicon({final String app = 'core'}) async { + /// Return a 32x32 favicon as png. + /// + /// 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: + /// * [app] ID of the app + /// + /// Status codes: + /// * 200: Favicon returned + /// * 404: Favicon not found + /// * 500 + /// + /// See: + /// * [getFaviconRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getFavicon({final String app = 'core'}) async { + final rawResponse = getFaviconRaw( + app: app, + ); + + return rawResponse.future; + } + + /// Return a 32x32 favicon as png. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [app] ID of the app + /// + /// Status codes: + /// * 200: Favicon returned + /// * 404: Favicon not found + /// * 500 + /// + /// See: + /// * [getFavicon] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getFaviconRaw({final String app = 'core'}) { var path = '/index.php/apps/theming/favicon/{app}'; final queryParameters = {}; final headers = { 'Accept': 'image/x-icon', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{app}', Uri.encodeQueryComponent(app)); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return response.bodyBytes; - } - throw await ThemingApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(Uint8List), + headersType: null, + serializers: _jsonSerializers, + ); + } + + /// Return a 512x512 icon for touch devices. + /// + /// 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: + /// * [app] ID of the app + /// + /// Status codes: + /// * 200: Touch icon returned + /// * 404: Touch icon not found + /// * 500 + /// + /// See: + /// * [getTouchIconRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getTouchIcon({final String app = 'core'}) async { + final rawResponse = getTouchIconRaw( + app: app, + ); + + return rawResponse.future; } - /// Return a 512x512 icon for touch devices - Future getTouchIcon({final String app = 'core'}) async { + /// Return a 512x512 icon for touch devices. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [app] ID of the app + /// + /// Status codes: + /// * 200: Touch icon returned + /// * 404: Touch icon not found + /// * 500 + /// + /// See: + /// * [getTouchIcon] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getTouchIconRaw({final String app = 'core'}) { var path = '/index.php/apps/theming/icon/{app}'; final queryParameters = {}; final headers = { 'Accept': 'image/png', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{app}', Uri.encodeQueryComponent(app)); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return response.bodyBytes; - } - throw await ThemingApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(Uint8List), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Get a themed icon - Future getThemedIcon({ + /// Get a themed icon. + /// + /// 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: + /// * [app] ID of the app + /// * [image] image file name (svg required) + /// + /// Status codes: + /// * 200: Themed icon returned + /// * 404: Themed icon not found + /// * 500 + /// + /// See: + /// * [getThemedIconRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getThemedIcon({ required final String app, required final String image, }) async { + final rawResponse = getThemedIconRaw( + app: app, + image: image, + ); + + return rawResponse.future; + } + + /// Get a themed icon. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [app] ID of the app + /// * [image] image file name (svg required) + /// + /// Status codes: + /// * 200: Themed icon returned + /// * 404: Themed icon not found + /// * 500 + /// + /// See: + /// * [getThemedIcon] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getThemedIconRaw({ + required final String app, + required final String image, + }) { var path = '/index.php/apps/theming/img/{app}/{image}'; final queryParameters = {}; final headers = { 'Accept': 'image/svg+xml', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{app}', Uri.encodeQueryComponent(app)); - if (!RegExp(r'^.+$').hasMatch(image)) { - throw Exception('Invalid value "$image" for parameter "image" with pattern "${r'^.+$'}"'); // coverage:ignore-line - } + checkPattern(image, RegExp(r'^.+$'), 'image'); // coverage:ignore-line path = path.replaceAll('{image}', Uri.encodeQueryComponent(image)); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return response.bodyBytes; - } - throw await ThemingApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(Uint8List), + headersType: null, + serializers: _jsonSerializers, + ); } } -/// Class ThemingController -/// handle ajax requests to update the theme +/// Class ThemingController. +/// handle ajax requests to update the theme. class ThemingThemingClient { ThemingThemingClient(this._rootClient); final ThemingClient _rootClient; - /// Get the CSS stylesheet for a theme - Future getThemeStylesheet({ + /// Get the CSS stylesheet for a theme. + /// + /// 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: + /// * [plain] Let the browser decide the CSS priority + /// * [withCustomCss] Include custom CSS + /// * [themeId] ID of the theme + /// + /// Status codes: + /// * 200: Stylesheet returned + /// * 404: Theme not found + /// + /// See: + /// * [getThemeStylesheetRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getThemeStylesheet({ required final String themeId, final int plain = 0, final int withCustomCss = 0, }) async { + final rawResponse = getThemeStylesheetRaw( + themeId: themeId, + plain: plain, + withCustomCss: withCustomCss, + ); + + return rawResponse.future; + } + + /// Get the CSS stylesheet for a theme. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [plain] Let the browser decide the CSS priority + /// * [withCustomCss] Include custom CSS + /// * [themeId] ID of the theme + /// + /// Status codes: + /// * 200: Stylesheet returned + /// * 404: Theme not found + /// + /// See: + /// * [getThemeStylesheet] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getThemeStylesheetRaw({ + required final String themeId, + final int plain = 0, + final int withCustomCss = 0, + }) { var path = '/index.php/apps/theming/theme/{themeId}.css'; final queryParameters = {}; final headers = { 'Accept': 'text/css', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{themeId}', Uri.encodeQueryComponent(themeId)); if (plain != 0) { queryParameters['plain'] = plain.toString(); @@ -223,89 +393,191 @@ class ThemingThemingClient { if (withCustomCss != 0) { queryParameters['withCustomCss'] = withCustomCss.toString(); } - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return response.body; - } - throw await ThemingApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(String), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Get an image - Future getImage({ + /// Get an image. + /// + /// 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: + /// * [useSvg] Return image as SVG + /// * [key] Key of the image + /// + /// Status codes: + /// * 200: Image returned + /// * 404: Image not found + /// * 500 + /// + /// See: + /// * [getImageRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getImage({ required final String key, final int useSvg = 1, }) async { + final rawResponse = getImageRaw( + key: key, + useSvg: useSvg, + ); + + return rawResponse.future; + } + + /// Get an image. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [useSvg] Return image as SVG + /// * [key] Key of the image + /// + /// Status codes: + /// * 200: Image returned + /// * 404: Image not found + /// * 500 + /// + /// See: + /// * [getImage] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getImageRaw({ + required final String key, + final int useSvg = 1, + }) { var path = '/index.php/apps/theming/image/{key}'; final queryParameters = {}; final headers = { 'Accept': '*/*', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{key}', Uri.encodeQueryComponent(key)); if (useSvg != 1) { queryParameters['useSvg'] = useSvg.toString(); } - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return response.bodyBytes; - } - throw await ThemingApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(Uint8List), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Get the manifest for an app - Future getManifest({required final String app}) async { + /// Get the manifest for an 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. + /// + /// Parameters: + /// * [app] ID of the app + /// + /// Status codes: + /// * 200: Manifest returned + /// + /// See: + /// * [getManifestRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getManifest({ + required final String app, + }) async { + final rawResponse = getManifestRaw( + app: app, + ); + + return rawResponse.future; + } + + /// Get the manifest for an app. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [app] ID of the app + /// + /// Status codes: + /// * 200: Manifest returned + /// + /// See: + /// * [getManifest] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getManifestRaw({ + required final String app, + }) { var path = '/index.php/apps/theming/manifest/{app}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{app}', Uri.encodeQueryComponent(app)); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ThemingThemingGetManifestResponseApplicationJson), - )! as ThemingThemingGetManifestResponseApplicationJson; - } - throw await ThemingApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ThemingThemingGetManifestResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } } @@ -314,66 +586,171 @@ class ThemingUserThemeClient { final ThemingClient _rootClient; - /// Get the background image - Future getBackground({final bool oCSAPIRequest = true}) async { + /// Get the background image. + /// + /// 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: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Background image returned + /// * 404: Background image not found + /// + /// See: + /// * [getBackgroundRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getBackground({final bool oCSAPIRequest = true}) async { + final rawResponse = getBackgroundRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get the background image. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Background image returned + /// * 404: Background image not found + /// + /// See: + /// * [getBackground] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getBackgroundRaw({final bool oCSAPIRequest = true}) { const path = '/index.php/apps/theming/background'; final queryParameters = {}; final headers = { 'Accept': '*/*', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return response.bodyBytes; - } - throw await ThemingApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(Uint8List), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Set the background - Future setBackground({ + /// Set the background. + /// + /// 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: + /// * [value] Path of the background image + /// * [color] Color for the background + /// * [type] Type of background + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Background set successfully + /// * 400: Setting background is not possible + /// * 500 + /// + /// See: + /// * [setBackgroundRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> setBackground({ required final String type, final String value = '', final String? color, final bool oCSAPIRequest = true, }) async { + final rawResponse = setBackgroundRaw( + type: type, + value: value, + color: color, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Set the background. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [value] Path of the background image + /// * [color] Color for the background + /// * [type] Type of background + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Background set successfully + /// * 400: Setting background is not possible + /// * 500 + /// + /// See: + /// * [setBackground] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse setBackgroundRaw({ + required final String type, + final String value = '', + final String? color, + final bool oCSAPIRequest = true, + }) { var path = '/index.php/apps/theming/background/{type}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{type}', Uri.encodeQueryComponent(type)); if (value != '') { queryParameters['value'] = value; @@ -382,134 +759,281 @@ class ThemingUserThemeClient { queryParameters['color'] = color; } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize(await response.jsonBody, specifiedType: const FullType(ThemingBackground))! - as ThemingBackground; - } - throw await ThemingApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ThemingBackground), + headersType: null, + serializers: _jsonSerializers, + ); + } + + /// Delete the background. + /// + /// 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: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Background deleted successfully + /// + /// See: + /// * [deleteBackgroundRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> deleteBackground({final bool oCSAPIRequest = true}) async { + final rawResponse = deleteBackgroundRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; } - /// Delete the background - Future deleteBackground({final bool oCSAPIRequest = true}) async { + /// Delete the background. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Background deleted successfully + /// + /// See: + /// * [deleteBackground] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse deleteBackgroundRaw({final bool oCSAPIRequest = true}) { const path = '/index.php/apps/theming/background/custom'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize(await response.jsonBody, specifiedType: const FullType(ThemingBackground))! - as ThemingBackground; - } - throw await ThemingApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'delete', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ThemingBackground), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Enable theme - Future enableTheme({ + /// Enable theme. + /// + /// 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: + /// * [themeId] the theme ID + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Theme enabled successfully + /// * 400: Enabling theme is not possible + /// * 500 + /// + /// See: + /// * [enableThemeRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> enableTheme({ required final String themeId, final bool oCSAPIRequest = true, }) async { + final rawResponse = enableThemeRaw( + themeId: themeId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Enable theme. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [themeId] the theme ID + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Theme enabled successfully + /// * 400: Enabling theme is not possible + /// * 500 + /// + /// See: + /// * [enableTheme] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse enableThemeRaw({ + required final String themeId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/theming/api/v1/theme/{themeId}/enable'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{themeId}', Uri.encodeQueryComponent(themeId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'put', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ThemingUserThemeEnableThemeResponseApplicationJson), - )! as ThemingUserThemeEnableThemeResponseApplicationJson; - } - throw await ThemingApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'put', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ThemingUserThemeEnableThemeResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } - /// Disable theme - Future disableTheme({ + /// Disable theme. + /// + /// 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: + /// * [themeId] the theme ID + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Theme disabled successfully + /// * 400: Disabling theme is not possible + /// * 500 + /// + /// See: + /// * [disableThemeRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> disableTheme({ required final String themeId, final bool oCSAPIRequest = true, }) async { + final rawResponse = disableThemeRaw( + themeId: themeId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Disable theme. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [themeId] the theme ID + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Theme disabled successfully + /// * 400: Disabling theme is not possible + /// * 500 + /// + /// See: + /// * [disableTheme] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse disableThemeRaw({ + required final String themeId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/theming/api/v1/theme/{themeId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{themeId}', Uri.encodeQueryComponent(themeId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, - ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(ThemingUserThemeDisableThemeResponseApplicationJson), - )! as ThemingUserThemeDisableThemeResponseApplicationJson; - } - throw await ThemingApiException.fromResponse(response); // coverage:ignore-line + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'delete', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(ThemingUserThemeDisableThemeResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, + ); } } @@ -922,14 +1446,8 @@ final Serializers _serializers = (Serializers().toBuilder() ..add(ThemingPublicCapabilities_Theming.serializer)) .build(); -Serializers get themingSerializers => _serializers; - final Serializers _jsonSerializers = (_serializers.toBuilder() ..addPlugin(StandardJsonPlugin()) ..addPlugin(const ContentStringPlugin())) .build(); - -T deserializeTheming(final Object data) => _serializers.deserialize(data, specifiedType: FullType(T))! as T; - -Object? serializeTheming(final T data) => _serializers.serialize(data, specifiedType: FullType(T)); // coverage:ignore-end diff --git a/packages/nextcloud/lib/src/api/updatenotification.openapi.dart b/packages/nextcloud/lib/src/api/updatenotification.openapi.dart index 75934437..7c641d6d 100644 --- a/packages/nextcloud/lib/src/api/updatenotification.openapi.dart +++ b/packages/nextcloud/lib/src/api/updatenotification.openapi.dart @@ -1,55 +1,23 @@ // ignore_for_file: camel_case_types +// ignore_for_file: discarded_futures // ignore_for_file: public_member_api_docs +// ignore_for_file: unreachable_switch_case import 'dart:typed_data'; import 'package:built_collection/built_collection.dart'; import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.dart'; import 'package:built_value/standard_json_plugin.dart'; +import 'package:collection/collection.dart'; import 'package:dynamite_runtime/content_string.dart'; import 'package:dynamite_runtime/http_client.dart'; +import 'package:meta/meta.dart'; import 'package:universal_io/io.dart'; export 'package:dynamite_runtime/http_client.dart'; part 'updatenotification.openapi.g.dart'; -class UpdatenotificationResponse extends DynamiteResponse { - UpdatenotificationResponse( - super.data, - super.headers, - ); - - @override - String toString() => 'UpdatenotificationResponse(data: $data, headers: $headers)'; -} - -class UpdatenotificationApiException extends DynamiteApiException { - UpdatenotificationApiException( - super.statusCode, - super.headers, - super.body, - ); - - static Future fromResponse(final HttpClientResponse response) async { - String body; - try { - body = await response.body; - } on FormatException { - body = 'binary'; - } - - return UpdatenotificationApiException( - response.statusCode, - response.responseHeaders, - body, - ); - } - - @override - String toString() => 'UpdatenotificationApiException(statusCode: $statusCode, headers: $headers, body: $body)'; -} - class UpdatenotificationClient extends DynamiteClient { UpdatenotificationClient( super.baseURL, { @@ -77,49 +45,104 @@ class UpdatenotificationApiClient { final UpdatenotificationClient _rootClient; - /// List available updates for apps + /// List available updates for apps. + /// + /// This endpoint requires admin access. + /// + /// 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: + /// * [apiVersion] + /// * [newVersion] Server version to check updates for + /// * [oCSAPIRequest] Required to be true for the API request to pass /// - /// This endpoint requires admin access - Future getAppList({ + /// Status codes: + /// * 200: Apps returned + /// * 404: New versions not found + /// + /// See: + /// * [getAppListRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getAppList({ required final String newVersion, final UpdatenotificationApiGetAppListApiVersion apiVersion = UpdatenotificationApiGetAppListApiVersion.v1, final bool oCSAPIRequest = true, }) async { + final rawResponse = getAppListRaw( + newVersion: newVersion, + apiVersion: apiVersion, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// List available updates for apps. + /// + /// This endpoint requires admin access. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [apiVersion] + /// * [newVersion] Server version to check updates for + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Apps returned + /// * 404: New versions not found + /// + /// See: + /// * [getAppList] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getAppListRaw({ + required final String newVersion, + final UpdatenotificationApiGetAppListApiVersion apiVersion = UpdatenotificationApiGetAppListApiVersion.v1, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/updatenotification/api/{apiVersion}/applist/{newVersion}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{newVersion}', Uri.encodeQueryComponent(newVersion)); path = path.replaceAll('{apiVersion}', Uri.encodeQueryComponent(apiVersion.name)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(UpdatenotificationApiGetAppListResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(UpdatenotificationApiGetAppListResponseApplicationJson), - )! as UpdatenotificationApiGetAppListResponseApplicationJson; - } - throw await UpdatenotificationApiException.fromResponse(response); // coverage:ignore-line } } @@ -335,15 +358,8 @@ final Serializers _serializers = (Serializers().toBuilder() )) .build(); -Serializers get updatenotificationSerializers => _serializers; - final Serializers _jsonSerializers = (_serializers.toBuilder() ..addPlugin(StandardJsonPlugin()) ..addPlugin(const ContentStringPlugin())) .build(); - -T deserializeUpdatenotification(final Object data) => - _serializers.deserialize(data, specifiedType: FullType(T))! as T; - -Object? serializeUpdatenotification(final T data) => _serializers.serialize(data, specifiedType: FullType(T)); // coverage:ignore-end diff --git a/packages/nextcloud/lib/src/api/uppush.openapi.dart b/packages/nextcloud/lib/src/api/uppush.openapi.dart index d33c7184..43468095 100644 --- a/packages/nextcloud/lib/src/api/uppush.openapi.dart +++ b/packages/nextcloud/lib/src/api/uppush.openapi.dart @@ -1,55 +1,23 @@ // ignore_for_file: camel_case_types +// ignore_for_file: discarded_futures // ignore_for_file: public_member_api_docs +// ignore_for_file: unreachable_switch_case import 'dart:typed_data'; import 'package:built_collection/built_collection.dart'; import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.dart'; import 'package:built_value/standard_json_plugin.dart'; +import 'package:collection/collection.dart'; import 'package:dynamite_runtime/content_string.dart'; import 'package:dynamite_runtime/http_client.dart'; +import 'package:meta/meta.dart'; import 'package:universal_io/io.dart'; export 'package:dynamite_runtime/http_client.dart'; part 'uppush.openapi.g.dart'; -class UppushResponse extends DynamiteResponse { - UppushResponse( - super.data, - super.headers, - ); - - @override - String toString() => 'UppushResponse(data: $data, headers: $headers)'; -} - -class UppushApiException extends DynamiteApiException { - UppushApiException( - super.statusCode, - super.headers, - super.body, - ); - - static Future fromResponse(final HttpClientResponse response) async { - String body; - try { - body = await response.body; - } on FormatException { - body = 'binary'; - } - - return UppushApiException( - response.statusCode, - response.responseHeaders, - body, - ); - } - - @override - String toString() => 'UppushApiException(statusCode: $statusCode, headers: $headers, body: $body)'; -} - class UppushClient extends DynamiteClient { UppushClient( super.baseURL, { @@ -69,350 +37,841 @@ class UppushClient extends DynamiteClient { authentications: client.authentications, ); - /// Check if the UnifiedPush provider is present - Future check() async { + /// Check if the UnifiedPush provider is present. + /// + /// 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 + /// + /// See: + /// * [checkRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> check() async { + final rawResponse = checkRaw(); + + return rawResponse.future; + } + + /// Check if the UnifiedPush provider is present. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [check] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse checkRaw() { const path = '/index.php/apps/uppush'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end - final response = await doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + +// coverage:ignore-end + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(UppushCheckResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(UppushCheckResponseApplicationJson), - )! as UppushCheckResponseApplicationJson; - } - throw await UppushApiException.fromResponse(response); // coverage:ignore-line } - /// Set keepalive interval + /// Set keepalive interval. + /// + /// This endpoint requires admin access. + /// + /// 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: + /// * [keepalive] Keep alive value in seconds + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [setKeepaliveRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> setKeepalive({ + required final int keepalive, + }) async { + final rawResponse = setKeepaliveRaw( + keepalive: keepalive, + ); + + return rawResponse.future; + } + + /// Set keepalive interval. + /// + /// This endpoint requires admin access. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [keepalive] Keep alive value in seconds /// - /// This endpoint requires admin access - Future setKeepalive({required final int keepalive}) async { + /// Status codes: + /// * 200 + /// + /// See: + /// * [setKeepalive] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse setKeepaliveRaw({required final int keepalive}) { const path = '/index.php/apps/uppush/keepalive'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['keepalive'] = keepalive.toString(); - final response = await doRequest( - 'put', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'put', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(UppushSetKeepaliveResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(UppushSetKeepaliveResponseApplicationJson), - )! as UppushSetKeepaliveResponseApplicationJson; - } - throw await UppushApiException.fromResponse(response); // coverage:ignore-line } - /// Request to create a new deviceId - Future createDevice({required final String deviceName}) async { + /// Request to create a new deviceId. + /// + /// 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: + /// * [deviceName] Name of the device + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [createDeviceRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> createDevice({ + required final String deviceName, + }) async { + final rawResponse = createDeviceRaw( + deviceName: deviceName, + ); + + return rawResponse.future; + } + + /// Request to create a new deviceId. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [deviceName] Name of the device + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [createDevice] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse createDeviceRaw({ + required final String deviceName, + }) { const path = '/index.php/apps/uppush/device'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['deviceName'] = deviceName; - final response = await doRequest( - 'put', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'put', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(UppushCreateDeviceResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(UppushCreateDeviceResponseApplicationJson), - )! as UppushCreateDeviceResponseApplicationJson; - } - throw await UppushApiException.fromResponse(response); // coverage:ignore-line } - /// Request to get push messages + /// Request to get push messages. + /// + /// This is a public page since it has to be handle by the non-connected app (NextPush app and not Nextcloud-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: + /// * 401: Missing permissions to sync device + /// + /// See: + /// * [syncDeviceRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> syncDevice({ + required final String deviceId, + }) async { + final rawResponse = syncDeviceRaw( + deviceId: deviceId, + ); + + return rawResponse.future; + } + + /// Request to get push messages. + /// + /// This is a public page since it has to be handle by the non-connected app (NextPush app and not Nextcloud-app). + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Status codes: + /// * 401: Missing permissions to sync device /// - /// This is a public page since it has to be handle by the non-connected app (NextPush app and not Nextcloud-app) - Future syncDevice({required final String deviceId}) async { + /// See: + /// * [syncDevice] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse syncDeviceRaw({required final String deviceId}) { var path = '/index.php/apps/uppush/device/{deviceId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{deviceId}', Uri.encodeQueryComponent(deviceId)); - final response = await doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'get', + uri, + headers, + body, + const {401}, + ), + bodyType: const FullType(UppushSyncDeviceResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 401) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(UppushSyncDeviceResponseApplicationJson), - )! as UppushSyncDeviceResponseApplicationJson; - } - throw await UppushApiException.fromResponse(response); // coverage:ignore-line } - /// Delete a device - Future deleteDevice({required final String deviceId}) async { + /// Delete a device. + /// + /// 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: Device deleted successfully + /// + /// See: + /// * [deleteDeviceRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> deleteDevice({ + required final String deviceId, + }) async { + final rawResponse = deleteDeviceRaw( + deviceId: deviceId, + ); + + return rawResponse.future; + } + + /// Delete a device. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: Device deleted successfully + /// + /// See: + /// * [deleteDevice] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse deleteDeviceRaw({ + required final String deviceId, + }) { var path = '/index.php/apps/uppush/device/{deviceId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{deviceId}', Uri.encodeQueryComponent(deviceId)); - final response = await doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'delete', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(UppushDeleteDeviceResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(UppushDeleteDeviceResponseApplicationJson), - )! as UppushDeleteDeviceResponseApplicationJson; - } - throw await UppushApiException.fromResponse(response); // coverage:ignore-line } - /// Create an authorization token for a new 3rd party service - Future createApp({ + /// Create an authorization token for a new 3rd party service. + /// + /// 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: + /// * [deviceId] ID of the device + /// * [appName] Name of the app + /// + /// Status codes: + /// * 200: App created successfully + /// + /// See: + /// * [createAppRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> createApp({ required final String deviceId, required final String appName, }) async { + final rawResponse = createAppRaw( + deviceId: deviceId, + appName: appName, + ); + + return rawResponse.future; + } + + /// Create an authorization token for a new 3rd party service. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [deviceId] ID of the device + /// * [appName] Name of the app + /// + /// Status codes: + /// * 200: App created successfully + /// + /// See: + /// * [createApp] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse createAppRaw({ + required final String deviceId, + required final String appName, + }) { const path = '/index.php/apps/uppush/app'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['deviceId'] = deviceId; queryParameters['appName'] = appName; - final response = await doRequest( - 'put', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'put', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(UppushCreateAppResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(UppushCreateAppResponseApplicationJson), - )! as UppushCreateAppResponseApplicationJson; - } - throw await UppushApiException.fromResponse(response); // coverage:ignore-line } - /// Delete an authorization token - Future deleteApp({required final String token}) async { + /// Delete an authorization token. + /// + /// 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: App deleted successfully + /// + /// See: + /// * [deleteAppRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> deleteApp({ + required final String token, + }) async { + final rawResponse = deleteAppRaw( + token: token, + ); + + return rawResponse.future; + } + + /// Delete an authorization token. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200: App deleted successfully + /// + /// See: + /// * [deleteApp] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse deleteAppRaw({required final String token}) { var path = '/index.php/apps/uppush/app/{token}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{token}', Uri.encodeQueryComponent(token)); - final response = await doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'delete', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(UppushDeleteAppResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(UppushDeleteAppResponseApplicationJson), - )! as UppushDeleteAppResponseApplicationJson; - } - throw await UppushApiException.fromResponse(response); // coverage:ignore-line } - /// Unifiedpush discovery Following specifications - Future unifiedpushDiscovery({required final String token}) async { + /// Unifiedpush discovery Following specifications. + /// + /// 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 + /// + /// See: + /// * [unifiedpushDiscoveryRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> unifiedpushDiscovery({ + required final String token, + }) async { + final rawResponse = unifiedpushDiscoveryRaw( + token: token, + ); + + return rawResponse.future; + } + + /// Unifiedpush discovery Following specifications. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [unifiedpushDiscovery] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse unifiedpushDiscoveryRaw({ + required final String token, + }) { var path = '/index.php/apps/uppush/push/{token}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{token}', Uri.encodeQueryComponent(token)); - final response = await doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(UppushUnifiedpushDiscoveryResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(UppushUnifiedpushDiscoveryResponseApplicationJson), - )! as UppushUnifiedpushDiscoveryResponseApplicationJson; - } - throw await UppushApiException.fromResponse(response); // coverage:ignore-line } - /// Receive notifications from 3rd parties - Future push({required final String token}) async { + /// Receive notifications from 3rd parties. + /// + /// 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: + /// * 201: Notification pushed successfully + /// + /// See: + /// * [pushRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> push({required final String token}) async { + final rawResponse = pushRaw( + token: token, + ); + + return rawResponse.future; + } + + /// Receive notifications from 3rd parties. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Status codes: + /// * 201: Notification pushed successfully + /// + /// See: + /// * [push] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse pushRaw({required final String token}) { var path = '/index.php/apps/uppush/push/{token}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{token}', Uri.encodeQueryComponent(token)); - final response = await doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'post', + uri, + headers, + body, + const {201}, + ), + bodyType: const FullType(UppushPushResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 201) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(UppushPushResponseApplicationJson), - )! as UppushPushResponseApplicationJson; - } - throw await UppushApiException.fromResponse(response); // coverage:ignore-line } - /// Matrix Gateway discovery - Future gatewayMatrixDiscovery() async { + /// Matrix Gateway discovery. + /// + /// 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 + /// + /// See: + /// * [gatewayMatrixDiscoveryRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> gatewayMatrixDiscovery() async { + final rawResponse = gatewayMatrixDiscoveryRaw(); + + return rawResponse.future; + } + + /// Matrix Gateway discovery. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [gatewayMatrixDiscovery] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse gatewayMatrixDiscoveryRaw() { const path = '/index.php/apps/uppush/gateway/matrix'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end - final response = await doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + +// coverage:ignore-end + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(UppushGatewayMatrixDiscoveryResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(UppushGatewayMatrixDiscoveryResponseApplicationJson), - )! as UppushGatewayMatrixDiscoveryResponseApplicationJson; - } - throw await UppushApiException.fromResponse(response); // coverage:ignore-line } - /// Matrix Gateway - Future gatewayMatrix() async { + /// Matrix Gateway. + /// + /// 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 + /// + /// See: + /// * [gatewayMatrixRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> gatewayMatrix() async { + final rawResponse = gatewayMatrixRaw(); + + return rawResponse.future; + } + + /// Matrix Gateway. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Status codes: + /// * 200 + /// + /// See: + /// * [gatewayMatrix] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse gatewayMatrixRaw() { const path = '/index.php/apps/uppush/gateway/matrix'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { - headers.addAll(authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers); + +// coverage:ignore-start + final authentication = authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { + headers.addAll( + authentication.headers, + ); } else { throw Exception('Missing authentication for basic_auth'); } - // coverage:ignore-end - final response = await doRequest( - 'post', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + +// coverage:ignore-end + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: doRequest( + 'post', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(UppushGatewayMatrixResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(UppushGatewayMatrixResponseApplicationJson), - )! as UppushGatewayMatrixResponseApplicationJson; - } - throw await UppushApiException.fromResponse(response); // coverage:ignore-line } } @@ -925,14 +1384,8 @@ final Serializers _serializers = (Serializers().toBuilder() ..addBuilderFactory(const FullType(BuiltList, [FullType(String)]), ListBuilder.new)) .build(); -Serializers get uppushSerializers => _serializers; - final Serializers _jsonSerializers = (_serializers.toBuilder() ..addPlugin(StandardJsonPlugin()) ..addPlugin(const ContentStringPlugin())) .build(); - -T deserializeUppush(final Object data) => _serializers.deserialize(data, specifiedType: FullType(T))! as T; - -Object? serializeUppush(final T data) => _serializers.serialize(data, specifiedType: FullType(T)); // coverage:ignore-end diff --git a/packages/nextcloud/lib/src/api/user_status.openapi.dart b/packages/nextcloud/lib/src/api/user_status.openapi.dart index 96563011..1a54c0f2 100644 --- a/packages/nextcloud/lib/src/api/user_status.openapi.dart +++ b/packages/nextcloud/lib/src/api/user_status.openapi.dart @@ -1,5 +1,7 @@ // ignore_for_file: camel_case_types +// ignore_for_file: discarded_futures // ignore_for_file: public_member_api_docs +// ignore_for_file: unreachable_switch_case import 'dart:typed_data'; import 'package:built_collection/built_collection.dart'; @@ -7,50 +9,16 @@ 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'; +import 'package:collection/collection.dart'; import 'package:dynamite_runtime/content_string.dart'; import 'package:dynamite_runtime/http_client.dart'; +import 'package:meta/meta.dart'; import 'package:universal_io/io.dart'; export 'package:dynamite_runtime/http_client.dart'; part 'user_status.openapi.g.dart'; -class UserStatusResponse extends DynamiteResponse { - UserStatusResponse( - super.data, - super.headers, - ); - - @override - String toString() => 'UserStatusResponse(data: $data, headers: $headers)'; -} - -class UserStatusApiException extends DynamiteApiException { - UserStatusApiException( - super.statusCode, - super.headers, - super.body, - ); - - static Future fromResponse(final HttpClientResponse response) async { - String body; - try { - body = await response.body; - } on FormatException { - body = 'binary'; - } - - return UserStatusApiException( - response.statusCode, - response.responseHeaders, - body, - ); - } - - @override - String toString() => 'UserStatusApiException(statusCode: $statusCode, headers: $headers, body: $body)'; -} - class UserStatusClient extends DynamiteClient { UserStatusClient( super.baseURL, { @@ -84,45 +52,98 @@ class UserStatusHeartbeatClient { final UserStatusClient _rootClient; - /// Keep the status alive - Future heartbeat({ + /// Keep the status alive. + /// + /// 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: + /// * [status] Only online, away + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Status successfully updated + /// * 400: Invalid status to update + /// * 500 + /// * 204: User has no status to keep alive + /// + /// See: + /// * [heartbeatRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> heartbeat({ required final String status, final bool oCSAPIRequest = true, }) async { + final rawResponse = heartbeatRaw( + status: status, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Keep the status alive. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [status] Only online, away + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Status successfully updated + /// * 400: Invalid status to update + /// * 500 + /// * 204: User has no status to keep alive + /// + /// See: + /// * [heartbeat] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse heartbeatRaw({ + required final String status, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/user_status/api/v1/heartbeat'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['status'] = status; headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'put', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'put', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(UserStatusHeartbeatHeartbeatResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(UserStatusHeartbeatHeartbeatResponseApplicationJson), - )! as UserStatusHeartbeatHeartbeatResponseApplicationJson; - } - throw await UserStatusApiException.fromResponse(response); // coverage:ignore-line } } @@ -131,41 +152,86 @@ class UserStatusPredefinedStatusClient { final UserStatusClient _rootClient; - /// Get all predefined messages - Future findAll({final bool oCSAPIRequest = true}) async { + /// Get all predefined messages. + /// + /// 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: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Predefined statuses returned + /// + /// See: + /// * [findAllRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> findAll({ + final bool oCSAPIRequest = true, + }) async { + final rawResponse = findAllRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get all predefined messages. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Predefined statuses returned + /// + /// See: + /// * [findAll] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse findAllRaw({ + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/user_status/api/v1/predefined_statuses'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(UserStatusPredefinedStatusFindAllResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(UserStatusPredefinedStatusFindAllResponseApplicationJson), - )! as UserStatusPredefinedStatusFindAllResponseApplicationJson; - } - throw await UserStatusApiException.fromResponse(response); // coverage:ignore-line } } @@ -174,31 +240,82 @@ class UserStatusStatusesClient { final UserStatusClient _rootClient; - /// Find statuses of users - Future findAll({ + /// Find statuses of users. + /// + /// 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: + /// * [limit] Maximum number of statuses to find + /// * [offset] Offset for finding statuses + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Statuses returned + /// + /// See: + /// * [findAllRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> findAll({ final int? limit, final int? offset, final bool oCSAPIRequest = true, }) async { + final rawResponse = findAllRaw( + limit: limit, + offset: offset, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Find statuses of users. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [limit] Maximum number of statuses to find + /// * [offset] Offset for finding statuses + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Statuses returned + /// + /// See: + /// * [findAll] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse findAllRaw({ + final int? limit, + final int? offset, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/user_status/api/v1/statuses'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end if (limit != null) { queryParameters['limit'] = limit.toString(); } @@ -206,60 +323,109 @@ class UserStatusStatusesClient { queryParameters['offset'] = offset.toString(); } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(UserStatusStatusesFindAllResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(UserStatusStatusesFindAllResponseApplicationJson), - )! as UserStatusStatusesFindAllResponseApplicationJson; - } - throw await UserStatusApiException.fromResponse(response); // coverage:ignore-line } - /// Find the status of a user - Future find({ + /// Find the status of a 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. + /// + /// Parameters: + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Status returned + /// * 404: The user was not found + /// + /// See: + /// * [findRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> find({ required final String userId, final bool oCSAPIRequest = true, }) async { + final rawResponse = findRaw( + userId: userId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Find the status of a user. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [userId] ID of the user + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Status returned + /// * 404: The user was not found + /// + /// See: + /// * [find] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse findRaw({ + required final String userId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/user_status/api/v1/statuses/{userId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{userId}', Uri.encodeQueryComponent(userId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(UserStatusStatusesFindResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(UserStatusStatusesFindResponseApplicationJson), - )! as UserStatusStatusesFindResponseApplicationJson; - } - throw await UserStatusApiException.fromResponse(response); // coverage:ignore-line } } @@ -268,155 +434,361 @@ class UserStatusUserStatusClient { final UserStatusClient _rootClient; - /// Get the status of the current user - Future getStatus({final bool oCSAPIRequest = true}) async { + /// Get the status of 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. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: The status was found successfully + /// * 404: The user was not found + /// + /// See: + /// * [getStatusRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getStatus({ + final bool oCSAPIRequest = true, + }) async { + final rawResponse = getStatusRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get the status of the current user. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: The status was found successfully + /// * 404: The user was not found + /// + /// See: + /// * [getStatus] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getStatusRaw({ + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/user_status/api/v1/user_status'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(UserStatusUserStatusGetStatusResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(UserStatusUserStatusGetStatusResponseApplicationJson), - )! as UserStatusUserStatusGetStatusResponseApplicationJson; - } - throw await UserStatusApiException.fromResponse(response); // coverage:ignore-line } - /// Update the status type of the current user - Future setStatus({ + /// Update the status type of 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. + /// + /// Parameters: + /// * [statusType] The new status type + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: The status was updated successfully + /// * 400: The status type is invalid + /// + /// See: + /// * [setStatusRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> setStatus({ required final String statusType, final bool oCSAPIRequest = true, }) async { + final rawResponse = setStatusRaw( + statusType: statusType, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Update the status type of the current user. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [statusType] The new status type + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: The status was updated successfully + /// * 400: The status type is invalid + /// + /// See: + /// * [setStatus] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse setStatusRaw({ + required final String statusType, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/user_status/api/v1/user_status/status'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['statusType'] = statusType; headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'put', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'put', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(UserStatusUserStatusSetStatusResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(UserStatusUserStatusSetStatusResponseApplicationJson), - )! as UserStatusUserStatusSetStatusResponseApplicationJson; - } - throw await UserStatusApiException.fromResponse(response); // coverage:ignore-line } - /// Set the message to a predefined message for the current user - Future setPredefinedMessage({ + /// Set the message to a predefined message 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. + /// + /// Parameters: + /// * [messageId] ID of the predefined message + /// * [clearAt] When the message should be cleared + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: The message was updated successfully + /// * 400: The clearAt or message-id is invalid + /// + /// See: + /// * [setPredefinedMessageRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> setPredefinedMessage({ required final String messageId, final int? clearAt, final bool oCSAPIRequest = true, }) async { + final rawResponse = setPredefinedMessageRaw( + messageId: messageId, + clearAt: clearAt, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Set the message to a predefined message for the current user. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [messageId] ID of the predefined message + /// * [clearAt] When the message should be cleared + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: The message was updated successfully + /// * 400: The clearAt or message-id is invalid + /// + /// See: + /// * [setPredefinedMessage] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse setPredefinedMessageRaw({ + required final String messageId, + final int? clearAt, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/user_status/api/v1/user_status/message/predefined'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['messageId'] = messageId; if (clearAt != null) { queryParameters['clearAt'] = clearAt.toString(); } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'put', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'put', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(UserStatusUserStatusSetPredefinedMessageResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(UserStatusUserStatusSetPredefinedMessageResponseApplicationJson), - )! as UserStatusUserStatusSetPredefinedMessageResponseApplicationJson; - } - throw await UserStatusApiException.fromResponse(response); // coverage:ignore-line } - /// Set the message to a custom message for the current user - Future setCustomMessage({ + /// Set the message to a custom message 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. + /// + /// Parameters: + /// * [statusIcon] Icon of the status + /// * [message] Message of the status + /// * [clearAt] When the message should be cleared + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: The message was updated successfully + /// * 400: The clearAt or icon is invalid or the message is too long + /// + /// See: + /// * [setCustomMessageRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> setCustomMessage({ final String? statusIcon, final String? message, final int? clearAt, final bool oCSAPIRequest = true, }) async { + final rawResponse = setCustomMessageRaw( + statusIcon: statusIcon, + message: message, + clearAt: clearAt, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Set the message to a custom message for the current user. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [statusIcon] Icon of the status + /// * [message] Message of the status + /// * [clearAt] When the message should be cleared + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: The message was updated successfully + /// * 400: The clearAt or icon is invalid or the message is too long + /// + /// See: + /// * [setCustomMessage] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse setCustomMessageRaw({ + final String? statusIcon, + final String? message, + final int? clearAt, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/user_status/api/v1/user_status/message/custom'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end if (statusIcon != null) { queryParameters['statusIcon'] = statusIcon; } @@ -427,99 +799,189 @@ class UserStatusUserStatusClient { queryParameters['clearAt'] = clearAt.toString(); } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'put', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'put', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(UserStatusUserStatusSetCustomMessageResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(UserStatusUserStatusSetCustomMessageResponseApplicationJson), - )! as UserStatusUserStatusSetCustomMessageResponseApplicationJson; - } - throw await UserStatusApiException.fromResponse(response); // coverage:ignore-line } - /// Clear the message of the current user - Future clearMessage({ + /// Clear the message of 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. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Message cleared successfully + /// + /// See: + /// * [clearMessageRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> clearMessage({ final bool oCSAPIRequest = true, }) async { + final rawResponse = clearMessageRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Clear the message of the current user. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Message cleared successfully + /// + /// See: + /// * [clearMessage] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse clearMessageRaw({ + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/user_status/api/v1/user_status/message'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'delete', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(UserStatusUserStatusClearMessageResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(UserStatusUserStatusClearMessageResponseApplicationJson), - )! as UserStatusUserStatusClearMessageResponseApplicationJson; - } - throw await UserStatusApiException.fromResponse(response); // coverage:ignore-line } - /// Revert the status to the previous status - Future revertStatus({ + /// Revert the status to the previous status. + /// + /// 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: + /// * [messageId] ID of the message to delete + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Status reverted + /// + /// See: + /// * [revertStatusRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> revertStatus({ required final String messageId, final bool oCSAPIRequest = true, }) async { + final rawResponse = revertStatusRaw( + messageId: messageId, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Revert the status to the previous status. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [messageId] ID of the message to delete + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Status reverted + /// + /// See: + /// * [revertStatus] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse revertStatusRaw({ + required final String messageId, + final bool oCSAPIRequest = true, + }) { var path = '/ocs/v2.php/apps/user_status/api/v1/user_status/revert/{messageId}'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end path = path.replaceAll('{messageId}', Uri.encodeQueryComponent(messageId)); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'delete', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'delete', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(UserStatusUserStatusRevertStatusResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(UserStatusUserStatusRevertStatusResponseApplicationJson), - )! as UserStatusUserStatusRevertStatusResponseApplicationJson; - } - throw await UserStatusApiException.fromResponse(response); // coverage:ignore-line } } @@ -766,7 +1228,7 @@ class _$UserStatusClearAt_TimeSerializer implements PrimitiveSerializer x != null).isNotEmpty, @@ -1747,14 +2209,8 @@ final Serializers _serializers = (Serializers().toBuilder() ..add(UserStatusCapabilities_UserStatus.serializer)) .build(); -Serializers get userStatusSerializers => _serializers; - final Serializers _jsonSerializers = (_serializers.toBuilder() ..addPlugin(StandardJsonPlugin()) ..addPlugin(const ContentStringPlugin())) .build(); - -T deserializeUserStatus(final Object data) => _serializers.deserialize(data, specifiedType: FullType(T))! as T; - -Object? serializeUserStatus(final T data) => _serializers.serialize(data, specifiedType: FullType(T)); // coverage:ignore-end diff --git a/packages/nextcloud/lib/src/api/weather_status.openapi.dart b/packages/nextcloud/lib/src/api/weather_status.openapi.dart index a0da9696..f884a2b0 100644 --- a/packages/nextcloud/lib/src/api/weather_status.openapi.dart +++ b/packages/nextcloud/lib/src/api/weather_status.openapi.dart @@ -1,55 +1,23 @@ // ignore_for_file: camel_case_types +// ignore_for_file: discarded_futures // ignore_for_file: public_member_api_docs +// ignore_for_file: unreachable_switch_case import 'dart:typed_data'; import 'package:built_collection/built_collection.dart'; import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.dart'; import 'package:built_value/standard_json_plugin.dart'; +import 'package:collection/collection.dart'; import 'package:dynamite_runtime/content_string.dart'; import 'package:dynamite_runtime/http_client.dart'; +import 'package:meta/meta.dart'; import 'package:universal_io/io.dart'; export 'package:dynamite_runtime/http_client.dart'; part 'weather_status.openapi.g.dart'; -class WeatherStatusResponse extends DynamiteResponse { - WeatherStatusResponse( - super.data, - super.headers, - ); - - @override - String toString() => 'WeatherStatusResponse(data: $data, headers: $headers)'; -} - -class WeatherStatusApiException extends DynamiteApiException { - WeatherStatusApiException( - super.statusCode, - super.headers, - super.body, - ); - - static Future fromResponse(final HttpClientResponse response) async { - String body; - try { - body = await response.body; - } on FormatException { - body = 'binary'; - } - - return WeatherStatusApiException( - response.statusCode, - response.responseHeaders, - body, - ); - } - - @override - String toString() => 'WeatherStatusApiException(statusCode: $statusCode, headers: $headers, body: $body)'; -} - class WeatherStatusClient extends DynamiteClient { WeatherStatusClient( super.baseURL, { @@ -77,151 +45,338 @@ class WeatherStatusWeatherStatusClient { final WeatherStatusClient _rootClient; - /// Change the weather status mode. There are currently 2 modes: - ask the browser - use the user defined address - Future setMode({ + /// Change the weather status mode. There are currently 2 modes: - ask the browser - use the user defined address. + /// + /// 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: + /// * [mode] New mode + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Weather status mode updated + /// + /// See: + /// * [setModeRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> setMode({ required final int mode, final bool oCSAPIRequest = true, }) async { + final rawResponse = setModeRaw( + mode: mode, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Change the weather status mode. There are currently 2 modes: - ask the browser - use the user defined address. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [mode] New mode + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Weather status mode updated + /// + /// See: + /// * [setMode] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse setModeRaw({ + required final int mode, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/weather_status/api/v1/mode'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['mode'] = mode.toString(); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'put', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'put', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(WeatherStatusWeatherStatusSetModeResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(WeatherStatusWeatherStatusSetModeResponseApplicationJson), - )! as WeatherStatusWeatherStatusSetModeResponseApplicationJson; - } - throw await WeatherStatusApiException.fromResponse(response); // coverage:ignore-line } - /// Try to use the address set in user personal settings as weather location - Future usePersonalAddress({ + /// Try to use the address set in user personal settings as weather location. + /// + /// 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: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Address updated + /// + /// See: + /// * [usePersonalAddressRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> + usePersonalAddress({final bool oCSAPIRequest = true}) async { + final rawResponse = usePersonalAddressRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Try to use the address set in user personal settings as weather location. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Address updated + /// + /// See: + /// * [usePersonalAddress] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse usePersonalAddressRaw({ final bool oCSAPIRequest = true, - }) async { + }) { const path = '/ocs/v2.php/apps/weather_status/api/v1/use-personal'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'put', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'put', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(WeatherStatusWeatherStatusUsePersonalAddressResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(WeatherStatusWeatherStatusUsePersonalAddressResponseApplicationJson), - )! as WeatherStatusWeatherStatusUsePersonalAddressResponseApplicationJson; - } - throw await WeatherStatusApiException.fromResponse(response); // coverage:ignore-line } - /// Get stored user location - Future getLocation({ + /// Get stored user location. + /// + /// 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: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Location returned + /// + /// See: + /// * [getLocationRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getLocation({ final bool oCSAPIRequest = true, }) async { + final rawResponse = getLocationRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get stored user location. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Location returned + /// + /// See: + /// * [getLocation] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getLocationRaw({ + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/weather_status/api/v1/location'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(WeatherStatusWeatherStatusGetLocationResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(WeatherStatusWeatherStatusGetLocationResponseApplicationJson), - )! as WeatherStatusWeatherStatusGetLocationResponseApplicationJson; - } - throw await WeatherStatusApiException.fromResponse(response); // coverage:ignore-line } - /// Set address and resolve it to get coordinates or directly set coordinates and get address with reverse geocoding - Future setLocation({ + /// Set address and resolve it to get coordinates or directly set coordinates and get address with reverse geocoding. + /// + /// 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: + /// * [address] Any approximative or exact address + /// * [lat] Latitude in decimal degree format + /// * [lon] Longitude in decimal degree format + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Location updated + /// + /// See: + /// * [setLocationRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> setLocation({ final String? address, final num? lat, final num? lon, final bool oCSAPIRequest = true, }) async { + final rawResponse = setLocationRaw( + address: address, + lat: lat, + lon: lon, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Set address and resolve it to get coordinates or directly set coordinates and get address with reverse geocoding. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [address] Any approximative or exact address + /// * [lat] Latitude in decimal degree format + /// * [lon] Longitude in decimal degree format + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Location updated + /// + /// See: + /// * [setLocation] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse setLocationRaw({ + final String? address, + final num? lat, + final num? lon, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/weather_status/api/v1/location'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end if (address != null) { queryParameters['address'] = address; } @@ -232,138 +387,273 @@ class WeatherStatusWeatherStatusClient { queryParameters['lon'] = lon.toString(); } headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'put', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'put', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(WeatherStatusWeatherStatusSetLocationResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(WeatherStatusWeatherStatusSetLocationResponseApplicationJson), - )! as WeatherStatusWeatherStatusSetLocationResponseApplicationJson; - } - throw await WeatherStatusApiException.fromResponse(response); // coverage:ignore-line } - /// Get forecast for current location - Future getForecast({ + /// Get forecast for current location. + /// + /// 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: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Forecast returned + /// * 404: Forecast not found + /// + /// See: + /// * [getForecastRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getForecast({ final bool oCSAPIRequest = true, }) async { + final rawResponse = getForecastRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get forecast for current location. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Forecast returned + /// * 404: Forecast not found + /// + /// See: + /// * [getForecast] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getForecastRaw({ + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/weather_status/api/v1/forecast'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(WeatherStatusWeatherStatusGetForecastResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(WeatherStatusWeatherStatusGetForecastResponseApplicationJson), - )! as WeatherStatusWeatherStatusGetForecastResponseApplicationJson; - } - throw await WeatherStatusApiException.fromResponse(response); // coverage:ignore-line } - /// Get favorites list - Future getFavorites({ + /// Get favorites list. + /// + /// 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: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Favorites returned + /// + /// See: + /// * [getFavoritesRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> getFavorites({ final bool oCSAPIRequest = true, }) async { + final rawResponse = getFavoritesRaw( + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Get favorites list. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Favorites returned + /// + /// See: + /// * [getFavorites] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse getFavoritesRaw({ + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/weather_status/api/v1/favorites'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'get', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'get', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(WeatherStatusWeatherStatusGetFavoritesResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(WeatherStatusWeatherStatusGetFavoritesResponseApplicationJson), - )! as WeatherStatusWeatherStatusGetFavoritesResponseApplicationJson; - } - throw await WeatherStatusApiException.fromResponse(response); // coverage:ignore-line } - /// Set favorites list - Future setFavorites({ + /// Set favorites list. + /// + /// 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: + /// * [favorites] Favorite addresses + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Favorites updated + /// + /// See: + /// * [setFavoritesRaw] for an experimental operation that returns a [DynamiteRawResponse] that can be serialized. + Future> setFavorites({ required final List favorites, final bool oCSAPIRequest = true, }) async { + final rawResponse = setFavoritesRaw( + favorites: favorites, + oCSAPIRequest: oCSAPIRequest, + ); + + return rawResponse.future; + } + + /// Set favorites list. + /// + /// This method and the response it returns is experimental. The API might change without a major version bump. + /// + /// Returns a [Future] containing a [DynamiteRawResponse] with the raw [HttpClientResponse] and serialization helpers. + /// Throws a [DynamiteApiException] if the API call does not return an expected status code. + /// + /// Parameters: + /// * [favorites] Favorite addresses + /// * [oCSAPIRequest] Required to be true for the API request to pass + /// + /// Status codes: + /// * 200: Favorites updated + /// + /// See: + /// * [setFavorites] for an operation that returns a [DynamiteResponse] with a stable API. + @experimental + DynamiteRawResponse setFavoritesRaw({ + required final List favorites, + final bool oCSAPIRequest = true, + }) { const path = '/ocs/v2.php/apps/weather_status/api/v1/favorites'; final queryParameters = {}; final headers = { 'Accept': 'application/json', }; Uint8List? body; - // coverage:ignore-start - if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'bearer').isNotEmpty) { - headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'bearer').headers, - ); - } else if (_rootClient.authentications.where((final a) => a.type == 'http' && a.scheme == 'basic').isNotEmpty) { + +// coverage:ignore-start + final authentication = _rootClient.authentications.firstWhereOrNull( + (final auth) => switch (auth) { + DynamiteHttpBearerAuthentication() || DynamiteHttpBasicAuthentication() => true, + _ => false, + }, + ); + + if (authentication != null) { headers.addAll( - _rootClient.authentications.singleWhere((final a) => a.type == 'http' && a.scheme == 'basic').headers, + authentication.headers, ); } else { throw Exception('Missing authentication for bearer_auth or basic_auth'); } - // coverage:ignore-end + +// coverage:ignore-end queryParameters['favorites[]'] = favorites.map((final e) => e); headers['OCS-APIRequest'] = oCSAPIRequest.toString(); - final response = await _rootClient.doRequest( - 'put', - Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null), - headers, - body, + final uri = Uri(path: path, queryParameters: queryParameters.isNotEmpty ? queryParameters : null); + return DynamiteRawResponse( + response: _rootClient.doRequest( + 'put', + uri, + headers, + body, + const {200}, + ), + bodyType: const FullType(WeatherStatusWeatherStatusSetFavoritesResponseApplicationJson), + headersType: null, + serializers: _jsonSerializers, ); - if (response.statusCode == 200) { - return _jsonSerializers.deserialize( - await response.jsonBody, - specifiedType: const FullType(WeatherStatusWeatherStatusSetFavoritesResponseApplicationJson), - )! as WeatherStatusWeatherStatusSetFavoritesResponseApplicationJson; - } - throw await WeatherStatusApiException.fromResponse(response); // coverage:ignore-line } } @@ -1813,14 +2103,8 @@ final Serializers _serializers = (Serializers().toBuilder() ..add(WeatherStatusCapabilities_WeatherStatus.serializer)) .build(); -Serializers get weatherStatusSerializers => _serializers; - final Serializers _jsonSerializers = (_serializers.toBuilder() ..addPlugin(StandardJsonPlugin()) ..addPlugin(const ContentStringPlugin())) .build(); - -T deserializeWeatherStatus(final Object data) => _serializers.deserialize(data, specifiedType: FullType(T))! as T; - -Object? serializeWeatherStatus(final T data) => _serializers.serialize(data, specifiedType: FullType(T)); // coverage:ignore-end diff --git a/packages/nextcloud/lib/src/client.dart b/packages/nextcloud/lib/src/client.dart index be53fd5a..c42c66ca 100644 --- a/packages/nextcloud/lib/src/client.dart +++ b/packages/nextcloud/lib/src/client.dart @@ -1,6 +1,3 @@ -import 'package:built_value/serializer.dart'; -import 'package:built_value/standard_json_plugin.dart'; -import 'package:dynamite_runtime/content_string.dart'; import 'package:nextcloud/nextcloud.dart'; // ignore: public_member_api_docs @@ -123,44 +120,3 @@ class NextcloudClient extends DynamiteClient { /// Client for the weather status APIs WeatherStatusClient get weatherStatus => _weatherStatus ??= WeatherStatusClient.fromClient(this); } - -// coverage:ignore-start - -// ignore: public_member_api_docs -final serializers = Serializers.merge([ - commentsSerializers, - coreSerializers, - dashboardSerializers, - davSerializers, - filesSerializers, - filesExternalSerializers, - filesRemindersSerializers, - filesSharingSerializers, - filesTrashbinSerializers, - filesVersionsSerializers, - newsSerializers, - notesSerializers, - notificationsSerializers, - provisioningApiSerializers, - settingsSerializers, - sharebymailSerializers, - themingSerializers, - updatenotificationSerializers, - uppushSerializers, - userStatusSerializers, - weatherStatusSerializers, -]); - -// ignore: public_member_api_docs -final Serializers jsonSerializers = (serializers.toBuilder() - ..addPlugin(StandardJsonPlugin()) - ..addPlugin(const ContentStringPlugin())) - .build(); - -// ignore: public_member_api_docs -T deserializeNextcloud(final Object data) => serializers.deserialize(data, specifiedType: FullType(T))! as T; - -// ignore: public_member_api_docs -Object? serializeNextcloud(final T data) => serializers.serialize(data, specifiedType: FullType(T)); - -// coverage:ignore-end diff --git a/packages/nextcloud/lib/src/version_supported.dart b/packages/nextcloud/lib/src/version_supported.dart index 4cf736fb..61008f20 100644 --- a/packages/nextcloud/lib/src/version_supported.dart +++ b/packages/nextcloud/lib/src/version_supported.dart @@ -35,9 +35,9 @@ extension NewsVersionSupported on NewsClient { /// /// Also returns the supported API version number Future<(bool, String)> isSupported() async { - final versions = await getSupportedApiVersions(); + final response = await getSupportedApiVersions(); return ( - versions.apiLevels!.contains(newsSupportedVersion), + response.body.apiLevels!.contains(newsSupportedVersion), newsSupportedVersion, ); } diff --git a/packages/nextcloud/lib/src/webdav/client.dart b/packages/nextcloud/lib/src/webdav/client.dart index 10114b8b..a7dd64d3 100644 --- a/packages/nextcloud/lib/src/webdav/client.dart +++ b/packages/nextcloud/lib/src/webdav/client.dart @@ -53,7 +53,7 @@ class WebDavClient { throw DynamiteApiException( response.statusCode, response.responseHeaders, - await response.body, + await response.string, ); } @@ -82,7 +82,7 @@ class WebDavClient { } Future _parseResponse(final HttpClientResponse response) async => - WebDavMultistatus.fromXmlElement(xml.XmlDocument.parse(await response.body).rootElement); + WebDavMultistatus.fromXmlElement(xml.XmlDocument.parse(await response.string).rootElement); Map _getUploadHeaders({ required final DateTime? lastModified, @@ -205,7 +205,7 @@ class WebDavClient { ); /// Gets the content of the file at [path]. - Future get(final Uri path) async => (await getStream(path)).bodyBytes; + Future get(final Uri path) async => (await getStream(path)).bytes; /// Gets the content of the file at [path]. Future getStream(final Uri path) async => _send( diff --git a/packages/nextcloud/pubspec.yaml b/packages/nextcloud/pubspec.yaml index 9c7dccf2..624ac68b 100644 --- a/packages/nextcloud/pubspec.yaml +++ b/packages/nextcloud/pubspec.yaml @@ -8,6 +8,7 @@ environment: dependencies: built_collection: ^5.1.1 built_value: ^8.6.3 + collection: ^1.17.1 crypto: ^3.0.3 crypton: ^2.2.0 dynamite_runtime: diff --git a/packages/nextcloud/test/core_test.dart b/packages/nextcloud/test/core_test.dart index 3e99b608..5f4a6326 100644 --- a/packages/nextcloud/test/core_test.dart +++ b/packages/nextcloud/test/core_test.dart @@ -19,55 +19,72 @@ void main() { tearDown(() => container.destroy()); test('Is supported from capabilities', () async { - final (supported, _) = client.core.isSupported((await client.core.ocs.getCapabilities()).ocs.data); + final response = await client.core.ocs.getCapabilities(); + + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + final (supported, _) = client.core.isSupported(response.body.ocs.data); expect(supported, isTrue); }); test('Is supported from status', () async { - final status = await client.core.getStatus(); - expect(status.isSupported, isTrue); + final response = await client.core.getStatus(); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.isSupported, isTrue); }); test('Get status', () async { - final status = await client.core.getStatus(); - expect(status.installed, true); - expect(status.maintenance, false); - expect(status.needsDbUpgrade, false); - expect(status.version, startsWith('$coreSupportedVersion.')); - expect(status.versionstring, startsWith('$coreSupportedVersion.')); - expect(status.edition, ''); - expect(status.productname, 'Nextcloud'); - expect(status.extendedSupport, false); + final response = await client.core.getStatus(); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.installed, isTrue); + expect(response.body.maintenance, isFalse); + expect(response.body.needsDbUpgrade, isFalse); + expect(response.body.version, startsWith('$coreSupportedVersion.')); + expect(response.body.versionstring, startsWith('$coreSupportedVersion.')); + expect(response.body.edition, ''); + expect(response.body.productname, 'Nextcloud'); + expect(response.body.extendedSupport, isFalse); }); test('Get capabilities', () async { - final capabilities = await client.core.ocs.getCapabilities(); - expect(capabilities.ocs.data.version.major, coreSupportedVersion); - expect(capabilities.ocs.data.version.string, startsWith('$coreSupportedVersion.')); - expect(capabilities.ocs.data.capabilities.commentsCapabilities, isNotNull); - expect(capabilities.ocs.data.capabilities.davCapabilities, isNotNull); - expect(capabilities.ocs.data.capabilities.filesCapabilities, isNotNull); - expect(capabilities.ocs.data.capabilities.filesSharingCapabilities, isNotNull); - expect(capabilities.ocs.data.capabilities.filesTrashbinCapabilities, isNotNull); - expect(capabilities.ocs.data.capabilities.filesVersionsCapabilities, isNotNull); - expect(capabilities.ocs.data.capabilities.notesCapabilities, isNotNull); - expect(capabilities.ocs.data.capabilities.notificationsCapabilities, isNotNull); - expect(capabilities.ocs.data.capabilities.provisioningApiCapabilities, isNotNull); - expect(capabilities.ocs.data.capabilities.sharebymailCapabilities, isNotNull); - expect(capabilities.ocs.data.capabilities.themingPublicCapabilities, isNotNull); - expect(capabilities.ocs.data.capabilities.userStatusCapabilities, isNotNull); - expect(capabilities.ocs.data.capabilities.weatherStatusCapabilities, isNotNull); + final response = await client.core.ocs.getCapabilities(); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.ocs.data.version.major, coreSupportedVersion); + expect(response.body.ocs.data.version.string, startsWith('$coreSupportedVersion.')); + expect(response.body.ocs.data.capabilities.commentsCapabilities, isNotNull); + expect(response.body.ocs.data.capabilities.davCapabilities, isNotNull); + expect(response.body.ocs.data.capabilities.filesCapabilities, isNotNull); + expect(response.body.ocs.data.capabilities.filesSharingCapabilities, isNotNull); + expect(response.body.ocs.data.capabilities.filesTrashbinCapabilities, isNotNull); + expect(response.body.ocs.data.capabilities.filesVersionsCapabilities, isNotNull); + expect(response.body.ocs.data.capabilities.notesCapabilities, isNotNull); + expect(response.body.ocs.data.capabilities.notificationsCapabilities, isNotNull); + expect(response.body.ocs.data.capabilities.provisioningApiCapabilities, isNotNull); + expect(response.body.ocs.data.capabilities.sharebymailCapabilities, isNotNull); + expect(response.body.ocs.data.capabilities.themingPublicCapabilities, isNotNull); + expect(response.body.ocs.data.capabilities.userStatusCapabilities, isNotNull); + expect(response.body.ocs.data.capabilities.weatherStatusCapabilities, isNotNull); }); test('Get navigation apps', () async { - final navigationApps = await client.core.navigation.getAppsNavigation(); - expect(navigationApps.ocs.data, hasLength(6)); - expect(navigationApps.ocs.data[0].id, 'dashboard'); - expect(navigationApps.ocs.data[1].id, 'files'); - expect(navigationApps.ocs.data[2].id, 'photos'); - expect(navigationApps.ocs.data[3].id, 'activity'); - expect(navigationApps.ocs.data[4].id, 'notes'); - expect(navigationApps.ocs.data[5].id, 'news'); + final response = await client.core.navigation.getAppsNavigation(); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + expect(response.body.ocs.data, hasLength(6)); + + 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, 'notes'); + expect(response.body.ocs.data[5].id, 'news'); }); test( @@ -82,48 +99,53 @@ void main() { ShareType.group.index, ], ); - expect(response.ocs.data, hasLength(3)); - - expect(response.ocs.data[0].id, 'admin'); - expect(response.ocs.data[0].label, 'admin'); - expect(response.ocs.data[0].icon, 'icon-user'); - expect(response.ocs.data[0].source, 'users'); - expect(response.ocs.data[0].status, isEmpty); - expect(response.ocs.data[0].subline, ''); - expect(response.ocs.data[0].shareWithDisplayNameUnique, 'admin@example.com'); - - expect(response.ocs.data[1].id, 'user2'); - expect(response.ocs.data[1].label, 'User Two'); - expect(response.ocs.data[1].icon, 'icon-user'); - expect(response.ocs.data[1].source, 'users'); - expect(response.ocs.data[1].status, isEmpty); - expect(response.ocs.data[1].subline, ''); - expect(response.ocs.data[1].shareWithDisplayNameUnique, 'user2'); - - expect(response.ocs.data[2].id, 'admin'); - expect(response.ocs.data[2].label, 'admin'); - expect(response.ocs.data[2].icon, ''); - expect(response.ocs.data[2].source, 'groups'); - expect(response.ocs.data[2].status, isEmpty); - expect(response.ocs.data[2].subline, ''); - expect(response.ocs.data[2].shareWithDisplayNameUnique, ''); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + expect(response.body.ocs.data, hasLength(3)); + + expect(response.body.ocs.data[0].id, 'admin'); + expect(response.body.ocs.data[0].label, 'admin'); + expect(response.body.ocs.data[0].icon, 'icon-user'); + expect(response.body.ocs.data[0].source, 'users'); + expect(response.body.ocs.data[0].status, isEmpty); + expect(response.body.ocs.data[0].subline, ''); + expect(response.body.ocs.data[0].shareWithDisplayNameUnique, 'admin@example.com'); + + expect(response.body.ocs.data[1].id, 'user2'); + expect(response.body.ocs.data[1].label, 'User Two'); + expect(response.body.ocs.data[1].icon, 'icon-user'); + expect(response.body.ocs.data[1].source, 'users'); + expect(response.body.ocs.data[1].status, isEmpty); + expect(response.body.ocs.data[1].subline, ''); + expect(response.body.ocs.data[1].shareWithDisplayNameUnique, 'user2'); + + expect(response.body.ocs.data[2].id, 'admin'); + expect(response.body.ocs.data[2].label, 'admin'); + expect(response.body.ocs.data[2].icon, ''); + expect(response.body.ocs.data[2].source, 'groups'); + expect(response.body.ocs.data[2].status, isEmpty); + expect(response.body.ocs.data[2].subline, ''); + expect(response.body.ocs.data[2].shareWithDisplayNameUnique, ''); }, skip: true, // TODO: This test only works on 28+ due to a bug fix with the status ); test('Get preview', () async { final response = await client.core.preview.getPreview(file: 'Nextcloud.png'); - expect(response, isNotEmpty); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body, isNotEmpty); }); test('Get avatar', () async { final response = await client.core.avatar.getAvatar(userId: 'admin', size: 32); - expect(response.data, isNotEmpty); + expect(response.body, isNotEmpty); }); test('Get dark avatar', () async { final response = await client.core.avatar.getAvatarDark(userId: 'admin', size: 32); - expect(response.data, isNotEmpty); + expect(response.body, isNotEmpty); }); test('Delete app password', () async { @@ -136,7 +158,10 @@ void main() { test('Unified search providers', () async { final response = await client.core.unifiedSearch.getProviders(); - expect(response.ocs.data, hasLength(13)); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.ocs.data, hasLength(13)); }); test('Unified search', () async { @@ -144,16 +169,20 @@ void main() { providerId: 'settings', term: 'Personal info', ); - expect(response.ocs.data.name, 'Settings'); - expect(response.ocs.data.isPaginated, isFalse); - expect(response.ocs.data.entries, hasLength(1)); - expect(response.ocs.data.entries.single.thumbnailUrl, isEmpty); - expect(response.ocs.data.entries.single.title, 'Personal info'); - expect(response.ocs.data.entries.single.subline, isEmpty); - expect(response.ocs.data.entries.single.resourceUrl, isNotEmpty); - expect(response.ocs.data.entries.single.icon, 'icon-settings-dark'); - expect(response.ocs.data.entries.single.rounded, isFalse); - expect(response.ocs.data.entries.single.attributes, isEmpty); + + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.ocs.data.name, 'Settings'); + expect(response.body.ocs.data.isPaginated, isFalse); + expect(response.body.ocs.data.entries, hasLength(1)); + expect(response.body.ocs.data.entries.single.thumbnailUrl, isEmpty); + expect(response.body.ocs.data.entries.single.title, 'Personal info'); + expect(response.body.ocs.data.entries.single.subline, isEmpty); + expect(response.body.ocs.data.entries.single.resourceUrl, isNotEmpty); + expect(response.body.ocs.data.entries.single.icon, 'icon-settings-dark'); + expect(response.body.ocs.data.entries.single.rounded, isFalse); + expect(response.body.ocs.data.entries.single.attributes, isEmpty); }); }, retry: retryCount, diff --git a/packages/nextcloud/test/dashboard_test.dart b/packages/nextcloud/test/dashboard_test.dart index ef7b6801..f529f82c 100644 --- a/packages/nextcloud/test/dashboard_test.dart +++ b/packages/nextcloud/test/dashboard_test.dart @@ -19,21 +19,21 @@ void main() { test('Get widgets', () async { final response = await client.dashboard.dashboardApi.getWidgets(); - expect(response.ocs.data.keys, equals(['activity', 'notes', 'recommendations', 'user_status'])); + expect(response.body.ocs.data.keys, equals(['activity', 'notes', 'recommendations', 'user_status'])); }); group('Get widget items', () { test('v1', () async { final response = await client.dashboard.dashboardApi.getWidgetItems(); - expect(response.ocs.data.keys, equals(['recommendations'])); - final items = response.ocs.data['recommendations']!; + expect(response.body.ocs.data.keys, equals(['recommendations'])); + final items = response.body.ocs.data['recommendations']!; expect(items, hasLength(7)); }); test('v2', () async { final response = await client.dashboard.dashboardApi.getWidgetItemsV2(); - expect(response.ocs.data.keys, equals(['recommendations'])); - final items = response.ocs.data['recommendations']!.items; + expect(response.body.ocs.data.keys, equals(['recommendations'])); + final items = response.body.ocs.data['recommendations']!.items; expect(items, hasLength(7)); }); }); diff --git a/packages/nextcloud/test/helper.dart b/packages/nextcloud/test/helper.dart index db2e0dd8..00f4cb75 100644 --- a/packages/nextcloud/test/helper.dart +++ b/packages/nextcloud/test/helper.dart @@ -141,7 +141,7 @@ Future getTestClient( try { await client.core.getStatus(); break; - } on CoreApiException catch (error) { + } on DynamiteApiException catch (error) { i++; await Future.delayed(const Duration(milliseconds: 100)); if (i >= 30) { diff --git a/packages/nextcloud/test/news_test.dart b/packages/nextcloud/test/news_test.dart index 36c944e6..8e54491f 100644 --- a/packages/nextcloud/test/news_test.dart +++ b/packages/nextcloud/test/news_test.dart @@ -26,12 +26,13 @@ void main() { }); tearDown(() => container.destroy()); - Future addWikipediaFeed([final int? folderID]) async => client.news.addFeed( + Future> addWikipediaFeed([final int? folderID]) async => + client.news.addFeed( url: 'http://host.docker.internal:${rssServer.port}/wikipedia.xml', folderId: folderID, ); - Future addNasaFeed() async => client.news.addFeed( + Future> addNasaFeed() async => client.news.addFeed( url: 'http://host.docker.internal:${rssServer.port}/nasa.xml', ); @@ -42,26 +43,38 @@ void main() { test('Add feed', () async { var response = await client.news.listFeeds(); - expect(response.starredCount, 0); - expect(response.newestItemId, null); - expect(response.feeds, hasLength(0)); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.starredCount, 0); + expect(response.body.newestItemId, null); + expect(response.body.feeds, hasLength(0)); response = await addWikipediaFeed(); - expect(response.starredCount, null); - expect(response.newestItemId, isNotNull); - expect(response.feeds, hasLength(1)); - expect(response.feeds[0].url, 'http://host.docker.internal:${rssServer.port}/wikipedia.xml'); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.starredCount, null); + expect(response.body.newestItemId, isNotNull); + expect(response.body.feeds, hasLength(1)); + expect(response.body.feeds[0].url, 'http://host.docker.internal:${rssServer.port}/wikipedia.xml'); response = await client.news.listFeeds(); - expect(response.starredCount, 0); - expect(response.newestItemId, isNotNull); - expect(response.feeds, hasLength(1)); - expect(response.feeds[0].url, 'http://host.docker.internal:${rssServer.port}/wikipedia.xml'); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.starredCount, 0); + expect(response.body.newestItemId, isNotNull); + expect(response.body.feeds, hasLength(1)); + expect(response.body.feeds[0].url, 'http://host.docker.internal:${rssServer.port}/wikipedia.xml'); }); test('Rename feed', () async { var response = await addWikipediaFeed(); - expect(response.feeds[0].title, 'Wikipedia featured articles feed'); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.feeds[0].title, 'Wikipedia featured articles feed'); await client.news.renameFeed( feedId: 1, @@ -69,7 +82,10 @@ void main() { ); response = await client.news.listFeeds(); - expect(response.feeds[0].title, 'test1'); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.feeds[0].title, 'test1'); }); test('Move feed to folder', () async { @@ -81,40 +97,57 @@ void main() { ); final response = await client.news.listFolders(); - expect(response.folders, hasLength(1)); - expect(response.folders[0].id, 1); - expect(response.folders[0].name, 'test1'); - expect(response.folders[0].opened, true); - expect(response.folders[0].feeds, hasLength(0)); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.folders, hasLength(1)); + expect(response.body.folders[0].id, 1); + expect(response.body.folders[0].name, 'test1'); + expect(response.body.folders[0].opened, true); + expect(response.body.folders[0].feeds, hasLength(0)); }); test('Mark feed as read', () async { final feedsResponse = await addWikipediaFeed(); - var articlesResponse = await client.news.listArticles(type: NewsListType.unread.index); - expect(articlesResponse.items.length, greaterThan(0)); + var response = await client.news.listArticles(type: NewsListType.unread.index); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.items.length, greaterThan(0)); await client.news.markFeedAsRead( - feedId: feedsResponse.feeds[0].id, - newestItemId: feedsResponse.newestItemId!, + feedId: feedsResponse.body.feeds[0].id, + newestItemId: feedsResponse.body.newestItemId!, ); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + response = await client.news.listArticles(type: NewsListType.unread.index); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); - articlesResponse = await client.news.listArticles(type: NewsListType.unread.index); - expect(articlesResponse.items, hasLength(0)); + expect(response.body.items, hasLength(0)); }); test('List articles', () async { var response = await client.news.listArticles(); - expect(response.items, hasLength(0)); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.items, hasLength(0)); await addWikipediaFeed(); response = await client.news.listArticles(); - expect(response.items.length, greaterThan(0)); - expect(response.items[0].body, isNotNull); - expect(response.items[0].feedId, 1); - expect(response.items[0].unread, true); - expect(response.items[0].starred, false); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.items.length, greaterThan(0)); + expect(response.body.items[0].body, isNotNull); + expect(response.body.items[0].feedId, 1); + expect(response.body.items[0].unread, true); + expect(response.body.items[0].starred, false); }); test('List updated articles', () async { @@ -126,146 +159,212 @@ void main() { await addWikipediaFeed(); var response = await client.news.listArticles(); - final wikipediaArticles = response.items.length; + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + final wikipediaArticles = response.body.items.length; expect(wikipediaArticles, greaterThan(0)); await addNasaFeed(); response = await client.news.listArticles(); - final nasaArticles = response.items.length - wikipediaArticles; + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + final nasaArticles = response.body.items.length - wikipediaArticles; expect(nasaArticles, greaterThan(0)); response = await client.news.listUpdatedArticles( - lastModified: response.items[response.items.length - 1 - nasaArticles].lastModified, + lastModified: response.body.items[response.body.items.length - 1 - nasaArticles].lastModified, ); - expect(response.items, hasLength(nasaArticles)); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.items, hasLength(nasaArticles)); }); test('Mark article as read', () async { await addWikipediaFeed(); var response = await client.news.listArticles(type: NewsListType.unread.index); - final unreadArticles = response.items.length; + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + final unreadArticles = response.body.items.length; expect(unreadArticles, greaterThan(0)); await client.news.markArticleAsRead( - itemId: response.items[0].id, + itemId: response.body.items[0].id, ); response = await client.news.listArticles(type: NewsListType.unread.index); - expect(response.items, hasLength(unreadArticles - 1)); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.items, hasLength(unreadArticles - 1)); }); test('Mark article as unread', () async { await addWikipediaFeed(); var response = await client.news.listArticles(type: NewsListType.unread.index); - final readArticle = response.items[0]; + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + final readArticle = response.body.items[0]; await client.news.markArticleAsRead(itemId: readArticle.id); response = await client.news.listArticles(type: NewsListType.unread.index); - final unreadArticles = response.items.length; + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + final unreadArticles = response.body.items.length; expect(unreadArticles, greaterThan(0)); await client.news.markArticleAsUnread(itemId: readArticle.id); response = await client.news.listArticles(type: NewsListType.unread.index); - expect(response.items, hasLength(unreadArticles + 1)); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.items, hasLength(unreadArticles + 1)); }); test('Star article', () async { await addWikipediaFeed(); var response = await client.news.listArticles(type: NewsListType.starred.index); - final starredArticles = response.items.length; + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + final starredArticles = response.body.items.length; expect(starredArticles, 0); response = await client.news.listArticles(); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + await client.news.starArticle( - itemId: response.items[0].id, + itemId: response.body.items[0].id, ); response = await client.news.listArticles(type: NewsListType.starred.index); - expect(response.items, hasLength(1)); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.items, hasLength(1)); }); test('Unstar article', () async { await addWikipediaFeed(); var response = await client.news.listArticles(); - final item = response.items[0]; + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + final item = response.body.items[0]; await client.news.starArticle( itemId: item.id, ); response = await client.news.listArticles(type: NewsListType.starred.index); - expect(response.items, hasLength(1)); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.items, hasLength(1)); await client.news.unstarArticle( itemId: item.id, ); response = await client.news.listArticles(type: NewsListType.starred.index); - expect(response.items, hasLength(0)); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.items, hasLength(0)); }); test('Create folder', () async { var response = await client.news.listFolders(); - expect(response.folders, hasLength(0)); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.folders, hasLength(0)); response = await client.news.createFolder(name: 'test1'); - expect(response.folders, hasLength(1)); - expect(response.folders[0].id, 1); - expect(response.folders[0].name, 'test1'); - expect(response.folders[0].opened, true); - expect(response.folders[0].feeds, hasLength(0)); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.folders, hasLength(1)); + expect(response.body.folders[0].id, 1); + expect(response.body.folders[0].name, 'test1'); + expect(response.body.folders[0].opened, true); + expect(response.body.folders[0].feeds, hasLength(0)); response = await client.news.listFolders(); - expect(response.folders, hasLength(1)); - expect(response.folders[0].id, 1); - expect(response.folders[0].name, 'test1'); - expect(response.folders[0].opened, true); - expect(response.folders[0].feeds, hasLength(0)); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.folders, hasLength(1)); + expect(response.body.folders[0].id, 1); + expect(response.body.folders[0].name, 'test1'); + expect(response.body.folders[0].opened, true); + expect(response.body.folders[0].feeds, hasLength(0)); }); test('List folders', () async { var response = await client.news.listFolders(); - expect(response.folders, hasLength(0)); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.folders, hasLength(0)); await client.news.createFolder(name: 'test1'); await client.news.createFolder(name: 'test2'); response = response = await client.news.listFolders(); - expect(response.folders, hasLength(2)); - expect(response.folders[0].id, 1); - expect(response.folders[0].name, 'test1'); - expect(response.folders[0].opened, true); - expect(response.folders[0].feeds, hasLength(0)); - expect(response.folders[1].id, 2); - expect(response.folders[1].name, 'test2'); - expect(response.folders[1].opened, true); - expect(response.folders[1].feeds, hasLength(0)); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.folders, hasLength(2)); + expect(response.body.folders[0].id, 1); + expect(response.body.folders[0].name, 'test1'); + expect(response.body.folders[0].opened, true); + expect(response.body.folders[0].feeds, hasLength(0)); + expect(response.body.folders[1].id, 2); + expect(response.body.folders[1].name, 'test2'); + expect(response.body.folders[1].opened, true); + expect(response.body.folders[1].feeds, hasLength(0)); }); test('Add feed to folder', () async { await client.news.createFolder(name: 'test1'); final response = await addWikipediaFeed(1); - expect(response.starredCount, null); - expect(response.newestItemId, isNotNull); - expect(response.feeds, hasLength(1)); - expect(response.feeds[0].folderId, 1); - expect(response.feeds[0].url, 'http://host.docker.internal:${rssServer.port}/wikipedia.xml'); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.starredCount, null); + expect(response.body.newestItemId, isNotNull); + expect(response.body.feeds, hasLength(1)); + expect(response.body.feeds[0].folderId, 1); + expect(response.body.feeds[0].url, 'http://host.docker.internal:${rssServer.port}/wikipedia.xml'); }); test('Mark folder as read', () async { final foldersResponse = await client.news.createFolder(name: 'test1'); final feedsResponse = await addWikipediaFeed(1); - var articlesResponse = await client.news.listArticles(type: NewsListType.unread.index); - expect(articlesResponse.items.length, greaterThan(0)); + var response = await client.news.listArticles(type: NewsListType.unread.index); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.items.length, greaterThan(0)); await client.news.markFolderAsRead( - folderId: foldersResponse.folders[0].id, - newestItemId: feedsResponse.newestItemId!, + folderId: foldersResponse.body.folders[0].id, + newestItemId: feedsResponse.body.newestItemId!, ); - articlesResponse = await client.news.listArticles(type: NewsListType.unread.index); - expect(articlesResponse.items, hasLength(0)); + response = await client.news.listArticles(type: NewsListType.unread.index); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.items, hasLength(0)); }); }, retry: retryCount, diff --git a/packages/nextcloud/test/notes_test.dart b/packages/nextcloud/test/notes_test.dart index 149298a1..c8f8b429 100644 --- a/packages/nextcloud/test/notes_test.dart +++ b/packages/nextcloud/test/notes_test.dart @@ -19,7 +19,11 @@ void main() { tearDown(() => container.destroy()); test('Is supported', () async { - final (supported, _) = client.notes.isSupported((await client.core.ocs.getCapabilities()).ocs.data); + final response = await client.core.ocs.getCapabilities(); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + final (supported, _) = client.notes.isSupported(response.body.ocs.data); expect(supported, isTrue); }); @@ -30,14 +34,17 @@ void main() { category: 'c', favorite: 1, ); - expect(response.id, isPositive); - expect(response.title, 'a'); - expect(response.content, 'b'); - expect(response.category, 'c'); - expect(response.favorite, true); - expect(response.readonly, false); - expect(response.etag, isNotNull); - expect(response.modified, isNotNull); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.id, isPositive); + expect(response.body.title, 'a'); + expect(response.body.content, 'b'); + expect(response.body.category, 'c'); + expect(response.body.favorite, true); + expect(response.body.readonly, false); + expect(response.body.etag, isNotNull); + expect(response.body.modified, isNotNull); }); test('Create note not favorite', () async { @@ -46,14 +53,17 @@ void main() { content: 'b', category: 'c', ); - expect(response.id, isPositive); - expect(response.title, 'a'); - expect(response.content, 'b'); - expect(response.category, 'c'); - expect(response.favorite, false); - expect(response.readonly, false); - expect(response.etag, isNotNull); - expect(response.modified, isNotNull); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.id, isPositive); + expect(response.body.title, 'a'); + expect(response.body.content, 'b'); + expect(response.body.category, 'c'); + expect(response.body.favorite, false); + expect(response.body.readonly, false); + expect(response.body.etag, isNotNull); + expect(response.body.modified, isNotNull); }); test('Get notes', () async { @@ -61,63 +71,84 @@ void main() { await client.notes.createNote(title: 'b'); final response = await client.notes.getNotes(); - expect(response, hasLength(2)); - expect(response[0].title, 'a'); - expect(response[1].title, 'b'); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body, hasLength(2)); + expect(response.body[0].title, 'a'); + expect(response.body[1].title, 'b'); }); test('Get note', () async { final response = await client.notes.getNote( - id: (await client.notes.createNote(title: 'a')).id, + id: (await client.notes.createNote(title: 'a')).body.id, ); - expect(response.title, 'a'); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.title, 'a'); }); test('Update note', () async { - final id = (await client.notes.createNote(title: 'a')).id; + final id = (await client.notes.createNote(title: 'a')).body.id; await client.notes.updateNote( id: id, title: 'b', ); final response = await client.notes.getNote(id: id); - expect(response.title, 'b'); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.title, 'b'); }); test('Update note fail changed on server', () async { final response = await client.notes.createNote(title: 'a'); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + await client.notes.updateNote( - id: response.id, + id: response.body.id, title: 'b', - ifMatch: '"${response.etag}"', + ifMatch: '"${response.body.etag}"', ); expect( () => client.notes.updateNote( - id: response.id, + id: response.body.id, title: 'c', - ifMatch: '"${response.etag}"', + ifMatch: '"${response.body.etag}"', ), throwsA(predicate((final e) => (e! as DynamiteApiException).statusCode == 412)), ); }); test('Delete note', () async { - final id = (await client.notes.createNote(title: 'a')).id; + final id = (await client.notes.createNote(title: 'a')).body.id; var response = await client.notes.getNotes(); - expect(response, hasLength(1)); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body, hasLength(1)); await client.notes.deleteNote(id: id); response = await client.notes.getNotes(); - expect(response, hasLength(0)); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body, hasLength(0)); }); test('Get settings', () async { final response = await client.notes.getSettings(); - expect(response.notesPath, 'Notes'); - expect(response.fileSuffix, '.md'); - expect(response.noteMode, NotesSettings_NoteMode.rich); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.notesPath, 'Notes'); + expect(response.body.fileSuffix, '.md'); + expect(response.body.noteMode, NotesSettings_NoteMode.rich); }); test('Update settings', () async { @@ -129,14 +160,20 @@ void main() { ..noteMode = NotesSettings_NoteMode.preview, ), ); - expect(response.notesPath, 'Test Notes'); - expect(response.fileSuffix, '.txt'); - expect(response.noteMode, NotesSettings_NoteMode.preview); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.notesPath, 'Test Notes'); + expect(response.body.fileSuffix, '.txt'); + expect(response.body.noteMode, NotesSettings_NoteMode.preview); response = await client.notes.getSettings(); - expect(response.notesPath, 'Test Notes'); - expect(response.fileSuffix, '.txt'); - expect(response.noteMode, NotesSettings_NoteMode.preview); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.notesPath, 'Test Notes'); + expect(response.body.fileSuffix, '.txt'); + expect(response.body.noteMode, NotesSettings_NoteMode.preview); }); }, retry: retryCount, diff --git a/packages/nextcloud/test/notifications_test.dart b/packages/nextcloud/test/notifications_test.dart index 62f245be..4afc936f 100644 --- a/packages/nextcloud/test/notifications_test.dart +++ b/packages/nextcloud/test/notifications_test.dart @@ -37,7 +37,7 @@ void main() { await sendTestNotification(); final startTime = DateTime.now().toUtc(); - final response = (await client.notifications.endpoint.listNotifications()).data; + final response = (await client.notifications.endpoint.listNotifications()).body; expect(response.ocs.data, hasLength(2)); expect(response.ocs.data[0].notificationId, 2); expect(response.ocs.data[0].app, 'admin_notifications'); @@ -61,28 +61,31 @@ void main() { final startTime = DateTime.now().toUtc(); final response = await client.notifications.endpoint.getNotification(id: 2); - expect(response.ocs.data.notificationId, 2); - expect(response.ocs.data.app, 'admin_notifications'); - expect(response.ocs.data.user, 'admin'); - expectDateInReasonableTimeRange(DateTime.parse(response.ocs.data.datetime), startTime); - expect(response.ocs.data.objectType, 'admin_notifications'); - expect(response.ocs.data.objectId, isNotNull); - expect(response.ocs.data.subject, '123'); - expect(response.ocs.data.message, '456'); - expect(response.ocs.data.link, ''); - expect(response.ocs.data.subjectRich, ''); - expect(response.ocs.data.subjectRichParameters, isEmpty); - expect(response.ocs.data.messageRich, ''); - expect(response.ocs.data.messageRichParameters, isEmpty); - expect(response.ocs.data.icon, isNotEmpty); - expect(response.ocs.data.actions, hasLength(0)); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.ocs.data.notificationId, 2); + expect(response.body.ocs.data.app, 'admin_notifications'); + expect(response.body.ocs.data.user, 'admin'); + expectDateInReasonableTimeRange(DateTime.parse(response.body.ocs.data.datetime), startTime); + expect(response.body.ocs.data.objectType, 'admin_notifications'); + expect(response.body.ocs.data.objectId, isNotNull); + expect(response.body.ocs.data.subject, '123'); + expect(response.body.ocs.data.message, '456'); + expect(response.body.ocs.data.link, ''); + expect(response.body.ocs.data.subjectRich, ''); + expect(response.body.ocs.data.subjectRichParameters, isEmpty); + expect(response.body.ocs.data.messageRich, ''); + expect(response.body.ocs.data.messageRichParameters, isEmpty); + expect(response.body.ocs.data.icon, isNotEmpty); + expect(response.body.ocs.data.actions, hasLength(0)); }); test('Delete notification', () async { await sendTestNotification(); await client.notifications.endpoint.deleteNotification(id: 2); - final response = (await client.notifications.endpoint.listNotifications()).data; + final response = (await client.notifications.endpoint.listNotifications()).body; expect(response.ocs.data, hasLength(1)); }); @@ -91,7 +94,7 @@ void main() { await sendTestNotification(); await client.notifications.endpoint.deleteAllNotifications(); - final response = (await client.notifications.endpoint.listNotifications()).data; + final response = (await client.notifications.endpoint.listNotifications()).body; expect(response.ocs.data, hasLength(0)); }); }); @@ -126,6 +129,7 @@ void main() { devicePublicKey: keypair.publicKey.toFormattedPEM(), proxyServer: 'https://example.com/', )) + .body .ocs .data; expect(subscription.publicKey, hasLength(451)); diff --git a/packages/nextcloud/test/provisioning_api_test.dart b/packages/nextcloud/test/provisioning_api_test.dart index f214e807..0df22560 100644 --- a/packages/nextcloud/test/provisioning_api_test.dart +++ b/packages/nextcloud/test/provisioning_api_test.dart @@ -22,30 +22,40 @@ void main() { group('Users', () { test('Get current user', () async { - final user = await client.provisioningApi.users.getCurrentUser(); - expect(user.ocs.data.id, 'admin'); - expect(user.ocs.data.displayName, 'admin'); - expect(user.ocs.data.displaynameScope, 'v2-federated'); - expect(user.ocs.data.language, 'en'); + final response = await client.provisioningApi.users.getCurrentUser(); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.ocs.data.id, 'admin'); + expect(response.body.ocs.data.displayName, 'admin'); + expect(response.body.ocs.data.displaynameScope, 'v2-federated'); + expect(response.body.ocs.data.language, 'en'); }); test('Get user by username', () async { - final user = await client.provisioningApi.users.getUser(userId: 'user1'); - expect(user.ocs.data.id, 'user1'); - expect(user.ocs.data.displayname, 'User One'); - expect(user.ocs.data.displaynameScope, null); - expect(user.ocs.data.language, 'en'); + final response = await client.provisioningApi.users.getUser(userId: 'user1'); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.ocs.data.id, 'user1'); + expect(response.body.ocs.data.displayname, 'User One'); + expect(response.body.ocs.data.displaynameScope, null); + expect(response.body.ocs.data.language, 'en'); }); }); group('Apps', () { test('Get apps', () async { final response = await client.provisioningApi.apps.getApps(); - expect(response.ocs.data.apps, hasLength(40)); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + expect(response.body.ocs.data.apps, hasLength(40)); - for (final id in response.ocs.data.apps) { + for (final id in response.body.ocs.data.apps) { final app = await client.provisioningApi.apps.getAppInfo(app: id); - expect(app.ocs.data.id, isNotEmpty); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + expect(app.body.ocs.data.id, isNotEmpty); } }); }); diff --git a/packages/nextcloud/test/settings_test.dart b/packages/nextcloud/test/settings_test.dart index b6d27e22..dd6036ab 100644 --- a/packages/nextcloud/test/settings_test.dart +++ b/packages/nextcloud/test/settings_test.dart @@ -22,8 +22,9 @@ Future run(final DockerImage image) async { tearDown(() => container.destroy()); test('Download log file', () async { - final response = utf8.decode((await client.settings.logSettings.download()).data); - expect(response, await container.nextcloudLogs()); + final response = await client.settings.logSettings.download(); + final logs = utf8.decode(response.body); + expect(logs, await container.nextcloudLogs()); }); }); } diff --git a/packages/nextcloud/test/uppush_test.dart b/packages/nextcloud/test/uppush_test.dart index bdd98898..e521a5cc 100644 --- a/packages/nextcloud/test/uppush_test.dart +++ b/packages/nextcloud/test/uppush_test.dart @@ -22,43 +22,64 @@ void main() { test('Is installed', () async { final response = await client.uppush.check(); - expect(response.success, isTrue); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.success, isTrue); }); test('Set keepalive', () async { final response = await client.uppush.setKeepalive(keepalive: 10); - expect(response.success, isTrue); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.success, isTrue); }); test('Create device', () async { final response = await client.uppush.createDevice(deviceName: 'Test'); - expect(response.success, isTrue); - expect(response.deviceId, isNotEmpty); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.success, isTrue); + expect(response.body.deviceId, isNotEmpty); }); test('Delete device', () async { - final deviceId = (await client.uppush.createDevice(deviceName: 'Test')).deviceId; + final deviceId = (await client.uppush.createDevice(deviceName: 'Test')).body.deviceId; final response = await client.uppush.deleteDevice(deviceId: deviceId); - expect(response.success, isTrue); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.success, isTrue); }); test('Create app', () async { - final deviceId = (await client.uppush.createDevice(deviceName: 'Test')).deviceId; + final deviceId = (await client.uppush.createDevice(deviceName: 'Test')).body.deviceId; final response = await client.uppush.createApp(deviceId: deviceId, appName: 'Test'); - expect(response.success, isTrue); - expect(response.token, isNotEmpty); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.success, isTrue); + expect(response.body.token, isNotEmpty); }); test('UnifiedPush discovery', () async { final response = await client.uppush.unifiedpushDiscovery(token: 'example'); - expect(response.unifiedpush.version, 1); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.unifiedpush.version, 1); }); test('Matrix gateway discovery', () async { final response = await client.uppush.gatewayMatrixDiscovery(); - expect(response.unifiedpush.gateway, 'matrix'); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.unifiedpush.gateway, 'matrix'); }); // Deleting an app, sending a notification (also via matrix gateway) or listening for notifications is not possible because redis is not set up diff --git a/packages/nextcloud/test/user_status_test.dart b/packages/nextcloud/test/user_status_test.dart index 7c4b55aa..4d11ec88 100644 --- a/packages/nextcloud/test/user_status_test.dart +++ b/packages/nextcloud/test/user_status_test.dart @@ -21,45 +21,50 @@ void main() { test('Find all predefined statuses', () async { final expectedStatusIDs = ['meeting', 'commuting', 'remote-work', 'sick-leave', 'vacationing']; final response = await client.userStatus.predefinedStatus.findAll(); - expect(response.ocs.data, hasLength(5)); - final responseIDs = response.ocs.data.map((final status) => status.id); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.ocs.data, hasLength(5)); + final responseIDs = response.body.ocs.data.map((final status) => status.id); expect(expectedStatusIDs.map(responseIDs.contains).contains(false), false); - for (final status in response.ocs.data) { + for (final status in response.body.ocs.data) { expect(status.icon, isNotNull); expect(status.message, isNotNull); } - final meeting = response.ocs.data.singleWhere((final s) => s.id == 'meeting').clearAt!; + final meeting = response.body.ocs.data.singleWhere((final s) => s.id == 'meeting').clearAt!; expect(meeting.type, UserStatusClearAt_Type.period); expect(meeting.time.$int, 3600); - final commuting = response.ocs.data.singleWhere((final s) => s.id == 'commuting').clearAt!; + final commuting = response.body.ocs.data.singleWhere((final s) => s.id == 'commuting').clearAt!; expect(commuting.type, UserStatusClearAt_Type.period); expect(commuting.time.$int, 1800); - final remoteWork = response.ocs.data.singleWhere((final s) => s.id == 'remote-work').clearAt!; + final remoteWork = response.body.ocs.data.singleWhere((final s) => s.id == 'remote-work').clearAt!; expect(remoteWork.type, UserStatusClearAt_Type.endOf); expect(remoteWork.time.clearAtTimeType, UserStatusClearAtTimeType.day); - final sickLeave = response.ocs.data.singleWhere((final s) => s.id == 'sick-leave').clearAt!; + final sickLeave = response.body.ocs.data.singleWhere((final s) => s.id == 'sick-leave').clearAt!; expect(sickLeave.type, UserStatusClearAt_Type.endOf); expect(sickLeave.time.clearAtTimeType, UserStatusClearAtTimeType.day); - final vacationing = response.ocs.data.singleWhere((final s) => s.id == 'vacationing').clearAt; + final vacationing = response.body.ocs.data.singleWhere((final s) => s.id == 'vacationing').clearAt; expect(vacationing, null); }); test('Set status', () async { final response = await client.userStatus.userStatus.setStatus(statusType: 'online'); - - expect(response.ocs.data.userId, 'user1'); - expect(response.ocs.data.message, null); - expect(response.ocs.data.messageId, null); - expect(response.ocs.data.messageIsPredefined, false); - expect(response.ocs.data.icon, null); - expect(response.ocs.data.clearAt, null); - expect(response.ocs.data.status, 'online'); - expect(response.ocs.data.statusIsUserDefined, true); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.ocs.data.userId, 'user1'); + expect(response.body.ocs.data.message, null); + expect(response.body.ocs.data.messageId, null); + expect(response.body.ocs.data.messageIsPredefined, false); + expect(response.body.ocs.data.icon, null); + expect(response.body.ocs.data.clearAt, null); + expect(response.body.ocs.data.status, 'online'); + expect(response.body.ocs.data.statusIsUserDefined, true); }); test('Get status', () async { @@ -68,29 +73,36 @@ void main() { await client.userStatus.userStatus.setStatus(statusType: 'online'); final response = await client.userStatus.userStatus.getStatus(); - expect(response.ocs.data.userId, 'user1'); - expect(response.ocs.data.message, null); - expect(response.ocs.data.messageId, null); - expect(response.ocs.data.messageIsPredefined, false); - expect(response.ocs.data.icon, null); - expect(response.ocs.data.clearAt, null); - expect(response.ocs.data.status, 'online'); - expect(response.ocs.data.statusIsUserDefined, true); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.ocs.data.userId, 'user1'); + expect(response.body.ocs.data.message, null); + expect(response.body.ocs.data.messageId, null); + expect(response.body.ocs.data.messageIsPredefined, false); + expect(response.body.ocs.data.icon, null); + expect(response.body.ocs.data.clearAt, null); + expect(response.body.ocs.data.status, 'online'); + expect(response.body.ocs.data.statusIsUserDefined, true); }); test('Find all statuses', () async { var response = await client.userStatus.statuses.findAll(); - expect(response.ocs.data, hasLength(0)); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + expect(response.body.ocs.data, hasLength(0)); await client.userStatus.userStatus.setStatus(statusType: 'online'); response = await client.userStatus.statuses.findAll(); - expect(response.ocs.data, hasLength(1)); - expect(response.ocs.data[0].userId, 'user1'); - expect(response.ocs.data[0].message, null); - expect(response.ocs.data[0].icon, null); - expect(response.ocs.data[0].clearAt, null); - expect(response.ocs.data[0].status, 'online'); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + expect(response.body.ocs.data, hasLength(1)); + expect(response.body.ocs.data[0].userId, 'user1'); + expect(response.body.ocs.data[0].message, null); + expect(response.body.ocs.data[0].icon, null); + expect(response.body.ocs.data[0].clearAt, null); + expect(response.body.ocs.data[0].status, 'online'); }); test('Find status', () async { @@ -98,11 +110,14 @@ void main() { await client.userStatus.userStatus.setStatus(statusType: 'online'); final response = await client.userStatus.statuses.find(userId: 'user1'); - expect(response.ocs.data.userId, 'user1'); - expect(response.ocs.data.message, null); - expect(response.ocs.data.icon, null); - expect(response.ocs.data.clearAt, null); - expect(response.ocs.data.status, 'online'); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.ocs.data.userId, 'user1'); + expect(response.body.ocs.data.message, null); + expect(response.body.ocs.data.icon, null); + expect(response.body.ocs.data.clearAt, null); + expect(response.body.ocs.data.status, 'online'); }); test('Set predefined message', () async { @@ -111,14 +126,17 @@ void main() { messageId: 'meeting', clearAt: clearAt, ); - expect(response.ocs.data.userId, 'user1'); - expect(response.ocs.data.message, null); - expect(response.ocs.data.messageId, 'meeting'); - expect(response.ocs.data.messageIsPredefined, true); - expect(response.ocs.data.icon, null); - expect(response.ocs.data.clearAt, clearAt); - expect(response.ocs.data.status, 'offline'); - expect(response.ocs.data.statusIsUserDefined, false); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.ocs.data.userId, 'user1'); + expect(response.body.ocs.data.message, null); + expect(response.body.ocs.data.messageId, 'meeting'); + expect(response.body.ocs.data.messageIsPredefined, true); + expect(response.body.ocs.data.icon, null); + expect(response.body.ocs.data.clearAt, clearAt); + expect(response.body.ocs.data.status, 'offline'); + expect(response.body.ocs.data.statusIsUserDefined, false); }); test('Set custom message', () async { @@ -128,14 +146,17 @@ void main() { message: 'bla', clearAt: clearAt, ); - expect(response.ocs.data.userId, 'user1'); - expect(response.ocs.data.message, 'bla'); - expect(response.ocs.data.messageId, null); - expect(response.ocs.data.messageIsPredefined, false); - expect(response.ocs.data.icon, '😀'); - expect(response.ocs.data.clearAt, clearAt); - expect(response.ocs.data.status, 'offline'); - expect(response.ocs.data.statusIsUserDefined, false); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.ocs.data.userId, 'user1'); + expect(response.body.ocs.data.message, 'bla'); + expect(response.body.ocs.data.messageId, null); + expect(response.body.ocs.data.messageIsPredefined, false); + expect(response.body.ocs.data.icon, '😀'); + expect(response.body.ocs.data.clearAt, clearAt); + expect(response.body.ocs.data.status, 'offline'); + expect(response.body.ocs.data.statusIsUserDefined, false); }); test('Clear message', () async { @@ -148,26 +169,32 @@ void main() { await client.userStatus.userStatus.clearMessage(); final response = await client.userStatus.userStatus.getStatus(); - expect(response.ocs.data.userId, 'user1'); - expect(response.ocs.data.message, null); - expect(response.ocs.data.messageId, null); - expect(response.ocs.data.messageIsPredefined, false); - expect(response.ocs.data.icon, null); - expect(response.ocs.data.clearAt, null); - expect(response.ocs.data.status, 'offline'); - expect(response.ocs.data.statusIsUserDefined, false); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.ocs.data.userId, 'user1'); + expect(response.body.ocs.data.message, null); + expect(response.body.ocs.data.messageId, null); + expect(response.body.ocs.data.messageIsPredefined, false); + expect(response.body.ocs.data.icon, null); + expect(response.body.ocs.data.clearAt, null); + expect(response.body.ocs.data.status, 'offline'); + expect(response.body.ocs.data.statusIsUserDefined, false); }); test('Heartbeat', () async { final response = await client.userStatus.heartbeat.heartbeat(status: 'online'); - expect(response.ocs.data.userId, 'user1'); - expect(response.ocs.data.message, null); - expect(response.ocs.data.messageId, null); - expect(response.ocs.data.messageIsPredefined, false); - expect(response.ocs.data.icon, null); - expect(response.ocs.data.clearAt, null); - expect(response.ocs.data.status, 'online'); - expect(response.ocs.data.statusIsUserDefined, false); + expect(response.statusCode, 200); + expect(() => response.headers, isA()); + + expect(response.body.ocs.data.userId, 'user1'); + expect(response.body.ocs.data.message, null); + expect(response.body.ocs.data.messageId, null); + expect(response.body.ocs.data.messageIsPredefined, false); + expect(response.body.ocs.data.icon, null); + expect(response.body.ocs.data.clearAt, null); + expect(response.body.ocs.data.status, 'online'); + expect(response.body.ocs.data.statusIsUserDefined, false); }); }, retry: retryCount,