Skip to content

Commit

Permalink
Refactor + addition of recursive type guestimation
Browse files Browse the repository at this point in the history
  • Loading branch information
mariusjp committed Nov 3, 2023
1 parent 25fe11a commit 5750543
Show file tree
Hide file tree
Showing 12 changed files with 330 additions and 113 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.0.0] 2023-11-03
### Added
- Refactor of how the stubs are processed
- Addition of recursive property generation
- Added a few flags to the `generate` command

## [0.X.0] 2023-10-XX
### Changed
- Lots of small fixes

## [0.1.0] 2023-10-27
### Created
- Initial setup of this library
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ The above-mentioned checkup runs multiple analyses of the package's code. This i

Continuous Integration
----------------------
[GitHub actions](https://github.com/features/actions) are used for continuous integration. Check out the [configuration file](https://github.com/mjtheone/typed-config-generator/blob/main/.github/workflows/ci.yml) if you'd like to know more.
[GitHub actions](https://github.com/features/actions) are used for continuous integration. Check out the [configuration file](https://github.com/mjtheone/typed-config-generator/blob/main/.github/workflows/run-tests.yml) if you'd like to know more.

Changelog
---------
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "Typed Classes for your Laravel configs!",
"type": "library",
"require": {
"php": "^8.1",
"php": "^8.2",
"illuminate/support": "^9.0|^10.0"
},
"require-dev": {
Expand Down
127 changes: 21 additions & 106 deletions src/Console/Commands/GenerateTypedConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
use Coderg33k\TypedConfigGenerator\Actions\GetConfigsForPredeterminedPackage;
use Coderg33k\TypedConfigGenerator\Enums\Package;
use Coderg33k\TypedConfigGenerator\Helper\ArrayFlatMap;
use Coderg33k\TypedConfigGenerator\Services\Stub\Builder;
use Coderg33k\TypedConfigGenerator\Services\Stub\Config;
use Illuminate\Console\Command;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Symfony\Component\Console\Attribute\AsCommand;

use function Laravel\Prompts\search;
Expand All @@ -21,13 +21,18 @@ final class GenerateTypedConfig extends Command
{
private const GENERATED_CONFIG_NAMESPACE_BASE = 'Config';

/** @var array<int, string> */
private array $configs = [];

private ?string $package = null;

/** @var string */
protected $signature = 'coderg33k:generate-typed-config
{--all : Generate guestimated classes for all configurations}
{--flat : Don\'t try to generate classes for nested configurations}
{--no-strict : Don\'t add declare(strict_types=1) to the generated classes}
{--no-final : Don\'t make the generated classes final}
{--no-readonly : Don\'t make the generated classes readonly}
{--package= : Generate classes for all configs in a package}
{--config=* : One or more configurations to generate classes for}';

/** @var string */
Expand All @@ -39,8 +44,8 @@ final class GenerateTypedConfig extends Command
EOF;

public function __construct(
private readonly Filesystem $files,
private readonly GetConfigsForPredeterminedPackage $getConfigsForPredeterminedPackage,
private readonly Builder $stubBuilder,
private readonly ArrayFlatMap $arrayFlatMap,
) {
parent::__construct();
Expand All @@ -61,7 +66,7 @@ private function determineWhatShouldBeGenerated(): void

$this->configs = (array) $this->option('config');

if (\count($this->configs) === 0) {
if (\count($this->configs) === 0 && !\is_string($this->option('package'))) {
$this->promptForConfigs();
}
}
Expand Down Expand Up @@ -137,37 +142,22 @@ private function generateTypedClasses(): void
$rootNamespace = $this->laravel->getNamespace();
$namespace = $rootNamespace . self::GENERATED_CONFIG_NAMESPACE_BASE;

$stubConfiguration = Config::make(
$this->option('flat'),
!$this->option('no-strict'),
!$this->option('no-final'),
!$this->option('no-readonly'),
);

// @todo: Get known namespaces for package configs.

$nullValues = [];
$properties = [];
foreach ($configsToProcess as $config) {
$configData = config($config);

foreach ($configData as $key => $value) {
// Let's start guestimating...
if (\is_array($value)) {
$properties[$key] = 'array';
} else if (\is_bool($value)) {
$properties[$key] = 'bool';
} else if (\is_float($value)) {
$properties[$key] = 'float';
} else if (\is_int($value)) {
$properties[$key] = 'int';
} else if (\is_null($value)) {
$properties[$key] = 'mixed';
$nullValues[$config][] = $key;
} else if (\is_string($value)) {
$properties[$key] = 'string';
} else {
$properties[$key] = 'mixed';
}
}

$this->buildStub(
$this->stubBuilder->handle(
config: $config,
namespace: $namespace,
properties: $properties,
nullValues: $nullValues,
stubConfiguration: $stubConfiguration,
);
}

Expand Down Expand Up @@ -196,82 +186,7 @@ private function discoverConfigsForPackage(): void
),
$allConfigs,
),
)
),
];
}

private function buildStub(
string $config,
string $namespace,
array $properties,
): void {
$stub = \file_get_contents($this->getStub());

$stub = \str_replace(
search: [
'{{ namespace }}',
'{{ properties }}',
'{{ class }}',
'{{ parent }}',
],
replace: [
$namespace,
$this->buildProperties($properties),
\ucfirst(Str::camel($config)),
'\\' . \Coderg33k\TypedConfigGenerator\TypedConfig::class,
],
subject: $stub,
);

$this->writeClass(
$stub,
$config,
$namespace,
);
}

private function getStub(): string
{
$relativePath = '/stubs/typed_config/default.stub';

return \file_exists($customPath = $this->laravel->basePath(\trim($relativePath, '/')))
? $customPath
: __DIR__ . $relativePath;
}

private function buildProperties(array $properties): string
{
$properties = \array_map(
fn (string $type, string $name): string =>
\sprintf(' public %s $%s,', $type, Str::camel($name)),
$properties,
\array_keys($properties),
);

return \implode(PHP_EOL, $properties);
}

private function writeClass(
string $stub,
string $config,
string $namespace,
): void {
$classDirectoryPath = \str_replace($this->laravel->getNamespace(), '', $namespace);

$this->files->makeDirectory(
path: app_path($classDirectoryPath),
recursive: true,
force: true,
);

$classPath = app_path(
\sprintf(
'%s/%s.php',
$classDirectoryPath,
\ucfirst(Str::camel($config)),
)
);

$this->files->put($classPath, $stub);
}
}
10 changes: 10 additions & 0 deletions src/Pipe/PipeInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace Coderg33k\TypedConfigGenerator\Pipe;

interface PipeInterface
{

}
Loading

0 comments on commit 5750543

Please sign in to comment.