generateService method

void generateService(
  1. String pathPackageLocal2dart
)

Implementation

void generateService(String pathPackageLocal2dart) {
  final dirService = join(pathPackageLocal2dart, 'lib', 'services');

  DirectoryHelper.createDir(dirService);

  final Map tables = local2dart['table'] ?? {};
  final Map query = local2dart['query'] ?? {};

  tables.forEach((tableName, table) {
    final Map columns = table['column'] ?? {};
    final Map foreigns = table['foreign'] ?? {};

    String primaryKey = '';
    String typePrimaryKey = '';

    List<String> variables = [];
    List<String> queryWithJoins = [];
    List<String> tableJoins = [];
    columns.forEach((columnName, column) {
      if (column is Map &&
          column['constraint']?.toString().toUpperCase() == 'PRIMARY KEY') {
        primaryKey = columnName.toString().snakeCase;
        typePrimaryKey = getType(column['type']?.toString() ?? '');
      }

      variables.add(
          "static const String column${columnName.toString().pascalCase} = '${columnName.toString().snakeCase}';");
      queryWithJoins.add(
          "${tableName.toString().snakeCase}.${columnName.toString().snakeCase} as '${tableName.toString().snakeCase}.${columnName.toString().snakeCase}'");
    });

    foreigns.forEach((foreignName, foreign) {
      final String columnForeign = foreign['to_column'] ?? '';
      final String tableNameForeign = foreign['to_table'] ?? '';
      final Map references = tables[tableNameForeign] ?? {};
      final Map columnsForeign = references['column'] ?? {};

      columnsForeign.forEach((key, value) {
        queryWithJoins.add(
            "${tableNameForeign.toString().snakeCase}.${key.toString().snakeCase} as '${tableNameForeign.toString().snakeCase}.${key.toString().snakeCase}'");
      });

      tableJoins.add(
          'LEFT JOIN ${tableNameForeign.snakeCase} ON ${tableName.toString().snakeCase}.${foreignName.toString().snakeCase} = ${tableNameForeign.snakeCase}.${columnForeign.snakeCase}');
    });

    List<String> importQueryModel = [];
    List<String> customQuery = [];

    final Map selectedQuery = query[tableName.toString().snakeCase] ?? {};
    selectedQuery.forEach((queryName, query) {
      importQueryModel.add(
        "import '../models/${queryName.toString().snakeCase}_query.dart';",
      );

      final where = query['where'] ?? '';

      final int whereArgsLength = RegExp(r'\?').allMatches(where).length;
      List<String> whereArgsParams = List.generate(
          whereArgsLength, (index) => 'Object? args${index + 1},');
      List<String> whereArgsImpl =
          List.generate(whereArgsLength, (index) => 'args${index + 1},');

      String rawQuery = getRawQuery(
        distinct: query['disticnt'] ?? false,
        column: query['column'],
        from: tableName,
        join: query['join'],
        where: query['where'],
        isWhereArgs: true,
        orderBy: query['order_by'],
        limit: query['limit'],
        offset: query['offset'],
        groupBy: query['group_by'],
        having: query['having'],
      );

      customQuery.add(
          '''static Future<List<${queryName.toString().pascalCase}Query>> ${queryName.toString().camelCase}(${whereArgsParams.join()}) async {
      final db = await getDatabase();
      ${whereArgsLength == 0 ? '' : '''final where = QueryHelper.whereQuery(
        where: '$where',
        whereArgs: [${whereArgsImpl.join()}],
      );'''}
      final query = await db.rawQuery("$rawQuery",);
      List<${queryName.toString().pascalCase}Query> result = [];
      for (var element in query) {
        result.add(${queryName.toString().pascalCase}Query.fromMap(element));
      }
      return result;
    }''');
    });

    join(dirService, '${tableName.toString().snakeCase}_local_service.dart')
        .write('''import 'package:local2dart/utils/database_instance.dart';
import 'package:sqflite/sqflite.dart';

import '../paginations/local_pagination.dart';
import '../utils/query_helper.dart';
import '../models/${tableName.toString().snakeCase}_table.dart';
import '../utils/bulk_insert.dart';
import '../utils/bulk_update.dart';
import '../utils/bulk_delete.dart';

${importQueryModel.join('\n')}

abstract class ${tableName.toString().pascalCase}LocalService {
static const String tableName = '${tableName.toString().snakeCase}';

${variables.join('\n')}

static Future<Database> getDatabase() async => (await DatabaseInstance.getInstance()).db;

${foreigns.isEmpty ? '' : '''static String _queryWithJoin({
  bool? distinct,
  String? where,
  List<Object?>? whereArgs,
  String? groupBy,
  String? having,
  String? orderBy,
  int? limit,
  int? offset,
}) {
  final allConditionalQuery = QueryHelper.allConditionalQuery(
    where: where,
    whereArgs: whereArgs,
    groupBy: groupBy,
    having: having,
    orderBy: orderBy,
    limit: limit,
    offset: offset,
  );
  return "SELECT \${QueryHelper.distinctQuery(distinct: distinct)} ${queryWithJoins.join(', ')} FROM ${tableName.toString().snakeCase} ${tableJoins.join(' ')} \$allConditionalQuery";
}
'''}


static Future<int> count({
  bool? distinct,
  String? where,
  List<Object?>? whereArgs,
  String? groupBy,
  String? having,
  String? orderBy,
  int? limit,
  int? offset,
}) async {
  final db = await getDatabase();
  final countQuery = QueryHelper.countQuery(
    tableName: tableName,
    distinct: distinct,
    where: where,
    whereArgs: whereArgs,
    groupBy: groupBy,
    having: having,
    orderBy: orderBy,
    limit: limit,
    offset: offset,
  );
  final count = Sqflite.firstIntValue(await db.rawQuery(countQuery));
  return count ?? 0;
}

static Future<List<${tableName.toString().pascalCase}Table>> get({
  bool? distinct,
  List<String>? columns,
  String? where,
  List<Object?>? whereArgs,
  String? groupBy,
  String? having,
  String? orderBy,
  int? limit,
  int? offset,
}) async {
  final db = await getDatabase();
  final query = await db.query(
    tableName,
    distinct: distinct,
    columns: columns,
    where: where,
    whereArgs: whereArgs,
    groupBy: groupBy,
    having: having,
    orderBy: orderBy,
    limit: limit,
    offset: offset,
  );
  List<${tableName.toString().pascalCase}Table> result = [];
  for (var element in query) {
    result.add(${tableName.toString().pascalCase}Table.fromMap(element));
  }
  return result;
}

static Future<LocalPagination<List<${tableName.toString().pascalCase}Table>>> getWithPagination({
  bool? distinct,
  List<String>? columns,
  String? where,
  List<Object?>? whereArgs,
  String? groupBy,
  String? having,
  String? orderBy,
  required int limit,
  required int page,
}) async {
  final db = await getDatabase();
  final offset = QueryHelper.offset(page: page, limit: limit);
  final total = await count(
    distinct: distinct,
    where: where,
    whereArgs: whereArgs,
    groupBy: groupBy,
    having: having,
    orderBy: orderBy,
    limit: limit,
    offset: offset,
  );
  final query = await db.query(
    tableName,
    distinct: distinct,
    columns: columns,
    where: where,
    whereArgs: whereArgs,
    groupBy: groupBy,
    having: having,
    orderBy: orderBy,
    limit: limit,
    offset: offset,
  );
  List<${tableName.toString().pascalCase}Table> result = [];
  for (var element in query) {
    result.add(${tableName.toString().pascalCase}Table.fromMap(element));
  }

  final meta = QueryHelper.metaPagination(
    total: total,
    page: page,
    limit: limit,
    offset: offset,
  );
  return LocalPagination(data: result, meta: meta);
}

${primaryKey.isEmpty ? '' : '''  static Future<${tableName.toString().pascalCase}Table?> getBy${primaryKey.pascalCase}($typePrimaryKey ${primaryKey.camelCase}) async {
  final db = await getDatabase();
  final query = await db.query(tableName, where: '\$column${primaryKey.pascalCase} = ?', whereArgs: [${primaryKey.camelCase}]);
  if (query.isEmpty) return null;
  return ${tableName.toString().pascalCase}Table.fromMap(query.first);
}
'''}


${foreigns.isEmpty ? '' : '''  static Future<List<${tableName.toString().pascalCase}Table>> getWithJoin({
  bool? distinct,
  String? where,
  List<Object?>? whereArgs,
  String? groupBy,
  String? having,
  String? orderBy,
  int? limit,
  int? offset,
}) async {
  final db = await getDatabase();
  final queryWithJoin = _queryWithJoin(
    distinct: distinct,
    where: where,
    whereArgs: whereArgs,
    groupBy: groupBy,
    having: having,
    orderBy: orderBy,
    limit: limit,
    offset: offset,
  );
  final query = await db.rawQuery(queryWithJoin);
  List<${tableName.toString().pascalCase}Table> result = [];
  for (var element in query) {
    result.add(${tableName.toString().pascalCase}Table.fromMapWithJoin(element));
  }
  return result;
}

static Future<LocalPagination<List<${tableName.toString().pascalCase}Table>>> getWithJoinPagination({
  bool? distinct,
  String? where,
  List<Object?>? whereArgs,
  String? groupBy,
  String? having,
  String? orderBy,
  required int limit,
  required int page,
}) async {
  final db = await getDatabase();
  final offset = QueryHelper.offset(page: page, limit: limit);
  final total = await count(
    distinct: distinct,
    where: where,
    whereArgs: whereArgs,
    groupBy: groupBy,
    having: having,
    orderBy: orderBy,
    limit: limit,
    offset: offset,
  );
  final queryWithJoin = _queryWithJoin(
    distinct: distinct,
    where: where,
    whereArgs: whereArgs,
    groupBy: groupBy,
    having: having,
    orderBy: orderBy,
    limit: limit,
    offset: offset,
  );
  final query = await db.rawQuery(queryWithJoin);
  List<${tableName.toString().pascalCase}Table> result = [];
  for (var element in query) {
    result.add(${tableName.toString().pascalCase}Table.fromMapWithJoin(element));
  }
  final meta = QueryHelper.metaPagination(
    total: total,
    page: page,
    limit: limit,
    offset: offset,
  );
  return LocalPagination(data: result, meta: meta);
}

${primaryKey.isEmpty ? '' : '''  static Future<${tableName.toString().pascalCase}Table?> getBy${primaryKey.pascalCase}WithJoin($typePrimaryKey ${primaryKey.camelCase}) async {
  final db = await getDatabase();
  final queryWithJoin = _queryWithJoin(where: '\$tableName.\$column${primaryKey.pascalCase} = ?', whereArgs: [${primaryKey.camelCase}]);
  final query = await db.rawQuery(queryWithJoin);
  if (query.isEmpty) return null;
  return ${tableName.toString().pascalCase}Table.fromMapWithJoin(query.first);
}'''}
'''}

static Future<int> insert({
  required ${tableName.toString().pascalCase}Table ${tableName.toString().camelCase}Table,
  String? nullColumnHack,
  ConflictAlgorithm? conflictAlgorithm,
}) async {
  final db = await getDatabase();
  return db.insert(
    tableName,
    ${tableName.toString().camelCase}Table.toMap(),
    nullColumnHack: nullColumnHack,
    conflictAlgorithm: conflictAlgorithm,
  );
}

static Future<List<Object?>> bulkInsert({
  required List<BulkInsert<${tableName.toString().pascalCase}Table>> bulkInsertTable,
  bool? exclusive,
  bool? noResult,
  bool? continueOnError,
}) async {
  final db = await getDatabase();
  final batch = db.batch();
  for (var element in bulkInsertTable) {
    batch.insert(
      tableName,
      element.data.toMap(),
      nullColumnHack: element.nullColumnHack,
      conflictAlgorithm: element.conflictAlgorithm,
    );
  }
  return batch.commit(
    exclusive: exclusive,
    noResult: noResult,
    continueOnError: continueOnError,
  );
}

${primaryKey.isEmpty ? '' : '''  static Future<int> upsert({required ${tableName.toString().pascalCase}Table ${tableName.toString().camelCase}Table}) async {
  final countData = await count(
    where: '\$column${primaryKey.pascalCase} = ?',
    whereArgs: [${tableName.toString().camelCase}Table.${primaryKey.camelCase}],
  );
  if (countData > 0) {
    return updateBy${primaryKey.pascalCase}(${primaryKey.camelCase}: ${tableName.toString().camelCase}Table.${primaryKey.camelCase}, ${tableName.toString().camelCase}Table: ${tableName.toString().camelCase}Table,);
  }
  return insert(${tableName.toString().camelCase}Table: ${tableName.toString().camelCase}Table);
}'''}

static Future<int> update({
  required ${tableName.toString().pascalCase}Table ${tableName.toString().camelCase}Table,
  String? where,
  List<Object?>? whereArgs,
  ConflictAlgorithm? conflictAlgorithm,
}) async {
  final db = await getDatabase();
  return db.update(
    tableName,
    ${tableName.toString().camelCase}Table.toMap(),
    where: where,
    whereArgs: whereArgs,
    conflictAlgorithm: conflictAlgorithm,
  );
}

static Future<List<Object?>> bulkUpdate({
  required List<BulkUpdate<${tableName.toString().pascalCase}Table>> bulkUpdateTables,
  bool? exclusive,
  bool? noResult,
  bool? continueOnError,
}) async {
  final db = await getDatabase();
  final batch = db.batch();
  for (var element in bulkUpdateTables) {
    batch.update(
      tableName,
      element.data.toMap(),
      where: element.where,
      whereArgs: element.whereArgs,
      conflictAlgorithm: element.conflictAlgorithm,
    );
  }
  return batch.commit(
    exclusive: exclusive,
    noResult: noResult,
    continueOnError: continueOnError,
  );
}

${primaryKey.isEmpty ? '' : '''  static Future<int> updateBy${primaryKey.pascalCase}({
  required $typePrimaryKey ${primaryKey.camelCase},
  required ${tableName.toString().pascalCase}Table ${tableName.toString().camelCase}Table,
  ConflictAlgorithm? conflictAlgorithm,
}) async {
  final db = await getDatabase();
  return db.update(
    tableName,
    ${tableName.toString().camelCase}Table.toMap(),
    where: '\$column${primaryKey.pascalCase} = ?',
    whereArgs: [${primaryKey.camelCase}],
    conflictAlgorithm: conflictAlgorithm,
  );
}'''}

${primaryKey.isEmpty ? '' : '''  static Future<List<Object?>> bulkUpdateBy${primaryKey.pascalCase}({
  required List<$typePrimaryKey> ${primaryKey.camelCase}s,
  required List<BulkUpdate<${tableName.toString().pascalCase}Table>> bulkUpdateTables,
  bool? exclusive,
  bool? noResult,
  bool? continueOnError,
}) async {
  final db = await getDatabase();
  final batch = db.batch();
  for (var i = 0; i < ${primaryKey.camelCase}s.length; i++) {
    batch.update(
      tableName,
      bulkUpdateTables[i].data.toMap(),
      where: '\$column${primaryKey.pascalCase} = ?',
      whereArgs: [${primaryKey.camelCase}s[i]],
      conflictAlgorithm: bulkUpdateTables[i].conflictAlgorithm,
    );
  }
  return batch.commit(
    exclusive: exclusive,
    noResult: noResult,
    continueOnError: continueOnError,
  );
}'''}


static Future<int> delete({
  String? where,
  List<Object?>? whereArgs,
}) async {
  final db = await getDatabase();
  return db.delete(
    tableName,
    where: where,
    whereArgs: whereArgs,
  );
}

static Future<List<Object?>> bulkDelete({
  required List<BulkDelete> bulkDelete,
  bool? exclusive,
  bool? noResult,
  bool? continueOnError,
}) async {
  final db = await getDatabase();
  final batch = db.batch();
  for (var element in bulkDelete) {
    batch.delete(
      tableName,
      where: element.where,
      whereArgs: element.whereArgs,
    );
  }
  return batch.commit(
    exclusive: exclusive,
    noResult: noResult,
    continueOnError: continueOnError,
  );
}

${primaryKey.isEmpty ? '' : '''  static Future<int> deleteBy${primaryKey.pascalCase}({required $typePrimaryKey ${primaryKey.camelCase}}) async {
  final db = await getDatabase();
  return db.delete(
    tableName,
    where: '\$column${primaryKey.pascalCase} = ?',
    whereArgs: [${primaryKey.camelCase}],
  );
}'''}

${primaryKey.isEmpty ? '' : '''  static Future<List<Object?>> bulkDeleteBy${primaryKey.pascalCase}({
  required List<$typePrimaryKey> ${primaryKey.camelCase}s,
  bool? exclusive,
  bool? noResult,
  bool? continueOnError,
}) async {
  final db = await getDatabase();
  final batch = db.batch();
  for (var element in ${primaryKey.camelCase}s) {
    batch.delete(
      tableName,
      where: '\$column${primaryKey.pascalCase} = ?',
      whereArgs: [element],
    );
  }
  return batch.commit(
    exclusive: exclusive,
    noResult: noResult,
    continueOnError: continueOnError,
  );
}'''}

${customQuery.isEmpty ? '' : customQuery.join('\n')}
}
''');
  });
}