diff --git a/lib/application.dart b/lib/application.dart index 444b545f..5d812e57 100644 --- a/lib/application.dart +++ b/lib/application.dart @@ -23,12 +23,15 @@ class Application extends Container { late BaseHttpServer _server; - Future initialize( - {required Map config, - List args = const []}) async { + Future initialize({ + required Map config, + List args = const [], + }) async { IoCContainer().register(() => RequestHandler()); - IoCContainer() - .register(() => SessionManager(), singleton: true); + IoCContainer().register( + () => SessionManager(), + singleton: true, + ); if (env('APP_KEY') == '' || env('APP_KEY') == null) { throw Exception('Key not found'); } diff --git a/lib/src/authentication/authenticate.dart b/lib/src/authentication/authenticate.dart index 98375cc5..6bec789b 100644 --- a/lib/src/authentication/authenticate.dart +++ b/lib/src/authentication/authenticate.dart @@ -11,11 +11,7 @@ class Authenticate extends Middleware { final String? guard; final bool basic; final String loginPath; - Authenticate({ - this.guard, - this.basic = false, - this.loginPath = '/login', - }); + Authenticate({this.guard, this.basic = false, this.loginPath = '/login'}); @mustCallSuper @override diff --git a/lib/src/authentication/authentication.dart b/lib/src/authentication/authentication.dart index a21b4e1a..21bcf120 100644 --- a/lib/src/authentication/authentication.dart +++ b/lib/src/authentication/authentication.dart @@ -158,17 +158,22 @@ class Auth { if (!customToken) { Map payload = HasApiTokens().verify( - token.replaceFirst('Bearer ', ''), _userGuard, 'refresh_token'); + token.replaceFirst('Bearer ', ''), + _userGuard, + 'refresh_token', + ); - Model? authenticatable = - Config().get('auth')['guards'][_userGuard]['provider']; + Model? authenticatable = Config().get( + 'auth', + )['guards'][_userGuard]['provider']; if (authenticatable == null) { throw InvalidArgumentException('Authenticatable class not found'); } - Map? user = - await authenticatable.query.where('id', '=', payload['id']).first(); + Map? user = await authenticatable.query + .where('id', '=', payload['id']) + .first(); if (user == null) { throw Unauthenticated(message: 'Invalid token'); @@ -193,10 +198,9 @@ class Auth { /// /// Returns true if the operation was successful. Future deleteTokens(dynamic userId) async { - await PersonalAccessToken() - .query - .where('tokenable_id', '=', userId) - .update({'deleted_at': DateTime.now()}); + await PersonalAccessToken().query.where('tokenable_id', '=', userId).update( + {'deleted_at': DateTime.now()}, + ); return true; } @@ -210,8 +214,7 @@ class Auth { /// Returns a Future that resolves to true if the operation was successful. /// Future deleteCurrentToken(String token) async { - await PersonalAccessToken() - .query + await PersonalAccessToken().query .where('token', '=', md5.convert(utf8.encode(token))) .update({'deleted_at': DateTime.now()}); return true; @@ -239,16 +242,18 @@ class Auth { Map? user, bool isCustomToken = false, }) async { - Map payload = HasApiTokens() - .verify(token.replaceFirst('Bearer ', ''), _userGuard, 'access_token'); + Map payload = HasApiTokens().verify( + token.replaceFirst('Bearer ', ''), + _userGuard, + 'access_token', + ); if (isCustomToken) { _user[_userGuard] = payload; _loggedIn = true; return true; } else { - Map? exists = await PersonalAccessToken() - .query + Map? exists = await PersonalAccessToken().query .where('token', '=', md5.convert(utf8.encode(token))) .whereNull('deleted_at') .first(['id']); @@ -257,20 +262,21 @@ class Auth { throw Unauthenticated(message: 'Invalid token'); } - await PersonalAccessToken() - .query + await PersonalAccessToken().query .where('token', '=', md5.convert(utf8.encode(token))) .update({'last_used_at': DateTime.now()}); if (user == null) { - Model? authenticatable = - Config().get('auth')['guards'][_userGuard]['provider']; + Model? authenticatable = Config().get( + 'auth', + )['guards'][_userGuard]['provider']; if (authenticatable == null) { throw InvalidArgumentException('Authenticatable class not found'); } - user = - await authenticatable.query.where('id', '=', payload['id']).first(); + user = await authenticatable.query + .where('id', '=', payload['id']) + .first(); } if (user != null) { diff --git a/lib/src/authentication/has_api_tokens.dart b/lib/src/authentication/has_api_tokens.dart index cef2d5a1..7397d665 100644 --- a/lib/src/authentication/has_api_tokens.dart +++ b/lib/src/authentication/has_api_tokens.dart @@ -45,11 +45,7 @@ class HasApiTokens { } final jwt = JWT( - { - 'user': jsonEncode(_userPayload), - 'type': 'access_token', - ...userId, - }, + {'user': jsonEncode(_userPayload), 'type': 'access_token', ...userId}, audience: env('JWT_AUDIENCE') == null ? null : Audience.one(env('JWT_AUDIENCE')), @@ -60,23 +56,25 @@ class HasApiTokens { Map payload = {}; Duration expirationTime = expiresIn ?? const Duration(hours: 1); - String accessToken = - jwt.sign(SecretKey('$secretKey$guard'), expiresIn: expirationTime); + String accessToken = jwt.sign( + SecretKey('$secretKey$guard'), + expiresIn: expirationTime, + ); payload['access_token'] = accessToken; if (withRefreshToken) { - final jwtRefresh = JWT({ - ...userId, - 'type': 'refresh_token', - }); - String refreshToken = jwtRefresh.sign(SecretKey('$secretKey$guard'), - expiresIn: const Duration(days: 120)); + final jwtRefresh = JWT({...userId, 'type': 'refresh_token'}); + String refreshToken = jwtRefresh.sign( + SecretKey('$secretKey$guard'), + expiresIn: const Duration(days: 120), + ); payload['refresh_token'] = refreshToken; } - payload['expires_in'] = - DateTime.now().add(expirationTime).toIso8601String(); + payload['expires_in'] = DateTime.now() + .add(expirationTime) + .toIso8601String(); return payload; } diff --git a/lib/src/authentication/redirect_if_authenticated.dart b/lib/src/authentication/redirect_if_authenticated.dart index 03da3da5..a0b141f3 100644 --- a/lib/src/authentication/redirect_if_authenticated.dart +++ b/lib/src/authentication/redirect_if_authenticated.dart @@ -12,10 +12,7 @@ class RedirectIfAuthenticated extends Middleware { Future handle(Request req) async { bool loggedIn = await getSession('logged_in') ?? false; if (loggedIn) { - throw RedirectException( - message: path, - responseType: ResponseType.html, - ); + throw RedirectException(message: path, responseType: ResponseType.html); } } } diff --git a/lib/src/aws/s3_client.dart b/lib/src/aws/s3_client.dart index 5efba957..76988c56 100644 --- a/lib/src/aws/s3_client.dart +++ b/lib/src/aws/s3_client.dart @@ -25,7 +25,11 @@ class S3Client { } Uint8List _getSignatureKey( - String key, String date, String regionName, String serviceName) { + String key, + String date, + String regionName, + String serviceName, + ) { var kDate = _hmacSha256(Uint8List.fromList(utf8.encode('AWS4$key')), date); var kRegion = _hmacSha256(kDate, regionName); var kService = _hmacSha256(kRegion, serviceName); @@ -55,25 +59,26 @@ class S3Client { 'x-amz-date:$dateTime', '', signedHeaders, - hash + hash, ].join('\n'); final stringToSign = [ algorithm, dateTime, scope, - sha256.convert(utf8.encode(canonicalRequest)).toString() + sha256.convert(utf8.encode(canonicalRequest)).toString(), ].join('\n'); final signingKey = _getSignatureKey(_secretKey, date, _region, service); - final signature = _hmacSha256(signingKey, stringToSign) - .map((e) => e.toRadixString(16).padLeft(2, '0')) - .join(); + final signature = _hmacSha256( + signingKey, + stringToSign, + ).map((e) => e.toRadixString(16).padLeft(2, '0')).join(); final authorizationHeader = [ '$algorithm Credential=$_accessKey/$scope', 'SignedHeaders=$signedHeaders', - 'Signature=$signature' + 'Signature=$signature', ].join(', '); return { diff --git a/lib/src/cache/file_cache_driver.dart b/lib/src/cache/file_cache_driver.dart index 718f908e..2073f64f 100644 --- a/lib/src/cache/file_cache_driver.dart +++ b/lib/src/cache/file_cache_driver.dart @@ -36,8 +36,11 @@ class FileCacheDriver implements CacheDriver { } @override - Future put(String key, dynamic value, - {Duration duration = const Duration(hours: 1)}) async { + Future put( + String key, + dynamic value, { + Duration duration = const Duration(hours: 1), + }) async { final file = _getCacheFile(key); await _ensureCacheDirectory(); @@ -57,10 +60,7 @@ class FileCacheDriver implements CacheDriver { final file = _getCacheFile(key); await _ensureCacheDirectory(); - final cache = { - 'value': value, - 'expiration': null, - }; + final cache = {'value': value, 'expiration': null}; await file.writeAsString(jsonEncode(cache)); } diff --git a/lib/src/config/defined_regexp.dart b/lib/src/config/defined_regexp.dart index 131ab4e6..77363eeb 100644 --- a/lib/src/config/defined_regexp.dart +++ b/lib/src/config/defined_regexp.dart @@ -10,4 +10,5 @@ final alphaRegExp = RegExp(r'^[a-zA-Z]+$'); final emailRegExp = RegExp(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'); final uuidRegExp = RegExp( - r'^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$'); + r'^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$', +); diff --git a/lib/src/contract/database/_connectors/_database_connection.dart b/lib/src/contract/database/_connectors/_database_connection.dart index 0b42c568..0faaadaa 100644 --- a/lib/src/contract/database/_connectors/_database_connection.dart +++ b/lib/src/contract/database/_connectors/_database_connection.dart @@ -4,10 +4,7 @@ abstract interface class DatabaseConnection { String query, [ Map bindings = const {}, ]); - Future insert( - String query, [ - Map bindings = const {}, - ]); + Future insert(String query, [Map bindings = const {}]); Future execute( String query, [ Map bindings = const {}, diff --git a/lib/src/contract/database/query_builder/_bulk_operations_builder.dart b/lib/src/contract/database/query_builder/_bulk_operations_builder.dart index 5fd5707d..7c3e7f7d 100644 --- a/lib/src/contract/database/query_builder/_bulk_operations_builder.dart +++ b/lib/src/contract/database/query_builder/_bulk_operations_builder.dart @@ -1,14 +1,6 @@ part of 'query_builder.dart'; -enum ConflictAction { - update, - - ignore, - - replace, - - delete, -} +enum ConflictAction { update, ignore, replace, delete } abstract class BulkOperationsBuilder { Future merge( @@ -53,16 +45,19 @@ abstract class BulkOperationsBuilder { Future batchProcess({ required int batchSize, required Future Function( - List> batch, int batchNumber) - processor, + List> batch, + int batchNumber, + ) + processor, List columns = const ['*'], }); Future chunkedProcess({ required int chunkSize, required Future>> Function( - List> chunk) - processor, + List> chunk, + ) + processor, String? destination, List columns = const ['*'], }); @@ -75,7 +70,5 @@ abstract class BulkOperationsBuilder { List? conflictColumns, }); - Future transactionalBulkOperation( - Future Function() operations, - ); + Future transactionalBulkOperation(Future Function() operations); } diff --git a/lib/src/contract/database/query_builder/_cte_builder.dart b/lib/src/contract/database/query_builder/_cte_builder.dart index c25e9b60..7d8bd203 100644 --- a/lib/src/contract/database/query_builder/_cte_builder.dart +++ b/lib/src/contract/database/query_builder/_cte_builder.dart @@ -1,11 +1,16 @@ part of 'query_builder.dart'; abstract class CteBuilder { - QueryBuilder withCte(String name, QueryBuilder subQuery, - {List? columns}); + QueryBuilder withCte( + String name, + QueryBuilder subQuery, { + List? columns, + }); - QueryBuilder withMultiple(Map ctes, - {Map>? columnsMap}); + QueryBuilder withMultiple( + Map ctes, { + Map>? columnsMap, + }); QueryBuilder withRecursive( String name, @@ -14,9 +19,15 @@ abstract class CteBuilder { List? columns, }); - QueryBuilder withMaterialized(String name, QueryBuilder subQuery, - {List? columns}); + QueryBuilder withMaterialized( + String name, + QueryBuilder subQuery, { + List? columns, + }); - QueryBuilder withNotMaterialized(String name, QueryBuilder subQuery, - {List? columns}); + QueryBuilder withNotMaterialized( + String name, + QueryBuilder subQuery, { + List? columns, + }); } diff --git a/lib/src/contract/database/query_builder/_insert_query_builder.dart b/lib/src/contract/database/query_builder/_insert_query_builder.dart index 61eb59e3..4962f517 100644 --- a/lib/src/contract/database/query_builder/_insert_query_builder.dart +++ b/lib/src/contract/database/query_builder/_insert_query_builder.dart @@ -1,19 +1,10 @@ part of 'query_builder.dart'; abstract interface class InsertQueryBuilder { - Future insert( - Map values, - ); - Future insertGetId( - Map values, [ - String? sequence, - ]); - Future insertMany( - List> values, - ); - Future insertOrIgnore( - Map values, - ); + Future insert(Map values); + Future insertGetId(Map values, [String? sequence]); + Future insertMany(List> values); + Future insertOrIgnore(Map values); Future insertUsing(List columns, QueryBuilder subQuery); Future upsert( Map values, diff --git a/lib/src/contract/database/query_builder/_join_clause_builder.dart b/lib/src/contract/database/query_builder/_join_clause_builder.dart index 5d295682..3c122091 100644 --- a/lib/src/contract/database/query_builder/_join_clause_builder.dart +++ b/lib/src/contract/database/query_builder/_join_clause_builder.dart @@ -1,10 +1,7 @@ part of 'query_builder.dart'; abstract interface class JoinClauseBuilder { - QueryBuilder crossJoin( - String table, [ - List bindings = const [], - ]); + QueryBuilder crossJoin(String table, [List bindings = const []]); QueryBuilder join( String table, diff --git a/lib/src/contract/database/query_builder/_query_executor_builder.dart b/lib/src/contract/database/query_builder/_query_executor_builder.dart index e06fa6a3..f813d8d4 100644 --- a/lib/src/contract/database/query_builder/_query_executor_builder.dart +++ b/lib/src/contract/database/query_builder/_query_executor_builder.dart @@ -13,9 +13,7 @@ abstract class QueryExecutorBuilder { ]); Future count([String columns = '*']); Future doesntExist(); - Future each( - void Function(Map) callback, - ); + Future each(void Function(Map) callback); Future exists(); Future?> find( dynamic id, { @@ -28,9 +26,7 @@ abstract class QueryExecutorBuilder { String byColumnName = 'id', List columns = const ['*'], }); - Future?> first([ - List columns, - ]); + Future?> first([List columns]); Future?> firstOrFail([ List columns = const ['*'], ]); @@ -40,17 +36,13 @@ abstract class QueryExecutorBuilder { dynamic value, List columns = const ['*'], ]); - Future>> get([ - List columns, - ]); + Future>> get([List columns]); Stream>> lazy([ int chunk = 1000, String column, ]); - Stream> cursor([ - int chunk = 1000, - ]); + Stream> cursor([int chunk = 1000]); Future max(String column); Future min(String column); Future> paginate({ @@ -59,10 +51,7 @@ abstract class QueryExecutorBuilder { String? pageName, int? page, }); - Future pluck( - String column, [ - String? key, - ]); + Future pluck(String column, [String? key]); Future> simplePaginate([ int perPage, List columns, diff --git a/lib/src/contract/database/query_builder/_select_query_builder.dart b/lib/src/contract/database/query_builder/_select_query_builder.dart index ede0a8dd..d79c081d 100644 --- a/lib/src/contract/database/query_builder/_select_query_builder.dart +++ b/lib/src/contract/database/query_builder/_select_query_builder.dart @@ -1,20 +1,10 @@ part of 'query_builder.dart'; abstract interface class SelectQueryBuilder { - QueryBuilder addSelect( - List columns, - ); + QueryBuilder addSelect(List columns); - QueryBuilder select([ - List columns, - ]); + QueryBuilder select([List columns]); - QueryBuilder selectRaw( - String query, [ - List bindings = const [], - ]); - QueryBuilder selectSub( - QueryBuilder subQuery, - String as, - ); + QueryBuilder selectRaw(String query, [List bindings = const []]); + QueryBuilder selectSub(QueryBuilder subQuery, String as); } diff --git a/lib/src/contract/database/query_builder/_update_query_builder.dart b/lib/src/contract/database/query_builder/_update_query_builder.dart index 674feb2f..f010c909 100644 --- a/lib/src/contract/database/query_builder/_update_query_builder.dart +++ b/lib/src/contract/database/query_builder/_update_query_builder.dart @@ -15,14 +15,9 @@ abstract interface class UpdateQueryBuilder { Map increments, [ Map extra = const {}, ]); - Future update( - Map values, - ); + Future update(Map values); - Future updateMany( - List> updates, - String column, - ); + Future updateMany(List> updates, String column); Future updateOrInsert( Map search, diff --git a/lib/src/contract/database/query_builder/_where_clauses_builder.dart b/lib/src/contract/database/query_builder/_where_clauses_builder.dart index a19a2b89..013a977a 100644 --- a/lib/src/contract/database/query_builder/_where_clauses_builder.dart +++ b/lib/src/contract/database/query_builder/_where_clauses_builder.dart @@ -7,31 +7,19 @@ abstract interface class WhereClausesBuilder { dynamic value, String boolean = 'and', ]); - QueryBuilder orWhereBetween( - String column, - List values, { - bool not = false, - }); + QueryBuilder orWhereBetween(String column, List values, {bool not = false}); QueryBuilder orWhereColumn( - String first, String operator, String secondColumn); - - QueryBuilder orWhereDate( - String column, + String first, String operator, - dynamic value, + String secondColumn, ); - QueryBuilder orWhereDay( - String column, - String operator, - dynamic value, - ); + QueryBuilder orWhereDate(String column, String operator, dynamic value); - QueryBuilder orWhereExists( - QueryCallback callback, { - bool not = false, - }); + QueryBuilder orWhereDay(String column, String operator, dynamic value); + + QueryBuilder orWhereExists(QueryCallback callback, {bool not = false}); QueryBuilder orWhereFullText( dynamic columns, @@ -39,87 +27,45 @@ abstract interface class WhereClausesBuilder { Map options = const {}, ]); - QueryBuilder orWhereHour( - String column, - String operator, - dynamic value, - ); + QueryBuilder orWhereHour(String column, String operator, dynamic value); - QueryBuilder orWhereIn( - String column, - List values, { - bool not = false, - }); + QueryBuilder orWhereIn(String column, List values, {bool not = false}); QueryBuilder orWhereJsonContains( String column, dynamic value, { bool not = false, }); - QueryBuilder orWhereJsonDoesntContain( - String column, - dynamic value, - ); - QueryBuilder orWhereJsonLength( - String column, - String operator, - dynamic value, - ); + QueryBuilder orWhereJsonDoesntContain(String column, dynamic value); + QueryBuilder orWhereJsonLength(String column, String operator, dynamic value); QueryBuilder orWhereLike( String column, dynamic value, { bool caseSensitive = false, }); - QueryBuilder orWhereMonth( - String column, - String operator, - dynamic value, - ); - QueryBuilder orWhereNotBetween( - String column, - List values, - ); - QueryBuilder orWhereNotExists( - QueryCallback callback, - ); + QueryBuilder orWhereMonth(String column, String operator, dynamic value); + QueryBuilder orWhereNotBetween(String column, List values); + QueryBuilder orWhereNotExists(QueryCallback callback); - QueryBuilder orWhereNotIn( - String column, - List values, - ); + QueryBuilder orWhereNotIn(String column, List values); QueryBuilder orWhereNotLike( String column, dynamic value, { bool caseSensitive = false, String boolean = 'and', }); - QueryBuilder orWhereNotNull( - String column, - ); - QueryBuilder orWhereNull( - String column, - ); + QueryBuilder orWhereNotNull(String column); + QueryBuilder orWhereNull(String column); - QueryBuilder orWhereRaw( - String sql, [ - List bindings = const [], - ]); + QueryBuilder orWhereRaw(String sql, [List bindings = const []]); QueryBuilder orWhereRowValues( List columns, String operator, List values, ); - QueryBuilder orWhereTime( - String column, - String operator, - dynamic value, - ); - QueryBuilder orWhereYear( - String column, - String operator, - dynamic value, - ); + QueryBuilder orWhereTime(String column, String operator, dynamic value); + QueryBuilder orWhereYear(String column, String operator, dynamic value); QueryBuilder where( dynamic condition, [ @@ -127,10 +73,7 @@ abstract interface class WhereClausesBuilder { dynamic value, String boolean = 'and', ]); - QueryBuilder whereAfterToday( - String column, { - String boolean = 'and', - }); + QueryBuilder whereAfterToday(String column, {String boolean = 'and'}); QueryBuilder whereAll( String column, @@ -143,10 +86,7 @@ abstract interface class WhereClausesBuilder { String boolean = 'and', }); - QueryBuilder whereBeforeToday( - String column, { - String boolean = 'and', - }); + QueryBuilder whereBeforeToday(String column, {String boolean = 'and'}); QueryBuilder whereBetween( String column, List values, { @@ -195,10 +135,7 @@ abstract interface class WhereClausesBuilder { dynamic query, [ Map options = const {}, ]); - QueryBuilder whereFuture( - String column, { - String boolean = 'and', - }); + QueryBuilder whereFuture(String column, {String boolean = 'and'}); QueryBuilder whereGreaterThan( dynamic condition, [ @@ -287,16 +224,9 @@ abstract interface class WhereClausesBuilder { dynamic value, String boolean = 'and', ]); - QueryBuilder whereNotExists( - QueryCallback callback, { - String boolean = 'and', - }); + QueryBuilder whereNotExists(QueryCallback callback, {String boolean = 'and'}); - QueryBuilder whereNotIn( - String column, - List values, { - String boolean = 'and', - }); + QueryBuilder whereNotIn(String column, List values, {String boolean = 'and'}); QueryBuilder whereNotLike( String column, @@ -305,28 +235,16 @@ abstract interface class WhereClausesBuilder { String boolean = 'and', }); - QueryBuilder whereNotNull( - String column, { - String boolean = 'and', - }); + QueryBuilder whereNotNull(String column, {String boolean = 'and'}); - QueryBuilder whereNowOrFuture( - String column, { - String boolean = 'and', - }); - QueryBuilder whereNowOrPast( - String column, { - String boolean = 'and', - }); + QueryBuilder whereNowOrFuture(String column, {String boolean = 'and'}); + QueryBuilder whereNowOrPast(String column, {String boolean = 'and'}); QueryBuilder whereNull( String column, { String boolean = 'and', bool not = false, }); - QueryBuilder wherePast( - String column, { - String boolean = 'and', - }); + QueryBuilder wherePast(String column, {String boolean = 'and'}); QueryBuilder whereRaw( String sql, [ List bindings = const [], @@ -344,19 +262,10 @@ abstract interface class WhereClausesBuilder { dynamic value, { String boolean = 'and', }); - QueryBuilder whereToday( - String column, { - String boolean = 'and', - }); - QueryBuilder whereTodayOrAfter( - String column, { - String boolean = 'and', - }); + QueryBuilder whereToday(String column, {String boolean = 'and'}); + QueryBuilder whereTodayOrAfter(String column, {String boolean = 'and'}); - QueryBuilder whereTodayOrBefore( - String column, { - String boolean = 'and', - }); + QueryBuilder whereTodayOrBefore(String column, {String boolean = 'and'}); QueryBuilder whereYear( String column, String operator, @@ -370,10 +279,7 @@ abstract interface class WhereClausesBuilder { String boolean = 'and', }); - QueryBuilder orWhereHas( - String relation, - QueryCallback callback, - ); + QueryBuilder orWhereHas(String relation, QueryCallback callback); QueryBuilder whereDoesntHave( String relation, @@ -381,10 +287,7 @@ abstract interface class WhereClausesBuilder { String boolean = 'and', }); - QueryBuilder orWhereDoesntHave( - String relation, - QueryCallback callback, - ); + QueryBuilder orWhereDoesntHave(String relation, QueryCallback callback); QueryBuilder withSoftDeletes([String column = 'deleted_at']); } diff --git a/lib/src/contract/database/query_builder/_window_functions_builder.dart b/lib/src/contract/database/query_builder/_window_functions_builder.dart index ec6090e7..860ada94 100644 --- a/lib/src/contract/database/query_builder/_window_functions_builder.dart +++ b/lib/src/contract/database/query_builder/_window_functions_builder.dart @@ -1,23 +1,11 @@ part of 'query_builder.dart'; abstract interface class WindowFunctionsBuilder { - QueryBuilder rowNumber({ - String? partitionBy, - String? orderBy, - String? as, - }); + QueryBuilder rowNumber({String? partitionBy, String? orderBy, String? as}); - QueryBuilder rank({ - String? partitionBy, - String? orderBy, - String? as, - }); + QueryBuilder rank({String? partitionBy, String? orderBy, String? as}); - QueryBuilder denseRank({ - String? partitionBy, - String? orderBy, - String? as, - }); + QueryBuilder denseRank({String? partitionBy, String? orderBy, String? as}); QueryBuilder lag( String column, { @@ -58,17 +46,9 @@ abstract interface class WindowFunctionsBuilder { String? as, }); - QueryBuilder percentRank({ - String? partitionBy, - String? orderBy, - String? as, - }); + QueryBuilder percentRank({String? partitionBy, String? orderBy, String? as}); - QueryBuilder cumeDist({ - String? partitionBy, - String? orderBy, - String? as, - }); + QueryBuilder cumeDist({String? partitionBy, String? orderBy, String? as}); QueryBuilder windowSum( String column, { diff --git a/lib/src/contract/database/query_builder/query_builder.dart b/lib/src/contract/database/query_builder/query_builder.dart index 3fd8eb7a..de5a8355 100644 --- a/lib/src/contract/database/query_builder/query_builder.dart +++ b/lib/src/contract/database/query_builder/query_builder.dart @@ -95,16 +95,12 @@ abstract class QueryBuilder } @protected - String formatValue( - dynamic value, - ) { + String formatValue(dynamic value) { if (value is num) return value.toString(); return "'$value'"; } - QueryBuilder groupBy( - List groups, - ); + QueryBuilder groupBy(List groups); QueryBuilder having( String column, [ String? operator, @@ -118,32 +114,18 @@ abstract class QueryBuilder String boolean = 'and', bool not = false, }); - QueryBuilder inRandomOrder([ - dynamic seed, - ]); - QueryBuilder latest([ - String column = 'created_at', - ]); + QueryBuilder inRandomOrder([dynamic seed]); + QueryBuilder latest([String column = 'created_at']); QueryBuilder limit(int value); QueryBuilder offset(int value); - QueryBuilder orderBy( - String column, [ - String direction = 'ASC', - ]); + QueryBuilder orderBy(String column, [String direction = 'ASC']); - QueryBuilder orderByAsc( - String column, - ); + QueryBuilder orderByAsc(String column); - QueryBuilder orderByDesc( - String column, - ); - QueryBuilder reorder([ - String? column, - String? direction, - ]); + QueryBuilder orderByDesc(String column); + QueryBuilder reorder([String? column, String? direction]); QueryBuilder skip(int value); diff --git a/lib/src/contract/orm/relation.dart b/lib/src/contract/orm/relation.dart index 88fde3c9..ff361ecb 100644 --- a/lib/src/contract/orm/relation.dart +++ b/lib/src/contract/orm/relation.dart @@ -14,7 +14,9 @@ abstract class Relation { }); Map>> buildDictionary( - List> results, String key) { + List> results, + String key, + ) { Map>> dictionary = {}; for (var result in results) { diff --git a/lib/src/cryptographic/hash.dart b/lib/src/cryptographic/hash.dart index 5a2cb84b..0b012068 100644 --- a/lib/src/cryptographic/hash.dart +++ b/lib/src/cryptographic/hash.dart @@ -51,8 +51,12 @@ class Hash { const charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; final random = Random(); - return String.fromCharCodes(Iterable.generate( - 4, (_) => charset.codeUnitAt(random.nextInt(charset.length)))); + return String.fromCharCodes( + Iterable.generate( + 4, + (_) => charset.codeUnitAt(random.nextInt(charset.length)), + ), + ); } /// Hashes the given [password] using the given [salt] and the APP_KEY or diff --git a/lib/src/cryptographic/vania_encryption.dart b/lib/src/cryptographic/vania_encryption.dart index 3f8769c6..fae40973 100644 --- a/lib/src/cryptographic/vania_encryption.dart +++ b/lib/src/cryptographic/vania_encryption.dart @@ -19,12 +19,15 @@ class VaniaEncryption { /// Returns: /// A Base64 encoded string representing the encrypted text. static Future encryptString( - String plainText, String passphrase) async { + String plainText, + String passphrase, + ) async { try { plainText = base64.encode(utf8.encode(plainText)); - final keyBytes = - utf8.encode(passphrase.padRight(32, '0').substring(0, 32)); + final keyBytes = utf8.encode( + passphrase.padRight(32, '0').substring(0, 32), + ); final secretKey = SecretKey(keyBytes); final plainBytes = utf8.encode(plainText); @@ -62,10 +65,13 @@ class VaniaEncryption { /// The original plaintext if decryption is successful, or an empty /// string if decryption fails. static Future decryptString( - String encryptedText, String passphrase) async { + String encryptedText, + String passphrase, + ) async { try { - final keyBytes = - utf8.encode(passphrase.padRight(32, '0').substring(0, 32)); + final keyBytes = utf8.encode( + passphrase.padRight(32, '0').substring(0, 32), + ); final secretKey = SecretKey(keyBytes); // Decode the base64 encrypted text @@ -75,11 +81,7 @@ class VaniaEncryption { final mac = encryptedBytes.sublist(encryptedBytes.length - 16); final cipherText = encryptedBytes.sublist(12, encryptedBytes.length - 16); - final secretBox = SecretBox( - cipherText, - nonce: nonce, - mac: Mac(mac), - ); + final secretBox = SecretBox(cipherText, nonce: nonce, mac: Mac(mac)); final aesGcm = AesGcm.with256bits(); final decryptedBytes = await aesGcm.decrypt( diff --git a/lib/src/database/_connection_manager.dart b/lib/src/database/_connection_manager.dart index 621adba8..607b405b 100644 --- a/lib/src/database/_connection_manager.dart +++ b/lib/src/database/_connection_manager.dart @@ -50,10 +50,7 @@ class ConnectionManager { } } on InvalidArgumentException catch (e) { Logger.log(e.message, type: Logger.ERROR); - throw DatabaseException( - "Failed to connect to the database", - e, - ); + throw DatabaseException("Failed to connect to the database", e); } } diff --git a/lib/src/database/_connectors/_database_connection_factory.dart b/lib/src/database/_connectors/_database_connection_factory.dart index 0fa6a25c..3e8fc3c2 100644 --- a/lib/src/database/_connectors/_database_connection_factory.dart +++ b/lib/src/database/_connectors/_database_connection_factory.dart @@ -12,8 +12,8 @@ class DatabaseConnectionFactory { 'pgsql' => PostgresConnector(config), 'sqlite' => SQLiteConnector(config), _ => throw InvalidArgumentException( - "Unsupported driver [${config.driver}].", - ), + "Unsupported driver [${config.driver}].", + ), }; } } diff --git a/lib/src/database/_connectors/_database_connection_proxy.dart b/lib/src/database/_connectors/_database_connection_proxy.dart index 462a7e96..1b2a0022 100644 --- a/lib/src/database/_connectors/_database_connection_proxy.dart +++ b/lib/src/database/_connectors/_database_connection_proxy.dart @@ -23,8 +23,10 @@ class DatabaseConnectionProxy implements DatabaseConnection { String _formatQuery(String? query, Map bindings) { if (query == null) { - Logger.log('Warning: Null query received in _formatQuery', - type: Logger.WARNING); + Logger.log( + 'Warning: Null query received in _formatQuery', + type: Logger.WARNING, + ); return 'INVALID QUERY: NULL'; } @@ -61,8 +63,10 @@ class DatabaseConnectionProxy implements DatabaseConnection { } @override - Future execute(String query, - [Map bindings = const {}]) async { + Future execute( + String query, [ + Map bindings = const {}, + ]) async { final startTime = DateTime.now(); try { final formattedQuery = _formatQuery(query, bindings); @@ -72,15 +76,20 @@ class DatabaseConnectionProxy implements DatabaseConnection { return result; } catch (e) { final duration = DateTime.now().difference(startTime); - _monitor.recordQuery(_connectionId, - 'Failed: ${_formatQuery(query, bindings)} - Error: $e', duration); + _monitor.recordQuery( + _connectionId, + 'Failed: ${_formatQuery(query, bindings)} - Error: $e', + duration, + ); rethrow; } } @override - Future>> select(String query, - [Map bindings = const {}]) async { + Future>> select( + String query, [ + Map bindings = const {}, + ]) async { final startTime = DateTime.now(); try { final formattedQuery = _formatQuery(query, bindings); @@ -90,15 +99,20 @@ class DatabaseConnectionProxy implements DatabaseConnection { return result; } catch (e) { final duration = DateTime.now().difference(startTime); - _monitor.recordQuery(_connectionId, - 'Failed: ${_formatQuery(query, bindings)} - Error: $e', duration); + _monitor.recordQuery( + _connectionId, + 'Failed: ${_formatQuery(query, bindings)} - Error: $e', + duration, + ); rethrow; } } @override - Future insert(String query, - [Map bindings = const {}]) async { + Future insert( + String query, [ + Map bindings = const {}, + ]) async { final startTime = DateTime.now(); try { final formattedQuery = _formatQuery(query, bindings); @@ -108,8 +122,11 @@ class DatabaseConnectionProxy implements DatabaseConnection { return result; } catch (e) { final duration = DateTime.now().difference(startTime); - _monitor.recordQuery(_connectionId, - 'Failed: ${_formatQuery(query, bindings)} - Error: $e', duration); + _monitor.recordQuery( + _connectionId, + 'Failed: ${_formatQuery(query, bindings)} - Error: $e', + duration, + ); rethrow; } } diff --git a/lib/src/database/_database_utils/_paginated_result.dart b/lib/src/database/_database_utils/_paginated_result.dart index 145bb30f..9ad8e01a 100644 --- a/lib/src/database/_database_utils/_paginated_result.dart +++ b/lib/src/database/_database_utils/_paginated_result.dart @@ -22,15 +22,15 @@ class PaginatedResult { }); Map toMap() => { - 'data': data, - 'current_page': currentPage, - 'per_page': perPage, - 'total': total, - 'last_page': lastPage, - 'is_first': isFirst, - 'is_last': isLast, - 'has_more': hasMore, - }; + 'data': data, + 'current_page': currentPage, + 'per_page': perPage, + 'total': total, + 'last_page': lastPage, + 'is_first': isFirst, + 'is_last': isLast, + 'has_more': hasMore, + }; @override String toString() { diff --git a/lib/src/database/_database_utils/_singularize.dart b/lib/src/database/_database_utils/_singularize.dart index bb341dc7..5778bc3e 100644 --- a/lib/src/database/_database_utils/_singularize.dart +++ b/lib/src/database/_database_utils/_singularize.dart @@ -262,7 +262,7 @@ class Singularize { 'oases', 'parentheses', 'synopses', - 'theses' + 'theses', }; if (irregularPlurals.contains(name)) return true; diff --git a/lib/src/database/adapters/_mysql_connector.dart b/lib/src/database/adapters/_mysql_connector.dart index 3070d553..e4ab3d50 100644 --- a/lib/src/database/adapters/_mysql_connector.dart +++ b/lib/src/database/adapters/_mysql_connector.dart @@ -52,8 +52,10 @@ class MySqlConnector implements DatabaseConnection { } @override - Future execute(String query, - [Map bindings = const {}]) async { + Future execute( + String query, [ + Map bindings = const {}, + ]) async { try { await _connection.execute(query, bindings); return true; @@ -66,8 +68,9 @@ class MySqlConnector implements DatabaseConnection { Future transaction(Future Function() action) async { try { if (_isPool) { - return await (_connection as MySQLConnectionPool) - .transactional((txConn) async { + return await (_connection as MySQLConnectionPool).transactional(( + txConn, + ) async { final previous = _connection; _connection = txConn; _isPool = false; @@ -79,8 +82,9 @@ class MySqlConnector implements DatabaseConnection { } }); } else { - return await (_connection as MySQLConnection) - .transactional((txConn) async { + return await (_connection as MySQLConnection).transactional(( + txConn, + ) async { final previous = _connection; _connection = txConn; try { @@ -96,17 +100,23 @@ class MySqlConnector implements DatabaseConnection { } @override - Future>> select(String query, - [Map bindings = const {}]) async { + Future>> select( + String query, [ + Map bindings = const {}, + ]) async { try { final IResultSet results; if (_isPool) { - results = - await (_connection as MySQLConnectionPool).execute(query, bindings); + results = await (_connection as MySQLConnectionPool).execute( + query, + bindings, + ); } else { - results = - await (_connection as MySQLConnection).execute(query, bindings); + results = await (_connection as MySQLConnection).execute( + query, + bindings, + ); } if (results.rows.isEmpty) { return []; @@ -131,16 +141,22 @@ class MySqlConnector implements DatabaseConnection { } @override - Future insert(String query, - [Map bindings = const {}]) async { + Future insert( + String query, [ + Map bindings = const {}, + ]) async { try { final IResultSet results; if (_isPool) { - results = - await (_connection as MySQLConnectionPool).execute(query, bindings); + results = await (_connection as MySQLConnectionPool).execute( + query, + bindings, + ); } else { - results = - await (_connection as MySQLConnection).execute(query, bindings); + results = await (_connection as MySQLConnection).execute( + query, + bindings, + ); } return results.lastInsertID; } catch (e) { diff --git a/lib/src/database/adapters/_postgres_connector.dart b/lib/src/database/adapters/_postgres_connector.dart index 1da309a5..7df71ac3 100644 --- a/lib/src/database/adapters/_postgres_connector.dart +++ b/lib/src/database/adapters/_postgres_connector.dart @@ -69,15 +69,17 @@ class PostgresConnector implements DatabaseConnection { ), ); } else { - _connection = await Connection.open(endpoint, - settings: ConnectionSettings( - timeZone: config.timezone, - encoding: _getEncoding(config.collation), - sslMode: sslMode, - onOpen: (conn) async { - await _onOpen(conn, config); - }, - )); + _connection = await Connection.open( + endpoint, + settings: ConnectionSettings( + timeZone: config.timezone, + encoding: _getEncoding(config.collation), + sslMode: sslMode, + onOpen: (conn) async { + await _onOpen(conn, config); + }, + ), + ); } } catch (e) { throw DatabaseException('Database connection failed', e); @@ -85,8 +87,10 @@ class PostgresConnector implements DatabaseConnection { } @override - Future execute(String query, - [Map bindings = const {}]) async { + Future execute( + String query, [ + Map bindings = const {}, + ]) async { try { final result = await _connection.execute( Sql.named(query.replaceAll(':p', '@p')), @@ -99,15 +103,14 @@ class PostgresConnector implements DatabaseConnection { } @override - Future>> select(String query, - [Map bindings = const {}]) async { + Future>> select( + String query, [ + Map bindings = const {}, + ]) async { try { final sql = Sql.named(query.replaceAll(':p', '@p')); - final result = await _connection.execute( - sql, - parameters: bindings, - ); + final result = await _connection.execute(sql, parameters: bindings); final rows = result.map((row) => row.toColumnMap()).toList(); final maps = >[]; if (rows.isNotEmpty) { @@ -115,8 +118,9 @@ class PostgresConnector implements DatabaseConnection { final map = {}; for (final col in row.entries) { final key = col.key; - final value = - col.value is UndecodedBytes ? col.value.asString : col.value; + final value = col.value is UndecodedBytes + ? col.value.asString + : col.value; map.addAll({key: value}); } maps.add(map); @@ -129,8 +133,10 @@ class PostgresConnector implements DatabaseConnection { } @override - Future insert(String query, - [Map bindings = const {}]) async { + Future insert( + String query, [ + Map bindings = const {}, + ]) async { try { final result = await _connection.execute( Sql.named(query.replaceAll(':p', '@p')), diff --git a/lib/src/database/adapters/_sqlite_connector.dart b/lib/src/database/adapters/_sqlite_connector.dart index cc2a2010..5012df28 100644 --- a/lib/src/database/adapters/_sqlite_connector.dart +++ b/lib/src/database/adapters/_sqlite_connector.dart @@ -27,8 +27,9 @@ class SQLiteConnector implements DatabaseConnection { if (config.openInMemorySQLite) { _connection = sqlite3.openInMemory(); } else { - _connection = sqlite3 - .open(config.filePath ?? '${env('APP_NAME', 'Vania')}.db'); + _connection = sqlite3.open( + config.filePath ?? '${env('APP_NAME', 'Vania')}.db', + ); } } catch (e) { throw DatabaseException('Database connection failed', e); @@ -44,7 +45,9 @@ class SQLiteConnector implements DatabaseConnection { } List _convertBindingsToList( - Map bindings, String query) { + Map bindings, + String query, + ) { if (bindings.isEmpty) return []; final List result = []; @@ -62,15 +65,14 @@ class SQLiteConnector implements DatabaseConnection { } String _convertNamedParamsToPositional(String query) { - return query.replaceAllMapped( - RegExp(r':(\w+)'), - (match) => '?', - ); + return query.replaceAllMapped(RegExp(r':(\w+)'), (match) => '?'); } @override - Future execute(String query, - [Map bindings = const {}]) async { + Future execute( + String query, [ + Map bindings = const {}, + ]) async { try { final positionalQuery = _convertNamedParamsToPositional(query); final params = _convertBindingsToList(bindings, query); @@ -86,8 +88,10 @@ class SQLiteConnector implements DatabaseConnection { } @override - Future>> select(String query, - [Map bindings = const {}]) async { + Future>> select( + String query, [ + Map bindings = const {}, + ]) async { try { final positionalQuery = _convertNamedParamsToPositional(query); final params = _convertBindingsToList(bindings, query); @@ -114,8 +118,10 @@ class SQLiteConnector implements DatabaseConnection { } @override - Future insert(String query, - [Map bindings = const {}]) async { + Future insert( + String query, [ + Map bindings = const {}, + ]) async { try { final positionalQuery = _convertNamedParamsToPositional(query); final params = _convertBindingsToList(bindings, query); diff --git a/lib/src/database/isolate_db.dart b/lib/src/database/isolate_db.dart index 1bb14971..15d01453 100644 --- a/lib/src/database/isolate_db.dart +++ b/lib/src/database/isolate_db.dart @@ -25,10 +25,7 @@ class IsolateDB { openInMemorySQLite: dbConfig['openInMemorySQLite'] ?? false, ); try { - await ConnectionManager().connect( - config, - dbConfig['driver'], - ); + await ConnectionManager().connect(config, dbConfig['driver']); return await callback(); } finally { await ConnectionManager().connection(dbConfig['driver'])?.close(); diff --git a/lib/src/database/migration/adapters/grammar/postgresql_grammar.dart b/lib/src/database/migration/adapters/grammar/postgresql_grammar.dart index 648fe988..51051ac9 100644 --- a/lib/src/database/migration/adapters/grammar/postgresql_grammar.dart +++ b/lib/src/database/migration/adapters/grammar/postgresql_grammar.dart @@ -7,99 +7,99 @@ class PostgreSqlGrammar extends BaseGrammar { @override Map get dataTypeMappings => { - // Integer types - r'BIGINT\(\d+\)': 'BIGINT', - r'MEDIUMINT\(\d+\)': 'INTEGER', - r'SMALLINT\(\d+\)': 'SMALLINT', - r'TINYINT\(\d+\)': 'SMALLINT', - - // Binary types - r'BINARY\(\d+\)': 'BYTEA', - r'VARBINARY\(\d+\)': 'BYTEA', - r'BIT\(\d+\)': 'BOOLEAN', - - // Date/time types - r'DATETIME\(\d+\)': 'TIMESTAMP', - r'TIME\(\d+\)': 'TIME', - - // Floating point types - r'DOUBLE\(\d+\)': 'DOUBLE PRECISION', - - // BLOB types - 'TINYBLOB': 'BYTEA', - 'BLOB': 'BYTEA', - 'MEDIUMBLOB': 'BYTEA', - 'LONGBLOB': 'BYTEA', - 'VARBYTEA': 'BYTEA', - 'MEDIUMBYTEA': 'BYTEA', - 'LONGBYTEA': 'BYTEA', - - // Text types - 'TINYTEXT': 'TEXT', - 'MEDIUMTEXT': 'TEXT', - r'LONGTEXT\(\d+\)': 'TEXT', - - // Geometry types - 'LINESTRING': 'LINE', - }; + // Integer types + r'BIGINT\(\d+\)': 'BIGINT', + r'MEDIUMINT\(\d+\)': 'INTEGER', + r'SMALLINT\(\d+\)': 'SMALLINT', + r'TINYINT\(\d+\)': 'SMALLINT', + + // Binary types + r'BINARY\(\d+\)': 'BYTEA', + r'VARBINARY\(\d+\)': 'BYTEA', + r'BIT\(\d+\)': 'BOOLEAN', + + // Date/time types + r'DATETIME\(\d+\)': 'TIMESTAMP', + r'TIME\(\d+\)': 'TIME', + + // Floating point types + r'DOUBLE\(\d+\)': 'DOUBLE PRECISION', + + // BLOB types + 'TINYBLOB': 'BYTEA', + 'BLOB': 'BYTEA', + 'MEDIUMBLOB': 'BYTEA', + 'LONGBLOB': 'BYTEA', + 'VARBYTEA': 'BYTEA', + 'MEDIUMBYTEA': 'BYTEA', + 'LONGBYTEA': 'BYTEA', + + // Text types + 'TINYTEXT': 'TEXT', + 'MEDIUMTEXT': 'TEXT', + r'LONGTEXT\(\d+\)': 'TEXT', + + // Geometry types + 'LINESTRING': 'LINE', + }; @override Map get keywordReplacements => { - 'UNSIGNED': '', - 'ZEROFILL': '', - 'AUTO_INCREMENT': '', - r"COLLATE '[\w\d_-]+'": '', - r"ENGINE\s*=\s*\w+": '', - r"COMMENT\s+'[^']*'": '', - }; + 'UNSIGNED': '', + 'ZEROFILL': '', + 'AUTO_INCREMENT': '', + r"COLLATE '[\w\d_-]+'": '', + r"ENGINE\s*=\s*\w+": '', + r"COMMENT\s+'[^']*'": '', + }; @override Map get regexTransformations => { - // Auto-increment primary key transformation - handle table.id() pattern - r'[`"](\w+)[`"]\s+BIGINT(?:\(\d+\))?\s+(?:UNSIGNED\s+)?NOT\s+NULL\s+AUTO_INCREMENT': - (match) => '"${match[1]}" SERIAL NOT NULL PRIMARY KEY', - - r'\s+ON\s+UPDATE\s+CURRENT_TIMESTAMP': (match) => '', - r'ON\s+UPDATE\s+CURRENT_TIMESTAMP': (match) => '', - - // Handle `BIGINT` NOT NULL without AUTO_INCREMENT but with separate PRIMARY KEY - r'[`"](\w+)[`"]\s+BIGINT(?:\(\d+\))?\s+(?:UNSIGNED\s+)?NOT\s+NULL(?!\s+AUTO_INCREMENT)': - (match) => '"${match[1]}" BIGINT NOT NULL', - - // Remove primary key declarations when SERIAL is used - r',\s*PRIMARY KEY \([`"][^`"]+[`"]\)': (match) => '', - r'PRIMARY KEY \([`"][^`"]+[`"]\)\s*,?': (match) => '', - - // Remove INDEX declarations - more comprehensive patterns - r',\s*INDEX\s+[`"][^`"]*[`"]\s*\([^)]*\)': (match) => '', - r'INDEX\s+[`"][^`"]*[`"]\s*\([^)]*\)\s*,': (match) => '', - r'INDEX\s+[`"][^`"]*[`"]\s*\([^)]*\)': (match) => '', - - // Remove CONSTRAINT UNIQUE (will be handled by adapter) - r',\s*CONSTRAINT\s+[`"][^`"]*[`"]\s+UNIQUE\s*\([^)]*\)': (match) => '', - r'CONSTRAINT\s+[`"][^`"]*[`"]\s+UNIQUE\s*\([^)]*\)\s*,': (match) => '', - r'CONSTRAINT\s+[`"][^`"]*[`"]\s+UNIQUE\s*\([^)]*\)': (match) => '', - - // Integer type with length - r'(^|\s|,)INT\((\d+)\)': (match) => '${match[1]}INTEGER', - r'(^|\s|,)INTEGER\((\d+)\)': (match) => '${match[1]}INTEGER', - - // VARCHAR with length preservation - r'VARCHAR\((\d+)\)': (match) => 'VARCHAR(${match[1]})', - r'VARCHARACTER\((\d+)\)': (match) => 'CHARACTER(${match[1]})', - - // FLOAT conversion - r'FLOAT\((\d+)\)': (match) => 'REAL', - - // ENUM to VARCHAR conversion - r"ENUM\((?:'[^']*'(?:\s*,\s*'[^']*')*)\)": (match) => 'VARCHAR', - - // Clean up empty spaces and commas that result from removals - r',\s*,+': (match) => ',', - r'^\s*,': (match) => '', - r',\s*\)': (match) => ')', - r'\(\s*,': (match) => '(', - }; + // Auto-increment primary key transformation - handle table.id() pattern + r'[`"](\w+)[`"]\s+BIGINT(?:\(\d+\))?\s+(?:UNSIGNED\s+)?NOT\s+NULL\s+AUTO_INCREMENT': + (match) => '"${match[1]}" SERIAL NOT NULL PRIMARY KEY', + + r'\s+ON\s+UPDATE\s+CURRENT_TIMESTAMP': (match) => '', + r'ON\s+UPDATE\s+CURRENT_TIMESTAMP': (match) => '', + + // Handle `BIGINT` NOT NULL without AUTO_INCREMENT but with separate PRIMARY KEY + r'[`"](\w+)[`"]\s+BIGINT(?:\(\d+\))?\s+(?:UNSIGNED\s+)?NOT\s+NULL(?!\s+AUTO_INCREMENT)': + (match) => '"${match[1]}" BIGINT NOT NULL', + + // Remove primary key declarations when SERIAL is used + r',\s*PRIMARY KEY \([`"][^`"]+[`"]\)': (match) => '', + r'PRIMARY KEY \([`"][^`"]+[`"]\)\s*,?': (match) => '', + + // Remove INDEX declarations - more comprehensive patterns + r',\s*INDEX\s+[`"][^`"]*[`"]\s*\([^)]*\)': (match) => '', + r'INDEX\s+[`"][^`"]*[`"]\s*\([^)]*\)\s*,': (match) => '', + r'INDEX\s+[`"][^`"]*[`"]\s*\([^)]*\)': (match) => '', + + // Remove CONSTRAINT UNIQUE (will be handled by adapter) + r',\s*CONSTRAINT\s+[`"][^`"]*[`"]\s+UNIQUE\s*\([^)]*\)': (match) => '', + r'CONSTRAINT\s+[`"][^`"]*[`"]\s+UNIQUE\s*\([^)]*\)\s*,': (match) => '', + r'CONSTRAINT\s+[`"][^`"]*[`"]\s+UNIQUE\s*\([^)]*\)': (match) => '', + + // Integer type with length + r'(^|\s|,)INT\((\d+)\)': (match) => '${match[1]}INTEGER', + r'(^|\s|,)INTEGER\((\d+)\)': (match) => '${match[1]}INTEGER', + + // VARCHAR with length preservation + r'VARCHAR\((\d+)\)': (match) => 'VARCHAR(${match[1]})', + r'VARCHARACTER\((\d+)\)': (match) => 'CHARACTER(${match[1]})', + + // FLOAT conversion + r'FLOAT\((\d+)\)': (match) => 'REAL', + + // ENUM to VARCHAR conversion + r"ENUM\((?:'[^']*'(?:\s*,\s*'[^']*')*)\)": (match) => 'VARCHAR', + + // Clean up empty spaces and commas that result from removals + r',\s*,+': (match) => ',', + r'^\s*,': (match) => '', + r',\s*\)': (match) => ')', + r'\(\s*,': (match) => '(', + }; @override String convertQuery(String query) { diff --git a/lib/src/database/migration/adapters/grammar/sqlite_grammar.dart b/lib/src/database/migration/adapters/grammar/sqlite_grammar.dart index cdfcd168..55c2cace 100644 --- a/lib/src/database/migration/adapters/grammar/sqlite_grammar.dart +++ b/lib/src/database/migration/adapters/grammar/sqlite_grammar.dart @@ -6,76 +6,76 @@ class SqliteGrammar extends BaseGrammar { @override Map get dataTypeMappings => { - // Integer types - SQLite uses INTEGER for all integer types - r'BIGINT\(\d+\)': 'INTEGER', - r'MEDIUMINT\(\d+\)': 'INTEGER', - r'SMALLINT\(\d+\)': 'INTEGER', - r'TINYINT\(\d+\)': 'INTEGER', - - // Binary and bit types - r'BINARY\(\d+\)': 'BLOB', - r'VARBINARY\(\d+\)': 'BLOB', - r'BIT\(\d+\)': 'INTEGER', - - // String types - SQLite uses TEXT for all string types - r'VARCHAR\(\d+\)': 'TEXT', - r'CHAR\(\d+\)': 'TEXT', - - // Date/time types - SQLite stores as TEXT or INTEGER - 'DATETIME': 'TEXT', - 'TIMESTAMP': 'TEXT', - 'DATE': 'TEXT', - 'TIME': 'TEXT', - 'YEAR': 'INTEGER', - - // BLOB types - 'TINYBLOB': 'BLOB', - 'BLOB': 'BLOB', - 'MEDIUMBLOB': 'BLOB', - 'LONGBLOB': 'BLOB', - - // Text types - 'TINYTEXT': 'TEXT', - 'MEDIUMTEXT': 'TEXT', - 'LONGTEXT': 'TEXT', - - // JSON - SQLite stores as TEXT - 'JSON': 'TEXT', - }; + // Integer types - SQLite uses INTEGER for all integer types + r'BIGINT\(\d+\)': 'INTEGER', + r'MEDIUMINT\(\d+\)': 'INTEGER', + r'SMALLINT\(\d+\)': 'INTEGER', + r'TINYINT\(\d+\)': 'INTEGER', + + // Binary and bit types + r'BINARY\(\d+\)': 'BLOB', + r'VARBINARY\(\d+\)': 'BLOB', + r'BIT\(\d+\)': 'INTEGER', + + // String types - SQLite uses TEXT for all string types + r'VARCHAR\(\d+\)': 'TEXT', + r'CHAR\(\d+\)': 'TEXT', + + // Date/time types - SQLite stores as TEXT or INTEGER + 'DATETIME': 'TEXT', + 'TIMESTAMP': 'TEXT', + 'DATE': 'TEXT', + 'TIME': 'TEXT', + 'YEAR': 'INTEGER', + + // BLOB types + 'TINYBLOB': 'BLOB', + 'BLOB': 'BLOB', + 'MEDIUMBLOB': 'BLOB', + 'LONGBLOB': 'BLOB', + + // Text types + 'TINYTEXT': 'TEXT', + 'MEDIUMTEXT': 'TEXT', + 'LONGTEXT': 'TEXT', + + // JSON - SQLite stores as TEXT + 'JSON': 'TEXT', + }; @override Map get keywordReplacements => { - 'UNSIGNED': '', - 'ZEROFILL': '', - 'AUTO_INCREMENT': '', - r"COLLATE\s+'[^']+'": '', - r"ENGINE\s*=\s*\w+": '', - r"COLLATE\s*=\s*'[^']+'": '', - }; + 'UNSIGNED': '', + 'ZEROFILL': '', + 'AUTO_INCREMENT': '', + r"COLLATE\s+'[^']+'": '', + r"ENGINE\s*=\s*\w+": '', + r"COLLATE\s*=\s*'[^']+'": '', + }; @override Map get regexTransformations => { - // Auto-increment primary key transformation - r'`(\w+)`\s+BIGINT\(\d+\)\s+UNSIGNED\s+NOT\s+NULL\s+AUTO_INCREMENT': - (match) => '"${match[1]}" INTEGER PRIMARY KEY AUTOINCREMENT', + // Auto-increment primary key transformation + r'`(\w+)`\s+BIGINT\(\d+\)\s+UNSIGNED\s+NOT\s+NULL\s+AUTO_INCREMENT': + (match) => '"${match[1]}" INTEGER PRIMARY KEY AUTOINCREMENT', - // Remove primary key declarations (handled by AUTOINCREMENT) - r'PRIMARY KEY \(`.*?`\) USING BTREE': (match) => '', - r'PRIMARY KEY \(`.*?`\)': (match) => '', + // Remove primary key declarations (handled by AUTOINCREMENT) + r'PRIMARY KEY \(`.*?`\) USING BTREE': (match) => '', + r'PRIMARY KEY \(`.*?`\)': (match) => '', - // Integer type with length - r'(^|\s|,)INT\((\d+)\)': (match) => '${match[1]}INTEGER', - r'(^|\s|,)INTEGER\((\d+)\)': (match) => '${match[1]}INTEGER', + // Integer type with length + r'(^|\s|,)INT\((\d+)\)': (match) => '${match[1]}INTEGER', + r'(^|\s|,)INTEGER\((\d+)\)': (match) => '${match[1]}INTEGER', - // Floating point types - r'FLOAT\((\d+),(\d+)\)': (match) => 'REAL', - r'DOUBLE\((\d+),(\d+)\)': (match) => 'REAL', - r'DECIMAL\((\d+),(\d+)\)': (match) => 'REAL', + // Floating point types + r'FLOAT\((\d+),(\d+)\)': (match) => 'REAL', + r'DOUBLE\((\d+),(\d+)\)': (match) => 'REAL', + r'DECIMAL\((\d+),(\d+)\)': (match) => 'REAL', - // ENUM - SQLite doesn't have ENUM, use TEXT with CHECK constraint - r'ENUM\(([^)]+)\)': (match) => - 'TEXT CHECK (${_extractColumnName()} IN (${match[1]}))', - }; + // ENUM - SQLite doesn't have ENUM, use TEXT with CHECK constraint + r'ENUM\(([^)]+)\)': (match) => + 'TEXT CHECK (${_extractColumnName()} IN (${match[1]}))', + }; String _extractColumnName() { return 'column_name'; @@ -93,9 +93,10 @@ class SqliteGrammar extends BaseGrammar { } String _handleEnumConstraints(String originalQuery, String convertedQuery) { - final enumMatch = - RegExp(r'"?(\w+)"?\s+ENUM\(([^)]+)\)', caseSensitive: false) - .firstMatch(originalQuery); + final enumMatch = RegExp( + r'"?(\w+)"?\s+ENUM\(([^)]+)\)', + caseSensitive: false, + ).firstMatch(originalQuery); if (enumMatch != null) { final columnName = enumMatch.group(1); diff --git a/lib/src/database/migration/adapters/postgresql_adapter.dart b/lib/src/database/migration/adapters/postgresql_adapter.dart index e23e6fda..f0f28758 100644 --- a/lib/src/database/migration/adapters/postgresql_adapter.dart +++ b/lib/src/database/migration/adapters/postgresql_adapter.dart @@ -37,7 +37,9 @@ class PostgreSqlAdapter implements DatabaseAdapterInterface { } Future executeStatements( - String query, Future Function(List) executor) async { + String query, + Future Function(List) executor, + ) async { List statements = adaptQueryToStatements(query); await executor(statements); } @@ -98,12 +100,16 @@ class PostgreSqlAdapter implements DatabaseAdapterInterface { final cols = parts[1]; final typeKey = parts.length > 2 ? parts[2] : ''; - final colList = - cols.split(',').map((c) => '"${c.trim()}"').toList().join(', '); + final colList = cols + .split(',') + .map((c) => '"${c.trim()}"') + .toList() + .join(', '); final prefix = typeKey.isNotEmpty ? '$typeKey ' : ''; - final stmt = 'CREATE ${prefix}INDEX IF NOT EXISTS "$name" ' + final stmt = + 'CREATE ${prefix}INDEX IF NOT EXISTS "$name" ' 'ON "$_currentTableName" ($colList)'; statements.add(stmt); } diff --git a/lib/src/database/migration/builders/column_definition.dart b/lib/src/database/migration/builders/column_definition.dart index 7b8d14a9..53c8da43 100644 --- a/lib/src/database/migration/builders/column_definition.dart +++ b/lib/src/database/migration/builders/column_definition.dart @@ -113,8 +113,10 @@ class ColumnDefinition { } /// Add index to column - NOW PROPERLY USED! - ColumnDefinition index( - [String? indexName, ColumnIndex type = ColumnIndex.indexKey]) { + ColumnDefinition index([ + String? indexName, + ColumnIndex type = ColumnIndex.indexKey, + ]) { _indexName = indexName ?? 'idx_${_schema.tableName}_$_name'; _indexType = type; @@ -122,8 +124,12 @@ class ColumnDefinition { return this; } - ColumnDefinition foreignKey(String referencesTable, String referencesColumn, - {String onUpdate = 'CASCADE', String onDelete = 'CASCADE'}) { + ColumnDefinition foreignKey( + String referencesTable, + String referencesColumn, { + String onUpdate = 'CASCADE', + String onDelete = 'CASCADE', + }) { _foreignTable = referencesTable; _foreignColumn = referencesColumn; _onUpdate = onUpdate; @@ -139,8 +145,10 @@ class ColumnDefinition { return this; } - ColumnDefinition generated(String expression, - {String virtuality = 'VIRTUAL'}) { + ColumnDefinition generated( + String expression, { + String virtuality = 'VIRTUAL', + }) { _expression = expression; _virtuality = virtuality; return this; @@ -162,8 +170,9 @@ class ColumnDefinition { String? finalComment = _comment; if (_charset != null) { String charsetInfo = 'charset: $_charset'; - finalComment = - _comment != null ? '$_comment ($charsetInfo)' : charsetInfo; + finalComment = _comment != null + ? '$_comment ($charsetInfo)' + : charsetInfo; } bool shouldBeUnique = _unique && _uniqueConstraintName == null; diff --git a/lib/src/database/migration/builders/column_types.dart b/lib/src/database/migration/builders/column_types.dart index a3d2a069..b75f6edd 100644 --- a/lib/src/database/migration/builders/column_types.dart +++ b/lib/src/database/migration/builders/column_types.dart @@ -7,22 +7,22 @@ export 'table_definition.dart'; extension ColumnTypes on Schema { /// Add an auto-incrementing primary key column ColumnDefinition id([String name = 'id']) { - final definition = ColumnDefinition(this, name, 'BIGINT') - .length(20) - .unsigned() - .autoIncrement() - .notNull(); + final definition = ColumnDefinition( + this, + name, + 'BIGINT', + ).length(20).unsigned().autoIncrement().notNull(); primary(name); return definition; } /// Add a big auto-incrementing column ColumnDefinition bigIncrements(String name) { - final definition = ColumnDefinition(this, name, 'BIGINT') - .length(20) - .unsigned() - .autoIncrement() - .notNull(); + final definition = ColumnDefinition( + this, + name, + 'BIGINT', + ).length(20).unsigned().autoIncrement().notNull(); return definition; } diff --git a/lib/src/database/migration/builders/schema.dart b/lib/src/database/migration/builders/schema.dart index dbc4d4f1..60e88776 100644 --- a/lib/src/database/migration/builders/schema.dart +++ b/lib/src/database/migration/builders/schema.dart @@ -46,10 +46,12 @@ class Schema implements SchemaInterface { if (type == ColumnIndex.indexKey) { _indexes.add( - 'INDEX `$indexName` (${columns.map((e) => "`$e`").join(', ')})'); + 'INDEX `$indexName` (${columns.map((e) => "`$e`").join(', ')})', + ); } else { _indexes.add( - '${type.name} INDEX `$indexName` (${columns.map((e) => "`$e`").join(', ')})'); + '${type.name} INDEX `$indexName` (${columns.map((e) => "`$e`").join(', ')})', + ); } }); } @@ -85,8 +87,9 @@ class Schema implements SchemaInterface { } String nullableStr = nullable ? 'NULL' : 'NOT NULL'; - columnDefinition - .write(' ' * (20 - columnDefinition.length % 20) + nullableStr); + columnDefinition.write( + ' ' * (20 - columnDefinition.length % 20) + nullableStr, + ); if (unique) { columnDefinition.write(' UNIQUE'); @@ -94,8 +97,9 @@ class Schema implements SchemaInterface { if (defaultValue != null) { RegExp funcRegex = RegExp( - r'^(CURRENT_TIMESTAMP|NOW\(\)|UUID\(\)|RAND\(\))$', - caseSensitive: false); + r'^(CURRENT_TIMESTAMP|NOW\(\)|UUID\(\)|RAND\(\))$', + caseSensitive: false, + ); if (funcRegex.hasMatch(defaultValue.toString())) { columnDefinition.write(" DEFAULT $defaultValue"); @@ -147,7 +151,8 @@ class Schema implements SchemaInterface { _indexes.add('INDEX `$name` (${columns.map((e) => "`$e`").join(',')})'); } else { _indexes.add( - '${type.name.toUpperCase()} INDEX `$name` (${columns.map((e) => "`$e`").join(',')})'); + '${type.name.toUpperCase()} INDEX `$name` (${columns.map((e) => "`$e`").join(',')})', + ); } } @@ -201,7 +206,9 @@ class Schema implements SchemaInterface { } void addCompositeUniqueConstraint( - String constraintName, List columns) { + String constraintName, + List columns, + ) { if (_compositeUniqueConstraints.containsKey(constraintName)) { _compositeUniqueConstraints[constraintName]!.addAll(columns); } else { @@ -210,7 +217,10 @@ class Schema implements SchemaInterface { } void addCompositeIndex( - String indexName, String columnName, ColumnIndex type) { + String indexName, + String columnName, + ColumnIndex type, + ) { if (_compositeIndexes.containsKey(indexName)) { _compositeIndexes[indexName]!['columns'].add(columnName); } else { @@ -225,8 +235,9 @@ class Schema implements SchemaInterface { _finalizeColumnDefinitions(); final query = StringBuffer(); - String createClause = - ifNotExists ? 'CREATE TABLE IF NOT EXISTS' : 'CREATE TABLE'; + String createClause = ifNotExists + ? 'CREATE TABLE IF NOT EXISTS' + : 'CREATE TABLE'; query.writeln('$createClause `$tableName` ('); diff --git a/lib/src/database/migration/builders/table_definition.dart b/lib/src/database/migration/builders/table_definition.dart index ba45534b..448a8de5 100644 --- a/lib/src/database/migration/builders/table_definition.dart +++ b/lib/src/database/migration/builders/table_definition.dart @@ -20,8 +20,8 @@ class TableDefinition implements Future { this._createFunction, { MigrationConnection? connection, DatabaseAdapterInterface? adapter, - }) : _connection = connection, - _adapter = adapter; + }) : _connection = connection, + _adapter = adapter; TableDefinition engine(String engine) { _engine = engine; @@ -54,14 +54,18 @@ class TableDefinition implements Future { } @override - Future then(FutureOr Function(void value) onValue, - {Function? onError}) { + Future then( + FutureOr Function(void value) onValue, { + Function? onError, + }) { return _getExecutionFuture().then(onValue, onError: onError); } @override - Future catchError(Function onError, - {bool Function(Object error)? test}) { + Future catchError( + Function onError, { + bool Function(Object error)? test, + }) { return _getExecutionFuture().catchError(onError, test: test); } diff --git a/lib/src/database/migration/migration.dart b/lib/src/database/migration/migration.dart index 73e96bef..ee102e03 100644 --- a/lib/src/database/migration/migration.dart +++ b/lib/src/database/migration/migration.dart @@ -27,22 +27,28 @@ abstract class Migration { @mustBeOverridden Future down(); - TableDefinition create(String tableName, Function(Schema) callback, - [bool ifNotExists = false]) { + TableDefinition create( + String tableName, + Function(Schema) callback, [ + bool ifNotExists = false, + ]) { _schemaBuilder.reset(); _schemaBuilder.setTableName(tableName); Future createFunction() async { callback(_schemaBuilder); - String sql = _schemaBuilder.generateCreateTableSql(tableName, - ifNotExists: ifNotExists); + String sql = _schemaBuilder.generateCreateTableSql( + tableName, + ifNotExists: ifNotExists, + ); if (_adapter != null && _adapter.driverName == 'pgsql') { final postgresAdapter = _adapter as dynamic; if (postgresAdapter.executeStatements != null) { - await postgresAdapter.executeStatements(sql, - (List statements) async { + await postgresAdapter.executeStatements(sql, ( + List statements, + ) async { for (String statement in statements) { await _connection.connection!.execute(statement); } @@ -57,33 +63,40 @@ abstract class Migration { try { await _connection.connection!.execute(sql); } on QueryException catch (e) { - stderr.writeln( - 'Error executing statement: $sql\nError: ${e.cause}', - ); + stderr.writeln('Error executing statement: $sql\nError: ${e.cause}'); exit(0); } } - return TableDefinition(tableName, createFunction, - connection: _connection, adapter: _adapter); + return TableDefinition( + tableName, + createFunction, + connection: _connection, + adapter: _adapter, + ); } @Deprecated('createTableIfNotExists will be deprecated in version 1.1.0') TableDefinition createTableIfNotExists( - String tableName, Function(Schema) callback) { + String tableName, + Function(Schema) callback, + ) { _schemaBuilder.reset(); _schemaBuilder.setTableName(tableName); Future createFunction() async { callback(_schemaBuilder); - String sql = - _schemaBuilder.generateCreateTableSql(tableName, ifNotExists: true); + String sql = _schemaBuilder.generateCreateTableSql( + tableName, + ifNotExists: true, + ); if (_adapter != null && _adapter.driverName == 'pgsql') { final postgresAdapter = _adapter as dynamic; if (postgresAdapter.executeStatements != null) { - await postgresAdapter.executeStatements(sql, - (String statement) async { + await postgresAdapter.executeStatements(sql, ( + String statement, + ) async { try { await _connection.connection!.execute(statement); } on QueryException catch (e) { @@ -103,15 +116,17 @@ abstract class Migration { try { await _connection.connection!.execute(sql); } on QueryException catch (e) { - stderr.writeln( - 'Error executing statement: $sql\nError: ${e.cause}', - ); + stderr.writeln('Error executing statement: $sql\nError: ${e.cause}'); exit(0); } } - return TableDefinition(tableName, createFunction, - connection: _connection, adapter: _adapter); + return TableDefinition( + tableName, + createFunction, + connection: _connection, + adapter: _adapter, + ); } TableDefinition alterColumn( @@ -136,15 +151,17 @@ abstract class Migration { } await _connection.connection!.execute(sql); } on QueryException catch (e) { - stderr.writeln( - '${e.cause}', - ); + stderr.writeln('${e.cause}'); exit(0); } } - return TableDefinition(table, createFunction, - connection: _connection, adapter: _adapter); + return TableDefinition( + table, + createFunction, + connection: _connection, + adapter: _adapter, + ); } Future drop(String tableName) async { @@ -166,9 +183,7 @@ abstract class Migration { try { await _connection.connection!.execute(sql); } on QueryException catch (e) { - stderr.writeln( - 'Error executing statement: $sql\nError: ${e.cause}', - ); + stderr.writeln('Error executing statement: $sql\nError: ${e.cause}'); exit(0); } } @@ -189,9 +204,7 @@ abstract class Migration { try { await _connection.connection!.execute(sql); } on QueryException catch (e) { - stderr.writeln( - 'Error executing statement: $sql\nError: ${e.cause}', - ); + stderr.writeln('Error executing statement: $sql\nError: ${e.cause}'); exit(0); } } @@ -204,9 +217,7 @@ abstract class Migration { try { await _connection.connection!.execute(sql); } on QueryException catch (e) { - stderr.writeln( - 'Error executing statement: $sql\nError: ${e.cause}', - ); + stderr.writeln('Error executing statement: $sql\nError: ${e.cause}'); exit(0); } } diff --git a/lib/src/database/migration/runners/migration_runner.dart b/lib/src/database/migration/runners/migration_runner.dart index 21a4f3fc..48dfe3ce 100644 --- a/lib/src/database/migration/runners/migration_runner.dart +++ b/lib/src/database/migration/runners/migration_runner.dart @@ -26,14 +26,16 @@ class MigrationRunner { stopwatch.stop(); stderr.writeln( - ' Migration $migrationName executed ....................................\x1B[32m ${stopwatch.elapsedMilliseconds}ms DONE\x1B[0m'); + ' Migration $migrationName executed ....................................\x1B[32m ${stopwatch.elapsedMilliseconds}ms DONE\x1B[0m', + ); } catch (e) { stopwatch.stop(); if (e is QueryException) { stderr.write(e.cause); } stderr.writeln( - '❌ Migration $migrationName failed ......................................\x1B[31m ${stopwatch.elapsedMilliseconds}ms FAILED\x1B[0m'); + '❌ Migration $migrationName failed ......................................\x1B[31m ${stopwatch.elapsedMilliseconds}ms FAILED\x1B[0m', + ); exit(1); } } @@ -51,9 +53,7 @@ class MigrationRunner { Future run(List args) async { if (MigrationConnection().connection == null) { - stderr.writeln( - 'Database connection not established', - ); + stderr.writeln('Database connection not established'); exit(1); } if (args.contains('--fresh')) { @@ -81,7 +81,9 @@ class MigrationRunner { } Future _runDown( - String migrationName, Function migrationCallback) async { + String migrationName, + Function migrationCallback, + ) async { final stopwatch = Stopwatch()..start(); try { @@ -90,34 +92,35 @@ class MigrationRunner { stopwatch.stop(); stderr.writeln( - ' Migration $migrationName rolled back....................................\x1B[32m ${stopwatch.elapsedMilliseconds}ms DONE\x1B[0m'); + ' Migration $migrationName rolled back....................................\x1B[32m ${stopwatch.elapsedMilliseconds}ms DONE\x1B[0m', + ); } catch (e) { stopwatch.stop(); stderr.writeln( - ' Migration $migrationName failed ......................................\x1B[31m ${stopwatch.elapsedMilliseconds}ms FAILED\x1B[0m'); + ' Migration $migrationName failed ......................................\x1B[31m ${stopwatch.elapsedMilliseconds}ms FAILED\x1B[0m', + ); exit(1); } } Future _isMigrationExecuted(String migrationName) async { if (MigrationConnection().connection == null) { - stderr.writeln( - 'Database connection not established', - ); + stderr.writeln('Database connection not established'); exit(1); } try { final snakeCaseName = toSnakeCase(migrationName); - final result = await MigrationConnection() - .connection! - .select("SELECT id FROM migrations WHERE migration='$snakeCaseName'"); + final result = await MigrationConnection().connection!.select( + "SELECT id FROM migrations WHERE migration='$snakeCaseName'", + ); return result.isNotEmpty; } catch (e) { if (e is QueryException) { - stderr - .writeln('❌ Failed to check if migration is executed: ${e.cause}'); + stderr.writeln( + '❌ Failed to check if migration is executed: ${e.cause}', + ); } else { stderr.writeln('❌ Failed to check if migration is executed: $e'); } @@ -126,11 +129,11 @@ class MigrationRunner { } Future _recordMigrationWithBatch( - String migrationName, int batch) async { + String migrationName, + int batch, + ) async { if (MigrationConnection().connection == null) { - stderr.writeln( - 'Database connection not established', - ); + stderr.writeln('Database connection not established'); exit(1); } @@ -160,9 +163,7 @@ class MigrationRunner { Future _removeMigrationRecord(String migrationName) async { if (MigrationConnection().connection == null) { - stderr.writeln( - 'Database connection not established', - ); + stderr.writeln('Database connection not established'); exit(1); } @@ -198,9 +199,7 @@ class MigrationRunner { Future _getCurrentBatchNumber() async { if (MigrationConnection().connection == null) { - stderr.writeln( - 'Database connection not established', - ); + stderr.writeln('Database connection not established'); exit(1); } @@ -287,8 +286,8 @@ class MigrationRunner { try { if (MigrationConnection().adapter != null) { - String migrationSql = - MigrationConnection().adapter!.getMigrationsTableSql(); + String migrationSql = MigrationConnection().adapter! + .getMigrationsTableSql(); await MigrationConnection().connection!.execute(migrationSql); stderr.writeln('✅ Migration repository installed successfully!'); } else { @@ -410,9 +409,7 @@ class MigrationRunner { Future> _getAllMigrationsInReverseOrder() async { if (MigrationConnection().connection == null) { - stderr.writeln( - 'Database connection not established', - ); + stderr.writeln('Database connection not established'); exit(1); } @@ -438,9 +435,7 @@ class MigrationRunner { Future> _getLastNMigrations(int n) async { if (MigrationConnection().connection == null) { - stderr.writeln( - 'Database connection not established', - ); + stderr.writeln('Database connection not established'); exit(1); } diff --git a/lib/src/database/monitoring/database_monitor.dart b/lib/src/database/monitoring/database_monitor.dart index 43e00304..864b516d 100644 --- a/lib/src/database/monitoring/database_monitor.dart +++ b/lib/src/database/monitoring/database_monitor.dart @@ -1,12 +1,7 @@ import 'dart:async'; import 'package:meta/meta.dart'; -enum AlertType { - slowQuery, - highConnectionUsage, - connectionError, - deadlock, -} +enum AlertType { slowQuery, highConnectionUsage, connectionError, deadlock } class DatabaseAlert { final AlertType type; @@ -73,15 +68,17 @@ class DatabaseMonitor { // Check for slow queries if (executionTime > slowQueryThreshold) { - _alertController.add(DatabaseAlert( - type: AlertType.slowQuery, - message: 'Slow query detected', - details: { - 'sql': sql, - 'execution_time': executionTime.inMilliseconds, - 'threshold': slowQueryThreshold.inMilliseconds, - }, - )); + _alertController.add( + DatabaseAlert( + type: AlertType.slowQuery, + message: 'Slow query detected', + details: { + 'sql': sql, + 'execution_time': executionTime.inMilliseconds, + 'threshold': slowQueryThreshold.inMilliseconds, + }, + ), + ); } if (_queryMetrics[connectionId]!.length > 1000) { @@ -93,15 +90,17 @@ class DatabaseMonitor { _connectionMetrics[connectionId] = metrics; if (metrics.usagePercentage > highConnectionUsageThreshold) { - _alertController.add(DatabaseAlert( - type: AlertType.highConnectionUsage, - message: 'High connection pool usage detected', - details: { - 'usage_percentage': metrics.usagePercentage, - 'active_connections': metrics.activeConnections, - 'max_connections': metrics.maxConnections, - }, - )); + _alertController.add( + DatabaseAlert( + type: AlertType.highConnectionUsage, + message: 'High connection pool usage detected', + details: { + 'usage_percentage': metrics.usagePercentage, + 'active_connections': metrics.activeConnections, + 'max_connections': metrics.maxConnections, + }, + ), + ); } } @@ -124,12 +123,13 @@ class DatabaseMonitor { (sum, metric) => sum + metric.executionTime, ); - final peakTime = queries.map((m) => m.executionTime).reduce( - (max, time) => time > max ? time : max, - ); + final peakTime = queries + .map((m) => m.executionTime) + .reduce((max, time) => time > max ? time : max); - final slowCount = - queries.where((m) => m.executionTime > slowQueryThreshold).length; + final slowCount = queries + .where((m) => m.executionTime > slowQueryThreshold) + .length; stats[entry.key] = PerformanceStats( averageQueryTime: totalTime ~/ queries.length, diff --git a/lib/src/database/orm/belongs_to.dart b/lib/src/database/orm/belongs_to.dart index 43026d7d..8123f8ff 100644 --- a/lib/src/database/orm/belongs_to.dart +++ b/lib/src/database/orm/belongs_to.dart @@ -13,12 +13,11 @@ class BelongsTo extends Relation { List> models, List> results, String relation, - ) => - matchOneOrMany( - models, - results, - relation, - foreignKey ?? '${related.runtimeType.toString()}_id', - localKey, - ); + ) => matchOneOrMany( + models, + results, + relation, + foreignKey ?? '${related.runtimeType.toString()}_id', + localKey, + ); } diff --git a/lib/src/database/orm/has_many.dart b/lib/src/database/orm/has_many.dart index bbe63df9..bfb17401 100644 --- a/lib/src/database/orm/has_many.dart +++ b/lib/src/database/orm/has_many.dart @@ -12,12 +12,11 @@ class HasMany extends Relation { List> models, List> results, String relation, - ) => - matchMany( - models, - results, - relation, - localKey, - foreignKey ?? '${related.runtimeType.toString()}_id', - ); + ) => matchMany( + models, + results, + relation, + localKey, + foreignKey ?? '${related.runtimeType.toString()}_id', + ); } diff --git a/lib/src/database/orm/has_one.dart b/lib/src/database/orm/has_one.dart index 6e750944..8b1a55a6 100644 --- a/lib/src/database/orm/has_one.dart +++ b/lib/src/database/orm/has_one.dart @@ -13,12 +13,11 @@ class HasOne extends Relation { List> models, List> results, String relation, - ) => - matchOneOrMany( - models, - results, - relation, - localKey, - foreignKey ?? '${related.runtimeType.toString().toLowerCase()}_id', - ); + ) => matchOneOrMany( + models, + results, + relation, + localKey, + foreignKey ?? '${related.runtimeType.toString().toLowerCase()}_id', + ); } diff --git a/lib/src/database/orm/model.dart b/lib/src/database/orm/model.dart index c9bf5bba..ff0f327c 100644 --- a/lib/src/database/orm/model.dart +++ b/lib/src/database/orm/model.dart @@ -81,9 +81,7 @@ abstract class Model extends QueryBuilderImpl { void registerRelations() {} @override - Future avg( - String column, - ) async { + Future avg(String column) async { if (softDeletes) { whereNull(deletedAt); } @@ -96,20 +94,18 @@ abstract class Model extends QueryBuilderImpl { String? foreignKey, String localKey = 'id', }) { - _relations.addEntries( - [ - MapEntry( - name, - BelongsTo( - related: model, - parent: this, - foreignKey: foreignKey ?? - '${model.runtimeType.toString()}_id'.toLowerCase(), - localKey: localKey, - ), + _relations.addEntries([ + MapEntry( + name, + BelongsTo( + related: model, + parent: this, + foreignKey: + foreignKey ?? '${model.runtimeType.toString()}_id'.toLowerCase(), + localKey: localKey, ), - ], - ); + ), + ]); } void belongsToMany( @@ -121,24 +117,23 @@ abstract class Model extends QueryBuilderImpl { parentLocalKey = 'id', relatedLocalKey = 'id', }) { - _relations.addEntries( - [ - MapEntry( - name, - BelongsToMany( - related: model, - parent: this, - pivotTable: pivotTable ?? - '${Singularize.make(model.runtimeType.toString())}_${Singularize.make(runtimeType.toString())}' - .toLowerCase(), - parentPivotKey: parentPivotKey, - relatedPivotKey: relatedPivotKey, - parentLocalKey: parentLocalKey, - relatedLocalKey: relatedLocalKey, - ), + _relations.addEntries([ + MapEntry( + name, + BelongsToMany( + related: model, + parent: this, + pivotTable: + pivotTable ?? + '${Singularize.make(model.runtimeType.toString())}_${Singularize.make(runtimeType.toString())}' + .toLowerCase(), + parentPivotKey: parentPivotKey, + relatedPivotKey: relatedPivotKey, + parentLocalKey: parentLocalKey, + relatedLocalKey: relatedLocalKey, ), - ], - ); + ), + ]); } @override @@ -354,20 +349,18 @@ abstract class Model extends QueryBuilderImpl { String? foreignKey, String localKey = 'id', }) { - _relations.addEntries( - [ - MapEntry( - name, - HasMany( - related: model, - parent: this, - foreignKey: - foreignKey ?? '${runtimeType.toString()}_id'.toLowerCase(), - localKey: localKey, - ), + _relations.addEntries([ + MapEntry( + name, + HasMany( + related: model, + parent: this, + foreignKey: + foreignKey ?? '${runtimeType.toString()}_id'.toLowerCase(), + localKey: localKey, ), - ], - ); + ), + ]); } void hasOne( @@ -376,26 +369,22 @@ abstract class Model extends QueryBuilderImpl { String? foreignKey, String localKey = 'id', }) { - _relations.addEntries( - [ - MapEntry( - name, - HasOne( - related: model, - parent: this, - foreignKey: - foreignKey ?? '${runtimeType.toString()}_id'.toLowerCase(), - localKey: localKey, - ), + _relations.addEntries([ + MapEntry( + name, + HasOne( + related: model, + parent: this, + foreignKey: + foreignKey ?? '${runtimeType.toString()}_id'.toLowerCase(), + localKey: localKey, ), - ], - ); + ), + ]); } @override - Future insert( - Map values, - ) async { + Future insert(Map values) async { _validateFieldsForAssignment(values); await super.insert(values); @@ -403,10 +392,7 @@ abstract class Model extends QueryBuilderImpl { } @override - Future insertGetId( - Map values, [ - String? sequence, - ]) async { + Future insertGetId(Map values, [String? sequence]) async { _validateFieldsForAssignment(values); final id = await super.insertGetId(values, sequence); @@ -436,106 +422,126 @@ abstract class Model extends QueryBuilderImpl { return super.min(column); } - void morphedByMany(String name, Model model, - {required String morphKey, - required String morphType, - required String type, - required String pivotTable, - required String relatedMorphKey, - String localKey = 'id'}) { + void morphedByMany( + String name, + Model model, { + required String morphKey, + required String morphType, + required String type, + required String pivotTable, + required String relatedMorphKey, + String localKey = 'id', + }) { _relations.addEntries([ MapEntry( - name, - MorphedByMany( - parent: this, - related: model, - morphKey: morphKey, - morphType: morphType, - pivotTable: pivotTable, - relatedMorphKey: relatedMorphKey, - type: type, - localKey: localKey, - )) + name, + MorphedByMany( + parent: this, + related: model, + morphKey: morphKey, + morphType: morphType, + pivotTable: pivotTable, + relatedMorphKey: relatedMorphKey, + type: type, + localKey: localKey, + ), + ), ]); } - void morphMany(String name, Model model, - {required String morphKey, - required String morphType, - required String type, - String localKey = 'id'}) { + void morphMany( + String name, + Model model, { + required String morphKey, + required String morphType, + required String type, + String localKey = 'id', + }) { _relations.addEntries([ MapEntry( - name, - MorphMany( - parent: this, - related: model, - morphKey: morphKey, - morphType: morphType, - type: type, - localKey: localKey, - )) + name, + MorphMany( + parent: this, + related: model, + morphKey: morphKey, + morphType: morphType, + type: type, + localKey: localKey, + ), + ), ]); } - void morphOne(String name, Model model, - {required String morphKey, - required String morphType, - required String type, - String localKey = 'id'}) { + void morphOne( + String name, + Model model, { + required String morphKey, + required String morphType, + required String type, + String localKey = 'id', + }) { _relations.addEntries([ MapEntry( - name, - MorphOne( - parent: this, - related: model, - morphKey: morphKey, - morphType: morphType, - type: type, - localKey: localKey, - )) + name, + MorphOne( + parent: this, + related: model, + morphKey: morphKey, + morphType: morphType, + type: type, + localKey: localKey, + ), + ), ]); } - void morphTo(String name, Model model, - {required String morphKey, - required String morphType, - required String type, - String localKey = 'id'}) { + void morphTo( + String name, + Model model, { + required String morphKey, + required String morphType, + required String type, + String localKey = 'id', + }) { _relations.addEntries([ MapEntry( - name, - MorphTo( - parent: this, - related: model, - morphKey: morphKey, - morphType: morphType, - type: type, - localKey: localKey, - )) + name, + MorphTo( + parent: this, + related: model, + morphKey: morphKey, + morphType: morphType, + type: type, + localKey: localKey, + ), + ), ]); } - void morphToMany(String name, Model model, - {required String morphKey, - required String morphType, - required String type, - required String pivotTable, - required String relatedMorphKey, - String localKey = 'id'}) { + void morphToMany( + String name, + Model model, { + required String morphKey, + required String morphType, + required String type, + required String pivotTable, + required String relatedMorphKey, + String localKey = 'id', + }) { _relations.addEntries([ MapEntry( - name, - MorphToMany( - parent: this, - related: model, - morphKey: morphKey, - morphType: morphType, - pivotTable: pivotTable, - relatedMorphKey: relatedMorphKey, - type: type, - localKey: localKey, - )) + name, + MorphToMany( + parent: this, + related: model, + morphKey: morphKey, + morphType: morphType, + pivotTable: pivotTable, + relatedMorphKey: relatedMorphKey, + type: type, + localKey: localKey, + ), + ), ]); } @@ -561,15 +567,15 @@ abstract class Model extends QueryBuilderImpl { final hasMore = currentPage < lastPage; return PaginatedResult( - data: pageData, - currentPage: currentPage, - perPage: perPage, - total: total, - lastPage: lastPage, - isFirst: isFirst, - isLast: isLast, - hasMore: hasMore) - .toMap(); + data: pageData, + currentPage: currentPage, + perPage: perPage, + total: total, + lastPage: lastPage, + isFirst: isFirst, + isLast: isLast, + hasMore: hasMore, + ).toMap(); } @override @@ -727,7 +733,8 @@ abstract class Model extends QueryBuilderImpl { if (!_relations.containsKey(primaryRelation)) { throw InvalidArgumentException( - 'Relation $relation not found in $runtimeType'); + 'Relation $relation not found in $runtimeType', + ); } Relation rela = _relations[primaryRelation] as Relation; @@ -746,35 +753,43 @@ abstract class Model extends QueryBuilderImpl { Set ids = models.map((m) => m[rela.localKey]).toSet(); if (rela is MorphToMany || rela is MorphedByMany) { - qb = qb - .whereIn(rela.morphKey, ids.toList()) - .whereEqualTo(rela.morphType, rela.type) - .join( - rela.related.tableName, - '${rela.pivotTable}.${rela.relatedMorphKey}', - '=', - '${rela.related.tableName}.${rela.localKey}', - ) as Model; + qb = + qb + .whereIn(rela.morphKey, ids.toList()) + .whereEqualTo(rela.morphType, rela.type) + .join( + rela.related.tableName, + '${rela.pivotTable}.${rela.relatedMorphKey}', + '=', + '${rela.related.tableName}.${rela.localKey}', + ) + as Model; qb.tableName = rela.pivotTable!; } else { - qb = qb - .whereIn(rela.morphKey, ids.toList()) - .whereEqualTo(rela.morphType, rela.type) as Model; + qb = + qb + .whereIn(rela.morphKey, ids.toList()) + .whereEqualTo(rela.morphType, rela.type) + as Model; } } } else { Set ids = models.map((m) => m[rela.localKey]).toSet(); if (rela is BelongsToMany) { - qb = qb - .whereIn( - '${rela.pivotTable}.${rela.parentPivotKey}', ids.toList()) - .join( - rela.pivotTable, - '${rela.pivotTable}.${rela.relatedPivotKey}', - '=', - '${rela.related.tableName}.${rela.relatedLocalKey}', - ) as Model; + qb = + qb + .whereIn( + '${rela.pivotTable}.${rela.parentPivotKey}', + ids.toList(), + ) + .join( + rela.pivotTable, + '${rela.pivotTable}.${rela.relatedPivotKey}', + '=', + '${rela.related.tableName}.${rela.relatedLocalKey}', + ) + as Model; } else if (rela is BelongsTo) { qb = qb.whereIn(rela.localKey, ids.toList()) as Model; } else { diff --git a/lib/src/database/orm/polymorphic/morph_many.dart b/lib/src/database/orm/polymorphic/morph_many.dart index 43b14b06..f313e2d9 100644 --- a/lib/src/database/orm/polymorphic/morph_many.dart +++ b/lib/src/database/orm/polymorphic/morph_many.dart @@ -15,14 +15,13 @@ class MorphMany extends MorphRelation { List> models, List> results, String relation, - ) => - matchMorphMany( - models, - results, - relation, - localKey, - morphKey, - morphType, - type ?? related.runtimeType.toString().toLowerCase(), - ); + ) => matchMorphMany( + models, + results, + relation, + localKey, + morphKey, + morphType, + type ?? related.runtimeType.toString().toLowerCase(), + ); } diff --git a/lib/src/database/orm/polymorphic/morph_one.dart b/lib/src/database/orm/polymorphic/morph_one.dart index 6800f4e2..b302f27d 100644 --- a/lib/src/database/orm/polymorphic/morph_one.dart +++ b/lib/src/database/orm/polymorphic/morph_one.dart @@ -15,14 +15,13 @@ class MorphOne extends MorphRelation { List> models, List> results, String relation, - ) => - matchMorphOneOrMany( - models, - results, - relation, - localKey, - morphKey, - morphType, - type ?? related.runtimeType.toString().toLowerCase(), - ); + ) => matchMorphOneOrMany( + models, + results, + relation, + localKey, + morphKey, + morphType, + type ?? related.runtimeType.toString().toLowerCase(), + ); } diff --git a/lib/src/database/orm/polymorphic/morph_to.dart b/lib/src/database/orm/polymorphic/morph_to.dart index c00294ea..3c2dd97b 100644 --- a/lib/src/database/orm/polymorphic/morph_to.dart +++ b/lib/src/database/orm/polymorphic/morph_to.dart @@ -16,12 +16,6 @@ class MorphTo extends MorphRelation { List> results, String relation, ) { - return matchMorphToOne( - models, - results, - relation, - morphKey, - localKey, - ); + return matchMorphToOne(models, results, relation, morphKey, localKey); } } diff --git a/lib/src/database/query_builder/_bulk_operations_builder_impl.dart b/lib/src/database/query_builder/_bulk_operations_builder_impl.dart index 8c8144a9..b9dc896d 100644 --- a/lib/src/database/query_builder/_bulk_operations_builder_impl.dart +++ b/lib/src/database/query_builder/_bulk_operations_builder_impl.dart @@ -29,12 +29,14 @@ abstract mixin class BulkOperationsBuilderImpl implements QueryBuilder { }) async { if (sourceData.isEmpty) { throw InvalidArgumentException( - 'Source data cannot be empty for merge operation'); + 'Source data cannot be empty for merge operation', + ); } if (matchOn.isEmpty) { throw InvalidArgumentException( - 'Match columns cannot be empty for merge operation'); + 'Match columns cannot be empty for merge operation', + ); } try { @@ -45,28 +47,33 @@ abstract mixin class BulkOperationsBuilderImpl implements QueryBuilder { final valueGroups = []; for (var row in sourceData) { - final placeholders = sourceColumns.map((column) { - final paramName = _nextParamName(); - paramBindings[paramName] = row[column]; - return ":$paramName"; - }).join(", "); + final placeholders = sourceColumns + .map((column) { + final paramName = _nextParamName(); + paramBindings[paramName] = row[column]; + return ":$paramName"; + }) + .join(", "); valueGroups.add("($placeholders)"); } final sourceClause = "(VALUES ${valueGroups.join(', ')}) AS source(${sourceColumns.join(', ')})"; - final matchConditions = - matchOn.map((col) => "$getTable.$col = source.$col").join(' AND '); + final matchConditions = matchOn + .map((col) => "$getTable.$col = source.$col") + .join(' AND '); String mergeSQL = "MERGE INTO $getTable USING $sourceClause ON $matchConditions"; if (whenMatched == ConflictAction.update) { - final columnsToUpdate = updateColumns ?? + final columnsToUpdate = + updateColumns ?? sourceColumns.where((col) => !matchOn.contains(col)).toList(); - final updateSets = - columnsToUpdate.map((col) => "$col = source.$col").join(', '); + final updateSets = columnsToUpdate + .map((col) => "$col = source.$col") + .join(', '); mergeSQL += " WHEN MATCHED THEN UPDATE SET $updateSets"; } else if (whenMatched == ConflictAction.delete) { mergeSQL += " WHEN MATCHED THEN DELETE"; @@ -74,8 +81,9 @@ abstract mixin class BulkOperationsBuilderImpl implements QueryBuilder { if (whenNotMatched != ConflictAction.ignore) { final columnsToInsert = insertColumns ?? sourceColumns; - final insertValues = - columnsToInsert.map((col) => "source.$col").join(', '); + final insertValues = columnsToInsert + .map((col) => "source.$col") + .join(', '); mergeSQL += " WHEN NOT MATCHED THEN INSERT (${columnsToInsert.join(', ')}) VALUES ($insertValues)"; } @@ -102,7 +110,8 @@ abstract mixin class BulkOperationsBuilderImpl implements QueryBuilder { }) async { if (data.isEmpty) { throw InvalidArgumentException( - 'Data cannot be empty for bulk insert operation'); + 'Data cannot be empty for bulk insert operation', + ); } try { @@ -115,11 +124,13 @@ abstract mixin class BulkOperationsBuilderImpl implements QueryBuilder { final valueGroups = []; for (var row in batch) { - final placeholders = columns.map((column) { - final paramName = _nextParamName(); - paramBindings[paramName] = row[column]; - return ":$paramName"; - }).join(", "); + final placeholders = columns + .map((column) { + final paramName = _nextParamName(); + paramBindings[paramName] = row[column]; + return ":$paramName"; + }) + .join(", "); valueGroups.add("($placeholders)"); } @@ -131,10 +142,12 @@ abstract mixin class BulkOperationsBuilderImpl implements QueryBuilder { "INSERT IGNORE INTO $getTable (${columns.join(', ')}) VALUES ${valueGroups.join(', ')}"; } else if (conflictAction == ConflictAction.update && conflictColumns != null) { - final updateCols = updateColumns ?? + final updateCols = + updateColumns ?? columns.where((col) => !conflictColumns.contains(col)).toList(); - final updateSets = - updateCols.map((col) => "$col = VALUES($col)").join(', '); + final updateSets = updateCols + .map((col) => "$col = VALUES($col)") + .join(', '); sql += " ON DUPLICATE KEY UPDATE $updateSets"; } else if (conflictAction == ConflictAction.replace) { sql = @@ -160,7 +173,8 @@ abstract mixin class BulkOperationsBuilderImpl implements QueryBuilder { }) async { if (updates.isEmpty) { throw InvalidArgumentException( - 'Updates cannot be empty for bulk update operation'); + 'Updates cannot be empty for bulk update operation', + ); } try { @@ -169,7 +183,8 @@ abstract mixin class BulkOperationsBuilderImpl implements QueryBuilder { for (int i = 0; i < updates.length; i += batchSize) { final batch = updates.skip(i).take(batchSize).toList(); - final columns = updateColumns ?? + final columns = + updateColumns ?? batch.first.keys.where((key) => key != matchColumn).toList(); final paramBindings = {}; @@ -188,8 +203,9 @@ abstract mixin class BulkOperationsBuilderImpl implements QueryBuilder { for (var column in columns) { final valueParamName = _nextParamName(); paramBindings[valueParamName] = row[column]; - caseClauses[column]! - .add("WHEN :$matchParamName THEN :$valueParamName"); + caseClauses[column]!.add( + "WHEN :$matchParamName THEN :$valueParamName", + ); } } @@ -227,7 +243,8 @@ abstract mixin class BulkOperationsBuilderImpl implements QueryBuilder { }) async { if (column == null || values == null || values.isEmpty) { throw InvalidArgumentException( - 'Column and values must be provided for bulk delete operation'); + 'Column and values must be provided for bulk delete operation', + ); } try { @@ -237,11 +254,13 @@ abstract mixin class BulkOperationsBuilderImpl implements QueryBuilder { final batch = values.skip(i).take(batchSize).toList(); final paramBindings = {}; - final placeholders = batch.map((value) { - final paramName = _nextParamName(); - paramBindings[paramName] = value; - return ":$paramName"; - }).join(', '); + final placeholders = batch + .map((value) { + final paramName = _nextParamName(); + paramBindings[paramName] = value; + return ":$paramName"; + }) + .join(', '); final sql = "DELETE FROM $getTable WHERE $column IN ($placeholders)"; @@ -261,7 +280,8 @@ abstract mixin class BulkOperationsBuilderImpl implements QueryBuilder { }) async { if (conditions.isEmpty) { throw InvalidArgumentException( - 'Conditions cannot be empty for bulk delete operation'); + 'Conditions cannot be empty for bulk delete operation', + ); } try { @@ -299,8 +319,10 @@ abstract mixin class BulkOperationsBuilderImpl implements QueryBuilder { Future batchProcess({ required int batchSize, required Future Function( - List> batch, int batchNumber) - processor, + List> batch, + int batchNumber, + ) + processor, List columns = const ['*'], }) async { int batchNumber = 1; @@ -330,8 +352,9 @@ abstract mixin class BulkOperationsBuilderImpl implements QueryBuilder { Future chunkedProcess({ required int chunkSize, required Future>> Function( - List> chunk) - processor, + List> chunk, + ) + processor, String? destination, List columns = const ['*'], }) async { @@ -371,7 +394,8 @@ abstract mixin class BulkOperationsBuilderImpl implements QueryBuilder { }) async { if (data.isEmpty) { throw InvalidArgumentException( - 'Data cannot be empty for parallel bulk insert operation'); + 'Data cannot be empty for parallel bulk insert operation', + ); } try { diff --git a/lib/src/database/query_builder/_cte/_cte_cache.dart b/lib/src/database/query_builder/_cte/_cte_cache.dart index 6ba4ef61..b8683357 100644 --- a/lib/src/database/query_builder/_cte/_cte_cache.dart +++ b/lib/src/database/query_builder/_cte/_cte_cache.dart @@ -15,7 +15,10 @@ class CteCache { } void updateCache( - String withClause, Map bindings, int hashCode) { + String withClause, + Map bindings, + int hashCode, + ) { _cachedWithClause = withClause; _cachedBindings = Map.from(bindings); _cteHashCode = hashCode; diff --git a/lib/src/database/query_builder/_cte/_cte_definition.dart b/lib/src/database/query_builder/_cte/_cte_definition.dart index eca459f3..56cbca4f 100644 --- a/lib/src/database/query_builder/_cte/_cte_definition.dart +++ b/lib/src/database/query_builder/_cte/_cte_definition.dart @@ -38,33 +38,48 @@ class CteDefinition { if (isRecursive && !config.supportsFeature(CteFeature.recursive)) { throw UnsupportedCteFeatureException( - CteFeature.recursive, config.databaseType, name); + CteFeature.recursive, + config.databaseType, + name, + ); } if (isMaterialized && !config.supportsFeature(CteFeature.materialized)) { throw UnsupportedCteFeatureException( - CteFeature.materialized, config.databaseType, name); + CteFeature.materialized, + config.databaseType, + name, + ); } if (isNotMaterialized && !config.supportsFeature(CteFeature.notMaterialized)) { throw UnsupportedCteFeatureException( - CteFeature.notMaterialized, config.databaseType, name); + CteFeature.notMaterialized, + config.databaseType, + name, + ); } if (isRecursive && recursiveQuery == null) { throw InvalidCteConfigurationException( - 'Recursive CTE must have recursive query', name); + 'Recursive CTE must have recursive query', + name, + ); } if (isMaterialized && isNotMaterialized) { throw InvalidCteConfigurationException( - 'CTE cannot be both materialized and not materialized', name); + 'CTE cannot be both materialized and not materialized', + name, + ); } if (isRecursive && (isMaterialized || isNotMaterialized)) { throw InvalidCteConfigurationException( - 'Recursive CTE cannot have materialization options', name); + 'Recursive CTE cannot have materialization options', + name, + ); } if (columns != null && columns!.isNotEmpty) { @@ -75,21 +90,26 @@ class CteDefinition { Set uniqueColumns = columns!.map((c) => c.toLowerCase()).toSet(); if (uniqueColumns.length != columns!.length) { throw InvalidCteConfigurationException( - 'CTE columns must be unique', name); + 'CTE columns must be unique', + name, + ); } } } String toSql( - IdentifierEscapingStrategy escapingStrategy, CteConfiguration config) { + IdentifierEscapingStrategy escapingStrategy, + CteConfiguration config, + ) { validate(config); String escapedName = escapingStrategy.escape(name); String sql = escapedName; if (columns != null && columns!.isNotEmpty) { - List escapedColumns = - columns!.map((col) => escapingStrategy.escape(col)).toList(); + List escapedColumns = columns! + .map((col) => escapingStrategy.escape(col)) + .toList(); sql += ' (${escapedColumns.join(', ')})'; } @@ -112,8 +132,8 @@ class CteDefinition { Map allBindings = {}; if (query is QueryBuilderAccessor) { - Map queryBindings = - (query as QueryBuilderAccessor).accessBindings(); + Map queryBindings = (query as QueryBuilderAccessor) + .accessBindings(); allBindings.addAll(queryBindings); } diff --git a/lib/src/database/query_builder/_cte/_cte_feature.dart b/lib/src/database/query_builder/_cte/_cte_feature.dart index 8f4e354c..2cfdc808 100644 --- a/lib/src/database/query_builder/_cte/_cte_feature.dart +++ b/lib/src/database/query_builder/_cte/_cte_feature.dart @@ -1,7 +1 @@ -enum CteFeature { - materialized, - - notMaterialized, - - recursive, -} +enum CteFeature { materialized, notMaterialized, recursive } diff --git a/lib/src/database/query_builder/_cte/_database_type.dart b/lib/src/database/query_builder/_cte/_database_type.dart index b9a31ce4..3c2e26b3 100644 --- a/lib/src/database/query_builder/_cte/_database_type.dart +++ b/lib/src/database/query_builder/_cte/_database_type.dart @@ -1,5 +1 @@ -enum DatabaseType { - postgresql, - mysql, - sqlite, -} +enum DatabaseType { postgresql, mysql, sqlite } diff --git a/lib/src/database/query_builder/_cte/_duplicate_cte_name_exception.dart b/lib/src/database/query_builder/_cte/_duplicate_cte_name_exception.dart index 9e95f789..ba67e98a 100644 --- a/lib/src/database/query_builder/_cte/_duplicate_cte_name_exception.dart +++ b/lib/src/database/query_builder/_cte/_duplicate_cte_name_exception.dart @@ -2,5 +2,5 @@ import '_cte_exception.dart'; class DuplicateCteNameException extends CteException { DuplicateCteNameException(String name) - : super('CTE with name "$name" already exists', name); + : super('CTE with name "$name" already exists', name); } diff --git a/lib/src/database/query_builder/_cte/_sql_identifier_escaper.dart b/lib/src/database/query_builder/_cte/_sql_identifier_escaper.dart index 51fbc2ab..c5748faf 100644 --- a/lib/src/database/query_builder/_cte/_sql_identifier_escaper.dart +++ b/lib/src/database/query_builder/_cte/_sql_identifier_escaper.dart @@ -87,8 +87,9 @@ class SqlIdentifierEscaper { identifier == identifier.toUpperCase() && identifier.isNotEmpty && RegExp(r'^[A-Z]+$').hasMatch(identifier)) { - if (RegExp(r'^(ID|URL|API|UUID|JSON|XML|HTML|CSS|JS)$') - .hasMatch(identifier)) { + if (RegExp( + r'^(ID|URL|API|UUID|JSON|XML|HTML|CSS|JS)$', + ).hasMatch(identifier)) { return false; } if (RegExp(r'(ID|NAME|CODE|TYPE|FLAG|DATA)$').hasMatch(identifier)) { @@ -97,18 +98,21 @@ class SqlIdentifierEscaper { return true; } - if (RegExp(r'^(select|insert|update|delete|create|drop|alter|grant|revoke)') - .hasMatch(lower)) { + if (RegExp( + r'^(select|insert|update|delete|create|drop|alter|grant|revoke)', + ).hasMatch(lower)) { return true; } - if (RegExp(r'^(count|sum|avg|min|max|concat|substr|trim|upper|lower)$') - .hasMatch(lower)) { + if (RegExp( + r'^(count|sum|avg|min|max|concat|substr|trim|upper|lower)$', + ).hasMatch(lower)) { return true; } - if (RegExp(r'^(now|today|current_date|current_time|current_timestamp)$') - .hasMatch(lower)) { + if (RegExp( + r'^(now|today|current_date|current_time|current_timestamp)$', + ).hasMatch(lower)) { return true; } @@ -120,14 +124,17 @@ class SqlIdentifierEscaper { return false; } - static void validateIdentifier(String identifier, - {String context = 'Identifier'}) { + static void validateIdentifier( + String identifier, { + String context = 'Identifier', + }) { if (identifier.trim().isEmpty) { throw InvalidArgumentException('$context cannot be empty or whitespace'); } if (identifier.length > 63) { throw InvalidArgumentException( - '$context name is too long (max 63 characters): ${identifier.length}'); + '$context name is too long (max 63 characters): ${identifier.length}', + ); } if (identifier.contains('0')) { throw InvalidArgumentException('$context cannot contain null character'); diff --git a/lib/src/database/query_builder/_cte/_unsupported_cte_feature_exception.dart b/lib/src/database/query_builder/_cte/_unsupported_cte_feature_exception.dart index 6dd7986f..7206dce8 100644 --- a/lib/src/database/query_builder/_cte/_unsupported_cte_feature_exception.dart +++ b/lib/src/database/query_builder/_cte/_unsupported_cte_feature_exception.dart @@ -7,9 +7,12 @@ class UnsupportedCteFeatureException extends CteException { final DatabaseType databaseType; - UnsupportedCteFeatureException(this.feature, this.databaseType, - [String? cteName]) - : super( - 'Feature ${feature.name} is not supported in ${databaseType.name}', - cteName); + UnsupportedCteFeatureException( + this.feature, + this.databaseType, [ + String? cteName, + ]) : super( + 'Feature ${feature.name} is not supported in ${databaseType.name}', + cteName, + ); } diff --git a/lib/src/database/query_builder/_cte_builder_impl.dart b/lib/src/database/query_builder/_cte_builder_impl.dart index f6735b28..94c319b8 100644 --- a/lib/src/database/query_builder/_cte_builder_impl.dart +++ b/lib/src/database/query_builder/_cte_builder_impl.dart @@ -37,15 +37,20 @@ abstract mixin class CteBuilderImpl implements QueryBuilder { CteConfiguration get cteConfiguration => _config; @override - QueryBuilder withCte(String name, QueryBuilder subQuery, - {List? columns}) { + QueryBuilder withCte( + String name, + QueryBuilder subQuery, { + List? columns, + }) { _validateAndAddCte(name, subQuery, columns: columns); return this; } @override - QueryBuilder withMultiple(Map ctes, - {Map>? columnsMap}) { + QueryBuilder withMultiple( + Map ctes, { + Map>? columnsMap, + }) { if (ctes.isEmpty) { throw InvalidArgumentException('CTEs map cannot be empty'); } @@ -74,7 +79,10 @@ abstract mixin class CteBuilderImpl implements QueryBuilder { }) { if (!_config.supportsFeature(CteFeature.recursive)) { throw UnsupportedCteFeatureException( - CteFeature.recursive, _config.databaseType, name); + CteFeature.recursive, + _config.databaseType, + name, + ); } _validateAndAddCte( @@ -88,11 +96,17 @@ abstract mixin class CteBuilderImpl implements QueryBuilder { } @override - QueryBuilder withMaterialized(String name, QueryBuilder subQuery, - {List? columns}) { + QueryBuilder withMaterialized( + String name, + QueryBuilder subQuery, { + List? columns, + }) { if (!_config.supportsFeature(CteFeature.materialized)) { throw UnsupportedCteFeatureException( - CteFeature.materialized, _config.databaseType, name); + CteFeature.materialized, + _config.databaseType, + name, + ); } _validateAndAddCte(name, subQuery, isMaterialized: true, columns: columns); @@ -100,15 +114,25 @@ abstract mixin class CteBuilderImpl implements QueryBuilder { } @override - QueryBuilder withNotMaterialized(String name, QueryBuilder subQuery, - {List? columns}) { + QueryBuilder withNotMaterialized( + String name, + QueryBuilder subQuery, { + List? columns, + }) { if (!_config.supportsFeature(CteFeature.notMaterialized)) { throw UnsupportedCteFeatureException( - CteFeature.notMaterialized, _config.databaseType, name); + CteFeature.notMaterialized, + _config.databaseType, + name, + ); } - _validateAndAddCte(name, subQuery, - isNotMaterialized: true, columns: columns); + _validateAndAddCte( + name, + subQuery, + isNotMaterialized: true, + columns: columns, + ); return this; } @@ -174,7 +198,8 @@ abstract mixin class CteBuilderImpl implements QueryBuilder { int recursiveCount = _ctes.where((cte) => cte.isRecursive).length; if (recursiveCount > _config.maxCteDepth) { throw InvalidCteConfigurationException( - 'Too many recursive CTEs: $recursiveCount (max: ${_config.maxCteDepth})'); + 'Too many recursive CTEs: $recursiveCount (max: ${_config.maxCteDepth})', + ); } } @@ -278,8 +303,9 @@ abstract mixin class CteBuilderImpl implements QueryBuilder { @protected bool removeCte(String name) { String lowerName = name.toLowerCase(); - final index = - _ctes.indexWhere((cte) => cte.name.toLowerCase() == lowerName); + final index = _ctes.indexWhere( + (cte) => cte.name.toLowerCase() == lowerName, + ); if (index != -1) { _ctes.removeAt(index); _cteNames.remove(lowerName); @@ -292,16 +318,18 @@ abstract mixin class CteBuilderImpl implements QueryBuilder { @protected List> getCteInfo() { return _ctes - .map((cte) => { - 'name': cte.name, - 'isRecursive': cte.isRecursive, - 'isMaterialized': cte.isMaterialized, - 'isNotMaterialized': cte.isNotMaterialized, - 'hasColumns': cte.columns != null && cte.columns!.isNotEmpty, - 'columnCount': cte.columns?.length ?? 0, - 'columns': cte.columns, - 'hashCode': cte.hashCode, - }) + .map( + (cte) => { + 'name': cte.name, + 'isRecursive': cte.isRecursive, + 'isMaterialized': cte.isMaterialized, + 'isNotMaterialized': cte.isNotMaterialized, + 'hasColumns': cte.columns != null && cte.columns!.isNotEmpty, + 'columnCount': cte.columns?.length ?? 0, + 'columns': cte.columns, + 'hashCode': cte.hashCode, + }, + ) .toList(); } diff --git a/lib/src/database/query_builder/_insert_query_builder_impl.dart b/lib/src/database/query_builder/_insert_query_builder_impl.dart index 6761e3c6..fa94bc0c 100644 --- a/lib/src/database/query_builder/_insert_query_builder_impl.dart +++ b/lib/src/database/query_builder/_insert_query_builder_impl.dart @@ -20,9 +20,7 @@ abstract mixin class InsertQueryBuilderImpl implements QueryBuilder { } @override - Future insert( - Map values, - ) async { + Future insert(Map values) async { try { if (values.isEmpty) { throw InvalidArgumentException( @@ -35,11 +33,13 @@ abstract mixin class InsertQueryBuilderImpl implements QueryBuilder { final paramBindings = {}; // Create parameter placeholders - final placeholders = values.keys.map((key) { - final paramName = _nextParamName(); - paramBindings[paramName] = values[key]; - return ":$paramName"; - }).join(", "); + final placeholders = values.keys + .map((key) { + final paramName = _nextParamName(); + paramBindings[paramName] = values[key]; + return ":$paramName"; + }) + .join(", "); final query = "INSERT INTO $getTable (${columns.join(', ')}) VALUES ($placeholders)"; @@ -51,10 +51,7 @@ abstract mixin class InsertQueryBuilderImpl implements QueryBuilder { } @override - Future insertGetId( - Map values, [ - String? sequence, - ]) async { + Future insertGetId(Map values, [String? sequence]) async { try { if (values.isEmpty) { throw InvalidArgumentException( @@ -66,11 +63,13 @@ abstract mixin class InsertQueryBuilderImpl implements QueryBuilder { final columns = values.keys.toList(); final paramBindings = {}; - final placeholders = values.keys.map((key) { - final paramName = _nextParamName(); - paramBindings[paramName] = values[key]; - return ":$paramName"; - }).join(", "); + final placeholders = values.keys + .map((key) { + final paramName = _nextParamName(); + paramBindings[paramName] = values[key]; + return ":$paramName"; + }) + .join(", "); final query = "INSERT INTO $getTable (${columns.join(', ')}) VALUES ($placeholders)"; @@ -82,9 +81,7 @@ abstract mixin class InsertQueryBuilderImpl implements QueryBuilder { } @override - Future insertMany( - List> valuesList, - ) async { + Future insertMany(List> valuesList) async { try { if (valuesList.isEmpty) { throw InvalidArgumentException( @@ -110,11 +107,13 @@ abstract mixin class InsertQueryBuilderImpl implements QueryBuilder { // Create parameter placeholders for each row for (var values in valuesList) { - final placeholders = columns.map((column) { - final paramName = _nextParamName(); - paramBindings[paramName] = values[column]; - return ":$paramName"; - }).join(", "); + final placeholders = columns + .map((column) { + final paramName = _nextParamName(); + paramBindings[paramName] = values[column]; + return ":$paramName"; + }) + .join(", "); valueGroups.add("($placeholders)"); } @@ -140,9 +139,7 @@ abstract mixin class InsertQueryBuilderImpl implements QueryBuilder { } @override - Future insertOrIgnore( - Map values, - ) async { + Future insertOrIgnore(Map values) async { try { if (values.isEmpty) { throw InvalidArgumentException( @@ -152,11 +149,13 @@ abstract mixin class InsertQueryBuilderImpl implements QueryBuilder { conn = await getConnection(); final columns = values.keys.toList(); final paramBindings = {}; - final placeholders = values.keys.map((key) { - final paramName = _nextParamName(); - paramBindings[paramName] = values[key]; - return ":$paramName"; - }).join(", "); + final placeholders = values.keys + .map((key) { + final paramName = _nextParamName(); + paramBindings[paramName] = values[key]; + return ":$paramName"; + }) + .join(", "); final query = "INSERT IGNORE INTO $getTable (${columns.join(', ')}) VALUES ($placeholders)"; @@ -168,10 +167,7 @@ abstract mixin class InsertQueryBuilderImpl implements QueryBuilder { } @override - Future insertUsing( - List columns, - QueryBuilder subQuery, - ) async { + Future insertUsing(List columns, QueryBuilder subQuery) async { try { String cols = columns.join(", "); String subSql = subQuery.toRawSql(); @@ -201,11 +197,13 @@ abstract mixin class InsertQueryBuilderImpl implements QueryBuilder { final columns = values.keys.toList(); final paramBindings = {}; - final placeholders = values.keys.map((key) { - final paramName = _nextParamName(); - paramBindings[paramName] = values[key]; - return ":$paramName"; - }).join(", "); + final placeholders = values.keys + .map((key) { + final paramName = _nextParamName(); + paramBindings[paramName] = values[key]; + return ":$paramName"; + }) + .join(", "); String sql = "INSERT INTO $getTable (${columns.join(', ')}) VALUES ($placeholders)"; @@ -218,11 +216,13 @@ abstract mixin class InsertQueryBuilderImpl implements QueryBuilder { } if (update.isNotEmpty) { - final updateClauses = update.entries.map((entry) { - final paramName = _nextParamName(); - paramBindings[paramName] = entry.value; - return "${entry.key} = :$paramName"; - }).join(", "); + final updateClauses = update.entries + .map((entry) { + final paramName = _nextParamName(); + paramBindings[paramName] = entry.value; + return "${entry.key} = :$paramName"; + }) + .join(", "); sql += " ON DUPLICATE KEY UPDATE $updateClauses"; } diff --git a/lib/src/database/query_builder/_join_clause_builder_impl.dart b/lib/src/database/query_builder/_join_clause_builder_impl.dart index 9efc0097..855a4600 100644 --- a/lib/src/database/query_builder/_join_clause_builder_impl.dart +++ b/lib/src/database/query_builder/_join_clause_builder_impl.dart @@ -3,10 +3,7 @@ import '../../contract/database/query_builder/query_builder.dart' abstract mixin class JoinClauseBuilderImpl implements QueryBuilder { @override - QueryBuilder crossJoin( - String table, [ - List bindings = const [], - ]) { + QueryBuilder crossJoin(String table, [List bindings = const []]) { String clause = "CROSS JOIN $table"; joins.add(clause); return this; @@ -55,14 +52,7 @@ abstract mixin class JoinClauseBuilderImpl implements QueryBuilder { String? secondColumn, bool where = false, ]) { - return join( - table, - firstColumn, - operator, - secondColumn, - "LEFT", - where, - ); + return join(table, firstColumn, operator, secondColumn, "LEFT", where); } @override @@ -73,14 +63,7 @@ abstract mixin class JoinClauseBuilderImpl implements QueryBuilder { String? operator, String? secondColumn, ]) { - return joinSub( - subQuery, - as, - firstColumn, - operator, - secondColumn, - "LEFT", - ); + return joinSub(subQuery, as, firstColumn, operator, secondColumn, "LEFT"); } @override @@ -90,12 +73,6 @@ abstract mixin class JoinClauseBuilderImpl implements QueryBuilder { String? operator, String? secondColumn, ]) { - return join( - table, - firstColumn, - operator, - secondColumn, - "RIGHT", - ); + return join(table, firstColumn, operator, secondColumn, "RIGHT"); } } diff --git a/lib/src/database/query_builder/_query_builder_impl.dart b/lib/src/database/query_builder/_query_builder_impl.dart index 99cc93d6..83ae2610 100644 --- a/lib/src/database/query_builder/_query_builder_impl.dart +++ b/lib/src/database/query_builder/_query_builder_impl.dart @@ -60,8 +60,7 @@ class QueryBuilderImpl extends QueryBuilder Future transaction( Future Function() action, [ String? conditionName, - ]) => - ConnectionManager().transaction(action, conditionName); + ]) => ConnectionManager().transaction(action, conditionName); @override Stream alerts() => ConnectionManager().alerts; @@ -198,9 +197,7 @@ class QueryBuilderImpl extends QueryBuilder } @override - QueryBuilder latest([ - String column = 'created_at', - ]) { + QueryBuilder latest([String column = 'created_at']) { return orderByDesc(column); } @@ -217,10 +214,7 @@ class QueryBuilderImpl extends QueryBuilder } @override - QueryBuilder orderBy( - String column, [ - String direction = 'ASC', - ]) { + QueryBuilder orderBy(String column, [String direction = 'ASC']) { _orderBy.add("$column $direction"); return this; } @@ -236,10 +230,7 @@ class QueryBuilderImpl extends QueryBuilder } @override - QueryBuilder reorder([ - String? column, - String? direction, - ]) { + QueryBuilder reorder([String? column, String? direction]) { _orderBy.clear(); if (column != null) { _orderBy.add("$column ${direction ?? 'asc'}"); diff --git a/lib/src/database/query_builder/_query_executor_builder_impl.dart b/lib/src/database/query_builder/_query_executor_builder_impl.dart index 019259ec..a8c921d5 100644 --- a/lib/src/database/query_builder/_query_executor_builder_impl.dart +++ b/lib/src/database/query_builder/_query_executor_builder_impl.dart @@ -9,14 +9,9 @@ import '../../contract/database/query_builder/query_builder.dart' abstract mixin class QueryExecutorBuilderImpl implements QueryBuilder { late DatabaseConnection conn; @override - Future avg( - String column, - ) async { + Future avg(String column) async { try { - String sql = build( - aggregateFunction: "AVG", - aggregateColumn: column, - ); + String sql = build(aggregateFunction: "AVG", aggregateColumn: column); final bindings = getBindings(); conn = await getConnection(); var result = await conn.select(sql, bindings); @@ -108,9 +103,7 @@ abstract mixin class QueryExecutorBuilderImpl implements QueryBuilder { } @override - Future each( - void Function(Map q) callback, - ) async { + Future each(void Function(Map q) callback) async { var results = await get(); for (var row in results) { callback(row); @@ -164,11 +157,7 @@ abstract mixin class QueryExecutorBuilderImpl implements QueryBuilder { String byColumnName = 'id', List columns = const [], }) async { - var result = await find( - id, - byColumnName: byColumnName, - columns: columns, - ); + var result = await find(id, byColumnName: byColumnName, columns: columns); if (result == null) { throw InvalidArgumentException("Record with id $id not found."); } @@ -176,9 +165,7 @@ abstract mixin class QueryExecutorBuilderImpl implements QueryBuilder { } @override - Future?> first([ - List columns = const [], - ]) async { + Future?> first([List columns = const []]) async { try { if (columns.isNotEmpty) { for (String column in columns) { @@ -267,9 +254,7 @@ abstract mixin class QueryExecutorBuilderImpl implements QueryBuilder { } @override - Stream> cursor([ - int chunk = 1000, - ]) async* { + Stream> cursor([int chunk = 1000]) async* { try { int offset = 0; @@ -339,15 +324,15 @@ abstract mixin class QueryExecutorBuilderImpl implements QueryBuilder { final hasMore = currentPage < lastPage; return PaginatedResult( - data: pageData, - currentPage: currentPage, - perPage: perPage, - total: total, - lastPage: lastPage, - isFirst: isFirst, - isLast: isLast, - hasMore: hasMore) - .toMap(); + data: pageData, + currentPage: currentPage, + perPage: perPage, + total: total, + lastPage: lastPage, + isFirst: isFirst, + isLast: isLast, + hasMore: hasMore, + ).toMap(); } @override diff --git a/lib/src/database/query_builder/_where_clauses_builder_impl.dart b/lib/src/database/query_builder/_where_clauses_builder_impl.dart index c3fd5994..30761457 100644 --- a/lib/src/database/query_builder/_where_clauses_builder_impl.dart +++ b/lib/src/database/query_builder/_where_clauses_builder_impl.dart @@ -24,7 +24,8 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { @override String build({String? aggregateFunction, String? aggregateColumn}) { throw UnimplementedError( - 'build() should be implemented by the concrete class'); + 'build() should be implemented by the concrete class', + ); } @override @@ -58,15 +59,8 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { } @override - QueryBuilder orWhereBetween( - String column, - List values, { - bool not = false, - }) { - _appendCondition( - _createBetweenCondition(column, values, not), - isOr: true, - ); + QueryBuilder orWhereBetween(String column, List values, {bool not = false}) { + _appendCondition(_createBetweenCondition(column, values, not), isOr: true); return this; } @@ -77,19 +71,12 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { String secondColumn, ) { String condition = "$first $operator $secondColumn"; - _appendCondition( - condition, - isOr: true, - ); + _appendCondition(condition, isOr: true); return this; } @override - QueryBuilder orWhereDate( - String column, - String operator, - dynamic value, - ) { + QueryBuilder orWhereDate(String column, String operator, dynamic value) { _appendCondition( _createDateCondition(column, operator, value, "DATE"), isOr: true, @@ -98,11 +85,7 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { } @override - QueryBuilder orWhereDay( - String column, - String operator, - dynamic value, - ) { + QueryBuilder orWhereDay(String column, String operator, dynamic value) { _appendCondition( _createDateCondition(column, operator, value, "DAY"), isOr: true, @@ -111,10 +94,7 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { } @override - QueryBuilder orWhereExists( - QueryCallback callback, { - bool not = false, - }) { + QueryBuilder orWhereExists(QueryCallback callback, {bool not = false}) { QueryBuilder subQuery = QueryBuilderImpl(); callback(subQuery); String condition = "${not ? 'NOT EXISTS' : 'EXISTS'} (${subQuery.toSql()})"; @@ -124,8 +104,11 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { } @override - QueryBuilder orWhereFullText(dynamic columns, dynamic query, - [Map options = const {}]) { + QueryBuilder orWhereFullText( + dynamic columns, + dynamic query, [ + Map options = const {}, + ]) { _appendCondition( _createFullTextCondition(columns, query, options), isOr: true, @@ -134,28 +117,14 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { } @override - QueryBuilder orWhereHour( - String column, - String operator, - dynamic value, - ) { - _appendCondition( - _createHourCondition(column, operator, value), - isOr: true, - ); + QueryBuilder orWhereHour(String column, String operator, dynamic value) { + _appendCondition(_createHourCondition(column, operator, value), isOr: true); return this; } @override - QueryBuilder orWhereIn( - String column, - List values, { - bool not = false, - }) { - _appendCondition( - _createInCondition(column, values, not), - isOr: true, - ); + QueryBuilder orWhereIn(String column, List values, {bool not = false}) { + _appendCondition(_createInCondition(column, values, not), isOr: true); return this; } @@ -165,16 +134,15 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { dynamic value, { bool not = false, }) { - _appendCondition(_createJsonContainsCondition(column, value, not), - isOr: true); + _appendCondition( + _createJsonContainsCondition(column, value, not), + isOr: true, + ); return this; } @override - QueryBuilder orWhereJsonDoesntContain( - String column, - dynamic value, - ) { + QueryBuilder orWhereJsonDoesntContain(String column, dynamic value) { _appendCondition( _createJsonContainsCondition(column, value, true), isOr: true, @@ -202,19 +170,19 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { bool caseSensitive = false, }) { _appendCondition( - _createLikeCondition(column, value, - not: false, caseSensitive: caseSensitive), + _createLikeCondition( + column, + value, + not: false, + caseSensitive: caseSensitive, + ), isOr: true, ); return this; } @override - QueryBuilder orWhereMonth( - String column, - String operator, - dynamic value, - ) { + QueryBuilder orWhereMonth(String column, String operator, dynamic value) { _appendCondition( _createDateCondition(column, operator, value, "MONTH"), isOr: true, @@ -224,26 +192,18 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { @override QueryBuilder orWhereNotBetween(String column, List values) { - _appendCondition( - _createBetweenCondition(column, values, true), - isOr: true, - ); + _appendCondition(_createBetweenCondition(column, values, true), isOr: true); return this; } @override - QueryBuilder orWhereNotExists( - QueryCallback callback, - ) { + QueryBuilder orWhereNotExists(QueryCallback callback) { return orWhereExists(callback, not: true); } @override QueryBuilder orWhereNotIn(String column, dynamic values) { - _appendCondition( - _createInCondition(column, values, true), - isOr: true, - ); + _appendCondition(_createInCondition(column, values, true), isOr: true); return this; } @@ -255,8 +215,12 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { String boolean = 'and', }) { _appendCondition( - _createLikeCondition(column, value, - not: true, caseSensitive: caseSensitive), + _createLikeCondition( + column, + value, + not: true, + caseSensitive: caseSensitive, + ), isOr: (boolean.toLowerCase() == 'or'), ); return this; @@ -264,27 +228,18 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { @override QueryBuilder orWhereNotNull(String column) { - _appendCondition( - _createNullCondition(column, true), - isOr: true, - ); + _appendCondition(_createNullCondition(column, true), isOr: true); return this; } @override QueryBuilder orWhereNull(String column) { - _appendCondition( - _createNullCondition(column, false), - isOr: true, - ); + _appendCondition(_createNullCondition(column, false), isOr: true); return this; } @override - QueryBuilder orWhereRaw( - String sql, [ - List rawBindings = const [], - ]) { + QueryBuilder orWhereRaw(String sql, [List rawBindings = const []]) { String processedSQL = _processRawSQL(sql, rawBindings); _appendCondition(processedSQL, isOr: true); return this; @@ -304,11 +259,7 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { } @override - QueryBuilder orWhereTime( - String column, - String operator, - dynamic value, - ) { + QueryBuilder orWhereTime(String column, String operator, dynamic value) { _appendCondition( _createDateCondition(column, operator, value, "TIME"), isOr: true, @@ -317,11 +268,7 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { } @override - QueryBuilder orWhereYear( - String column, - String operator, - dynamic value, - ) { + QueryBuilder orWhereYear(String column, String operator, dynamic value) { _appendCondition( _createDateCondition(column, operator, value, "YEAR"), isOr: true, @@ -339,14 +286,18 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { if (condition is String) { final paramName = _nextParamName(); bindings[paramName] = value; - _appendCondition("$condition $operator :$paramName", - isOr: (boolean.toLowerCase() == 'or')); + _appendCondition( + "$condition $operator :$paramName", + isOr: (boolean.toLowerCase() == 'or'), + ); } else if (condition is QueryCallback) { QueryBuilderImpl nested = QueryBuilderImpl() ..paramCounter = _paramCounter; condition(nested); - _appendCondition("(${nested.toSql()})", - isOr: (boolean.toLowerCase() == 'or')); + _appendCondition( + "(${nested.toSql()})", + isOr: (boolean.toLowerCase() == 'or'), + ); bindings.addAll(nested.getBindings()); } else { throw InvalidArgumentException( @@ -357,10 +308,7 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { } @override - QueryBuilder whereAfterToday( - String column, { - String boolean = 'and', - }) { + QueryBuilder whereAfterToday(String column, {String boolean = 'and'}) { _appendCondition( "DATE($column) > CURDATE()", isOr: (boolean.toLowerCase() == 'or'), @@ -375,9 +323,7 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { String boolean = 'and', }) { if (values.isEmpty) { - throw InvalidArgumentException( - "The list of values must not be empty.", - ); + throw InvalidArgumentException("The list of values must not be empty."); } List conditions = []; @@ -401,9 +347,7 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { String boolean = 'and', }) { if (values.isEmpty) { - throw InvalidArgumentException( - "The list of values must not be empty.", - ); + throw InvalidArgumentException("The list of values must not be empty."); } _appendCondition( @@ -414,10 +358,7 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { } @override - QueryBuilder whereBeforeToday( - String column, { - String boolean = 'and', - }) { + QueryBuilder whereBeforeToday(String column, {String boolean = 'and'}) { _appendCondition( "DATE($column) < CURDATE()", isOr: (boolean.toLowerCase() == 'or'), @@ -426,8 +367,12 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { } @override - QueryBuilder whereBetween(String column, List values, - {String boolean = 'and', bool not = false}) { + QueryBuilder whereBetween( + String column, + List values, { + String boolean = 'and', + bool not = false, + }) { _appendCondition( _createBetweenCondition(column, values, not), isOr: (boolean.toLowerCase() == 'or'), @@ -456,10 +401,7 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { String boolean = 'and', ]) { String condition = "$firstColumn $operator $secondColumn"; - _appendCondition( - condition, - isOr: (boolean.toLowerCase() == 'or'), - ); + _appendCondition(condition, isOr: (boolean.toLowerCase() == 'or')); return this; } @@ -492,11 +434,7 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { } @override - QueryBuilder whereEqualTo( - condition, [ - value, - String boolean = 'and', - ]) => + QueryBuilder whereEqualTo(condition, [value, String boolean = 'and']) => where(condition, '=', value, boolean); @override @@ -508,10 +446,7 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { QueryBuilder subQuery = QueryBuilderImpl(); callback(subQuery); String condition = "${not ? 'NOT EXISTS' : 'EXISTS'} (${subQuery.toSql()})"; - _appendCondition( - condition, - isOr: (boolean.toLowerCase() == 'or'), - ); + _appendCondition(condition, isOr: (boolean.toLowerCase() == 'or')); bindings.addAll(subQuery.getBindings()); return this; } @@ -530,23 +465,13 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { } @override - QueryBuilder whereFuture( - String column, { - String boolean = 'and', - }) { - _appendCondition( - "$column > NOW()", - isOr: (boolean.toLowerCase() == 'or'), - ); + QueryBuilder whereFuture(String column, {String boolean = 'and'}) { + _appendCondition("$column > NOW()", isOr: (boolean.toLowerCase() == 'or')); return this; } @override - QueryBuilder whereGreaterThan( - condition, [ - value, - String boolean = 'and', - ]) => + QueryBuilder whereGreaterThan(condition, [value, String boolean = 'and']) => where(condition, '>', value, boolean); @override @@ -554,8 +479,7 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { condition, [ value, String boolean = 'and', - ]) => - where(condition, '>=', value, boolean); + ]) => where(condition, '>=', value, boolean); @override QueryBuilder whereHour( @@ -564,8 +488,10 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { dynamic value, { String boolean = 'and', }) { - _appendCondition(_createHourCondition(column, operator, value), - isOr: (boolean.toLowerCase() == 'or')); + _appendCondition( + _createHourCondition(column, operator, value), + isOr: (boolean.toLowerCase() == 'or'), + ); return this; } @@ -625,11 +551,7 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { } @override - QueryBuilder whereLessThan( - condition, [ - value, - String boolean = 'and', - ]) => + QueryBuilder whereLessThan(condition, [value, String boolean = 'and']) => where(condition, '<', value, boolean); @override @@ -637,8 +559,7 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { condition, [ value, String boolean = 'and', - ]) => - where(condition, '<=', value, boolean); + ]) => where(condition, '<=', value, boolean); @override QueryBuilder whereLike( @@ -648,8 +569,12 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { String boolean = 'and', }) { _appendCondition( - _createLikeCondition(column, value, - not: false, caseSensitive: caseSensitive), + _createLikeCondition( + column, + value, + not: false, + caseSensitive: caseSensitive, + ), isOr: (boolean.toLowerCase() == 'or'), ); return this; @@ -676,9 +601,7 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { String boolean = 'and', }) { if (values.isEmpty) { - throw InvalidArgumentException( - "The list of values must not be empty.", - ); + throw InvalidArgumentException("The list of values must not be empty."); } _appendCondition( @@ -715,11 +638,7 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { } @override - QueryBuilder whereNotEqualTo( - condition, [ - value, - String boolean = 'and', - ]) => + QueryBuilder whereNotEqualTo(condition, [value, String boolean = 'and']) => where(condition, '<>', value, boolean); @override @@ -751,18 +670,19 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { String boolean = 'and', }) { _appendCondition( - _createLikeCondition(column, value, - not: true, caseSensitive: caseSensitive), + _createLikeCondition( + column, + value, + not: true, + caseSensitive: caseSensitive, + ), isOr: (boolean.toLowerCase() == 'or'), ); return this; } @override - QueryBuilder whereNotNull( - String column, { - String boolean = 'and', - }) { + QueryBuilder whereNotNull(String column, {String boolean = 'and'}) { _appendCondition( _createNullCondition(column, true), isOr: (boolean.toLowerCase() == 'or'), @@ -771,26 +691,14 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { } @override - QueryBuilder whereNowOrFuture( - String column, { - String boolean = 'and', - }) { - _appendCondition( - "$column >= NOW()", - isOr: (boolean.toLowerCase() == 'or'), - ); + QueryBuilder whereNowOrFuture(String column, {String boolean = 'and'}) { + _appendCondition("$column >= NOW()", isOr: (boolean.toLowerCase() == 'or')); return this; } @override - QueryBuilder whereNowOrPast( - String column, { - String boolean = 'and', - }) { - _appendCondition( - "$column <= NOW()", - isOr: (boolean.toLowerCase() == 'or'), - ); + QueryBuilder whereNowOrPast(String column, {String boolean = 'and'}) { + _appendCondition("$column <= NOW()", isOr: (boolean.toLowerCase() == 'or')); return this; } @@ -808,14 +716,8 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { } @override - QueryBuilder wherePast( - String column, { - String boolean = 'and', - }) { - _appendCondition( - "$column < NOW()", - isOr: (boolean.toLowerCase() == 'or'), - ); + QueryBuilder wherePast(String column, {String boolean = 'and'}) { + _appendCondition("$column < NOW()", isOr: (boolean.toLowerCase() == 'or')); return this; } @@ -826,10 +728,7 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { String boolean = 'and', ]) { String processedSQL = _processRawSQL(sql, rawBindings); - _appendCondition( - processedSQL, - isOr: (boolean.toLowerCase() == 'or'), - ); + _appendCondition(processedSQL, isOr: (boolean.toLowerCase() == 'or')); return this; } @@ -862,10 +761,7 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { } @override - QueryBuilder whereToday( - String column, { - String boolean = 'and', - }) { + QueryBuilder whereToday(String column, {String boolean = 'and'}) { _appendCondition( "DATE($column) = CURDATE()", isOr: (boolean.toLowerCase() == 'or'), @@ -874,10 +770,7 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { } @override - QueryBuilder whereTodayOrAfter( - String column, { - String boolean = 'and', - }) { + QueryBuilder whereTodayOrAfter(String column, {String boolean = 'and'}) { _appendCondition( "DATE($column) >= CURDATE()", isOr: (boolean.toLowerCase() == 'or'), @@ -886,10 +779,7 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { } @override - QueryBuilder whereTodayOrBefore( - String column, { - String boolean = 'and', - }) { + QueryBuilder whereTodayOrBefore(String column, {String boolean = 'and'}) { _appendCondition( "DATE($column) <= CURDATE()", isOr: (boolean.toLowerCase() == 'or'), @@ -918,18 +808,12 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { String boolean = 'and', }) { String condition = _createRelationshipCondition(relation, callback, false); - _appendCondition( - condition, - isOr: (boolean.toLowerCase() == 'or'), - ); + _appendCondition(condition, isOr: (boolean.toLowerCase() == 'or')); return this; } @override - QueryBuilder orWhereHas( - String relation, - QueryCallback callback, - ) { + QueryBuilder orWhereHas(String relation, QueryCallback callback) { String condition = _createRelationshipCondition(relation, callback, false); _appendCondition(condition, isOr: true); return this; @@ -942,18 +826,12 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { String boolean = 'and', }) { String condition = _createRelationshipCondition(relation, callback, true); - _appendCondition( - condition, - isOr: (boolean.toLowerCase() == 'or'), - ); + _appendCondition(condition, isOr: (boolean.toLowerCase() == 'or')); return this; } @override - QueryBuilder orWhereDoesntHave( - String relation, - QueryCallback callback, - ) { + QueryBuilder orWhereDoesntHave(String relation, QueryCallback callback) { String condition = _createRelationshipCondition(relation, callback, true); _appendCondition(condition, isOr: true); return this; @@ -1009,8 +887,11 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { } } - String _createBetweenColumnsCondition(String column, List columns, - {bool not = false}) { + String _createBetweenColumnsCondition( + String column, + List columns, { + bool not = false, + }) { if (columns.length < 2) { throw InvalidArgumentException( 'At least two columns must be provided for whereBetweenColumns.', @@ -1020,11 +901,7 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { return "$column $op ${columns[0]} AND ${columns[1]}"; } - String _createBetweenCondition( - String column, - List values, - bool not, - ) { + String _createBetweenCondition(String column, List values, bool not) { if (values.length < 2) { throw InvalidArgumentException( 'The list of values must contain at least two items.', @@ -1080,11 +957,7 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { return "MATCH($colStr) AGAINST(:$paramName$mode)"; } - String _createHourCondition( - String column, - String operator, - dynamic value, - ) { + String _createHourCondition(String column, String operator, dynamic value) { if (value == null) { throw InvalidArgumentException( 'The value for whereHour must not be null.', @@ -1097,11 +970,7 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { return "HOUR($column) $operator :$paramName"; } - String _createInCondition( - String column, - dynamic values, - bool not, - ) { + String _createInCondition(String column, dynamic values, bool not) { String clause = not ? "NOT IN" : "IN"; if (values is List) { @@ -1130,11 +999,7 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { } } - String _createJsonContainsCondition( - String column, - dynamic value, - bool not, - ) { + String _createJsonContainsCondition(String column, dynamic value, bool not) { final paramName = _nextParamName(); bindings[paramName] = value; @@ -1156,8 +1021,12 @@ abstract mixin class WhereClausesBuilderImpl implements QueryBuilder { return "JSON_LENGTH($column) $operator :$paramName"; } - String _createLikeCondition(String column, dynamic value, - {bool not = false, bool caseSensitive = false}) { + String _createLikeCondition( + String column, + dynamic value, { + bool not = false, + bool caseSensitive = false, + }) { final paramName = _nextParamName(); bindings[paramName] = value; diff --git a/lib/src/database/query_builder/_window_functions_builder_impl.dart b/lib/src/database/query_builder/_window_functions_builder_impl.dart index e2a10c7f..7f1d8760 100644 --- a/lib/src/database/query_builder/_window_functions_builder_impl.dart +++ b/lib/src/database/query_builder/_window_functions_builder_impl.dart @@ -23,7 +23,10 @@ abstract mixin class WindowFunctionsBuilderImpl implements QueryBuilder { } void _addWindowFunction( - String functionName, String overClause, String? alias) { + String functionName, + String overClause, + String? alias, + ) { String windowFunc = "$functionName $overClause"; if (alias != null && alias.isNotEmpty) { windowFunc += " AS $alias"; @@ -34,37 +37,31 @@ abstract mixin class WindowFunctionsBuilderImpl implements QueryBuilder { } @override - QueryBuilder rowNumber({ - String? partitionBy, - String? orderBy, - String? as, - }) { - final overClause = - _buildOverClause(partitionBy: partitionBy, orderBy: orderBy); + QueryBuilder rowNumber({String? partitionBy, String? orderBy, String? as}) { + final overClause = _buildOverClause( + partitionBy: partitionBy, + orderBy: orderBy, + ); _addWindowFunction("ROW_NUMBER()", overClause, as); return this; } @override - QueryBuilder rank({ - String? partitionBy, - String? orderBy, - String? as, - }) { - final overClause = - _buildOverClause(partitionBy: partitionBy, orderBy: orderBy); + QueryBuilder rank({String? partitionBy, String? orderBy, String? as}) { + final overClause = _buildOverClause( + partitionBy: partitionBy, + orderBy: orderBy, + ); _addWindowFunction("RANK()", overClause, as); return this; } @override - QueryBuilder denseRank({ - String? partitionBy, - String? orderBy, - String? as, - }) { - final overClause = - _buildOverClause(partitionBy: partitionBy, orderBy: orderBy); + QueryBuilder denseRank({String? partitionBy, String? orderBy, String? as}) { + final overClause = _buildOverClause( + partitionBy: partitionBy, + orderBy: orderBy, + ); _addWindowFunction("DENSE_RANK()", overClause, as); return this; } @@ -80,7 +77,8 @@ abstract mixin class WindowFunctionsBuilderImpl implements QueryBuilder { }) { if (column.isEmpty) { throw InvalidArgumentException( - 'Column name cannot be empty for LAG function'); + 'Column name cannot be empty for LAG function', + ); } String lagFunc = "LAG($column, $offset"; @@ -93,8 +91,10 @@ abstract mixin class WindowFunctionsBuilderImpl implements QueryBuilder { } lagFunc += ")"; - final overClause = - _buildOverClause(partitionBy: partitionBy, orderBy: orderBy); + final overClause = _buildOverClause( + partitionBy: partitionBy, + orderBy: orderBy, + ); _addWindowFunction(lagFunc, overClause, as); return this; } @@ -110,7 +110,8 @@ abstract mixin class WindowFunctionsBuilderImpl implements QueryBuilder { }) { if (column.isEmpty) { throw InvalidArgumentException( - 'Column name cannot be empty for LEAD function'); + 'Column name cannot be empty for LEAD function', + ); } String leadFunc = "LEAD($column, $offset"; @@ -123,8 +124,10 @@ abstract mixin class WindowFunctionsBuilderImpl implements QueryBuilder { } leadFunc += ")"; - final overClause = - _buildOverClause(partitionBy: partitionBy, orderBy: orderBy); + final overClause = _buildOverClause( + partitionBy: partitionBy, + orderBy: orderBy, + ); _addWindowFunction(leadFunc, overClause, as); return this; } @@ -138,11 +141,14 @@ abstract mixin class WindowFunctionsBuilderImpl implements QueryBuilder { }) { if (column.isEmpty) { throw InvalidArgumentException( - 'Column name cannot be empty for FIRST_VALUE function'); + 'Column name cannot be empty for FIRST_VALUE function', + ); } - final overClause = - _buildOverClause(partitionBy: partitionBy, orderBy: orderBy); + final overClause = _buildOverClause( + partitionBy: partitionBy, + orderBy: orderBy, + ); _addWindowFunction("FIRST_VALUE($column)", overClause, as); return this; } @@ -156,11 +162,14 @@ abstract mixin class WindowFunctionsBuilderImpl implements QueryBuilder { }) { if (column.isEmpty) { throw InvalidArgumentException( - 'Column name cannot be empty for LAST_VALUE function'); + 'Column name cannot be empty for LAST_VALUE function', + ); } - final overClause = - _buildOverClause(partitionBy: partitionBy, orderBy: orderBy); + final overClause = _buildOverClause( + partitionBy: partitionBy, + orderBy: orderBy, + ); _addWindowFunction("LAST_VALUE($column)", overClause, as); return this; } @@ -174,35 +183,34 @@ abstract mixin class WindowFunctionsBuilderImpl implements QueryBuilder { }) { if (buckets <= 0) { throw InvalidArgumentException( - 'Number of buckets must be greater than 0'); + 'Number of buckets must be greater than 0', + ); } - final overClause = - _buildOverClause(partitionBy: partitionBy, orderBy: orderBy); + final overClause = _buildOverClause( + partitionBy: partitionBy, + orderBy: orderBy, + ); _addWindowFunction("NTILE($buckets)", overClause, as); return this; } @override - QueryBuilder percentRank({ - String? partitionBy, - String? orderBy, - String? as, - }) { - final overClause = - _buildOverClause(partitionBy: partitionBy, orderBy: orderBy); + QueryBuilder percentRank({String? partitionBy, String? orderBy, String? as}) { + final overClause = _buildOverClause( + partitionBy: partitionBy, + orderBy: orderBy, + ); _addWindowFunction("PERCENT_RANK()", overClause, as); return this; } @override - QueryBuilder cumeDist({ - String? partitionBy, - String? orderBy, - String? as, - }) { - final overClause = - _buildOverClause(partitionBy: partitionBy, orderBy: orderBy); + QueryBuilder cumeDist({String? partitionBy, String? orderBy, String? as}) { + final overClause = _buildOverClause( + partitionBy: partitionBy, + orderBy: orderBy, + ); _addWindowFunction("CUME_DIST()", overClause, as); return this; } @@ -216,11 +224,14 @@ abstract mixin class WindowFunctionsBuilderImpl implements QueryBuilder { }) { if (column.isEmpty) { throw InvalidArgumentException( - 'Column name cannot be empty for SUM window function'); + 'Column name cannot be empty for SUM window function', + ); } - final overClause = - _buildOverClause(partitionBy: partitionBy, orderBy: orderBy); + final overClause = _buildOverClause( + partitionBy: partitionBy, + orderBy: orderBy, + ); _addWindowFunction("SUM($column)", overClause, as); return this; } @@ -234,11 +245,14 @@ abstract mixin class WindowFunctionsBuilderImpl implements QueryBuilder { }) { if (column.isEmpty) { throw InvalidArgumentException( - 'Column name cannot be empty for AVG window function'); + 'Column name cannot be empty for AVG window function', + ); } - final overClause = - _buildOverClause(partitionBy: partitionBy, orderBy: orderBy); + final overClause = _buildOverClause( + partitionBy: partitionBy, + orderBy: orderBy, + ); _addWindowFunction("AVG($column)", overClause, as); return this; } @@ -252,11 +266,14 @@ abstract mixin class WindowFunctionsBuilderImpl implements QueryBuilder { }) { if (column.isEmpty) { throw InvalidArgumentException( - 'Column name cannot be empty for COUNT window function'); + 'Column name cannot be empty for COUNT window function', + ); } - final overClause = - _buildOverClause(partitionBy: partitionBy, orderBy: orderBy); + final overClause = _buildOverClause( + partitionBy: partitionBy, + orderBy: orderBy, + ); _addWindowFunction("COUNT($column)", overClause, as); return this; } @@ -270,11 +287,14 @@ abstract mixin class WindowFunctionsBuilderImpl implements QueryBuilder { }) { if (column.isEmpty) { throw InvalidArgumentException( - 'Column name cannot be empty for MAX window function'); + 'Column name cannot be empty for MAX window function', + ); } - final overClause = - _buildOverClause(partitionBy: partitionBy, orderBy: orderBy); + final overClause = _buildOverClause( + partitionBy: partitionBy, + orderBy: orderBy, + ); _addWindowFunction("MAX($column)", overClause, as); return this; } @@ -288,11 +308,14 @@ abstract mixin class WindowFunctionsBuilderImpl implements QueryBuilder { }) { if (column.isEmpty) { throw InvalidArgumentException( - 'Column name cannot be empty for MIN window function'); + 'Column name cannot be empty for MIN window function', + ); } - final overClause = - _buildOverClause(partitionBy: partitionBy, orderBy: orderBy); + final overClause = _buildOverClause( + partitionBy: partitionBy, + orderBy: orderBy, + ); _addWindowFunction("MIN($column)", overClause, as); return this; } diff --git a/lib/src/database/seeder/seeder_factory.dart b/lib/src/database/seeder/seeder_factory.dart index 5da55410..6ecdfb54 100644 --- a/lib/src/database/seeder/seeder_factory.dart +++ b/lib/src/database/seeder/seeder_factory.dart @@ -18,8 +18,10 @@ abstract class SeederFactory { return data; } - List> makeMany(int count, - [Map? attributes]) { + List> makeMany( + int count, [ + Map? attributes, + ]) { return List.generate(count, (index) => make(attributes)); } @@ -27,8 +29,10 @@ abstract class SeederFactory { return make(attributes); } - List> createMany(int count, - [Map? attributes]) { + List> createMany( + int count, [ + Map? attributes, + ]) { return makeMany(count, attributes); } @@ -65,8 +69,12 @@ abstract class SeederFactory { if (includeNumbers) chars += numbers; if (includeSymbols) chars += symbols; - return String.fromCharCodes(Iterable.generate( - length, (_) => chars.codeUnitAt(_random.nextInt(chars.length)))); + return String.fromCharCodes( + Iterable.generate( + length, + (_) => chars.codeUnitAt(_random.nextInt(chars.length)), + ), + ); } String randomEmail() { @@ -85,11 +93,13 @@ abstract class SeederFactory { 'live.com', 'msn.com', 'fastmail.com', - 'tutanota.com' + 'tutanota.com', ]; - final username = - randomString(8, includeNumbers: true, includeSymbols: false) - .toLowerCase(); + final username = randomString( + 8, + includeNumbers: true, + includeSymbols: false, + ).toLowerCase(); final domain = randomElement(domains); return '$username@$domain'; } @@ -196,7 +206,7 @@ abstract class SeederFactory { 'Carter', 'Harper', 'Sebastian', - 'Evelyn' + 'Evelyn', ]; final lastNames = [ 'Smith', @@ -324,7 +334,7 @@ abstract class SeederFactory { 'Alexander', 'Hamilton', 'Graham', - 'Reynolds' + 'Reynolds', ]; return '${randomElement(firstNames)} ${randomElement(lastNames)}'; @@ -419,14 +429,16 @@ abstract class SeederFactory { 'anim', 'id', 'est', - 'laborum' + 'laborum', ]; final result = []; for (int i = 0; i < sentences; i++) { final sentenceLength = randomInt(5, 15); - final sentence = - List.generate(sentenceLength, (_) => randomElement(words)); + final sentence = List.generate( + sentenceLength, + (_) => randomElement(words), + ); sentence[0] = sentence[0][0].toUpperCase() + sentence[0].substring(1); result.add('${sentence.join(' ')}.'); } @@ -434,8 +446,11 @@ abstract class SeederFactory { return result.join(' '); } - double randomPrice( - [double min = 1.0, double max = 1000.0, int decimals = 2]) { + double randomPrice([ + double min = 1.0, + double max = 1000.0, + int decimals = 2, + ]) { return double.parse(randomDouble(min, max).toStringAsFixed(decimals)); } diff --git a/lib/src/database/seeder/seeder_runner.dart b/lib/src/database/seeder/seeder_runner.dart index e6b77875..01ef196d 100644 --- a/lib/src/database/seeder/seeder_runner.dart +++ b/lib/src/database/seeder/seeder_runner.dart @@ -18,19 +18,19 @@ class SeederRunner { SeederRunner._internal(); DBConfig _config(Map database) => DBConfig( - driver: database['driver'] ?? '', - host: database['host'] ?? '', - port: database['port'] ?? '', - database: database['database'] ?? '', - username: database['username'] ?? '', - password: database['password'] ?? '', - sslMode: database['sslmode'] ?? '', - collation: database['collation'] ?? '', - pool: database['pool'] ?? false, - poolSize: database['poolsize'] ?? 0, - filePath: database['file_path'] ?? '', - openInMemorySQLite: database['openInMemorySQLite'] ?? false, - ); + driver: database['driver'] ?? '', + host: database['host'] ?? '', + port: database['port'] ?? '', + database: database['database'] ?? '', + username: database['username'] ?? '', + password: database['password'] ?? '', + sslMode: database['sslmode'] ?? '', + collation: database['collation'] ?? '', + pool: database['pool'] ?? false, + poolSize: database['poolsize'] ?? 0, + filePath: database['file_path'] ?? '', + openInMemorySQLite: database['openInMemorySQLite'] ?? false, + ); Future setup({ required Map database, @@ -57,7 +57,8 @@ class SeederRunner { await seeder.run(); stopwatch.stop(); stderr.writeln( - ' Seeder ${toSnakeCase(seeder.runtimeType.toString())} executed ....................................\x1B[32m ${stopwatch.elapsedMilliseconds}ms DONE\x1B[0m'); + ' Seeder ${toSnakeCase(seeder.runtimeType.toString())} executed ....................................\x1B[32m ${stopwatch.elapsedMilliseconds}ms DONE\x1B[0m', + ); } on QueryException catch (e) { stopwatch.stop(); stderr.write(e.cause); @@ -66,8 +67,9 @@ class SeederRunner { } } await ConnectionManager().connection(database['default'])!.close(); - stderr - .write('\x1B[32m All database seeders executed successfully \x1B[0m'); + stderr.write( + '\x1B[32m All database seeders executed successfully \x1B[0m', + ); exit(0); } } diff --git a/lib/src/enum/column_index.dart b/lib/src/enum/column_index.dart index 4d62cdb0..4dd6b2d5 100644 --- a/lib/src/enum/column_index.dart +++ b/lib/src/enum/column_index.dart @@ -1,6 +1 @@ -enum ColumnIndex { - unique, - indexKey, - fulltext, - spatial, -} +enum ColumnIndex { unique, indexKey, fulltext, spatial } diff --git a/lib/src/exception/http_exception.dart b/lib/src/exception/http_exception.dart index f6787053..0ffe5270 100644 --- a/lib/src/exception/http_exception.dart +++ b/lib/src/exception/http_exception.dart @@ -2,8 +2,5 @@ import 'dart:io'; import 'base_http_exception.dart'; class HttpResponseException extends BaseHttpResponseException { - HttpResponseException({ - super.message, - super.code = HttpStatus.found, - }); + HttpResponseException({super.message, super.code = HttpStatus.found}); } diff --git a/lib/src/exception/query_exception.dart b/lib/src/exception/query_exception.dart index f813d8a5..b8bbf77d 100644 --- a/lib/src/exception/query_exception.dart +++ b/lib/src/exception/query_exception.dart @@ -1,6 +1,4 @@ class QueryException implements Exception { final String? cause; - QueryException([ - this.cause, - ]); + QueryException([this.cause]); } diff --git a/lib/src/exception/throttle_exception.dart b/lib/src/exception/throttle_exception.dart index f39acf05..91e36c2a 100644 --- a/lib/src/exception/throttle_exception.dart +++ b/lib/src/exception/throttle_exception.dart @@ -21,8 +21,11 @@ class ThrottleException extends BaseHttpResponseException { : {'message': message}; if (headers != null) { - return Response.jsonWithHeader(responseData, - statusCode: code, headers: headers!); + return Response.jsonWithHeader( + responseData, + statusCode: code, + headers: headers!, + ); } return Response.json(responseData, code); diff --git a/lib/src/exception/unauthenticated.dart b/lib/src/exception/unauthenticated.dart index bcafa631..d349fcaf 100644 --- a/lib/src/exception/unauthenticated.dart +++ b/lib/src/exception/unauthenticated.dart @@ -3,8 +3,9 @@ import 'dart:io'; import 'base_http_exception.dart'; class Unauthenticated extends BaseHttpResponseException { - Unauthenticated( - {required super.message, - super.code = HttpStatus.unauthorized, - super.responseType}); + Unauthenticated({ + required super.message, + super.code = HttpStatus.unauthorized, + super.responseType, + }); } diff --git a/lib/src/extensions/localization_extension.dart b/lib/src/extensions/localization_extension.dart index 81a7b8f1..945f0f50 100644 --- a/lib/src/extensions/localization_extension.dart +++ b/lib/src/extensions/localization_extension.dart @@ -1,10 +1,7 @@ import 'package:vania/src/localization_handler/localization.dart'; extension LocalizationExtension on String { - String trans({ - Map? args, - String? locale, - }) { + String trans({Map? args, String? locale}) { return Localization().trans(this, args, locale); } } diff --git a/lib/src/http/controller/controller_handler.dart b/lib/src/http/controller/controller_handler.dart index 63ff5dc2..8563fdb5 100644 --- a/lib/src/http/controller/controller_handler.dart +++ b/lib/src/http/controller/controller_handler.dart @@ -26,10 +26,7 @@ class ControllerHandler { } } - void create({ - required RouteData route, - required Request request, - }) async { + void create({required RouteData route, required Request request}) async { List positionalArguments = []; if (route.params != null) { try { @@ -54,11 +51,14 @@ class ControllerHandler { response.makeResponse(request.response); } on ValidationException catch (error) { - bool isHtml = - request.request.headers.value('accept').toString().contains('html'); + bool isHtml = request.request.headers + .value('accept') + .toString() + .contains('html'); if (isHtml) { - Response.redirect(RouteHistory().previousRoute) - .makeResponse(request.response); + Response.redirect( + RouteHistory().previousRoute, + ).makeResponse(request.response); } else { error.response(false).makeResponse(request.response); } @@ -80,11 +80,6 @@ void _response(Request req, message, [statusCode = 500]) { if (req.headers['accept'].toString().contains('html')) { Response.html(message).makeResponse(req.response); } else { - Response.json( - { - "message": message, - }, - statusCode, - ).makeResponse(req.response); + Response.json({"message": message}, statusCode).makeResponse(req.response); } } diff --git a/lib/src/http/request/request.dart b/lib/src/http/request/request.dart index 66c05b40..97a5f3c3 100644 --- a/lib/src/http/request/request.dart +++ b/lib/src/http/request/request.dart @@ -101,9 +101,12 @@ class Request { Future extractBody() async { _extractCookies(); - final whereMethod = ['post', 'patch', 'put', 'delete'] - .where((method) => method == request.method.toLowerCase()) - .toList(); + final whereMethod = [ + 'post', + 'patch', + 'put', + 'delete', + ].where((method) => method == request.method.toLowerCase()).toList(); if (whereMethod.isNotEmpty) { body = await RequestBody.extractBody(request: request); } @@ -228,7 +231,8 @@ class Request { return _all[key]; } - bool hasFile(String key) => (_all[key].toString().isNotEmpty && + bool hasFile(String key) => + (_all[key].toString().isNotEmpty && (file(key) != null || files(key) != null)); List? files(String key) { @@ -276,10 +280,7 @@ class Request { } } - dynamic query([ - String? key, - String? defaultVal, - ]) { + dynamic query([String? key, String? defaultVal]) { if (key == null) { return _query.values; } @@ -349,20 +350,23 @@ class Request { Map messages = const {}, ]) async { assert( - rules is Map || - rules is List || - rules is List || - rules is FormValidation, - 'Rules must be either Map or List. or FormRequest'); + rules is Map || + rules is List || + rules is List || + rules is FormValidation, + 'Rules must be either Map or List. or FormRequest', + ); TemplateEngine().sessionErrors.clear(); if (rules is Map) { await _validate(rules, messages); } else if (rules is List) { Map ruleMessages = Map.from(messages); - final rulesMap = Map.fromEntries(rules.map((rule) { - ruleMessages.addAll(rule.toMapMessages); - return MapEntry(rule.fieldName, rule.toString()); - })); + final rulesMap = Map.fromEntries( + rules.map((rule) { + ruleMessages.addAll(rule.toMapMessages); + return MapEntry(rule.fieldName, rule.toString()); + }), + ); await _validate(rulesMap, ruleMessages); } else if (rules is FormValidation) { await _formRequestValidate(rules); @@ -387,10 +391,12 @@ class Request { Map rulesMap = {}; if (rules is List) { - rulesMap = Map.fromEntries(rules.map((rule) { - messages.addAll(rule.toMapMessages); - return MapEntry(rule.fieldName, rule.toString()); - })); + rulesMap = Map.fromEntries( + rules.map((rule) { + messages.addAll(rule.toMapMessages); + return MapEntry(rule.fieldName, rule.toString()); + }), + ); } else { rulesMap = formRequest.rules(); } @@ -436,8 +442,9 @@ class Request { Map errors = {}; final data = all(); for (Validation validation in validations) { - dynamic fieldValue = - data.containsKey(validation.field) ? data[validation.field] : null; + dynamic fieldValue = data.containsKey(validation.field) + ? data[validation.field] + : null; for (ValidationRule rule in validation.rules) { if (!rule.validate(fieldValue, data)) { errors[validation.field] = rule.errorMessage; diff --git a/lib/src/http/request/request_body.dart b/lib/src/http/request/request_body.dart index cff67700..fae5cad7 100644 --- a/lib/src/http/request/request_body.dart +++ b/lib/src/http/request/request_body.dart @@ -9,8 +9,10 @@ import 'package:vania/vania.dart' show env; class RequestBody { const RequestBody(); - static final int _maxBodySizeBytes = - env('MAX_BODY_SIZE', 10 * 1024 * 1024); + static final int _maxBodySizeBytes = env( + 'MAX_BODY_SIZE', + 10 * 1024 * 1024, + ); static Future> extractBody({ required HttpRequest request, diff --git a/lib/src/http/request/request_file.dart b/lib/src/http/request/request_file.dart index 553e9bf7..d80b0477 100644 --- a/lib/src/http/request/request_file.dart +++ b/lib/src/http/request/request_file.dart @@ -55,18 +55,18 @@ class RequestFile { /// Store the file via your Storage layer. /// - `destPath` should include trailing slash if desired. - Future store({ - String path = '', - required String name, - }) => - Storage.put(path, name, stream); + Future store({String path = '', required String name}) async { + try { + final content = await bytes; + return await Storage.put(path, name, content.toList()); + } catch (e) { + throw FileSystemException('Failed to store file as $name: $e'); + } + } /// Move the file into a local path on disk. /// Creates directories as needed. - Future move({ - required String toPath, - required String name, - }) async { + Future move({required String toPath, required String name}) async { final fullPath = sanitizeRoutePath('$toPath/$name'); final file = File(fullPath); await file.parent.create(recursive: true); diff --git a/lib/src/http/request/request_form_data.dart b/lib/src/http/request/request_form_data.dart index c7b10d98..fb445570 100644 --- a/lib/src/http/request/request_form_data.dart +++ b/lib/src/http/request/request_form_data.dart @@ -24,8 +24,10 @@ class RequestFormData { // split request stream into MimeMultipart parts final transformer = MimeMultipartTransformer(boundary); - final parts = - await request.cast>().transform(transformer).toList(); + final parts = await request + .cast>() + .transform(transformer) + .toList(); for (final part in parts) { final disposition = part.headers['content-disposition']; @@ -44,10 +46,9 @@ class RequestFormData { final filename = params['filename']; if (filename == null || filename.isEmpty) { // text field - final raw = utf8.decode(await part.fold>( - [], - (buf, b) => buf..addAll(b), - )); + final raw = utf8.decode( + await part.fold>([], (buf, b) => buf..addAll(b)), + ); final value = int.tryParse(raw) ?? raw; if (name.endsWith('[]')) { final key = name.substring(0, name.length - 2); diff --git a/lib/src/http/request/request_handler.dart b/lib/src/http/request/request_handler.dart index c3844ee0..bc7bf2c3 100644 --- a/lib/src/http/request/request_handler.dart +++ b/lib/src/http/request/request_handler.dart @@ -62,9 +62,10 @@ class RequestHandler { if (isHtml) { TemplateEngine().formData.addAll(request.all()); - await IoCContainer() - .resolve() - .sessionStart(req, req.response); + await IoCContainer().resolve().sessionStart( + req, + req.response, + ); RouteHistory().updateRouteHistory(req); } if (env('CSRF_PROTECTION_ENABLED', false)) { @@ -77,10 +78,7 @@ class RequestHandler { } /// Controller and method handler - ControllerHandler().create( - route: route, - request: request, - ); + ControllerHandler().create(route: route, request: request); if (env('APP_DEBUG')) { var endTime = DateTime.now(); @@ -89,7 +87,8 @@ class RequestHandler { ? requestUri.padRight(118 - requestUri.length, '.') : ''.padRight(118, '.'); stderr.writeln( - '$starteRequest $requestMethod $requestedPath ~ ${duration}ms'); + '$starteRequest $requestMethod $requestedPath ~ ${duration}ms', + ); } } } on BaseHttpResponseException catch (error) { @@ -119,11 +118,7 @@ class RequestHandler { return Response.redirect(error.message).makeResponse(req.response); } - error - .response( - isHtml, - ) - .makeResponse(req.response); + error.response(isHtml).makeResponse(req.response); } on InvalidArgumentException catch (e) { Logger.log(e.message, type: Logger.ERROR); _response(req, e.message); @@ -142,12 +137,9 @@ class RequestHandler { if (req.headers.value('accept').toString().contains('html')) { Response.html(message).makeResponse(req.response); } else { - Response.json( - { - "message": message, - }, - statusCode, - ).makeResponse(req.response); + Response.json({ + "message": message, + }, statusCode).makeResponse(req.response); } } } diff --git a/lib/src/http/response/response.dart b/lib/src/http/response/response.dart index 7ed17f7e..c106521a 100644 --- a/lib/src/http/response/response.dart +++ b/lib/src/http/response/response.dart @@ -6,15 +6,7 @@ import 'package:vania/src/http/response/stream_file.dart'; import 'package:vania/src/route/route_history.dart'; import 'package:vania/src/view_engine/template_engine.dart'; -enum ResponseType { - json, - none, - redirect, - html, - sse, - streamFile, - download, -} +enum ResponseType { json, none, redirect, html, sse, streamFile, download } class Response { @protected @@ -118,14 +110,12 @@ class Response { } static Response redirect(String location) => Response( - responseType: ResponseType.redirect, - data: location, - httpStatusCode: HttpStatus.found); + responseType: ResponseType.redirect, + data: location, + httpStatusCode: HttpStatus.found, + ); - static Response json( - dynamic jsonData, [ - int statusCode = HttpStatus.ok, - ]) => + static Response json(dynamic jsonData, [int statusCode = HttpStatus.ok]) => Response( data: jsonData, responseType: ResponseType.json, @@ -136,63 +126,52 @@ class Response { dynamic jsonData, { int statusCode = HttpStatus.ok, Map headers = const {}, - }) => - Response( - data: jsonData, - responseType: ResponseType.json, - httpStatusCode: statusCode, - headers: headers, - ); + }) => Response( + data: jsonData, + responseType: ResponseType.json, + httpStatusCode: statusCode, + headers: headers, + ); static Response html( dynamic htmlData, { Map headers = const {}, - }) => - Response( - data: htmlData, - responseType: ResponseType.html, - headers: headers, - ); + }) => Response( + data: htmlData, + responseType: ResponseType.html, + headers: headers, + ); static Response file( String fileName, Uint8List bytes, { Map headers = const {}, - }) => - Response( - data: { - "fileName": fileName, - "bytes": bytes, - }, - responseType: ResponseType.streamFile, - headers: headers, - ); + }) => Response( + data: {"fileName": fileName, "bytes": bytes}, + responseType: ResponseType.streamFile, + headers: headers, + ); static Response sse( Stream eventStream, { int statusCode = HttpStatus.ok, Map headers = const {}, - }) => - Response( - data: eventStream, - responseType: ResponseType.sse, - httpStatusCode: statusCode, - headers: headers, - ); + }) => Response( + data: eventStream, + responseType: ResponseType.sse, + httpStatusCode: statusCode, + headers: headers, + ); static Response download( String fileName, Uint8List bytes, { Map headers = const {}, - }) => - Response( - data: { - "fileName": fileName, - "bytes": bytes, - }, - responseType: ResponseType.download, - headers: headers, - ); + }) => Response( + data: {"fileName": fileName, "bytes": bytes}, + responseType: ResponseType.download, + headers: headers, + ); static Response back([String? key, String? message]) { String previousRoute = RouteHistory().previousRoute; diff --git a/lib/src/http/response/stream_file.dart b/lib/src/http/response/stream_file.dart index 81245f92..a44d67ab 100644 --- a/lib/src/http/response/stream_file.dart +++ b/lib/src/http/response/stream_file.dart @@ -6,10 +6,7 @@ import 'package:mime/mime.dart'; class StreamFile { final String fileName; final Uint8List bytes; - StreamFile({ - required this.fileName, - required this.bytes, - }); + StreamFile({required this.fileName, required this.bytes}); ContentType? _contentType; Stream>? _stream; diff --git a/lib/src/http/session/session_file_store.dart b/lib/src/http/session/session_file_store.dart index 0ad6ff45..39da1880 100644 --- a/lib/src/http/session/session_file_store.dart +++ b/lib/src/http/session/session_file_store.dart @@ -45,7 +45,9 @@ class SessionFileStore { "expiration": expiration, }; final String content = await VaniaEncryption.encryptString( - json.encode(sessionData), _secretKey); + json.encode(sessionData), + _secretKey, + ); final raf = await file.open(mode: FileMode.write); try { @@ -91,8 +93,10 @@ class SessionFileStore { await raf.close(); } - final String decrypted = - await VaniaEncryption.decryptString(fileContent, _secretKey); + final String decrypted = await VaniaEncryption.decryptString( + fileContent, + _secretKey, + ); if (decrypted.isEmpty) { return null; } @@ -100,8 +104,8 @@ class SessionFileStore { int expiration = int.tryParse(data['expiration'].toString()) ?? 0; if (!DateTime.now().toUtc().isBefore( - DateTime.fromMillisecondsSinceEpoch(expiration), - )) { + DateTime.fromMillisecondsSinceEpoch(expiration), + )) { await file.delete(); return null; } diff --git a/lib/src/http/session/session_manager.dart b/lib/src/http/session/session_manager.dart index 75826ae4..abfe8b81 100644 --- a/lib/src/http/session/session_manager.dart +++ b/lib/src/http/session/session_manager.dart @@ -18,8 +18,9 @@ class SessionManager { Map get allSessions => _allSessions; - final Duration _sessionLifeTime = - Duration(seconds: env('SESSION_LIFETIME', 9000)); + final Duration _sessionLifeTime = Duration( + seconds: env('SESSION_LIFETIME', 9000), + ); bool secureSession = env('SECURE_SESSION', true); /// Generates a new session ID. @@ -50,7 +51,9 @@ class SessionManager { /// attributes such as domain, expiration, SameSite policy, and HTTP-only flag /// to mitigate CSRF attacks. Future createXsrfToken( - HttpRequest request, HttpResponse response) async { + HttpRequest request, + HttpResponse response, + ) async { Cookie requestCookie = request.cookies.firstWhere( (cookie) => cookie.name == 'XSRF-TOKEN', orElse: () => Cookie('XSRF-TOKEN', ''), @@ -106,13 +109,9 @@ class SessionManager { String _computeCsrfCookieValue(String token, String iv) { var hmac = Hmac(sha512, utf8.encode(iv)); final Digest digest = hmac.convert(utf8.encode(token)); - return base64.encode(utf8.encode( - jsonEncode( - { - 'token': base64.encode(digest.bytes), - }, - ), - )); + return base64.encode( + utf8.encode(jsonEncode({'token': base64.encode(digest.bytes)})), + ); } /// Starts a new session or retrieves an existing session from the request. @@ -133,10 +132,7 @@ class SessionManager { /// /// Returns: /// A string representing the session. - Future sessionStart( - HttpRequest request, - HttpResponse response, - ) async { + Future sessionStart(HttpRequest request, HttpResponse response) async { _request = null; _request ??= request; final cookie = request.cookies.firstWhere( @@ -209,8 +205,9 @@ class SessionManager { Future setSession(String key, dynamic value) async { final sessionId = getSessionId(); if (sessionId != null) { - Map? session = - await SessionFileStore().retrieveSession(sessionId); + Map? session = await SessionFileStore().retrieveSession( + sessionId, + ); if (session != null) { session.addAll({key: value}); } else { @@ -233,8 +230,9 @@ class SessionManager { Future deleteSession(String key) async { final String? sessionId = getSessionId(); if (sessionId != null) { - Map? session = - await SessionFileStore().retrieveSession(sessionId); + Map? session = await SessionFileStore().retrieveSession( + sessionId, + ); if (session != null) { session.remove(key); _allSessions = session; diff --git a/lib/src/http/validation/field_validation.dart b/lib/src/http/validation/field_validation.dart index 9686f7af..297bf407 100644 --- a/lib/src/http/validation/field_validation.dart +++ b/lib/src/http/validation/field_validation.dart @@ -6,10 +6,10 @@ class FieldValidation { FieldValidation(this.fieldName); Map get toMapMessages => _messages.map((key, message) { - final parts = key.split('.*.'); - final ruleName = parts.isNotEmpty ? parts.last : key; - return MapEntry(ruleName, message); - }); + final parts = key.split('.*.'); + final ruleName = parts.isNotEmpty ? parts.last : key; + return MapEntry(ruleName, message); + }); FieldValidation alpha({String? messages}) { _rules.add('alpha'); diff --git a/lib/src/http/validation/nested_validation.dart b/lib/src/http/validation/nested_validation.dart index b86d324d..83c80ab4 100644 --- a/lib/src/http/validation/nested_validation.dart +++ b/lib/src/http/validation/nested_validation.dart @@ -46,14 +46,15 @@ class NestedValidation { if (fields.length == 1) { dynamic value = item.getParam(field); - fieldsToValidate.add(ValidationItem( - field: fieldNameWithPositionIndex, - name: field.split('.').last, - value: value, - rule: rule, - )); + fieldsToValidate.add( + ValidationItem( + field: fieldNameWithPositionIndex, + name: field.split('.').last, + value: value, + rule: rule, + ), + ); } - /// this mean we still need to get the actual field value else if (fields.length >= 2) { List fieldsExceptMainField = fields.sublist(1); diff --git a/lib/src/http/validation/rules.dart b/lib/src/http/validation/rules.dart index 6efd35a4..527c9df4 100644 --- a/lib/src/http/validation/rules.dart +++ b/lib/src/http/validation/rules.dart @@ -4,7 +4,10 @@ import 'package:vania/src/http/request/request_file.dart'; class Rules { /// Check field is required static bool isRequired( - Map data, dynamic value, String args) { + Map data, + dynamic value, + String args, + ) { if (value == null) { return false; } @@ -17,7 +20,8 @@ class Rules { /// Check field is email static bool isEmail(Map data, dynamic value, String args) { RegExp emailRegex = RegExp( - r'^[\w-]+(\.[\w-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*(\.[a-zA-Z]{2,})$'); + r'^[\w-]+(\.[\w-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*(\.[a-zA-Z]{2,})$', + ); return emailRegex.hasMatch(value.toString()); } @@ -92,14 +96,20 @@ class Rules { /// Check field is only with alphabetic, dash or underscore static bool isAlphaDash( - Map data, dynamic value, String args) { + Map data, + dynamic value, + String args, + ) { RegExp alphaDashRegex = RegExp(r'^[a-zA-Z-_]+$'); return alphaDashRegex.hasMatch(value.toString()); } /// Check field is only with alphabetic, number static bool isAlphaNumeric( - Map data, dynamic value, String args) { + Map data, + dynamic value, + String args, + ) { RegExp alphaNumericRegex = RegExp(r'^[a-zA-Z0-9]+$'); return alphaNumericRegex.hasMatch(value.toString()); } @@ -127,7 +137,8 @@ class Rules { /// Check field is a valid uuid static bool isUUID(Map data, dynamic value, String args) { RegExp uuidRegex = RegExp( - r'^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$'); + r'^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$', + ); return uuidRegex.hasMatch(value.toString()); } @@ -143,7 +154,10 @@ class Rules { /// Check field character is between given length static bool lengthBetween( - Map data, dynamic value, String values) { + Map data, + dynamic value, + String values, + ) { List parts = values.toString().split(','); num value1 = num.parse(parts[0]); num value2 = num.parse(parts[1]); @@ -163,8 +177,10 @@ class Rules { List parts = values.toString().split(','); String table = parts[0]; String column = parts[1]; - final exists = - await DB.table(table).whereEqualTo(column, value).doesntExist(); + final exists = await DB + .table(table) + .whereEqualTo(column, value) + .doesntExist(); return exists; } @@ -182,14 +198,20 @@ class Rules { /// Check field is greater than given value static bool greaterThan( - Map data, dynamic value, String compare) { + Map data, + dynamic value, + String compare, + ) { value = num.parse(value.toString()); return value > num.parse(compare.toString()); } /// Check field is less than given value static bool lessThan( - Map data, dynamic value, String compare) { + Map data, + dynamic value, + String compare, + ) { value = num.parse(value.toString()); return value < num.parse(compare.toString()); } @@ -220,7 +242,10 @@ class Rules { /// Check field start with given text static bool startWith( - Map data, dynamic value, String start) { + Map data, + dynamic value, + String start, + ) { return value.toString().startsWith(start.toString()); } @@ -256,7 +281,10 @@ class Rules { /// Check field is required when condition is not matched static bool requiredIfNot( - Map data, dynamic value, String payload) { + Map data, + dynamic value, + String payload, + ) { List parts = payload.toString().split(','); String secondField = parts[0]; String secondFieldValueFromRule = parts[1].toString(); @@ -283,7 +311,7 @@ class Rules { 'svg', 'webp', 'tiff', - 'ico' + 'ico', ]; if (args.toString().isNotEmpty) { extensions = args.toString().split(','); diff --git a/lib/src/http/validation/validation_chain/rules/between.dart b/lib/src/http/validation/validation_chain/rules/between.dart index b7aa10cb..31a37cf8 100644 --- a/lib/src/http/validation/validation_chain/rules/between.dart +++ b/lib/src/http/validation/validation_chain/rules/between.dart @@ -3,10 +3,11 @@ import 'package:vania/src/http/validation/validation_chain/validation_rule.dart' class Between extends ValidationRule { final num lowerBoundary; final num higherBoundary; - Between( - {required this.lowerBoundary, - required this.higherBoundary, - super.message}); + Between({ + required this.lowerBoundary, + required this.higherBoundary, + super.message, + }); @override bool validate(value, data) { diff --git a/lib/src/http/validation/validation_chain/rules/greater_than.dart b/lib/src/http/validation/validation_chain/rules/greater_than.dart index 7480b518..ce407b97 100644 --- a/lib/src/http/validation/validation_chain/rules/greater_than.dart +++ b/lib/src/http/validation/validation_chain/rules/greater_than.dart @@ -16,12 +16,8 @@ class GreaterThan extends ValidationRule { return 'The $field be greater than $compare'; } - GreaterThan copyWith({ - num? compare, - }) { - return GreaterThan( - compare: compare ?? this.compare, - ); + GreaterThan copyWith({num? compare}) { + return GreaterThan(compare: compare ?? this.compare); } Map toMap() { @@ -33,9 +29,7 @@ class GreaterThan extends ValidationRule { } factory GreaterThan.fromMap(Map map) { - return GreaterThan( - compare: map['compare'] ?? 0, - ); + return GreaterThan(compare: map['compare'] ?? 0); } String toJson() => json.encode(toMap()); diff --git a/lib/src/http/validation/validation_chain/rules/is_image.dart b/lib/src/http/validation/validation_chain/rules/is_image.dart index 282b5dbf..400ea159 100644 --- a/lib/src/http/validation/validation_chain/rules/is_image.dart +++ b/lib/src/http/validation/validation_chain/rules/is_image.dart @@ -34,5 +34,5 @@ List extensions = [ 'svg', 'webp', 'tiff', - 'ico' + 'ico', ]; diff --git a/lib/src/http/validation/validation_chain/rules/lenght_between.dart b/lib/src/http/validation/validation_chain/rules/lenght_between.dart index dadbe29e..9bbbfbe1 100644 --- a/lib/src/http/validation/validation_chain/rules/lenght_between.dart +++ b/lib/src/http/validation/validation_chain/rules/lenght_between.dart @@ -3,10 +3,11 @@ import 'package:vania/src/http/validation/validation_chain/validation_rule.dart' class LengthBetween extends ValidationRule { final num lowerBoundary; final num higherBoundary; - LengthBetween( - {super.message, - required this.lowerBoundary, - required this.higherBoundary}); + LengthBetween({ + super.message, + required this.lowerBoundary, + required this.higherBoundary, + }); @override bool validate(value, data) { diff --git a/lib/src/http/validation/validator.dart b/lib/src/http/validation/validator.dart index 503d5931..0918314b 100644 --- a/lib/src/http/validation/validator.dart +++ b/lib/src/http/validation/validator.dart @@ -77,8 +77,11 @@ class Validator { String rule = entry.value; if (_isNestedValidation(field)) { - NestedValidation v = - NestedValidation(data: data, field: field, rule: rule); + NestedValidation v = NestedValidation( + data: data, + field: field, + rule: rule, + ); for (ValidationItem item in v.fieldsToValidate) { await _validateItem(item); } @@ -102,8 +105,12 @@ class Validator { List rulesForEachName = item.rule.split('|'); for (String rule in rulesForEachName) { - String? error = - await _applyMatchingRule(item.field, item.name, item.value, rule); + String? error = await _applyMatchingRule( + item.field, + item.name, + item.value, + rule, + ); if (error != null) { _errors[item.field] = error; break; @@ -126,8 +133,11 @@ class Validator { return null; } - var result = - Function.apply(match['function'], [data, value, args]); + var result = Function.apply(match['function'], [ + data, + value, + args, + ]); if (result is Future) { result = await result; @@ -152,145 +162,145 @@ class Validator { final Map> _matchingRules = >{ - 'required': { - 'message': 'The {field} is required', - 'function': Rules.isRequired, - }, - 'email': { - 'message': 'The {field} is not a valid email', - 'function': Rules.isEmail, - }, - 'string': { - 'message': 'The {field} must be a string', - 'function': Rules.isString, - }, - 'numeric': { - 'message': 'The {field} must be a number', - 'function': Rules.isNumeric, - }, - 'ip': { - 'message': 'The {field} must be an ip address', - 'function': Rules.isIp, - }, - 'boolean': { - 'message': 'The {field} must be a boolean', - 'function': Rules.isBoolean, - }, - 'integer': { - 'message': 'The {field} must be an integer', - 'function': Rules.isInteger, - }, - 'double': { - 'message': 'The {field} must be a double', - 'function': Rules.isDouble, - }, - 'array': { - 'message': 'The {field} must be an array', - 'function': Rules.isArray, - }, - 'json': { - 'message': 'The {field} is not a valid json', - 'function': Rules.isJson, - }, - 'alpha': { - 'message': 'The {field} must be an alphabetic', - 'function': Rules.isAlpha, - }, - 'alpha_dash': { - 'message': 'The {field} must be only alphabetic and dash', - 'function': Rules.isAlphaDash, - }, - 'alpha_numeric': { - 'message': 'The {field} must be only alphabetic and number', - 'function': Rules.isAlphaNumeric, - }, - 'date': { - 'message': 'The {field} must be a date', - 'function': Rules.isDate, - }, - 'url': { - 'message': 'The {field} must be a url', - 'function': Rules.isUrl, - }, - 'uuid': { - 'message': 'The {field} is invalid uuid', - 'function': Rules.isUUID, - }, - 'min_length': { - 'message': 'The {field} must be at least %s character', - 'function': Rules.minLength, - }, - 'max_length': { - 'message': 'The {field} may not be greater than %s character', - 'function': Rules.maxLength, - }, - 'length_between': { - 'message': 'The {field} must be between %s and %s character', - 'function': Rules.lengthBetween, - }, - 'between': { - 'message': 'The {field} must be between %s and %s', - 'function': Rules.between, - }, - 'in': { - 'message': 'The selected {field} is invalid. Valid options are %s', - 'function': Rules.inArray, - }, - 'not_in': { - 'message': 'The {field} field cannot be {value}', - 'function': Rules.notInArray, - }, - 'start_with': { - 'message': 'The {field} must start with %s', - 'function': Rules.startWith, - }, - 'end_with': { - 'message': 'The {field} must end with %s', - 'function': Rules.endWith, - }, - 'greater_than': { - 'message': 'The {field} must be greater than %s', - 'function': Rules.greaterThan, - }, - 'less_than': { - 'message': 'The {field} must be less than %s', - 'function': Rules.lessThan, - }, - 'min': { - 'message': 'The {field} must be greater than or equal %s', - 'function': Rules.min, - }, - 'max': { - 'message': 'The {field} must be less than or equal %s', - 'function': Rules.max, - }, - 'confirmed': { - 'message': 'The two password did not match', - 'function': Rules.confirmed, - }, - 'required_if': { - 'message': 'The {field} is required', - 'function': Rules.requiredIf, - }, - 'required_if_not': { - 'message': 'The {field} is required', - 'function': Rules.requiredIfNot, - }, - 'image': { - 'message': 'The {field} is either invalid or unsupported extension', - 'function': Rules.isImage, - }, - 'file': { - 'message': 'The {field} is either invalid or unsupported extension', - 'function': Rules.isFile, - }, - 'reg_exp': { - 'message': 'The {field} is either invalid or unsupported extension', - 'function': Rules.regExp, - }, - 'unique': { - 'message': 'This {field} is exist', - 'function': Rules.unique, - }, - }; + 'required': { + 'message': 'The {field} is required', + 'function': Rules.isRequired, + }, + 'email': { + 'message': 'The {field} is not a valid email', + 'function': Rules.isEmail, + }, + 'string': { + 'message': 'The {field} must be a string', + 'function': Rules.isString, + }, + 'numeric': { + 'message': 'The {field} must be a number', + 'function': Rules.isNumeric, + }, + 'ip': { + 'message': 'The {field} must be an ip address', + 'function': Rules.isIp, + }, + 'boolean': { + 'message': 'The {field} must be a boolean', + 'function': Rules.isBoolean, + }, + 'integer': { + 'message': 'The {field} must be an integer', + 'function': Rules.isInteger, + }, + 'double': { + 'message': 'The {field} must be a double', + 'function': Rules.isDouble, + }, + 'array': { + 'message': 'The {field} must be an array', + 'function': Rules.isArray, + }, + 'json': { + 'message': 'The {field} is not a valid json', + 'function': Rules.isJson, + }, + 'alpha': { + 'message': 'The {field} must be an alphabetic', + 'function': Rules.isAlpha, + }, + 'alpha_dash': { + 'message': 'The {field} must be only alphabetic and dash', + 'function': Rules.isAlphaDash, + }, + 'alpha_numeric': { + 'message': 'The {field} must be only alphabetic and number', + 'function': Rules.isAlphaNumeric, + }, + 'date': { + 'message': 'The {field} must be a date', + 'function': Rules.isDate, + }, + 'url': { + 'message': 'The {field} must be a url', + 'function': Rules.isUrl, + }, + 'uuid': { + 'message': 'The {field} is invalid uuid', + 'function': Rules.isUUID, + }, + 'min_length': { + 'message': 'The {field} must be at least %s character', + 'function': Rules.minLength, + }, + 'max_length': { + 'message': 'The {field} may not be greater than %s character', + 'function': Rules.maxLength, + }, + 'length_between': { + 'message': 'The {field} must be between %s and %s character', + 'function': Rules.lengthBetween, + }, + 'between': { + 'message': 'The {field} must be between %s and %s', + 'function': Rules.between, + }, + 'in': { + 'message': 'The selected {field} is invalid. Valid options are %s', + 'function': Rules.inArray, + }, + 'not_in': { + 'message': 'The {field} field cannot be {value}', + 'function': Rules.notInArray, + }, + 'start_with': { + 'message': 'The {field} must start with %s', + 'function': Rules.startWith, + }, + 'end_with': { + 'message': 'The {field} must end with %s', + 'function': Rules.endWith, + }, + 'greater_than': { + 'message': 'The {field} must be greater than %s', + 'function': Rules.greaterThan, + }, + 'less_than': { + 'message': 'The {field} must be less than %s', + 'function': Rules.lessThan, + }, + 'min': { + 'message': 'The {field} must be greater than or equal %s', + 'function': Rules.min, + }, + 'max': { + 'message': 'The {field} must be less than or equal %s', + 'function': Rules.max, + }, + 'confirmed': { + 'message': 'The two password did not match', + 'function': Rules.confirmed, + }, + 'required_if': { + 'message': 'The {field} is required', + 'function': Rules.requiredIf, + }, + 'required_if_not': { + 'message': 'The {field} is required', + 'function': Rules.requiredIfNot, + }, + 'image': { + 'message': 'The {field} is either invalid or unsupported extension', + 'function': Rules.isImage, + }, + 'file': { + 'message': 'The {field} is either invalid or unsupported extension', + 'function': Rules.isFile, + }, + 'reg_exp': { + 'message': 'The {field} is either invalid or unsupported extension', + 'function': Rules.regExp, + }, + 'unique': { + 'message': 'This {field} is exist', + 'function': Rules.unique, + }, + }; } diff --git a/lib/src/ioc_container.dart b/lib/src/ioc_container.dart index 21cf0348..c2e061d6 100644 --- a/lib/src/ioc_container.dart +++ b/lib/src/ioc_container.dart @@ -23,6 +23,7 @@ class IoCContainer { return _factories[T]!() as T; } throw Exception( - 'Service of type $T is not registered in the IoC container.'); + 'Service of type $T is not registered in the IoC container.', + ); } } diff --git a/lib/src/localization_handler/localization.dart b/lib/src/localization_handler/localization.dart index 16858b1b..0d9ad601 100644 --- a/lib/src/localization_handler/localization.dart +++ b/lib/src/localization_handler/localization.dart @@ -24,16 +24,19 @@ class Localization { Directory languagePath = Directory(env('APP_LANG_PATH', 'lib/lang')); if (languagePath.existsSync()) { - for (var entity - in languagePath.listSync(recursive: true, followLinks: false)) { + for (var entity in languagePath.listSync( + recursive: true, + followLinks: false, + )) { if (entity is Directory) { final segments = entity.uri.pathSegments.where((s) => s.isNotEmpty); final subdirName = segments.last.toLowerCase(); final fileMap = {}; - for (var file in entity - .listSync(recursive: false) - .whereType() - .where((f) => f.path.toLowerCase().endsWith('.json'))) { + for (var file + in entity + .listSync(recursive: false) + .whereType() + .where((f) => f.path.toLowerCase().endsWith('.json'))) { try { final content = file.readAsStringSync(); final decoded = json.decode(content); diff --git a/lib/src/logger/logger.dart b/lib/src/logger/logger.dart index 5f461fb5..70e2d372 100644 --- a/lib/src/logger/logger.dart +++ b/lib/src/logger/logger.dart @@ -13,8 +13,11 @@ class Logger { static const INFO = 'INFO'; static const DEBUG = 'DEBUG'; - static void log(String content, - {String type = INFO, String fileName = 'vania'}) { + static void log( + String content, { + String type = INFO, + String fileName = 'vania', + }) { final now = DateTime.now(); final directory = Directory(storagePath('logs')); diff --git a/lib/src/mail/content.dart b/lib/src/mail/content.dart index 4d0baaf5..590a6ac2 100644 --- a/lib/src/mail/content.dart +++ b/lib/src/mail/content.dart @@ -5,8 +5,5 @@ class Content { /// The Blade view that should be rendered for the mailable. final String? html; - const Content({ - this.text, - this.html, - }); + const Content({this.text, this.html}); } diff --git a/lib/src/mail/mail_view.dart b/lib/src/mail/mail_view.dart index fd6c4bf4..01b8618e 100644 --- a/lib/src/mail/mail_view.dart +++ b/lib/src/mail/mail_view.dart @@ -2,8 +2,5 @@ class MailView { final String view; final Map? data; - const MailView({ - required this.view, - this.data, - }); + const MailView({required this.view, this.data}); } diff --git a/lib/src/mail/mailable.dart b/lib/src/mail/mailable.dart index 8e1ad037..b39200c9 100644 --- a/lib/src/mail/mailable.dart +++ b/lib/src/mail/mailable.dart @@ -74,7 +74,8 @@ class Mailable implements Mail { Future send() async { final message = mailer.Message(); - message.from = envelope().from ?? + message.from = + envelope().from ?? Address( env('MAIL_FROM_ADDRESS', ''), env('MAIL_FROM_NAME', ''), @@ -113,13 +114,14 @@ class Mailable implements Mail { ); return sendReport; } on SmtpMessageValidationException catch (e) { - stderr.writeln('Failed to send email:${e.problems.map((error) => { - message: error.msg, - error: error.code - }).toList()}'); - throw Exception(e.problems - .map((error) => {message: error.msg, error: error.code}) - .toList()); + stderr.writeln( + 'Failed to send email:${e.problems.map((error) => {message: error.msg, error: error.code}).toList()}', + ); + throw Exception( + e.problems + .map((error) => {message: error.msg, error: error.code}) + .toList(), + ); } catch (e) { stderr.writeln('Failed to send email: $e'); rethrow; diff --git a/lib/src/redis/command/client.dart b/lib/src/redis/command/client.dart index fe68ebe8..10c47aa8 100644 --- a/lib/src/redis/command/client.dart +++ b/lib/src/redis/command/client.dart @@ -64,7 +64,7 @@ class CommandsClient implements Commands { return res.isInteger && res.integerValue == 1; } -// key-value operation(String) commands + // key-value operation(String) commands @override Future exists(K key) async { @@ -79,8 +79,9 @@ class CommandsClient implements Commands { @override Future expire(K key, Duration duration) async { final keyString = keyCodec.encode(key); - _connection - .sendCommand(Resp(['EXPIRE', keyString, '${duration.inSeconds}'])); + _connection.sendCommand( + Resp(['EXPIRE', keyString, '${duration.inSeconds}']), + ); final res = await _connection.receive(); res.throwIfError(); @@ -156,8 +157,9 @@ class CommandsClient implements Commands { Future setEx(K key, int ttl, V value) async { final keyString = keyCodec.encode(key); final valueString = valueCodec.encode(value); - _connection - .sendCommand(Resp(['SETEX', keyString, ttl.toString(), valueString])); + _connection.sendCommand( + Resp(['SETEX', keyString, ttl.toString(), valueString]), + ); final res = await _connection.receive(); res.throwIfError(); @@ -246,7 +248,8 @@ class CommandsClient implements Commands { Future getRange(K key, int start, int end) async { final keyString = keyCodec.encode(key); _connection.sendCommand( - Resp(['GETRANGE', keyString, start.toString(), end.toString()])); + Resp(['GETRANGE', keyString, start.toString(), end.toString()]), + ); final res = await _connection.receive(); res.throwIfError(); final str = res.stringValue; @@ -291,8 +294,9 @@ class CommandsClient implements Commands { @override Future incrByFloat(K key, double increment) async { final keyString = keyCodec.encode(key); - _connection - .sendCommand(Resp(['INCRBYFLOAT', keyString, increment.toString()])); + _connection.sendCommand( + Resp(['INCRBYFLOAT', keyString, increment.toString()]), + ); final res = await _connection.receive(); res.throwIfError(); return res.doubleValue; @@ -339,7 +343,8 @@ class CommandsClient implements Commands { Future setBit(K key, int offset, int value) async { final keyString = keyCodec.encode(key); _connection.sendCommand( - Resp(['SETBIT', keyString, offset.toString(), value.toString()])); + Resp(['SETBIT', keyString, offset.toString(), value.toString()]), + ); final res = await _connection.receive(); res.throwIfError(); return res.integerValue; @@ -349,8 +354,9 @@ class CommandsClient implements Commands { Future pSetEx(K key, int ttl, V value) async { final keyString = keyCodec.encode(key); final valueString = valueCodec.encode(value); - _connection - .sendCommand(Resp(['PSETEX', keyString, ttl.toString(), valueString])); + _connection.sendCommand( + Resp(['PSETEX', keyString, ttl.toString(), valueString]), + ); final res = await _connection.receive(); res.throwIfError(); final s = res.stringValue; @@ -375,7 +381,8 @@ class CommandsClient implements Commands { final keyString = keyCodec.encode(key); final valueString = valueCodec.encode(value); _connection.sendCommand( - Resp(['SETRANGE', keyString, offset.toString(), valueString])); + Resp(['SETRANGE', keyString, offset.toString(), valueString]), + ); final res = await _connection.receive(); res.throwIfError(); return res.integerValue; @@ -410,13 +417,14 @@ class CommandsClient implements Commands { return l.last.stringValue; } -// List operation commands + // List operation commands @override Future> lrange(K key, int startIndex, int endIndex) async { final keyString = keyCodec.encode(key); - _connection.sendCommand(Resp( - ['LRANGE', keyString, startIndex.toString(), endIndex.toString()])); + _connection.sendCommand( + Resp(['LRANGE', keyString, startIndex.toString(), endIndex.toString()]), + ); final res = await _connection.receive(); res.throwIfError(); @@ -458,8 +466,9 @@ class CommandsClient implements Commands { Future lset(K key, int index, V value) async { final keyString = keyCodec.encode(key); final valueString = valueCodec.encode(value); - _connection - .sendCommand(Resp(['LSET', keyString, index.toString(), valueString])); + _connection.sendCommand( + Resp(['LSET', keyString, index.toString(), valueString]), + ); final res = await _connection.receive(); res.throwIfError(); @@ -532,8 +541,10 @@ class RedisClient { String? username, String? password, }) async { - final rpc = - await RedisProtocolClient.createConnection(host: host, port: port); + final rpc = await RedisProtocolClient.createConnection( + host: host, + port: port, + ); if (password != null) { await _auth(rpc, username: username, password: password); @@ -559,10 +570,7 @@ class RedisClient { res.throwIfError(); } on RedisException catch (e) { Logger.log( - jsonEncode({ - 'error': 'RedisException', - 'message': e.message, - }), + jsonEncode({'error': 'RedisException', 'message': e.message}), type: Logger.ERROR, ); } diff --git a/lib/src/redis/command/codec.dart b/lib/src/redis/command/codec.dart index 70a8d69a..3b37cb8b 100644 --- a/lib/src/redis/command/codec.dart +++ b/lib/src/redis/command/codec.dart @@ -17,10 +17,7 @@ class RedisCodec { final RedisEncoder encoder; final RedisDecoder decoder; - RedisCodec({ - required this.encoder, - required this.decoder, - }); + RedisCodec({required this.encoder, required this.decoder}); } /// builtin String to String encoder diff --git a/lib/src/redis/exception.dart b/lib/src/redis/exception.dart index aeadebd7..b38db91c 100644 --- a/lib/src/redis/exception.dart +++ b/lib/src/redis/exception.dart @@ -12,5 +12,5 @@ class RedisException implements Exception { /// Convert error exception class class RedisConvertException extends RedisException { const RedisConvertException(String message) - : super('convert error: $message'); + : super('convert error: $message'); } diff --git a/lib/src/redis/lowlevel/resp.dart b/lib/src/redis/lowlevel/resp.dart index 2753b3bc..d74d0e33 100644 --- a/lib/src/redis/lowlevel/resp.dart +++ b/lib/src/redis/lowlevel/resp.dart @@ -14,15 +14,7 @@ class RedisError { } /// Redis protocol type -enum RespType { - STRING, - ARRAY, - INTEGER, - DOUBLE, - ERROR, - NULL, - UNKNOWN, -} +enum RespType { STRING, ARRAY, INTEGER, DOUBLE, ERROR, NULL, UNKNOWN } /// Redis protocol data class Resp { @@ -47,7 +39,7 @@ class Resp { if (value is List) { final data = [ '*${value.length}$_CRLF', - ...value.map((e) => _serializeValue(e, isBulkString: true)) + ...value.map((e) => _serializeValue(e, isBulkString: true)), ].join(''); return data; } @@ -215,10 +207,7 @@ _DeserializeResult? _deserializeError(List s, int startIndex) { return _DeserializeResult( startIndex + 1, - RedisError( - prefix: prefix, - message: message, - ), + RedisError(prefix: prefix, message: message), ); } diff --git a/lib/src/route/middleware/csrf_middleware.dart b/lib/src/route/middleware/csrf_middleware.dart index a3afd85e..d03ab090 100644 --- a/lib/src/route/middleware/csrf_middleware.dart +++ b/lib/src/route/middleware/csrf_middleware.dart @@ -12,8 +12,8 @@ import 'package:vania/src/utils/functions.dart'; import 'dart:async'; class CsrfMiddleware extends Middleware { - final SessionManager _sessionManager = - IoCContainer().resolve(); + final SessionManager _sessionManager = IoCContainer() + .resolve(); @override Future handle(Request req) async { @@ -23,37 +23,41 @@ class CsrfMiddleware extends Middleware { List csrfExcept = ['api/*']; csrfExcept.addAll(Config().get('csrf_except') ?? []); - String uri = - Uri.parse(sanitizeRoutePath(req.uri.toString())).path.toLowerCase(); + String uri = Uri.parse( + sanitizeRoutePath(req.uri.toString()), + ).path.toLowerCase(); if (!_isUrlExcluded(uri, csrfExcept)) { String requestCookie = req.cookie('XSRF-TOKEN') ?? ''; Map cookie = {}; if (requestCookie.isNotEmpty) { cookie = jsonDecode( - utf8.decode(base64.decode(_fixBase64Padding(requestCookie)))); + utf8.decode(base64.decode(_fixBase64Padding(requestCookie))), + ); } - String? token = req.input('_csrf') ?? + String? token = + req.input('_csrf') ?? req.input('_token') ?? req.header('X-CSRF-TOKEN'); if (token == null || token.isEmpty) { if (req.isJson()) { throw PageExpiredException( - message: - 'Security Error: The CSRF token is missing or incorrect', - responseType: ResponseType.json); + message: 'Security Error: The CSRF token is missing or incorrect', + responseType: ResponseType.json, + ); } throw PageExpiredException(); } - final storedToken = - await _sessionManager.getSession('x_csrf_token'); + final storedToken = await _sessionManager.getSession( + 'x_csrf_token', + ); if (storedToken == null || storedToken.isEmpty) { if (req.isJson()) { throw PageExpiredException( - message: - 'Security Error: The CSRF token is missing or incorrect', - responseType: ResponseType.json); + message: 'Security Error: The CSRF token is missing or incorrect', + responseType: ResponseType.json, + ); } throw PageExpiredException(); } @@ -61,9 +65,9 @@ class CsrfMiddleware extends Middleware { if (storedToken != token) { if (req.isJson()) { throw PageExpiredException( - message: - 'Security Error: The CSRF token is missing or incorrect', - responseType: ResponseType.json); + message: 'Security Error: The CSRF token is missing or incorrect', + responseType: ResponseType.json, + ); } throw PageExpiredException(); } @@ -75,9 +79,9 @@ class CsrfMiddleware extends Middleware { if (expectedCookie != cookie['token']) { if (req.isJson()) { throw PageExpiredException( - message: - 'Security Error: The CSRF token is missing or incorrect', - responseType: ResponseType.json); + message: 'Security Error: The CSRF token is missing or incorrect', + responseType: ResponseType.json, + ); } throw PageExpiredException(); } @@ -95,18 +99,20 @@ class CsrfMiddleware extends Middleware { bool _isUrlExcluded(String path, List csrfExcept) { final cleanPath = path.startsWith('/') ? path.substring(1) : path; for (var pattern in csrfExcept) { - final cleanPattern = - pattern.startsWith('/') ? pattern.substring(1) : pattern; + final cleanPattern = pattern.startsWith('/') + ? pattern.substring(1) + : pattern; if (cleanPattern.contains('*')) { - final regexStr = - cleanPattern.replaceAll('*', '.*').replaceAll('/', '\\/'); + final regexStr = cleanPattern + .replaceAll('*', '.*') + .replaceAll('/', '\\/'); final regex = RegExp('^$regexStr\$', caseSensitive: false); if (regex.hasMatch(cleanPath)) { return true; } - } else if (cleanPath - .toLowerCase() - .startsWith(cleanPattern.toLowerCase())) { + } else if (cleanPath.toLowerCase().startsWith( + cleanPattern.toLowerCase(), + )) { return true; } } diff --git a/lib/src/route/middleware/throttle.dart b/lib/src/route/middleware/throttle.dart index 98f44f5b..e822aeab 100644 --- a/lib/src/route/middleware/throttle.dart +++ b/lib/src/route/middleware/throttle.dart @@ -25,10 +25,7 @@ class Throttle extends Middleware { this.headers, this.bypassInDevelopment = true, }) { - _throttle = ThrottleRequests( - maxAttempts: maxAttempts, - duration: duration, - ); + _throttle = ThrottleRequests(maxAttempts: maxAttempts, duration: duration); } @override @@ -48,10 +45,7 @@ class Throttle extends Middleware { throw ThrottleException( message: customMessage ?? 'Too Many Requests. Please try again later.', code: HttpStatus.tooManyRequests, - headers: { - 'Retry-After': retryAfter.inSeconds.toString(), - ...?headers, - }, + headers: {'Retry-After': retryAfter.inSeconds.toString(), ...?headers}, ); } } @@ -72,7 +66,9 @@ class Throttle extends Middleware { void _addRateLimitHeaders(HttpResponse response, int remaining) { response.headers.add('X-RateLimit-Limit', maxAttempts.toString()); response.headers.add('X-RateLimit-Remaining', remaining.toString()); - response.headers - .add('X-RateLimit-Reset', _throttle.resetTime().toIso8601String()); + response.headers.add( + 'X-RateLimit-Reset', + _throttle.resetTime().toIso8601String(), + ); } } diff --git a/lib/src/route/route_handler.dart b/lib/src/route/route_handler.dart index 42035e23..9a805bcc 100644 --- a/lib/src/route/route_handler.dart +++ b/lib/src/route/route_handler.dart @@ -10,8 +10,9 @@ import 'package:vania/src/utils/functions.dart'; import 'package:vania/src/utils/helper.dart' show env; final Map _regexCache = {}; -final _lookupCache = - _LruCache<_LookupKey, RouteData?>(env("ROUTE_LOOK_UP_SIZE", 2000)); +final _lookupCache = _LruCache<_LookupKey, RouteData?>( + env("ROUTE_LOOK_UP_SIZE", 2000), +); final Map> _staticRoutes = {}; final List _dynamicRoutes = []; @@ -67,8 +68,9 @@ void initializeRoutes() { final router = Router(); for (var route in router.routes) { final method = route.method.toLowerCase(); - final normalizedPath = - _normalizePath(_normalizePrefix(route.prefix) + route.path); + final normalizedPath = _normalizePath( + _normalizePrefix(route.prefix) + route.path, + ); route.regex?.forEach((param, pattern) { _regexCache.putIfAbsent(pattern, () => RegExp(pattern)); }); @@ -128,8 +130,9 @@ RouteData? _findMatchingRoute( final staticList = _staticRoutes[method] ?? []; for (final route in staticList) { - String fullPath = - _normalizePath(_normalizePrefix(route.prefix) + route.path); + String fullPath = _normalizePath( + _normalizePrefix(route.prefix) + route.path, + ); if (fullPath.endsWith('/')) { fullPath = fullPath.substring(0, fullPath.length - 1); } @@ -139,8 +142,9 @@ RouteData? _findMatchingRoute( } } - for (final route - in _dynamicRoutes.where((r) => r.method.toLowerCase() == method)) { + for (final route in _dynamicRoutes.where( + (r) => r.method.toLowerCase() == method, + )) { if (!_domainMatches(domain, route.domain)) continue; final result = _matchDynamic(requestPath, route, domain); if (result != null) return result; @@ -180,8 +184,9 @@ RouteData _applyDomainParams(RouteData route, String domain) { ); if (route.domain != null && route.domain!.contains('{')) { - final placeholder = - RegExp(r'{([^}]+)}').firstMatch(route.domain!)!.group(1)!; + final placeholder = RegExp( + r'{([^}]+)}', + ).firstMatch(route.domain!)!.group(1)!; copy.params![placeholder] = domain.split('.').first; } @@ -190,8 +195,9 @@ RouteData _applyDomainParams(RouteData route, String domain) { /// Matches dynamic (parameterized) routes and validates params RouteData? _matchDynamic(String requestPath, RouteData route, String domain) { - final patternPath = - _normalizePath(_normalizePrefix(route.prefix) + route.path); + final patternPath = _normalizePath( + _normalizePrefix(route.prefix) + route.path, + ); final reqParts = _normalizePath(requestPath).split('/'); final patternParts = patternPath.split('/'); diff --git a/lib/src/route/router.dart b/lib/src/route/router.dart index 18577c65..b982e77f 100644 --- a/lib/src/route/router.dart +++ b/lib/src/route/router.dart @@ -23,8 +23,9 @@ class Router { List get routes => List.unmodifiable(_routes); static String url(String name, [Map? params]) { - RouteData routeData = - Router()._routes.where((route) => route.name == name).first; + RouteData routeData = Router()._routes + .where((route) => route.name == name) + .first; if (params == null) { return '${env('APP_URL')}/${routeData.path}'; @@ -45,8 +46,9 @@ class Router { Router()._prefix = null; return; } - Router()._prefix = - prefix.endsWith("/") ? prefix.substring(0, prefix.length - 1) : prefix; + Router()._prefix = prefix.endsWith("/") + ? prefix.substring(0, prefix.length - 1) + : prefix; } bool _getRequestVar(String input) { @@ -74,15 +76,17 @@ class Router { } final normalizedPath = _normalizePath(path); - _routes.add(RouteData( - method: method.name, - path: normalizedPath, - action: action, - prefix: _prefix, - paramTypes: paramTypes, - regex: regex, - hasRequest: hasRequest, - )); + _routes.add( + RouteData( + method: method.name, + path: normalizedPath, + action: action, + prefix: _prefix, + paramTypes: paramTypes, + regex: regex, + hasRequest: hasRequest, + ), + ); return this; } @@ -106,7 +110,7 @@ class Router { if (middleware != null && _routes.isNotEmpty) { _routes.last.preMiddleware = [ ..._routes.last.preMiddleware, - ...middleware + ...middleware, ]; } return this; @@ -115,11 +119,13 @@ class Router { Router prefix([String? prefix]) { if (prefix != null && _routes.isNotEmpty) { final route = _routes.last; - final basePath = - route.path.startsWith('/') ? route.path.substring(1) : route.path; + final basePath = route.path.startsWith('/') + ? route.path.substring(1) + : route.path; - route.path = - prefix.endsWith("/") ? "$prefix$basePath" : "$prefix/$basePath"; + route.path = prefix.endsWith("/") + ? "$prefix$basePath" + : "$prefix/$basePath"; } return this; } @@ -247,44 +253,40 @@ class Router { String? domain, String regex = r'\d+(.\d+)?', }) { - Router.get(path, controller.index) - .middleware(middleware) - .domain(domain) - .prefix(prefix); - - Router.get("$path/create", controller.create) - .middleware(middleware) - .domain(domain) - .prefix(prefix); - - Router.post(path, controller.store) - .middleware(middleware) - .domain(domain) - .prefix(prefix); - - Router.get("$path/{id}", controller.show) - .middleware(middleware) - .domain(domain) - .prefix(prefix) - .where('id', regex); - - Router.get("$path/{id}/edit", controller.edit) - .middleware(middleware) - .domain(domain) - .prefix(prefix) - .where('id', regex); - - Router.put("$path/{id}", controller.update) - .middleware(middleware) - .domain(domain) - .prefix(prefix) - .where('id', regex); - - Router.delete("$path/{id}", controller.destroy) - .middleware(middleware) - .domain(domain) - .prefix(prefix) - .where('id', regex); + Router.get( + path, + controller.index, + ).middleware(middleware).domain(domain).prefix(prefix); + + Router.get( + "$path/create", + controller.create, + ).middleware(middleware).domain(domain).prefix(prefix); + + Router.post( + path, + controller.store, + ).middleware(middleware).domain(domain).prefix(prefix); + + Router.get( + "$path/{id}", + controller.show, + ).middleware(middleware).domain(domain).prefix(prefix).where('id', regex); + + Router.get( + "$path/{id}/edit", + controller.edit, + ).middleware(middleware).domain(domain).prefix(prefix).where('id', regex); + + Router.put( + "$path/{id}", + controller.update, + ).middleware(middleware).domain(domain).prefix(prefix).where('id', regex); + + Router.delete( + "$path/{id}", + controller.destroy, + ).middleware(middleware).domain(domain).prefix(prefix).where('id', regex); } static void websocket( @@ -302,7 +304,8 @@ class Router { } eventCallback( - WebSocketHandler().websocketRoute(fullPath, middleware: middleware)); + WebSocketHandler().websocketRoute(fullPath, middleware: middleware), + ); } static void group( @@ -350,8 +353,9 @@ class Router { static String _joinPrefixes(String basePrefix, String newPrefix) { final base = basePrefix.endsWith('/') ? basePrefix : '$basePrefix/'; - final prefix = - newPrefix.startsWith('/') ? newPrefix.substring(1) : newPrefix; + final prefix = newPrefix.startsWith('/') + ? newPrefix.substring(1) + : newPrefix; return '$base$prefix'.replaceAll(RegExp(r'//'), '/'); } } diff --git a/lib/src/route/set_static_path.dart b/lib/src/route/set_static_path.dart index 98d7ca70..f04e1944 100644 --- a/lib/src/route/set_static_path.dart +++ b/lib/src/route/set_static_path.dart @@ -7,11 +7,7 @@ import 'package:path/path.dart' as path; bool setStaticPath(HttpRequest req) { String routePath = Uri.decodeComponent( - Uri.parse( - sanitizeRoutePath( - req.uri.toString(), - ), - ).path.toLowerCase(), + Uri.parse(sanitizeRoutePath(req.uri.toString())).path.toLowerCase(), ); if (!routePath.endsWith("/") && req.method.toLowerCase() == 'get') { if (req.uri.path == '/') { diff --git a/lib/src/route/throttle_requests.dart b/lib/src/route/throttle_requests.dart index 840e5bc3..c70e3836 100644 --- a/lib/src/route/throttle_requests.dart +++ b/lib/src/route/throttle_requests.dart @@ -3,10 +3,7 @@ class ThrottleRequests { final Duration duration; final Map _requests = {}; - ThrottleRequests({ - required this.maxAttempts, - required this.duration, - }); + ThrottleRequests({required this.maxAttempts, required this.duration}); bool request(String identifier) { _cleanup(); @@ -60,7 +57,8 @@ class ThrottleRequests { void _cleanup() { final now = DateTime.now(); _requests.removeWhere( - (_, data) => now.difference(data.firstAttempt) >= duration); + (_, data) => now.difference(data.firstAttempt) >= duration, + ); } } @@ -68,8 +66,5 @@ class _ThrottleData { DateTime firstAttempt; int attempts; - _ThrottleData({ - required this.firstAttempt, - required this.attempts, - }); + _ThrottleData({required this.firstAttempt, required this.attempts}); } diff --git a/lib/src/server/base_http_server.dart b/lib/src/server/base_http_server.dart index 7e5866a2..1f4e537e 100644 --- a/lib/src/server/base_http_server.dart +++ b/lib/src/server/base_http_server.dart @@ -31,9 +31,7 @@ class BaseHttpServer { /// /// Throws an error if the server fails to start. - Future startServer({ - Function? onError, - }) async { + Future startServer({Function? onError}) async { String host = env('APP_HOST', InternetAddress.anyIPv6.host); int port = env('APP_PORT', 8000); diff --git a/lib/src/server/initialize_config.dart b/lib/src/server/initialize_config.dart index 96a3006d..ccb192a0 100644 --- a/lib/src/server/initialize_config.dart +++ b/lib/src/server/initialize_config.dart @@ -41,18 +41,18 @@ Future initializeConfig(Map config) async { } DBConfig _config(Map database) => DBConfig( - driver: database['driver'] ?? '', - host: database['host'] ?? '', - port: database['port'] ?? '', - database: database['database'] ?? '', - username: database['username'] ?? '', - password: database['password'] ?? '', - sslMode: database['sslmode'] ?? '', - collation: database['collation'] ?? 'utf8', - timezone: database['timezone'] ?? 'UTC', - pool: database['pool'], - poolSize: database['poolsize'], - filePath: database['file_path'] ?? '', - schema: database['schema'] ?? 'public', - openInMemorySQLite: database['openInMemorySQLite'] ?? false, - ); + driver: database['driver'] ?? '', + host: database['host'] ?? '', + port: database['port'] ?? '', + database: database['database'] ?? '', + username: database['username'] ?? '', + password: database['password'] ?? '', + sslMode: database['sslmode'] ?? '', + collation: database['collation'] ?? 'utf8', + timezone: database['timezone'] ?? 'UTC', + pool: database['pool'], + poolSize: database['poolsize'], + filePath: database['file_path'] ?? '', + schema: database['schema'] ?? 'public', + openInMemorySQLite: database['openInMemorySQLite'] ?? false, +); diff --git a/lib/src/storage/s3_storage.dart b/lib/src/storage/s3_storage.dart index dcc4f881..88997dbb 100644 --- a/lib/src/storage/s3_storage.dart +++ b/lib/src/storage/s3_storage.dart @@ -109,8 +109,10 @@ class S3Storage implements StorageDriver { final bytes = await getAsBytes(file); if (bytes != null) { - return lookupMimeType(file, - headerBytes: bytes.sublist(0, min(4096, bytes.length))); + return lookupMimeType( + file, + headerBytes: bytes.sublist(0, min(4096, bytes.length)), + ); } return null; } @@ -191,8 +193,9 @@ class S3Storage implements StorageDriver { if (response.statusCode != 200) return null; final metadata = _CachedMetadata( - contentLength: - int.tryParse(response.headers.value('content-length') ?? ''), + contentLength: int.tryParse( + response.headers.value('content-length') ?? '', + ), contentType: response.headers.value('content-type'), lastModified: response.headers.value('last-modified'), ); @@ -215,11 +218,8 @@ class _CachedMetadata { final String? lastModified; final DateTime cacheTime; - _CachedMetadata({ - this.contentLength, - this.contentType, - this.lastModified, - }) : cacheTime = DateTime.now(); + _CachedMetadata({this.contentLength, this.contentType, this.lastModified}) + : cacheTime = DateTime.now(); bool get isExpired => DateTime.now().difference(cacheTime) > S3Storage._metadataCacheDuration; diff --git a/lib/src/storage/storage.dart b/lib/src/storage/storage.dart index 6142160d..e4a448d1 100644 --- a/lib/src/storage/storage.dart +++ b/lib/src/storage/storage.dart @@ -62,7 +62,8 @@ class Storage { return Storage()._driver.put(fullPath, data); } else { throw Exception( - 'Content must be a list of int, a string, or a Stream>.'); + 'Content must be a list of int, a string, or a Stream>.', + ); } } diff --git a/lib/src/storage/storage_driver.dart b/lib/src/storage/storage_driver.dart index 045157c9..fdee59d5 100644 --- a/lib/src/storage/storage_driver.dart +++ b/lib/src/storage/storage_driver.dart @@ -1,10 +1,7 @@ import 'dart:typed_data'; abstract class StorageDriver { - Future put( - String filename, - dynamic content, - ); + Future put(String filename, dynamic content); Future get(String filename); Future getAsBytes(String filename); diff --git a/lib/src/utils/_pluralize.dart b/lib/src/utils/_pluralize.dart index bd7d7e82..6a2596e4 100644 --- a/lib/src/utils/_pluralize.dart +++ b/lib/src/utils/_pluralize.dart @@ -52,7 +52,7 @@ class Pluralize { 'crisis': 'crises', 'appendix': 'appendices', 'barracks': 'barracks', - 'headquarters': 'headquarters' + 'headquarters': 'headquarters', }; String make(String singular) { diff --git a/lib/src/utils/functions.dart b/lib/src/utils/functions.dart index d42225b6..ac17067c 100644 --- a/lib/src/utils/functions.dart +++ b/lib/src/utils/functions.dart @@ -2,8 +2,10 @@ import 'dart:math'; String toSnakeCase(String input) { if (input.isEmpty) return input; - final result = input.replaceAllMapped(RegExp(r'[A-Z]'), - (match) => (match.start > 0 ? '_' : '') + match.group(0)!.toLowerCase()); + final result = input.replaceAllMapped( + RegExp(r'[A-Z]'), + (match) => (match.start > 0 ? '_' : '') + match.group(0)!.toLowerCase(), + ); return result.toLowerCase(); } @@ -26,8 +28,8 @@ String randomString({ bool numbers = false, bool special = false, }) { - List strList = - 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''); + List strList = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' + .split(''); if (numbers) { strList.addAll('1234567890'.split('')); @@ -40,8 +42,12 @@ String randomString({ strList.shuffle(); String chars = strList.join(''); Random rnd = Random(); - return String.fromCharCodes(Iterable.generate( - length, (_) => chars.codeUnitAt(rnd.nextInt(chars.length)))); + return String.fromCharCodes( + Iterable.generate( + length, + (_) => chars.codeUnitAt(rnd.nextInt(chars.length)), + ), + ); } /// Generate a random number as a string of a given length @@ -67,8 +73,12 @@ T randomInt([int length = 6]) { strList.shuffle(); String chars = strList.join(''); Random rnd = Random(); - String random = String.fromCharCodes(Iterable.generate( - length, (_) => chars.codeUnitAt(rnd.nextInt(chars.length)))); + String random = String.fromCharCodes( + Iterable.generate( + length, + (_) => chars.codeUnitAt(rnd.nextInt(chars.length)), + ), + ); if (T is int) { return int.parse(random) as T; diff --git a/lib/src/utils/helper.dart b/lib/src/utils/helper.dart index a5335b02..e5976a29 100644 --- a/lib/src/utils/helper.dart +++ b/lib/src/utils/helper.dart @@ -25,11 +25,7 @@ bool cannot(String ability) => Gate().denies(ability); T env(String key, [dynamic defaultValue]) => Env.get(key, defaultValue); -String trans( - String key, { - Map? args, - String? locale, -}) => +String trans(String key, {Map? args, String? locale}) => Localization().trans(key, args, locale); void setLocale(String locale) => Localization().setLocale(locale); bool isLocale(String locale) => Localization().isLocale(locale); diff --git a/lib/src/view_engine/processor_engine/csrf_processor.dart b/lib/src/view_engine/processor_engine/csrf_processor.dart index 31f46953..bbfd27ad 100644 --- a/lib/src/view_engine/processor_engine/csrf_processor.dart +++ b/lib/src/view_engine/processor_engine/csrf_processor.dart @@ -5,10 +5,7 @@ import 'package:vania/src/view_engine/processor_engine/abs_processor.dart'; class CsrfProcessor implements AbsProcessor { @override String parse(String content, [Map? context]) { - final csrfPattern = RegExp( - r"\{@\s*csrf\s*@\}", - dotAll: true, - ); + final csrfPattern = RegExp(r"\{@\s*csrf\s*@\}", dotAll: true); return content.replaceAllMapped(csrfPattern, (match) { String csrfToken = IoCContainer().resolve().csrfToken; return ''; diff --git a/lib/src/view_engine/processor_engine/for_loop_processor.dart b/lib/src/view_engine/processor_engine/for_loop_processor.dart index c9643864..765ae6da 100644 --- a/lib/src/view_engine/processor_engine/for_loop_processor.dart +++ b/lib/src/view_engine/processor_engine/for_loop_processor.dart @@ -49,8 +49,9 @@ class ForLoopProcessor extends AbsProcessor { break; } - final forExpression = - template.substring(startPos + 6, forStartClose).trim(); + final forExpression = template + .substring(startPos + 6, forStartClose) + .trim(); int loopContentStart = forStartClose + 2; int searchPos = loopContentStart; @@ -109,7 +110,10 @@ class ForLoopProcessor extends AbsProcessor { /// `_runItemInListLoop`. Returns the expanded loop content as a string. String _expandLoop( - String forExpression, String loopBlock, Map context) { + String forExpression, + String loopBlock, + Map context, + ) { final cStylePattern = RegExp( r'^(\w+)\s*=\s*(.+?);\s*\1\s*([<>]=?|[<>])\s*(.+?);\s*(.+)$', ); @@ -168,11 +172,7 @@ class ForLoopProcessor extends AbsProcessor { final buffer = StringBuffer(); for (var i = 0; i < listObj.length; i++) { final item = listObj[i]; - final subCtx = { - ...context, - itemName: item, - 'index': i, - }; + final subCtx = {...context, itemName: item, 'index': i}; buffer.write(TemplateEngine().renderString(loopBlock, subCtx)); } @@ -266,10 +266,7 @@ class ForLoopProcessor extends AbsProcessor { final buffer = StringBuffer(); while (checkCondition(current)) { - final subCtx = { - ...context, - varName: current, - }; + final subCtx = {...context, varName: current}; buffer.write(TemplateEngine().renderString(loopBlock, subCtx)); current = increment(current); diff --git a/lib/src/view_engine/processor_engine/if_statement_processor.dart b/lib/src/view_engine/processor_engine/if_statement_processor.dart index dc19543e..62c11b16 100644 --- a/lib/src/view_engine/processor_engine/if_statement_processor.dart +++ b/lib/src/view_engine/processor_engine/if_statement_processor.dart @@ -63,8 +63,9 @@ class IfStatementProcessor implements AbsProcessor { buffer.write(template.substring(startPos)); break; } - final ifConditionExpr = - template.substring(startPos + 5, ifStartClose).trim(); + final ifConditionExpr = template + .substring(startPos + 5, ifStartClose) + .trim(); int blockStart = ifStartClose + 2; int searchPos = blockStart; int nested = 0; @@ -121,8 +122,11 @@ class IfStatementProcessor implements AbsProcessor { /// /// - Returns: A string with the expanded content for the first true condition or the `else` block. - String _expandIfBlock(String ifConditionExpr, String ifBlockContent, - Map context) { + String _expandIfBlock( + String ifConditionExpr, + String ifBlockContent, + Map context, + ) { var cursor = 0; var currentCondition = ifConditionExpr; final segments = <_ConditionalSegment>[]; @@ -131,8 +135,9 @@ class IfStatementProcessor implements AbsProcessor { final elseRegex = RegExp(r'\{@\s*else\s*@\}'); while (true) { - final matchElseIf = - elseIfRegex.firstMatch(ifBlockContent.substring(cursor)); + final matchElseIf = elseIfRegex.firstMatch( + ifBlockContent.substring(cursor), + ); final matchElse = elseRegex.firstMatch(ifBlockContent.substring(cursor)); final elseIfPos = (matchElseIf == null) ? -1 : cursor + matchElseIf.start; @@ -158,38 +163,46 @@ class IfStatementProcessor implements AbsProcessor { if (nextPos == -1) { final block = ifBlockContent.substring(cursor); - segments.add(_ConditionalSegment( - condition: currentCondition, - content: block, - isConditionSegment: true, - )); + segments.add( + _ConditionalSegment( + condition: currentCondition, + content: block, + isConditionSegment: true, + ), + ); break; } else { final block = ifBlockContent.substring(cursor, nextPos); - segments.add(_ConditionalSegment( - condition: currentCondition, - content: block, - isConditionSegment: true, - )); + segments.add( + _ConditionalSegment( + condition: currentCondition, + content: block, + isConditionSegment: true, + ), + ); if (isElseIf) { - final elseIfMatch = - elseIfRegex.firstMatch(ifBlockContent.substring(nextPos)); + final elseIfMatch = elseIfRegex.firstMatch( + ifBlockContent.substring(nextPos), + ); if (elseIfMatch == null) break; currentCondition = elseIfMatch.group(1)!.trim(); cursor = nextPos + elseIfMatch.end; } else { - final elseMatch = - elseRegex.firstMatch(ifBlockContent.substring(nextPos)); + final elseMatch = elseRegex.firstMatch( + ifBlockContent.substring(nextPos), + ); if (elseMatch == null) break; final elseStart = nextPos + elseMatch.end; final elseContent = ifBlockContent.substring(elseStart); - segments.add(_ConditionalSegment( - condition: '', - content: elseContent, - isConditionSegment: false, - )); + segments.add( + _ConditionalSegment( + condition: '', + content: elseContent, + isConditionSegment: false, + ), + ); break; } } diff --git a/lib/src/view_engine/processor_engine/route_processor.dart b/lib/src/view_engine/processor_engine/route_processor.dart index 4860ac32..06b66eed 100644 --- a/lib/src/view_engine/processor_engine/route_processor.dart +++ b/lib/src/view_engine/processor_engine/route_processor.dart @@ -22,13 +22,14 @@ class RouteProcessor implements AbsProcessor { slash = '/'; } - List filteredRoute = Router() - .routes + List filteredRoute = Router().routes .where((e) => e.name?.toLowerCase() == routeName.toLowerCase()) .toList(); if (filteredRoute.isEmpty) { throw InternalServerError( - message: 'Route $routeName not found', code: 500); + message: 'Route $routeName not found', + code: 500, + ); } String path = filteredRoute.first.path; diff --git a/lib/src/view_engine/processor_engine/section_processor.dart b/lib/src/view_engine/processor_engine/section_processor.dart index d90f0f27..a036c63d 100644 --- a/lib/src/view_engine/processor_engine/section_processor.dart +++ b/lib/src/view_engine/processor_engine/section_processor.dart @@ -59,8 +59,9 @@ class SectionProcessor implements AbsProcessor { dotAll: true, ); - childTemplate = - childTemplate.replaceAllMapped(blockSectionPattern, (match) { + childTemplate = childTemplate.replaceAllMapped(blockSectionPattern, ( + match, + ) { final sectionName = match.group(1) ?? ''; final content = match.group(2) ?? ''; sections[sectionName] = content; @@ -72,8 +73,9 @@ class SectionProcessor implements AbsProcessor { dotAll: true, ); - childTemplate = - childTemplate.replaceAllMapped(inlineSectionPattern, (match) { + childTemplate = childTemplate.replaceAllMapped(inlineSectionPattern, ( + match, + ) { final sectionName = match.group(1) ?? ''; final inlineContent = match.group(2) ?? ''; sections[sectionName] = inlineContent; diff --git a/lib/src/view_engine/processor_engine/translate_processor.dart b/lib/src/view_engine/processor_engine/translate_processor.dart index a613669e..c90748da 100644 --- a/lib/src/view_engine/processor_engine/translate_processor.dart +++ b/lib/src/view_engine/processor_engine/translate_processor.dart @@ -29,11 +29,7 @@ class TranslateProcessor implements AbsProcessor { if (rawLocale != null) { locale = rawLocale.trim().replaceAll(stripQuotes, ''); } - return trans( - key, - args: args, - locale: locale, - ); + return trans(key, args: args, locale: locale); }); } } diff --git a/lib/src/view_engine/processor_engine/variables_processor.dart b/lib/src/view_engine/processor_engine/variables_processor.dart index 67054b1e..cd81aeac 100644 --- a/lib/src/view_engine/processor_engine/variables_processor.dart +++ b/lib/src/view_engine/processor_engine/variables_processor.dart @@ -28,8 +28,10 @@ class VariablesProcessor implements AbsProcessor { } if (_looksLikeVariablePath(rawExpression)) { - final value = - _fetchValueWithBracketNotation(rawExpression, context ?? {}); + final value = _fetchValueWithBracketNotation( + rawExpression, + context ?? {}, + ); if (value != null) return value.toString(); } @@ -55,7 +57,9 @@ class VariablesProcessor implements AbsProcessor { /// Returns the filtered variable value as a string. String _handleVariableWithFilters( - String rawExpression, Map context) { + String rawExpression, + Map context, + ) { final parts = rawExpression.split('|').map((e) => e.trim()).toList(); final variableName = parts.first; final filters = parts.length > 1 ? parts.sublist(1) : []; @@ -85,7 +89,9 @@ class VariablesProcessor implements AbsProcessor { /// The function returns `null` if any segment in the expression is `null`. /// dynamic _fetchValueWithBracketNotation( - String expression, Map context) { + String expression, + Map context, + ) { expression = _resolveBracketIndexVars(expression, context); final segments = expression.split('.'); @@ -99,7 +105,9 @@ class VariablesProcessor implements AbsProcessor { } String _resolveBracketIndexVars( - String expression, Map context) { + String expression, + Map context, + ) { final bracketVarRegex = RegExp(r'\[([^\[\]]+)\]'); return expression.replaceAllMapped(bracketVarRegex, (m) { final inside = m.group(1)!; diff --git a/lib/src/websocket/web_socket_handler.dart b/lib/src/websocket/web_socket_handler.dart index 93c4ab7c..0e4ea6f5 100644 --- a/lib/src/websocket/web_socket_handler.dart +++ b/lib/src/websocket/web_socket_handler.dart @@ -46,12 +46,12 @@ class WebSocketHandler implements WebSocketEvent { routePath: routePath, ); - websocket.add(jsonEncode({ - 'event': 'connected', - 'payload': { - 'session_id': sessionId, - }, - })); + websocket.add( + jsonEncode({ + 'event': 'connected', + 'payload': {'session_id': sessionId}, + }), + ); try { if (_middleware[_websocketRoute] != null) { @@ -61,12 +61,12 @@ class WebSocketHandler implements WebSocketEvent { ); } } on WebSocketException catch (e) { - websocket.add(jsonEncode({ - 'event': 'error', - 'payload': { - 'message': e.message, - }, - })); + websocket.add( + jsonEncode({ + 'event': 'error', + 'payload': {'message': e.message}, + }), + ); return; } @@ -75,57 +75,61 @@ class WebSocketHandler implements WebSocketEvent { Function.apply(openFunction, [client]); } - websocket.listen((data) async { - Map payload = jsonDecode(data); - String event = '${routePath}_${payload[webScoketEventKey]}'; - - /// client join the room - if (event == '${routePath}_$webSocketJoinRoomEventName') { - String? roomId = payload[webSocketRoomKey].toString(); - if (roomId.isNotEmpty) { - _session.joinRoom(sessionId, '${routePath}_$roomId'); + websocket.listen( + (data) async { + Map payload = jsonDecode(data); + String event = '${routePath}_${payload[webScoketEventKey]}'; + + /// client join the room + if (event == '${routePath}_$webSocketJoinRoomEventName') { + String? roomId = payload[webSocketRoomKey].toString(); + if (roomId.isNotEmpty) { + _session.joinRoom(sessionId, '${routePath}_$roomId'); + } + return; } - return; - } - /// client left the room - if (event == webSocketLeftRoomEventName) { - String? roomId = payload[webSocketRoomKey].toString(); - if (roomId.isNotEmpty) { - _session.leftRoom(sessionId, '${routePath}_$roomId'); + /// client left the room + if (event == webSocketLeftRoomEventName) { + String? roomId = payload[webSocketRoomKey].toString(); + if (roomId.isNotEmpty) { + _session.leftRoom(sessionId, '${routePath}_$roomId'); + } + return; } - return; - } - /// websocket response - /// ``` - /// event.on('event',function(WebSocketClient client,message){ - /// response - /// }); - /// ``` - dynamic message = payload[webSocketMessageKey]; + /// websocket response + /// ``` + /// event.on('event',function(WebSocketClient client,message){ + /// response + /// }); + /// ``` + dynamic message = payload[webSocketMessageKey]; - Function? controller = _events[event]; + Function? controller = _events[event]; - if (controller == null) { - return; - } - Function.apply(controller, [client, message]); - }, onDone: () { - Function? openFunction = _events['${routePath}_disconnect']; - if (openFunction != null) { - Function.apply(openFunction, [client]); - } + if (controller == null) { + return; + } + Function.apply(controller, [client, message]); + }, + onDone: () { + Function? openFunction = _events['${routePath}_disconnect']; + if (openFunction != null) { + Function.apply(openFunction, [client]); + } - _session.removeSession(sessionId); - }, onError: (_) { - Function? openFunction = _events['${routePath}_error']; - if (openFunction != null) { - Function.apply(openFunction, [client]); - } + _session.removeSession(sessionId); + }, + onError: (_) { + Function? openFunction = _events['${routePath}_error']; + if (openFunction != null) { + Function.apply(openFunction, [client]); + } - _session.removeSession(sessionId); - }); + _session.removeSession(sessionId); + }, + ); } /// Listener diff --git a/lib/src/websocket/websocket_client.dart b/lib/src/websocket/websocket_client.dart index 94cb28ee..58eb81d6 100644 --- a/lib/src/websocket/websocket_client.dart +++ b/lib/src/websocket/websocket_client.dart @@ -40,10 +40,7 @@ class WebSocketClientImpl implements WebSocketClient { void emit(String event, dynamic payload) { SessionInfo? info = session.getWebSocketInfo(id); if (info != null) { - info.websocket.add(jsonEncode({ - 'event': event, - 'payload': payload, - })); + info.websocket.add(jsonEncode({'event': event, 'payload': payload})); } } @@ -59,10 +56,7 @@ class WebSocketClientImpl implements WebSocketClient { for (String member in members) { SessionInfo? info = session.getWebSocketInfo(member); if (info != null) { - info.websocket.add(jsonEncode({ - 'event': event, - 'payload': payload, - })); + info.websocket.add(jsonEncode({'event': event, 'payload': payload})); } } } @@ -75,10 +69,7 @@ class WebSocketClientImpl implements WebSocketClient { void to(String clientId, String event, dynamic payload) { SessionInfo? info = session.getWebSocketInfo(clientId); if (info != null) { - info.websocket.add(jsonEncode({ - 'event': event, - 'payload': payload, - })); + info.websocket.add(jsonEncode({'event': event, 'payload': payload})); } } @@ -92,10 +83,7 @@ class WebSocketClientImpl implements WebSocketClient { sessions.removeWhere((item) => item.sessionId == id); sessions.shuffle(); for (SessionInfo session in sessions) { - session.websocket.add(jsonEncode({ - 'event': event, - 'payload': payload, - })); + session.websocket.add(jsonEncode({'event': event, 'payload': payload})); } } diff --git a/lib/src/websocket/websocket_session.dart b/lib/src/websocket/websocket_session.dart index 3ebcc2ed..4dd5420c 100644 --- a/lib/src/websocket/websocket_session.dart +++ b/lib/src/websocket/websocket_session.dart @@ -28,10 +28,7 @@ class WebsocketSession { /// add new websocket session to the active sessions void addNewSession(String sessionId, WebSocket ws) { _activeSessions.addAll({ - sessionId: SessionInfo( - sessionId: sessionId, - websocket: ws, - ) + sessionId: SessionInfo(sessionId: sessionId, websocket: ws), }); } diff --git a/test/src/extensions/number_extension_test.dart b/test/src/extensions/number_extension_test.dart index 0de44f25..1e41c84d 100644 --- a/test/src/extensions/number_extension_test.dart +++ b/test/src/extensions/number_extension_test.dart @@ -34,12 +34,14 @@ void main() { expect(result, isA()); }); - test('should return an integer when rounding integers with zero decimals', - () { - var result = 100.toFixed(0); - expect(result, equals(100)); - expect(result, isA()); - }); + test( + 'should return an integer when rounding integers with zero decimals', + () { + var result = 100.toFixed(0); + expect(result, equals(100)); + expect(result, isA()); + }, + ); test('should handle negative numbers correctly', () { expect((-123.456).toFixed(2), equals(-123.46)); diff --git a/test/src/extensions/string_list_extension_test.dart b/test/src/extensions/string_list_extension_test.dart index 4c4649e4..3f0575a6 100644 --- a/test/src/extensions/string_list_extension_test.dart +++ b/test/src/extensions/string_list_extension_test.dart @@ -16,18 +16,24 @@ void main() { }); test('joins multiple elements with default separator and conjunction', () { - expect(['apple', 'orange', 'banana'].joinWithAnd(), - equals('apple, orange and banana')); + expect( + ['apple', 'orange', 'banana'].joinWithAnd(), + equals('apple, orange and banana'), + ); }); test('allows custom separator and conjunction', () { - expect(['apple', 'orange', 'banana'].joinWithAnd(' / ', 'or'), - equals('apple / orange or banana')); + expect( + ['apple', 'orange', 'banana'].joinWithAnd(' / ', 'or'), + equals('apple / orange or banana'), + ); }); test('considers only the last two elements for conjunction', () { - expect(['apple', 'orange', 'banana', 'mango'].joinWithAnd(), - equals('apple, orange, banana and mango')); + expect( + ['apple', 'orange', 'banana', 'mango'].joinWithAnd(), + equals('apple, orange, banana and mango'), + ); }); }); } diff --git a/test/unit/validation_test.dart b/test/unit/validation_test.dart index 32098698..aaa0293b 100644 --- a/test/unit/validation_test.dart +++ b/test/unit/validation_test.dart @@ -32,20 +32,16 @@ void main() { }); test('Validation password confirmed', () { - Validator validator = Validator(data: { - 'password': '12345678', - 'password_confirmation': '112233445566', - }); + Validator validator = Validator( + data: {'password': '12345678', 'password_confirmation': '112233445566'}, + ); validator.validate({'password': 'confirmed'}).then((_) { expect(validator.errors['password'], 'The two password did not match'); }); }); test('Validation required if', () { - Validator validator = Validator(data: { - 'username': '', - 'type': 'login', - }); + Validator validator = Validator(data: {'username': '', 'type': 'login'}); validator.validate({'username': 'required_if:type,login'}).then((_) { expect(validator.errors['username'], 'The username is required'); });