import 'dart:io'; import 'dart:convert'; import 'dart:math'; import 'package:mason/mason.dart'; import 'package:yaml/yaml.dart'; void run(HookContext context) async { final logger = context.logger; final String functionName = context.vars['function_name'] ?? ''; final String requestObject = context.vars['request_object'] ?? ''; final cName = functionName.camelCase; final pName = functionName.pascalCase; final uName = functionName.snakeCase.toUpperCase(); final secureKeyValue = _generateSecureKey(uName); String projectName = 'your_project'; final pubspecFile = File('pubspec.yaml'); if (pubspecFile.existsSync()) { final doc = loadYaml(pubspecFile.readAsStringSync()); projectName = doc['name'] ?? projectName; } final bool isList = requestObject.startsWith('List<'); final bool isString = requestObject.toLowerCase() == 'string'; String baseType = requestObject; if (isList) { baseType = requestObject.substring(5, requestObject.length - 1); } final files = [ 'lib/Grounded/memory/ConnectInternalMemory.dart', 'lib/Grounded/memory/InternalMemory.dart', 'lib/Grounded/informatics/AppDataManager.dart' ]; String? importLine; String? importFileName; if (!isString) { final result = await _findClassData(baseType, projectName); importLine = result?['line']; importFileName = result?['fileName']; } // --- Implementation Logic --- String getLogic = ""; String setLogic = ""; if (isString) { getLogic = "return await groundedStorage.read(key: $uName) ?? '';"; setLogic = "await groundedStorage.write(key: $uName, value: data);"; } else if (isList) { getLogic = ''' final dataString = await groundedStorage.read(key: $uName); if (dataString != null && dataString.isNotEmpty) { return (jsonDecode(dataString) as List) .map((item) => $baseType.fromJson(item)) .toList(); } return [];'''; setLogic = ''' final jsonString = jsonEncode(data.map((item) => item.toJson()).toList()); await groundedStorage.write(key: $uName, value: jsonString);'''; } else { getLogic = ''' final jsonString = await groundedStorage.read(key: $uName); if (jsonString != null && jsonString.isNotEmpty) { return $baseType.fromJson(jsonDecode(jsonString)); } return $baseType();'''; setLogic = ''' await groundedStorage.write(key: $uName, value: jsonEncode(data.toJson()));'''; } // --- 1. ConnectInternalMemory (No space between the pair) --- final interfaceCode = " Future<$requestObject> get$pName();\n Future set$pName($requestObject data);"; await _inject(files[0], interfaceCode, logger, importLine: importLine, importFileName: importFileName, duplicateCheck: "get$pName()"); // --- 2. InternalMemory (Key spacing at TOP) --- final String keyLine = '\n\n static const String $uName = "$secureKeyValue";\n'; final String methods = ''' @override Future<$requestObject> get$pName() async { $getLogic } @override Future set$pName($requestObject data) async { $setLogic }'''; await _injectInternalMemory(files[1], keyLine, methods, logger, importLine: importLine, importFileName: importFileName, duplicateCheck: "get$pName()"); // --- 3. AppDataManager --- final String wrapper = ''' @override Future<$requestObject> get$pName() async { return await connectInternalMemory.get$pName(); } @override Future set$pName($requestObject data) async { return await connectInternalMemory.set$pName(data); }'''; await _inject(files[2], wrapper, logger, importLine: importLine, importFileName: importFileName, duplicateCheck: "get$pName()"); // --- 4. Format --- try { await Process.run('dart', ['format', 'lib/Grounded/']); } catch (_) {} logger.success('✨ Internal Memory synced with corrected spacing.'); } String _generateSecureKey(String base) { final random = Random.secure(); final values = List.generate(12, (i) => random.nextInt(256)); return "${base}_${base64Url.encode(values).replaceAll('=', '').substring(0, 16)}"; } Future?> _findClassData(String className, String projectName) async { final dir = Directory('lib'); if (!dir.existsSync()) return null; for (var f in dir.listSync(recursive: true)) { if (f is File && f.path.endsWith('.dart')) { final content = await f.readAsString(); if (content.contains('class $className')) { return { 'line': "import 'package:$projectName/${f.path.replaceFirst('lib/', '')}';", 'fileName': f.path.split('/').last, }; } } } return null; } Future _inject(String path, String content, Logger logger, {String? importLine, String? importFileName, String? duplicateCheck}) async { final file = File(path); if (!await file.exists()) return; String fileContent = await file.readAsString(); if (duplicateCheck != null && fileContent.contains(duplicateCheck)) return; if (importLine != null && importFileName != null && !fileContent.contains(importFileName)) { fileContent = "$importLine\n$fileContent"; } final lastBrace = fileContent.lastIndexOf('}'); if (lastBrace != -1) { // Inject with double newlines between previous content and new content fileContent = fileContent.substring(0, lastBrace).trimRight() + '\n\n$content\n' + fileContent.substring(lastBrace); await file.writeAsString(fileContent); } } Future _injectInternalMemory(String path, String keyLine, String methods, Logger logger, {String? importLine, String? importFileName, String? duplicateCheck}) async { final file = File(path); if (!await file.exists()) return; String content = await file.readAsString(); if (duplicateCheck != null && content.contains(duplicateCheck)) return; if (importLine != null && importFileName != null && !content.contains(importFileName)) { content = "$importLine\n$content"; } if (!content.contains("import 'dart:convert';")) { content = "import 'dart:convert';\n$content"; } // Inject Key at the top with forced extra spacing final classStart = content.indexOf('{'); if (classStart != -1) { content = content.substring(0, classStart + 1) + "$keyLine" + content.substring(classStart + 1); } // Inject Methods at the bottom final lastBrace = content.lastIndexOf('}'); if (lastBrace != -1) { content = content.substring(0, lastBrace).trimRight() + "\n\n$methods\n" + content.substring(lastBrace); } await file.writeAsString(content); }