diff --git a/.langsync/config.hive b/.langsync/config.hive deleted file mode 100644 index e69de29..0000000 diff --git a/.langsync/config.lock b/.langsync/config.lock deleted file mode 100644 index e69de29..0000000 diff --git a/README.md b/README.md index 6250ff5..e69de29 100644 --- a/README.md +++ b/README.md @@ -1 +0,0 @@ -// TODO: add confirmation to logout command. \ No newline at end of file diff --git a/bin/langsync.dart b/bin/langsync.dart index e15e51d..25e1821 100644 --- a/bin/langsync.dart +++ b/bin/langsync.dart @@ -6,9 +6,6 @@ import 'package:langsync/src/etc/utils.dart'; Future main(List args) async { final configDir = utils.localeDataDir(); final langSyncDir = await Directory('${configDir.path}/langsync').create(); - final a = utils.isValidApiKeyFormatted( - '1939cf5177f5ae3805c24cc56c03a8186969c8e15a26bcbf1ab3caf96daacabb', - ); Hive.init(langSyncDir.path); @@ -17,13 +14,8 @@ Future main(List args) async { await _flushThenExit(await LangsyncCommandRunner().run(args)); } -/// Flushes the stdout and stderr streams, then exits the program with the given -/// status code. -/// -/// This returns a Future that will never complete, since the program will have -/// exited already. This is useful to prevent Future chains from proceeding -/// after you've decided to exit. -Future _flushThenExit(int status) { - return Future.wait([stdout.close(), stderr.close()]) - .then((_) => exit(status)); +Future _flushThenExit(int status) async { + await Future.wait([stdout.close(), stderr.close()]); + + exit(status); } diff --git a/bin/langsync.exe b/bin/langsync.exe index 9271136..608044b 100644 Binary files a/bin/langsync.exe and b/bin/langsync.exe differ diff --git a/langsync.yaml b/langsync.yaml deleted file mode 100644 index 36e86a4..0000000 --- a/langsync.yaml +++ /dev/null @@ -1,7 +0,0 @@ -langsync: - - source: './example/locales/en.json' - - output: './example/locales' - - target: [fr, de, ar, de, zh] diff --git a/lib/src/command_runner.dart b/lib/src/command_runner.dart index 0500ed6..6fef261 100644 --- a/lib/src/command_runner.dart +++ b/lib/src/command_runner.dart @@ -50,7 +50,7 @@ class LangsyncCommandRunner extends CompletionCommandRunner { addCommand(AccountCommand(logger: _logger)); addCommand(ConfigCommand(logger: _logger)); addCommand(SupportedLangsCommand(logger: _logger)); - addCommand(UpdateCommand(logger: _logger, pubUpdater: _pubUpdater)); + // addCommand(UpdateCommand(logger: _logger, pubUpdater: _pubUpdater)); addCommand(StartCommand(logger: _logger)); } @@ -124,10 +124,10 @@ class LangsyncCommandRunner extends CompletionCommandRunner { exitCode = await super.runCommand(topLevelResults); } - // Check for updates - if (topLevelResults.command?.name != UpdateCommand.commandName) { - await _checkForUpdates(); - } + // // Check for updates + // if (topLevelResults.command?.name != UpdateCommand.commandName) { + // await _checkForUpdates(); + // } return exitCode; } diff --git a/lib/src/commands/account_command/account_command.dart b/lib/src/commands/account_command/account_command.dart index a71fcd3..3369ece 100644 --- a/lib/src/commands/account_command/account_command.dart +++ b/lib/src/commands/account_command/account_command.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:args/command_runner.dart'; +import 'package:langsync/src/commands/account_command/sub_commands/api_key_command.dart'; import 'package:langsync/src/commands/account_command/sub_commands/auth_command.dart'; import 'package:langsync/src/commands/account_command/sub_commands/info_command.dart'; import 'package:langsync/src/commands/account_command/sub_commands/logout_command.dart'; @@ -13,6 +14,7 @@ class AccountCommand extends Command { addSubcommand(AuthCommand(logger: _logger)); addSubcommand(InfoCommand(logger: _logger)); addSubcommand(LogoutCommand(logger: _logger)); + addSubcommand(ApiKeyCommand(logger: _logger)); } @override @@ -22,9 +24,4 @@ class AccountCommand extends Command { String get name => 'account'; final Logger _logger; - - @override - FutureOr? run() { - return super.run(); - } } diff --git a/lib/src/commands/account_command/sub_commands/api_key_command.dart b/lib/src/commands/account_command/sub_commands/api_key_command.dart new file mode 100644 index 0000000..bcfc419 --- /dev/null +++ b/lib/src/commands/account_command/sub_commands/api_key_command.dart @@ -0,0 +1,71 @@ +import 'dart:async'; + +import 'package:args/command_runner.dart'; +import 'package:langsync/src/etc/extensions.dart'; +import 'package:langsync/src/etc/networking/client.dart'; +import 'package:mason_logger/mason_logger.dart'; + +class ApiKeyCommand extends Command { + ApiKeyCommand({ + required this.logger, + }); + + final Logger logger; + + @override + String get description => 'Create your unique API key'; + + @override + String get name => 'apiKey'; + + @override + FutureOr? run() async { + final userSure = logger.confirm( + "You're about to create a brand new unique API key, do you want to continue?"); + if (!userSure) { + logger.info('Aborted!'); + return 0; + } + + logger.info('\n'); + + final userName = logger.prompt( + 'Please enter your desired username (will be used to identify you): '); + + if (userName.isEmpty) { + logger.err("Username can't be empty!"); + return 1; + } + + final progress = logger.progress('Creating your API key...'); + + try { + final apiKeyDoc = await NetClient.instance.createApiKey(userName); + + progress.complete('API key created successfully!'); + logger.info('\n'); + + logger + // ..info('Your username: ${apiKeyDoc.username}') + ..success('Your API key: ${apiKeyDoc.apiKey}') + ..info('\n') + ..warn( + "Please make sure to save your API key somewhere safe, as you won't be able to retrieve it again!", + ) + ..info('\n') + ..info( + "run 'langsync account auth' to configure LangSync with that API key to start using it.", + ); + + return ExitCode.success.code; + } catch (e) { + logger.customErr( + progress: progress, + update: 'Failed to create API key!', + error: e, + ); + + return ExitCode.software.code; + } + } +} diff --git a/lib/src/commands/account_command/sub_commands/info_command.dart b/lib/src/commands/account_command/sub_commands/info_command.dart index 5416efc..b773695 100644 --- a/lib/src/commands/account_command/sub_commands/info_command.dart +++ b/lib/src/commands/account_command/sub_commands/info_command.dart @@ -65,7 +65,9 @@ class InfoCommand extends Command { } return ExitCode.success.code; - } catch (e) { + } catch (e, s) { + print(s); + logger.customErr( error: e, progress: fetchingProgress, diff --git a/lib/src/commands/supported_laungages_command/supported_laungages_command.dart b/lib/src/commands/supported_laungages_command/supported_laungages_command.dart index 4a14bc5..7d336e4 100644 --- a/lib/src/commands/supported_laungages_command/supported_laungages_command.dart +++ b/lib/src/commands/supported_laungages_command/supported_laungages_command.dart @@ -5,8 +5,6 @@ import 'package:langsync/src/etc/extensions.dart'; import 'package:langsync/src/etc/networking/client.dart'; import 'package:mason_logger/mason_logger.dart'; -// TODO: openai offers 3 requests/min. - class SupportedLangsCommand extends Command { SupportedLangsCommand({ required this.logger, diff --git a/lib/src/etc/controllers/yaml.dart b/lib/src/etc/controllers/yaml.dart index 3baffac..525c80e 100644 --- a/lib/src/etc/controllers/yaml.dart +++ b/lib/src/etc/controllers/yaml.dart @@ -75,8 +75,6 @@ abstract class YamlController { static bool validateConfigFields(Map parsedYaml) { final langsyncConfig = parsedYaml['langsync']; - // TODO: validate source file and output dir. - if (langsyncConfig == null) { throw Exception('langsync.yaml file is missing a `langsync` key.'); } else { @@ -90,7 +88,9 @@ abstract class YamlController { throw Exception( 'langsync.yaml file is missing a `source` key under `langsync`.', ); - } else if (outputDir == null) { + } + + if (outputDir == null) { throw Exception( 'langsync.yaml file is missing a `output` key under `langsync`.', ); diff --git a/lib/src/etc/models/Localization_doc.dart b/lib/src/etc/models/Localization_doc.dart new file mode 100644 index 0000000..e29e521 --- /dev/null +++ b/lib/src/etc/models/Localization_doc.dart @@ -0,0 +1,38 @@ +import 'package:equatable/equatable.dart'; + +class LocalizationDoc extends Equatable { + const LocalizationDoc({ + required this.createdAt, + required this.partitionId, + required this.jsonPartsLength, + this.outputLangs, + }); + + final DateTime createdAt; + final String partitionId; + final int jsonPartsLength; + final List? outputLangs; + + @override + List get props => [ + createdAt, + partitionId, + jsonPartsLength, + outputLangs, + ]; + + factory LocalizationDoc.fromJson(Map json) { + return LocalizationDoc( + createdAt: DateTime.parse(json['createdAt'] as String), + partitionId: json['partitionId'] as String, + jsonPartsLength: json['jsonPartsLength'] is int + ? json['jsonPartsLength'] as int + : int.parse(json['jsonPartsLength'] as String), + outputLangs: json['outputLangs'] != null + ? (json['outputLangs'] as List) + .map((dynamic e) => e as String) + .toList() + : null, + ); + } +} diff --git a/lib/src/etc/models/api_key_res.dart b/lib/src/etc/models/api_key_res.dart new file mode 100644 index 0000000..d124635 --- /dev/null +++ b/lib/src/etc/models/api_key_res.dart @@ -0,0 +1,21 @@ +import 'package:equatable/equatable.dart'; + +class APIKeyResponse extends Equatable { + const APIKeyResponse({ + required this.username, + required this.apiKey, + }); + + factory APIKeyResponse.fromJson(Map json) { + return APIKeyResponse( + username: json['username'] as String, + apiKey: json['apiKey'] as String, + ); + } + + final String username; + final String apiKey; + + @override + List get props => [username, apiKey]; +} diff --git a/lib/src/etc/models/user_info.dart b/lib/src/etc/models/user_info.dart index c466153..5ec216e 100644 --- a/lib/src/etc/models/user_info.dart +++ b/lib/src/etc/models/user_info.dart @@ -1,41 +1,59 @@ import 'package:equatable/equatable.dart'; import 'package:langsync/src/etc/extensions.dart'; +import 'package:langsync/src/etc/models/Localization_doc.dart'; class UserInfo extends Equatable { const UserInfo({ required this.userId, required this.createdAt, required this.apiKeysLength, + required this.localizationDocs, }); factory UserInfo.fromJson(Map json) { final userJson = json['user']; + print(userJson['localizationDocs'].runtimeType); + return UserInfo( userId: userJson['userId'] as String, createdAt: DateTime.parse(userJson['createdAt'] as String), apiKeysLength: userJson['apiKeysLength'] is int ? userJson['apiKeysLength'] as int : int.parse(userJson['apiKeysLength'] as String), + localizationDocs: (userJson['localizationDocs'] as List) + .map((dynamic e) => + LocalizationDoc.fromJson(e as Map)) + .toList(), ); } final String userId; final DateTime createdAt; final int apiKeysLength; + final List localizationDocs; @override List get props => [ userId, createdAt, apiKeysLength, + localizationDocs, ]; Map toJson() { return { 'User ID': userId, - 'User Account Creation Time': createdAt.toProperHumanReadableDate(), - 'available API keys': apiKeysLength, + 'User Account Creation Date': + '${createdAt.toProperHumanReadableDate()} - ${createdAt.toIso8601String()}', + 'Available API keys': apiKeysLength, + 'Processed Localizations': localizationDocs.length, + 'Most Recent Localization ID': localizationDocs.isNotEmpty + ? localizationDocs.last.partitionId + : 'You have no processed localizations.', + 'Most Recent Localization Date': localizationDocs.isNotEmpty + ? '${localizationDocs.last.createdAt.toProperHumanReadableDate()} - ${localizationDocs.last.createdAt.toIso8601String()}' + : 'You have no processed localizations.', }; } } diff --git a/lib/src/etc/networking/client.dart b/lib/src/etc/networking/client.dart index b897c64..7beb5e7 100644 --- a/lib/src/etc/networking/client.dart +++ b/lib/src/etc/networking/client.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'dart:io'; import 'package:http/http.dart' as http; +import 'package:langsync/src/etc/models/api_key_res.dart'; import 'package:langsync/src/etc/models/config.dart'; import 'package:langsync/src/etc/models/partition.dart'; import 'package:langsync/src/etc/models/result_locale.dart'; @@ -32,7 +33,6 @@ class NetClient { 'langs': lang, }, (res) { final map = {}; - print(res); final list = (res['checkResultList'] as List).cast(); @@ -181,4 +181,12 @@ class NetClient { }, ); } + + Future createApiKey(String userName) { + return _makeRes('/create-account-with-api-key-beta', 'POST', {}, { + 'username': userName, + }, (res) { + return APIKeyResponse.fromJson(res); + }); + } } diff --git a/lib/src/version.dart b/lib/src/version.dart index 044d006..79ad5ba 100644 --- a/lib/src/version.dart +++ b/lib/src/version.dart @@ -1 +1 @@ -const packageVersion = '0.0.3'; +const packageVersion = '0.0.6'; diff --git a/pubspec.yaml b/pubspec.yaml index 6a80daa..8ebb568 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: langsync description: A Very Good Project created by Very Good CLI. -version: 0.0.3 +version: 0.0.6 publish_to: none environment: