diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..641c7c9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,55 @@ +# Created by https://www.toptal.com/developers/gitignore/api/dart,visualstudiocode +# Edit at https://www.toptal.com/developers/gitignore?templates=dart,visualstudiocode + +### Dart ### +# See https://www.dartlang.org/guides/libraries/private-files + +# Files and directories created by pub +.dart_tool/ +.packages +# If you're building an application, you may want to check-in your pubspec.lock +pubspec.lock + +# Directory created by dartdoc +# If you don't generate documentation locally you can remove this line. +doc/api/ + +# dotenv environment variables file +.env* + +# Avoid committing generated Javascript files: +*.dart.js +*.info.json # Produced by the --dump-info flag. +*.js # When generated by dart2js. Don't specify *.js if your + # project includes source files written in JavaScript. +*.js_ +*.js.deps +*.js.map + +.flutter-plugins +.flutter-plugins-dependencies + +### Dart Patch ### +# dotenv environment variables file +.env + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history +.ionide + +# End of https://www.toptal.com/developers/gitignore/api/dart,visualstudiocode \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..effe43c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,3 @@ +## 1.0.0 + +- Initial version. diff --git a/README.md b/README.md new file mode 100644 index 0000000..8b55e73 --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ + + +TODO: Put a short description of the package here that helps potential users +know whether this package might be useful for them. + +## Features + +TODO: List what your package can do. Maybe include images, gifs, or videos. + +## Getting started + +TODO: List prerequisites and provide or point to information on how to +start using the package. + +## Usage + +TODO: Include short and useful examples for package users. Add longer examples +to `/example` folder. + +```dart +const like = 'sample'; +``` + +## Additional information + +TODO: Tell users more about the package: where to find more information, how to +contribute to the package, how to file issues, what response they can expect +from the package authors, and more. diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..dee8927 --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,30 @@ +# This file configures the static analysis results for your project (errors, +# warnings, and lints). +# +# This enables the 'recommended' set of lints from `package:lints`. +# This set helps identify many issues that may lead to problems when running +# or consuming Dart code, and enforces writing Dart using a single, idiomatic +# style and format. +# +# If you want a smaller set of lints you can change this to specify +# 'package:lints/core.yaml'. These are just the most critical lints +# (the recommended set includes the core lints). +# The core lints are also what is used by pub.dev for scoring packages. + +include: package:lints/recommended.yaml + +# Uncomment the following section to specify additional rules. + +# linter: +# rules: +# - camel_case_types + +# analyzer: +# exclude: +# - path/to/excluded/files/** + +# For more information about the core and recommended set of lints, see +# https://dart.dev/go/core-lints + +# For additional information about configuring this file, see +# https://dart.dev/guides/language/analysis-options diff --git a/example/dart_framework_example.dart b/example/dart_framework_example.dart new file mode 100644 index 0000000..2a7eb4e --- /dev/null +++ b/example/dart_framework_example.dart @@ -0,0 +1,6 @@ +import 'package:dart_framework/dart_framework.dart'; + +void main() { + var awesome = Awesome(); + print('awesome: ${awesome.isAwesome}'); +} diff --git a/lib/core/app_data_manager.dart b/lib/core/app_data_manager.dart new file mode 100644 index 0000000..536fcdd --- /dev/null +++ b/lib/core/app_data_manager.dart @@ -0,0 +1,120 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; +//import 'package:flutter/services.dart' show rootBundle; + +import 'package:dart_framework/core/process.dart'; +import 'package:dart_framework/model/app_data.dart'; + +enum SCMType { Svn, Git } + +class AppDataManager { + AppDataManager._privateConstructor(); + static final AppDataManager _instance = AppDataManager._privateConstructor(); + static AppDataManager get to => _instance; + + late SCMType _scm; + late String _workspace; + late String _relativeAssetPath; + + // Future read(String relativeAssetPath) async { + // return AppData.fromJson(jsonDecode( + // await rootBundle.loadString('$relativeAssetPath/app_data.json'))); + // } + + Future create( + SCMType scm, String workspace, String relativeAssetPath) async { + _scm = scm; + _workspace = workspace; + _relativeAssetPath = relativeAssetPath; + var c = Completer(); + var appData = AppData(); + appData.version = await getVersion(); + appData.buildDate = getBuildTime(); + if (_scm == SCMType.Git) { + appData.gitHash = await getHash(); + } + await createFile(jsonEncode(appData.toJson())); + c.complete(appData); + return c.future; + } + + Future getVersion() async { + var c = Completer(); + var number = 0; + var shell = StringBuffer(); + switch (this._scm) { + case SCMType.Svn: + break; + case SCMType.Git: + shell.writeln('git rev-list --all HEAD --all --count'); + var process = + await ProcessExecutor.start(shell, workspace: this._workspace); + await process.process.exitCode; + number = int.parse(process.stdoutArr.last); + break; + } + + var version = this.numberToVersion(number); + print('#### Version: ' + version); + c.complete(version); + return c.future; + } + + String numberToVersion(int number, {int masterVersion = 0}) { + var arr = number.toString().split(''); + var length = arr.length; + var ver = ''; + var versionList = []; + for (int i = 0; i < length; ++i) { + if (i != 0 && i % 3 == 0) { + versionList.add(int.parse(ver)); + ver = ''; + } + ver = arr[length - (i + 1)].toString() + ver; + } + if (ver != '') versionList.add(int.parse(ver)); + + ver = ''; + length = 3; + var list = ['0', '0', '0']; + for (int i = 0; i < length; ++i) { + var versionValue = versionList.length <= i ? 0 : versionList[i]; + var versionStr = i == 2 + ? (versionValue + masterVersion).toString() + : versionValue.toString(); + list[length - (i + 1)] = versionStr; + } + return list.join('.'); + } + + Future getHash() async { + var c = Completer(); + var shell = StringBuffer(); + shell.writeln('git rev-parse HEAD'); + var process = + await ProcessExecutor.start(shell, workspace: this._workspace); + await process.process.exitCode; + var hash = process.stdoutArr.last; + print('#### Git Hash: ' + hash); + c.complete(hash); + return c.future; + } + + String getBuildTime() { + var date = DateTime.now().toString(); + date = date.substring(0, date.lastIndexOf('.')); + print('#### Build Date: ' + date); + return date; + } + + Future createFile(String json) async { + var c = Completer(); + var dir = Directory('$_workspace/$_relativeAssetPath'); + if (!dir.existsSync()) dir.createSync(recursive: true); + var file = File('$_workspace/$_relativeAssetPath/app_data.json'); + await file.writeAsString(json); + c.complete(); + return c.future; + } +} diff --git a/lib/core/process.dart b/lib/core/process.dart new file mode 100644 index 0000000..c139e32 --- /dev/null +++ b/lib/core/process.dart @@ -0,0 +1,520 @@ +import 'dart:async'; +import 'dart:io'; +import 'dart:convert'; +import 'dart:math'; + +class ProcessData { + late Process process; + late File file; + late bool isRunning; + late int exitCode; + Function(ProcessData)? _endListener; + late StringBuffer stdout; + late StringBuffer stderr; + + Function(ProcessData)? get endListener { + return _endListener; + } + + bool get isSuccess { + return ProcessExecutor.getSuccess(exitCode); + } + + List get stdoutArr { + return getBufferToArray(stdout); + } + + List get stderrArr { + return getBufferToArray(stderr); + } + + List getBufferToArray(StringBuffer buffer) { + var list = []; + var arr = buffer.toString().split('\n'); + var length = arr.length; + for (var i = 0; i < length; ++i) { + if (arr[i].isNotEmpty) { + list.add(arr[i]); + } + } + return list; + } + + set processValue(Process value) { + process = value; + stdout = StringBuffer(); + stderr = StringBuffer(); + process.stdout.transform(utf8.decoder).listen((event) { + stdout.writeln(event); + print(event); + }); + process.stderr.transform(utf8.decoder).listen((event) { + stderr.writeln(event); + print(event); + }); + isRunning = true; + checkExit(); + } + + void addEndListener(Function(ProcessData) listener) { + _endListener = listener; + } + + void removeEndListener() { + _endListener = null; + } + + void checkExit() async { + exitCode = await this.process.exitCode; + print('#### Exit Code: $exitCode'); + deleteFile(); + isRunning = false; + if (_endListener != null) _endListener!(this); + } + + void terminate() { + process.kill(); + } + + void deleteFile() async { + if (await file.exists()) { + await file.delete(); + } + } + + void dispose() async { + deleteFile(); + } +} + +class ProcessExecutor { + static Future startExe(String exe, List args, + {String? workspace}) async { + var c = Completer(); + var arg = '$exe ${args.join(' ')}'; + var processData = ProcessData(); + if (Platform.isMacOS || Platform.isWindows) { + workspace = workspace ?? Directory.current.path; + print('Execute Shell: $arg'); + try { + processData.processValue = + await Process.start(exe, args, workingDirectory: workspace); + } on Exception catch (e) { + print(e); + } + } else { + print('This platform not support process executor.'); + } + c.complete(processData); + return c.future; + } + + static Future start(StringBuffer shell, + {String? workspace}) async { + var c = Completer(); + + try { + var processData = ProcessData(); + var fileName = DateTime.now(); + if (Platform.isMacOS) { + workspace = workspace ?? Directory.current.path; + var file = + File('$workspace/temp_${fileName.microsecondsSinceEpoch}.sh'); + processData.file = file; + print('Execute Shell: ${file.path} \n ${shell.toString()}'); + if (await file.exists()) { + await file.delete(); + } + file.createSync(); + file.writeAsStringSync(shell.toString()); + try { + processData.processValue = await Process.start('zsh', [file.path], + workingDirectory: workspace, runInShell: false); + } on Exception catch (e) { + print(e); + } + } else if (Platform.isWindows) { + workspace = workspace ?? Directory.current.path; + var file = + File('$workspace/temp_${fileName.microsecondsSinceEpoch}.bat'); + processData.file = file; + print('Execute Shell: ${file.path} \n ${shell.toString()}'); + if (await file.exists()) { + await file.delete(); + } + file.createSync(); + file.writeAsStringSync(shell.toString()); + try { + processData.processValue = await Process.start( + 'cmd', ['/C', file.path], + workingDirectory: workspace, runInShell: false); + } on Exception catch (e) { + print(e); + } + } else { + print('This platform not support process executor.'); + } + c.complete(processData); + } on Exception catch (e) { + print('General Exception in ProcessExecutor.start: $e'); + } + return c.future; + } + + static Future run(StringBuffer shell, + {String? workspace, bool printStdout = true}) async { + var c = Completer(); + ProcessResult? processResult; + if (Platform.isMacOS) { + workspace = workspace ?? Directory.current.path; + var file = File('$workspace/temp.sh'); + print('Execute Shell: ${file.path} \n ${shell.toString()}'); + file.createSync(); + file.writeAsStringSync(shell.toString()); + try { + await Process.run('zsh', [file.path], workingDirectory: workspace) + .then((ProcessResult result) { + processResult = result; + }); + if (printStdout) { + print( + // ignore: prefer_interpolation_to_compose_strings + '[ProcessExecutor] Exit Code: ${processResult!.exitCode}, Result: ' + + processResult!.stdout); + } + } on Exception catch (e) { + print(e); + } finally { + file.deleteSync(); + } + c.complete(processResult); + } else if (Platform.isWindows) { + workspace = workspace ?? Directory.current.path; + var file = File('$workspace/temp.bat'); + print('Execute Bat: ${file.path} \n ${shell.toString()}'); + file.createSync(); + file.writeAsStringSync(shell.toString()); + await Process.run('cmd', ['/C', file.path], workingDirectory: workspace) + .then((ProcessResult result) { + processResult = result; + }); + if (printStdout) { + print( + // ignore: prefer_interpolation_to_compose_strings + '[ProcessExecutor] Exit Code: ${processResult!.exitCode}, Result: ' + + processResult!.stdout); + } + file.deleteSync(); + c.complete(processResult); + } else { + print('This platform not support process executor.'); + c.complete(null); + } + return c.future; + } + + static bool getSuccess(int exitCode) { + if (Platform.isMacOS) return exitCode == 0; + if (Platform.isWindows) return exitCode == 1; + return false; + } +} + +class NetStatData { + late String type; + late String from; + late String to; + late String state; + late int pid; + + NetStatData(List categories) { + var count = 0; + var length = categories.length; + for (var i = 0; i < length; ++i) { + var category = categories[i].replaceAll(' ', ''); + if (category.isNotEmpty) { + switch (count) { + case 0: + type = category; + break; + case 1: + from = category; + break; + case 2: + to = category; + break; + case 3: + state = category; + break; + case 4: + var value = int.tryParse(category); + if (value == null) value = -1; + pid = value; + break; + } + count++; + } + } + } +} + +bool _removedBat = false; +Future removeTempBat() async { + var c = Completer(); + if (!_removedBat) { + _removedBat = true; + var reg = RegExp(r'(temp_bat_)([0-9_]+)(.bat)'); + var list = Directory.current.listSync(); + for (var item in list) { + var match = reg.stringMatch(item.path); + if (match != null) { + await item.delete(); + } + } + await Future.delayed(Duration(milliseconds: 500)); + } + c.complete(); + return c.future; +} + +Future> findNetStat(String searchWord) async { + await removeTempBat(); + var c = Completer>(); + var shell = StringBuffer('netstat -ano | findstr $searchWord'); + var stdout = await ProcessSilentExecutor.run(shell); + var netList = []; + var returnPattern = RegExp('\n|\r'); + var list = stdout.split(returnPattern); + for (var item in list) { + item = item.replaceAll(returnPattern, ''); + if (item.isNotEmpty) { + var categories = item.split(' '); + if (categories.length > 0) { + netList.add(NetStatData(categories)); + } + } + } + c.complete(netList); + return c.future; +} + +Future> findProcess(String searchWord) async { + await removeTempBat(); + var c = Completer>(); + var shell = StringBuffer('tasklist /fo "csv" | findstr $searchWord'); + var stdout = await ProcessSilentExecutor.run(shell); + var pList = parseProcessStd(stdout); + c.complete(pList); + return c.future; +} + +List parseProcessStd(String stdout) { + var pList = []; + var returnPattern = RegExp('\n|\r'); + var list = stdout.split(returnPattern); + for (var item in list) { + item = item.replaceAll(returnPattern, ''); + if (item.isNotEmpty) { + var categories = item.split(','); + if (categories.length > 4) { + pList.add(ProcessInfo(categories)); + } + } + } + return pList; +} + +Future> findProcessByPid(int pid) async { + // await removeTempBat(); + var c = Completer>(); + var batch = getTempBat(fixedName: pid.toString()); + if (!batch.existsSync()) { + batch.writeAsStringSync( + 'tasklist /fi "pid eq ${pid.toString()}" /nh /fo "csv"'); + } + String stdout = await ProcessSilentExecutor.runBat(batch.path); + var pList = parseProcessStd(stdout); + c.complete(pList); + return c.future; +} + +class ProcessSilentExecutor { + static bool _initialized = false; + static Future initialize() async { + if (!_initialized) { + _initialized = true; + //remove before files + var regBat = RegExp(r'(silent_bat_)([0-9_]+)(.bat)'); + var regLog = RegExp(r'(silent_log_)([0-9_]+)(.txt)'); + var list = Directory.current.listSync(); + for (var item in list) { + var matchBat = regBat.stringMatch(item.path); + var matchLog = regLog.stringMatch(item.path); + if (matchBat != null || matchLog != null) { + item.deleteSync(); + } + } + } + } + + static Future run(StringBuffer shell) async { + initialize(); + var c = Completer(); + var batch = + File('${Directory.current.path}/silent_bat_${getRnadomPostfix()}.bat'); + batch.writeAsStringSync(shell.toString()); + var result = await runBat(batch.path); + await batch.delete(); + c.complete(result); + return c.future; + } + + static Future runBat(String batchPath) async { + initialize(); + var c = Completer(); + var current = Directory.current; + String result; + var log = File('${current.path}/silent_log_${getRnadomPostfix()}.txt'); + await Process.run('${current.path}/silentbatch.exe', [batchPath, log.path]) + .then((resultData) { + Process.killPid(resultData.pid); + // print('"$batchPath" => exitCode: ${resultData.exitCode}'); + }); + try { + result = await log.readAsString(); + } on Exception catch (e) { + print(e); + result = ''; + } + await log.delete(); + c.complete(result); + return c.future; + } +} + +String getRnadomPostfix() { + return '${DateTime.now().microsecondsSinceEpoch}_${Random().nextInt(100)}'; +} + +File getTempBat({String? fixedName}) { + fixedName ??= getRnadomPostfix(); + File batch = File('${Directory.current.path}/temp_bat_$fixedName.bat'); + return batch; +} + +class ProcessInfoListener { + late ProcessInfo? _process; + bool isRunning = false; + late Timer? _timer; + late int _checkInterval; + late Function(ProcessInfoListener, bool)? _connectionListener; + set _isRunning(bool value) { + if (isRunning != value) { + isRunning = value; + changedConnection(); + } + } + + ProcessInfoListener(this._process, this._checkInterval) { + this.checkLive(); + } + + void checkLive() async { + stopChecker(); + _isRunning = true; + _timer = Timer.periodic(Duration(seconds: _checkInterval), (time) async { + var enable = false; + if (_process != null) { + var list = await findProcessByPid(_process!.pid); + if (list.isNotEmpty) { + print('process live'); + enable = true; + this._isRunning = true; + } + } + + if (!enable) { + _isRunning = false; + stopChecker(); + } + }); + } + + void stopChecker() { + if (_timer != null) { + _timer!.cancel(); + _timer = null; + } + } + + void changedConnection() { + if (_connectionListener != null) { + _connectionListener!(this, isRunning); + } + } + + Function(ProcessInfoListener, bool)? get endListener { + return _connectionListener; + } + + void addEndListener(Function(ProcessInfoListener, bool)? listener) { + _connectionListener = listener; + } + + void removeConnectionListener() { + _connectionListener = null; + } + + void dispose() { + stopChecker(); + removeConnectionListener(); + _isRunning = false; + _process = null; + } + + void terminate() { + if (isRunning && _process != null) { + Process.killPid(this._process?.pid as int); + } + } +} + +class ProcessInfo { + late String name; + late int pid; + late String sessionName; + late int session; + late String memory; + + ProcessInfo(List categories) { + var count = 0; + var length = categories.length; + for (var i = 0; i < length; ++i) { + var category = categories[i].replaceAll('"', ''); + if (category.isNotEmpty) { + switch (count) { + case 0: + name = category; + break; + case 1: + var value = int.tryParse(category); + value ??= -1; + pid = value; + break; + case 2: + sessionName = category; + break; + case 3: + var value = int.tryParse(category); + value ??= -1; + session = value; + break; + case 4: + memory = category; + break; + } + count++; + } + } + } +} diff --git a/lib/dart_framework.dart b/lib/dart_framework.dart new file mode 100644 index 0000000..5509324 --- /dev/null +++ b/lib/dart_framework.dart @@ -0,0 +1,8 @@ +/// Support for doing something awesome. +/// +/// More dartdocs go here. +library dart_framework; + +export 'src/dart_framework_base.dart'; + +// TODO: Export any libraries intended for clients of this package. diff --git a/lib/model/app_data.dart b/lib/model/app_data.dart new file mode 100644 index 0000000..768f814 --- /dev/null +++ b/lib/model/app_data.dart @@ -0,0 +1,16 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'app_data.g.dart'; + +@JsonSerializable() +class AppData { + AppData(); + + late String version; + late String gitHash; + late String buildDate; + + factory AppData.fromJson(Map json) => + _$AppDataFromJson(json); + Map toJson() => _$AppDataToJson(this); +} diff --git a/lib/model/app_data.g.dart b/lib/model/app_data.g.dart new file mode 100644 index 0000000..46bba23 --- /dev/null +++ b/lib/model/app_data.g.dart @@ -0,0 +1,18 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'app_data.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +AppData _$AppDataFromJson(Map json) => AppData() + ..version = json['version'] as String + ..gitHash = json['gitHash'] as String + ..buildDate = json['buildDate'] as String; + +Map _$AppDataToJson(AppData instance) => { + 'version': instance.version, + 'gitHash': instance.gitHash, + 'buildDate': instance.buildDate, + }; diff --git a/lib/src/dart_framework_base.dart b/lib/src/dart_framework_base.dart new file mode 100644 index 0000000..e8a6f15 --- /dev/null +++ b/lib/src/dart_framework_base.dart @@ -0,0 +1,6 @@ +// TODO: Put public facing types in this file. + +/// Checks if you are awesome. Spoiler: you are. +class Awesome { + bool get isAwesome => true; +} diff --git a/lib/utils/os_startup.dart b/lib/utils/os_startup.dart new file mode 100644 index 0000000..45b14f2 --- /dev/null +++ b/lib/utils/os_startup.dart @@ -0,0 +1,58 @@ +import 'dart:io'; +import 'dart:async'; + +import 'package:path/path.dart'; +import 'package:dart_framework/core/process.dart'; + +class OSStartup { + static final String windowsStartupPath = + '\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\'; + + static Future isRegistedStartup(String label) async { + var c = Completer(); + var exist = false; + if (Platform.isMacOS) { + } else if (Platform.isWindows) { + //For Windows 8, 10 + var userPath = Platform.environment['UserProfile']; + exist = File('$userPath$windowsStartupPath$label').existsSync(); + } else if (Platform.isLinux) {} + c.complete(exist); + return c.future; + } + + static Future registStartup(String executableFilePath, + {String? label}) async { + var c = Completer(); + var file = File(executableFilePath); + var fileName = basename(file.path); + var targetName = label ?? fileName; + ProcessResult? result; + if (Platform.isMacOS) { + } else if (Platform.isWindows) { + //For Windows 8, 10 + var symbolicPath = '%userprofile%$windowsStartupPath$targetName'; + result = await ProcessExecutor.run( + StringBuffer('mklink "$symbolicPath" "$executableFilePath"')); + } else if (Platform.isLinux) {} + c.complete(result == null ? false : result.exitCode == 0); + return c.future; + } + + static Future unregistStartup(String label) async { + var c = Completer(); + var success = false; + if (Platform.isMacOS) { + } else if (Platform.isWindows) { + //For Windows 8, 10 + var userPath = Platform.environment['UserProfile']; + var file = File('$userPath$windowsStartupPath$label'); + if (file.existsSync()) { + await file.delete(); + success = true; + } + } else if (Platform.isLinux) {} + c.complete(success); + return c.future; + } +} diff --git a/lib/utils/path.dart b/lib/utils/path.dart new file mode 100644 index 0000000..95d51f5 --- /dev/null +++ b/lib/utils/path.dart @@ -0,0 +1,94 @@ +import 'dart:io'; +import 'dart:async'; +import 'package:path/path.dart' as path; + +enum FileType { + none, //not exit file + file, + directory, + link +} + +class Path { + static String? getParent(String path) { + path = getNormal(path); + var separator = '/'; + int index = path.lastIndexOf(separator); + if (index == -1) { + return null; + } else { + return path.substring(0, index); + } + } + + static String getName(String path) { + path = getNormal(path); + var parent = getParent(path); + var separator = '/'; + return path.replaceAll('$parent$separator', ''); + } + + static String getNormal(String path) { + return path.replaceAll('\\', '/'); + } + + //Remove last slush(/) + static String getNormalizePath(String path) { + var separator = Platform.isMacOS ? '/' : '\\'; + if (path.lastIndexOf(separator) == path.length - 1) { + path = path.substring(0, path.lastIndexOf(separator)); + } + return path; + } + + static FileType getType(String path) { + if (Directory(path).existsSync()) return FileType.directory; + if (File(path).existsSync()) return FileType.file; + return FileType.none; + } + + static Future copy(String startPath, String destPath, bool isDir, + {required List ignorePattern, + required List ignoredList}) async { + var c = Completer(); + var result = true; + if (ignorePattern != null) { + for (var pattern in ignorePattern) { + if (startPath.contains(pattern)) { + if (ignoredList != null) ignoredList.add(startPath); + c.complete(true); + return c.future; + } + } + } + try { + var name = Path.getName(startPath); + var destChildPath = path.join(destPath, name); + if (isDir) { + var startDir = Directory(startPath); + var destDir = Directory(destChildPath); + if (!startDir.existsSync()) + throw ArgumentError('Start - $startPath is not exist'); + if (!destDir.existsSync()) destDir.createSync(recursive: true); + var files = startDir.listSync(); + for (var file in files) { + if (file is File) + await copy(file.path, destDir.path, false, + ignorePattern: ignorePattern, ignoredList: ignoredList); + if (file is Directory) + await copy(file.path, destDir.path, true, + ignorePattern: ignorePattern, ignoredList: ignoredList); + } + } else { + var destDir = Directory(destPath); + if (!destDir.existsSync()) destDir.createSync(recursive: true); + print('File copy: $startPath --> $destChildPath'); + await File(startPath).copy(destChildPath); + } + } on Exception catch (e) { + result = false; + } + c.complete(result); + return c.future; + } +} diff --git a/lib/utils/system_util.dart b/lib/utils/system_util.dart new file mode 100644 index 0000000..aabfef2 --- /dev/null +++ b/lib/utils/system_util.dart @@ -0,0 +1,69 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +Map?> envArguments(List arguments) { + var dic = ?>{}; + var list = []; + var length = arguments.length; + for (var i = 0; i < length; ++i) { + var value = arguments[i]; + var key = _getKey(value); + if (key != null) { + var index = i + 1; + list.clear(); + while (index < length) { + var arg = arguments[index]; + if (_getKey(arg) == null) { + list.add(arg); + index++; + } else { + i = index - 1; + break; + } + } + List? arr = List.from(list); + if (arr.isEmpty) arr = null; + dic[key] = arr; + } + } + return dic; +} + +String? _getKey(String value) { + String? key; + if (value.indexOf('-') == 0) { + key = value.substring(1, value.length); + } + return key; +} + +Map? getMapFromJson(String jsonStr) { + Map? map; + if (jsonStr.length > 5) { + JsonCodec codec = JsonCodec(); + try { + map = codec.decode(jsonStr); + } catch (e) { + print("Error: $e"); + } + } + return map; +} + +Future getIPAddress(String domain) async { + var c = Completer(); + var ipAddress; + var regEx = RegExp(r'(://)([a-zA-Z0-9-.]+)(/|:)'); + var match = regEx.firstMatch(domain); + if (match != null && match.groupCount > 2) { + domain = match.group(2)!; + var list = await InternetAddress.lookup(domain); + for (var address in list) { + ipAddress = address.address; + break; + } + } + c.complete(ipAddress); + return c.future; +} diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..160b1ea --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,21 @@ +name: dart_framework +description: A starting point for Dart libraries or applications. +version: 1.0.0 +# repository: https://github.com/my_org/my_repo + +environment: + sdk: '>=2.19.0-96.0.dev <3.0.0' + +# Add regular dependencies here. +dependencies: + path: ^1.8.2 + args: ^2.3.2 + json_annotation: ^4.8.0 + archive: ^3.3.5 + ftpconnect: ^2.0.5 + +dev_dependencies: + lints: ^2.0.0 + test: ^1.21.0 + build_runner: ^2.1.4 + json_serializable: ^6.0.1 diff --git a/test/dart_framework_test.dart b/test/dart_framework_test.dart new file mode 100644 index 0000000..27882d5 --- /dev/null +++ b/test/dart_framework_test.dart @@ -0,0 +1,16 @@ +import 'package:dart_framework/dart_framework.dart'; +import 'package:test/test.dart'; + +void main() { + group('A group of tests', () { + final awesome = Awesome(); + + setUp(() { + // Additional setup goes here. + }); + + test('First Test', () { + expect(awesome.isAwesome, isTrue); + }); + }); +}