Tweak commands

This commit is contained in:
2025-03-15 14:41:43 +01:00
parent cc5c711d32
commit 9e880467d9
10 changed files with 169 additions and 13 deletions

View File

@ -22,7 +22,7 @@
"repositories": {
"slotdb-client": {
"type": "vcs",
"url": "../slotdb-client-php"
"url": "git@dev.noccylabs.info:slotdb/slotdb-client-php.git"
}
},
"bin": [

8
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "9dc3a3ca30d0b0d1698b2e4e26577e67",
"content-hash": "8140c4572894cc393ef74de8ad3fe56c",
"packages": [
{
"name": "guzzlehttp/guzzle",
@ -593,8 +593,8 @@
"version": "dev-master",
"source": {
"type": "git",
"url": "../slotdb-client-php",
"reference": "4734ca5fe4ed02da5bc3e0df3c9ecbabc3474af3"
"url": "git@dev.noccylabs.info:slotdb/slotdb-client-php.git",
"reference": "e6e1e980eaa9500fc38bfd22dfdc23ca13258ad3"
},
"require": {
"psr/http-client": "^1.0"
@ -620,7 +620,7 @@
}
],
"description": "SlotDB PHP Client",
"time": "2025-03-14T14:34:28+00:00"
"time": "2025-03-15T13:25:21+00:00"
},
{
"name": "symfony/console",

View File

@ -16,8 +16,8 @@ class Application extends \Symfony\Component\Console\Application
$psr = new Client();
$client = new SlotDbClient($psr, $baseUrl);
$this->add(new Command\ImportCommand());
$this->add(new Command\ExportCommand());
$this->add(new Command\ImportCommand($client));
$this->add(new Command\ExportCommand($client));
$this->add(new Command\Slot\SlotCreateCommand($client));
$this->add(new Command\Slot\SlotQueryCommand($client));

View File

@ -2,10 +2,73 @@
namespace SlotDb\Cli\Command;
use SlotDb\Client\SlotDbClient;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
#[AsCommand(name:"export", description:"Export the database to a file")]
class ExportCommand extends BaseCommand
{
public function __construct(
private readonly SlotDbClient $client
)
{
parent::__construct();
}
protected function configure()
{
$this->addOption("all-props", "A", InputOption::VALUE_NONE, "Include all slot properties. If not specified, properties that match the group property will be stripped.");
$this->addOption("output", "o", InputOption::VALUE_REQUIRED, "Write to file instead of standard output");
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
// TODO implement paging
$groups = $this->client->findGroups();
$indexedGroups = array_combine(
array_map(fn($group) => $group['_group'], $groups),
array_values($groups)
);
$slots = $this->client->findSlots();
if (!$input->getOption("all-props")) {
foreach ($slots as &$slot) {
if ($slot['_group'] && isset($indexedGroups[$slot['_group']])) {
$group = $indexedGroups[$slot['_group']];
foreach ($slot as $k=>$v) {
if (str_starts_with($k,"_")) continue;
if (isset($group[$k]) && $group[$k] == $v) {
unset($slot[$k]);
}
}
}
}
}
$export = json_encode([
'comment' => "This is an exported SlotDB database.",
'timestamp' => date('Y-m-d H:i:s P'),
'generator' => "SlotCLI v".APP_VERSION." (".APP_BUILT.")",
'export' => [
'schemas' => [],
'hooks' => [],
'groups' => $groups,
'slots' => $slots,
],
], JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
if ($input->getOption("output")) {
$file = $input->getOption("output");
file_put_contents($file, $export."\n");
} else {
$output->writeln($export);
}
return self::SUCCESS;
}
}

View File

@ -42,8 +42,14 @@ class GroupFindCommand extends Command
foreach ($groups as $group) {
$row = [];
foreach ($keys as $key) {
$row[] = isset($group[$key]) ? json_encode($group[$key]) : null;
$row[] = isset($group[$key]) ? $group[$key] : null;
}
$row = array_map(fn($v) => match(true) {
is_bool($v) => "<fg=magenta>".($v?"true":"false")."</>",
is_int($v) => "<fg=cyan>{$v}</>",
is_string($v) => "<fg=yellow>{$v}</>",
default => $v,
}, $row);
$table->addRow($row);
}

View File

@ -32,7 +32,7 @@ class GroupQueryCommand extends Command
try {
$group = $this->client->queryGroup($groupId);
} catch (\RuntimeException $e) {
$output->writeln("<error>Invalid group id: {$slotId}</>");
$output->writeln("<error>Invalid group id: {$groupId}</>");
return self::INVALID;
}

View File

@ -2,10 +2,68 @@
namespace SlotDb\Cli\Command;
use SlotDb\Client\SlotDbClient;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
#[AsCommand(name:"import", description:"Import database from file")]
class ImportCommand extends BaseCommand
{
public function __construct(
private readonly SlotDbClient $client
)
{
parent::__construct();
}
protected function configure()
{
$this->addOption("hard-reset", "R", InputOption::VALUE_NONE, "Completely wipe the database before importing the new data.");
$this->addArgument("filename", InputArgument::OPTIONAL, "Filename to read from, if omitted read standard input.");
$this->addOption("assume-yes", "y", InputOption::VALUE_NONE, "Assume yes on all questions.");
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
if ($input->getArgument("filename")) {
$file = $input->getArgument("filename");
$json = file_get_contents($file);
} else {
$json = stream_get_contents(STDIN);
}
$export = json_decode($json);
$output->writeln("File was generated <fg=yellow>{$export->timestamp}</>");
$output->writeln("Generated using <fg=yellow>{$export->generator}</>");
$output->writeln("");
if (!$input->getOption("assume-yes")) {
$confirm = (new SymfonyStyle($input, $output))->confirm("Do you want to continue", false);
if (!$confirm) {
return self::FAILURE;
}
$output->writeln("");
}
$output->writeln("+ <options=bold>Importing schemas...</>");
$output->writeln("+ <options=bold>Importing hooks...</>");
$output->writeln("+ <options=bold>Importing groups...</>");
foreach ($export->export->groups as $group) {
$output->writeln(" - <fg=green>".$group->_group."</>");
}
$output->writeln("+ <options=bold>Importing slots...</>");
foreach ($export->export->slots as $slot) {
$output->writeln(" - <fg=green>".$slot->_slot."</>");
}
return self::SUCCESS;
}
}

View File

@ -23,7 +23,7 @@ class SlotCreateCommand extends Command
protected function configure()
{
$this
->addOption("name", "n", InputOption::VALUE_REQUIRED, "Set slot name")
->addOption("name", "N", InputOption::VALUE_REQUIRED, "Set slot name")
->addArgument("slot", InputArgument::REQUIRED, "Slot ID")
->addArgument("properties", InputArgument::IS_ARRAY, "Properties to assign to the slot")
;
@ -32,8 +32,25 @@ class SlotCreateCommand extends Command
protected function execute(InputInterface $input, OutputInterface $output): int
{
// $slotId = $input->getArgument("slot");
// $slot = $this->client->querySlot($slotId);
$slotId = $input->getArgument("slot");
$slotName = $input->getOption("name") ?? $slotId;
$props = [];
foreach ($input->getArgument("properties") as $prop) {
if (!str_contains($prop, '=')) {
$output->writeln("<error>Invalid property \"{$prop}\", should be in the form of key=value.</>");
return self::INVALID;
}
[$k, $v] = explode("=", $prop, 2);
$props[$k] = match ($v) {
'true','false','null' => json_decode($v),
default => json_decode($v) ?? $v,
};
}
$slot = $this->client->createSlot($slotId, $slotName, $props);
var_dump($slot);
return self::SUCCESS;
}

View File

@ -55,8 +55,14 @@ class SlotFindCommand extends Command
foreach ($slots as $slot) {
$row = [];
foreach ($keys as $key) {
$row[] = isset($slot[$key]) ? json_encode($slot[$key]) : null;
$row[] = isset($slot[$key]) ? $slot[$key] : null;
}
$row = array_map(fn($v) => match(true) {
is_bool($v) => "<fg=magenta>".($v?"true":"false")."</>",
is_int($v) => "<fg=cyan>{$v}</>",
is_string($v) => "<fg=yellow>{$v}</>",
default => $v,
}, $row);
$table->addRow($row);
}

View File

@ -2,6 +2,12 @@
require_once __DIR__."/../vendor/autoload.php";
$buildInfo = (file_exists(__DIR__."/build.php"))
? include __DIR__."/build.php"
: [ 'version' => '0.0.0', 'builddate' => 'never' ];
define("APP_VERSION", $buildInfo['version']);
define("APP_BUILT", $buildInfo['builddate']);
$app = new SlotDb\Cli\Application();
$app->run();