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')}
}
''');
});
}