diff --git a/README.md b/README.md
index 104f6495..f8784850 100644
--- a/README.md
+++ b/README.md
@@ -960,10 +960,10 @@ In fact, this can be considered as partial inheritance.
**If something went wrong**
If you're having trouble working with presets and don't understand how the CSV Blueprint under the hood understands it,
-just add `--dump-schema` to see it. Also, there is a separate CLI command for validating schema:
+just add `--dump-schema` to see it. Also, there is a separate CLI command to dump schema:
```shell
-./csv-blueprint validate:schema --dump-schema --schema=./your/schema.yml
+./csv-blueprint debug-schema -s ./your/schema.yml
```
@@ -1542,6 +1542,49 @@ Options:
+`./csv-blueprint dump-schema --help`
+
+
+ CLICK to see debug-schema help messege
+
+
+```
+Description:
+ Show the internal representation of the schema taking into account presets.
+
+Usage:
+ debug-schema [options]
+
+Options:
+ -s, --schema=SCHEMA Specify the path to a schema file, supporting YAML, JSON, or PHP formats.
+ Examples: /full/path/name.yml; p/file.yml
+ -d, --hide-defaults Hide default values in the output.
+ --no-progress Disable progress bar animation for logs. It will be used only for text output format.
+ --mute-errors Mute any sort of errors. So exit code will be always "0" (if it's possible).
+ It has major priority then --non-zero-on-error. It's on your own risk!
+ --stdout-only For any errors messages application will use StdOut instead of StdErr. It's on your own risk!
+ --non-zero-on-error None-zero exit code on any StdErr message.
+ --timestamp Show timestamp at the beginning of each message.It will be used only for text output format.
+ --profile Display timing and memory usage information.
+ --output-mode=OUTPUT-MODE Output format. Available options:
+ text - Default text output format, userfriendly and easy to read.
+ cron - Shortcut for crontab. It's basically focused on human-readable logs output.
+ It's combination of --timestamp --profile --stdout-only --no-progress -vv.
+ logstash - Logstash output format, for integration with ELK stack.
+ [default: "text"]
+ --cron Alias for --output-mode=cron. Deprecated!
+ -h, --help Display help for the given command. When no command is given display help for the list command
+ -q, --quiet Do not output any message
+ -V, --version Display this application version
+ --ansi|--no-ansi Force (or disable --no-ansi) ANSI output
+ -n, --no-interaction Do not ask any interactive question
+ -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
+```
+
+
+
+
+
`./csv-blueprint create:schema --help`
It's beta. Work in progress.
@@ -1599,6 +1642,7 @@ Options:
+
## Report examples
The validation process culminates in a human-readable report detailing any errors identified within the CSV file. While
diff --git a/src/Commands/DebugSchema.php b/src/Commands/DebugSchema.php
new file mode 100644
index 00000000..46f73824
--- /dev/null
+++ b/src/Commands/DebugSchema.php
@@ -0,0 +1,65 @@
+setName('debug-schema')
+ ->setDescription('Show the internal representation of the schema taking into account presets.')
+ ->addOption(
+ 'schema',
+ 's',
+ InputOption::VALUE_REQUIRED,
+ \implode("\n", [
+ 'Specify the path to a schema file, supporting YAML, JSON, or PHP formats. ',
+ 'Examples: /full/path/name.yml; p/file.yml',
+ ]),
+ )
+ ->addOption(
+ 'hide-defaults',
+ 'd',
+ InputOption::VALUE_NONE,
+ 'Hide default values in the output.',
+ );
+
+ parent::configure();
+ }
+
+ protected function executeAction(): int
+ {
+ $decorated = $this->outputMode->getOutput()->isDecorated();
+
+ $schemaFilename = $this->getOptString('schema');
+ if (!\file_exists($schemaFilename)) {
+ throw new Exception("Schema file not found: {$schemaFilename}");
+ }
+
+ $this->_((new Schema($schemaFilename))->dumpAsYamlString($this->getOptBool('hide-defaults'), $decorated));
+
+ return self::SUCCESS;
+ }
+}
diff --git a/tests/Commands/DebugSchemaTest.php b/tests/Commands/DebugSchemaTest.php
new file mode 100644
index 00000000..892eac4e
--- /dev/null
+++ b/tests/Commands/DebugSchemaTest.php
@@ -0,0 +1,299 @@
+ Tools::DEMO_YML_VALID,
+ ]);
+
+ $expected = <<<'YAML'
+ # Schema file is "./tests/schemas/demo_valid.yml"
+ name: ''
+ description: ''
+ presets: []
+ filename_pattern: '/(demo|demo_.*|demo-.*)\.csv$/'
+ csv:
+ header: true
+ delimiter: ','
+ quote_char: \
+ enclosure: '"'
+ encoding: utf-8
+ bom: false
+ structural_rules:
+ strict_column_order: true
+ allow_extra_columns: false
+ columns:
+ - name: Name
+ description: ''
+ example: ~
+ required: true
+ rules:
+ not_empty: true
+ length_min: 4
+ length_max: 7
+ aggregate_rules:
+ is_unique: true
+
+ - name: City
+ description: ''
+ example: ~
+ required: true
+ rules:
+ not_empty: true
+ is_capitalize: true
+ aggregate_rules: []
+
+ - name: Float
+ description: ''
+ example: ~
+ required: true
+ rules:
+ not_empty: true
+ is_float: true
+ num_min: -19366059128
+ num_max: 4825.186
+ aggregate_rules:
+ sum_max: 4692
+
+ - name: Birthday
+ description: ''
+ example: ~
+ required: true
+ rules:
+ not_empty: true
+ date_format: Y-m-d
+ aggregate_rules: []
+
+ - name: 'Favorite color'
+ description: ''
+ example: ~
+ required: true
+ rules:
+ not_empty: true
+ allow_values:
+ - red
+ - green
+ - blue
+ aggregate_rules: []
+
+ YAML;
+
+ isSame($expected, $actual);
+ isSame(0, $exitCode, $actual);
+ }
+
+ public function testDumpHideDefaults(): void
+ {
+ [$actual, $exitCode] = Tools::virtualExecution('debug-schema', [
+ 'schema' => Tools::DEMO_YML_VALID,
+ 'hide-defaults' => null,
+ ]);
+
+ $expected = <<<'YAML'
+ # Schema file is "./tests/schemas/demo_valid.yml"
+ filename_pattern: '/(demo|demo_.*|demo-.*)\.csv$/'
+ columns:
+ - name: Name
+ rules:
+ not_empty: true
+ length_min: 4
+ length_max: 7
+ aggregate_rules:
+ is_unique: true
+
+ - name: City
+ rules:
+ not_empty: true
+ is_capitalize: true
+
+ - name: Float
+ rules:
+ not_empty: true
+ is_float: true
+ num_min: -19366059128
+ num_max: 4825.186
+ aggregate_rules:
+ sum_max: 4692
+
+ - name: Birthday
+ rules:
+ not_empty: true
+ date_format: Y-m-d
+
+ - name: 'Favorite color'
+ rules:
+ not_empty: true
+ allow_values:
+ - red
+ - green
+ - blue
+
+ YAML;
+
+ isSame($expected, $actual);
+ isSame(0, $exitCode, $actual);
+ }
+
+ public function testDumpPresetUsage(): void
+ {
+ [$actual, $exitCode] = Tools::virtualExecution('debug-schema', [
+ 'schema' => './schema-examples/preset_usage.yml',
+ 'hide-defaults' => null,
+ ]);
+
+ $expected = <<<'YAML'
+ # Schema file is "./schema-examples/preset_usage.yml"
+ name: 'Schema uses presets and add new columns + specific rules.'
+ description: 'This schema uses presets. Also, it demonstrates how to override preset values.'
+ presets:
+ users: /schema-examples/preset_users.yml
+ db: /schema-examples/preset_database.yml
+ csv:
+ delimiter: ;
+ enclosure: '|'
+ columns:
+ - name: id
+ description: 'Unique identifier, usually used to denote a primary key in databases.'
+ example: 12345
+ rules:
+ not_empty: true
+ is_trimmed: true
+ is_int: true
+ num_min: 1
+ aggregate_rules:
+ is_unique: true
+ sorted:
+ - asc
+ - numeric
+
+ - name: status
+ description: 'Status in database'
+ example: active
+ rules:
+ not_empty: true
+ allow_values:
+ - active
+ - inactive
+ - pending
+ - deleted
+
+ - name: login
+ description: "User's login name"
+ example: johndoe
+ rules:
+ not_empty: true
+ length_min: 3
+ length_max: 20
+ is_trimmed: true
+ is_lowercase: true
+ is_slug: true
+ is_alnum: true
+ aggregate_rules:
+ is_unique: true
+
+ - name: email
+ description: "User's email address"
+ example: user@example.com
+ rules:
+ not_empty: true
+ is_trimmed: true
+ is_lowercase: true
+ is_email: true
+ aggregate_rules:
+ is_unique: true
+
+ - name: full_name
+ description: "User's full name"
+ example: 'John Doe Smith'
+ rules:
+ not_empty: true
+ is_trimmed: true
+ is_capitalize: true
+ word_count_min: 2
+ word_count_max: 8
+ contains: ' '
+ charset: UTF-8
+ aggregate_rules:
+ is_unique: true
+
+ - name: birthday
+ description: "Validates the user's birthday."
+ example: '1990-01-01'
+ rules:
+ not_empty: true
+ is_trimmed: true
+ is_date: true
+ date_max: now
+ date_format: Y-m-d
+ date_age_greater: 0
+ date_age_less: 150
+
+ - name: phone
+ description: "User's phone number in US"
+ example: '+1 650 253 00 00'
+ rules:
+ not_empty: true
+ is_trimmed: true
+ starts_with: '+1'
+ phone: US
+
+ - name: password
+ description: "User's password"
+ example: 9RfzE$8NKD
+ rules:
+ not_empty: true
+ length_min: 10
+ length_max: 20
+ is_trimmed: true
+ contains_none:
+ - password
+ - '123456'
+ - qwerty
+ - ' '
+ password_strength_min: 7
+ is_password_safe_chars: true
+ charset: UTF-8
+
+ - name: admin_note
+ description: 'Admin note'
+ rules:
+ not_empty: true
+ length_min: 1
+ length_max: 10
+ aggregate_rules:
+ is_unique: true
+ sorted:
+ - asc
+ - numeric
+
+ YAML;
+
+ $actual = \str_replace(PROJECT_ROOT, '', $actual);
+
+ isSame($expected, $actual);
+ isSame(0, $exitCode, $actual);
+ }
+}
diff --git a/tests/ReadmeTest.php b/tests/ReadmeTest.php
index 74cf09ae..a188f02d 100644
--- a/tests/ReadmeTest.php
+++ b/tests/ReadmeTest.php
@@ -78,6 +78,17 @@ public function testCreateSchemaHelp(): void
Tools::insertInReadme('create-schema-help', $text);
}
+ public function testDumpSchemaHelp(): void
+ {
+ $text = \implode("\n", [
+ '```',
+ \trim(Tools::realExecution('debug-schema', ['help' => null])),
+ '```',
+ ]);
+
+ Tools::insertInReadme('debug-schema-help', $text);
+ }
+
public function testTableOutputExample(): void
{
success('Replaced to image');
diff --git a/tests/Tools.php b/tests/Tools.php
index c28b8767..6e368b51 100644
--- a/tests/Tools.php
+++ b/tests/Tools.php
@@ -18,6 +18,7 @@
use JBZoo\Cli\CliApplication;
use JBZoo\CsvBlueprint\Commands\CreateSchema;
+use JBZoo\CsvBlueprint\Commands\DebugSchema;
use JBZoo\CsvBlueprint\Commands\ValidateCsv;
use JBZoo\CsvBlueprint\Commands\ValidateSchema;
use JBZoo\Utils\Cli;
@@ -59,6 +60,7 @@ public static function virtualExecution(string $action, array|string $params = [
$application->add(new ValidateCsv());
$application->add(new ValidateSchema());
$application->add(new CreateSchema());
+ $application->add(new DebugSchema());
$command = $application->find($action);
$buffer = new BufferedOutput();