Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow config and temp directories to be configured independently. #763

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions camel/Camel.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,21 @@
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Knuckles\Camel\Output\OutputEndpointData;
use Knuckles\Scribe\Configuration\PathConfig;
use Knuckles\Scribe\Tools\Utils;
use Symfony\Component\Yaml\Yaml;


class Camel
{
public static function cacheDir(string $docsName = 'scribe'): string
public static function cacheDir(PathConfig $paths): string
{
return ".$docsName/endpoints.cache";
return $paths->intermediateOutputPath('endpoints.cache');
}

public static function camelDir(string $docsName = 'scribe'): string
public static function camelDir(PathConfig $paths): string
{
return ".$docsName/endpoints";
return $paths->intermediateOutputPath('endpoints');
}

/**
Expand Down
1 change: 1 addition & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
<file>tests/Unit/ExtractorTest.php</file>
<file>tests/Unit/ExtractorPluginSystemTest.php</file>
<file>tests/Unit/ConfigDifferTest.php</file>
<file>tests/Unit/PathConfigurationTest.php</file>
</testsuite>
<testsuite name="Unit Tests 2">
<file>tests/Unit/ExtractedEndpointDataTest.php</file>
Expand Down
39 changes: 27 additions & 12 deletions src/Commands/GenerateDocumentation.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Illuminate\Support\Facades\URL;
use Illuminate\Support\Str;
use Knuckles\Camel\Camel;
use Knuckles\Scribe\Configuration\PathConfig;
use Knuckles\Scribe\GroupedEndpoints\GroupedEndpointsFactory;
use Knuckles\Scribe\Matching\RouteMatcherInterface;
use Knuckles\Scribe\Tools\ConsoleOutputUtils as c;
Expand All @@ -23,7 +24,8 @@ class GenerateDocumentation extends Command
{--force : Discard any changes you've made to the YAML or Markdown files}
{--no-extraction : Skip extraction of route and API info and just transform the YAML and Markdown files into HTML}
{--no-upgrade-check : Skip checking for config file upgrades. Won't make things faster, but can be helpful if the command is buggy}
{--config=scribe : choose which config file to use}
{--config=scribe : Choose which config file to use}
{--scribe-dir= : Specify the directory where Scribe stores its intermediate output and cache. Defaults to `.<config_file>`}
";

protected $description = 'Generate API documentation from your Laravel/Dingo routes.';
Expand All @@ -34,7 +36,7 @@ class GenerateDocumentation extends Command

protected bool $forcing;

protected string $configName;
protected PathConfig $paths;

public function handle(RouteMatcherInterface $routeMatcher, GroupedEndpointsFactory $groupedEndpointsFactory): void
{
Expand All @@ -47,9 +49,9 @@ public function handle(RouteMatcherInterface $routeMatcher, GroupedEndpointsFact
}

// Extraction stage - extract endpoint info either from app or existing Camel files (previously extracted data)
$groupedEndpointsInstance = $groupedEndpointsFactory->make($this, $routeMatcher, $this->configName);
$groupedEndpointsInstance = $groupedEndpointsFactory->make($this, $routeMatcher, $this->paths);
$extractedEndpoints = $groupedEndpointsInstance->get();
$userDefinedEndpoints = Camel::loadUserDefinedEndpoints(Camel::camelDir($this->configName));
$userDefinedEndpoints = Camel::loadUserDefinedEndpoints(Camel::camelDir($this->paths));
$groupedEndpoints = $this->mergeUserDefinedEndpoints($extractedEndpoints, $userDefinedEndpoints);

// Output stage
Expand All @@ -61,7 +63,7 @@ public function handle(RouteMatcherInterface $routeMatcher, GroupedEndpointsFact
$this->writeExampleCustomEndpoint();
}

$writer = new Writer($this->docConfig, $this->configName);
$writer = new Writer($this->docConfig, $this->paths);
$writer->writeDocs($groupedEndpoints);

$this->upgradeConfigFileIfNeeded();
Expand Down Expand Up @@ -98,12 +100,19 @@ public function bootstrap(): void

c::bootstrapOutput($this->output);

$this->configName = $this->option('config');
if (!config($this->configName)) {
throw new \InvalidArgumentException("The specified config (config/{$this->configName}.php) doesn't exist.");
$configName = $this->option('config');
if (!config($configName)) {
throw new \InvalidArgumentException("The specified config (config/{$configName}.php) doesn't exist.");
}

$this->docConfig = new DocumentationConfig(config($this->configName));
$this->paths = new PathConfig(configName: $configName);
if ($this->hasOption('scribe-dir') && !empty($this->option('scribe-dir'))) {
$this->paths = new PathConfig(
configName: $configName, scribeDir: $this->option('scribe-dir')
);
}

$this->docConfig = new DocumentationConfig(config($this->paths->configName));

// Force root URL so it works in Postman collection
$baseUrl = $this->docConfig->get('base_url') ?? config('app.url');
Expand Down Expand Up @@ -146,7 +155,7 @@ protected function mergeUserDefinedEndpoints(array $groupedEndpoints, array $use
protected function writeExampleCustomEndpoint(): void
{
// We add an example to guide users in case they need to add a custom endpoint.
copy(__DIR__ . '/../../resources/example_custom_endpoint.yaml', Camel::camelDir($this->configName) . '/custom.0.yaml');
copy(__DIR__ . '/../../resources/example_custom_endpoint.yaml', Camel::camelDir($this->paths) . '/custom.0.yaml');
}

protected function upgradeConfigFileIfNeeded(): void
Expand All @@ -155,12 +164,18 @@ protected function upgradeConfigFileIfNeeded(): void

$this->info("Checking for any pending upgrades to your config file...");
try {
if (! $this->laravel['files']->exists($this->laravel->configPath("{$this->configName}.php"))) {
if (!$this->laravel['files']->exists(
$this->laravel->configPath($this->paths->configFileName())
)
) {
$this->info("No config file to upgrade.");
return;
}

$upgrader = Upgrader::ofConfigFile("config/{$this->configName}.php", __DIR__ . '/../../config/scribe.php')
$upgrader = Upgrader::ofConfigFile(
userOldConfigRelativePath: "config/{$this->paths->configFileName()}",
sampleNewConfigAbsolutePath: __DIR__ . '/../../config/scribe.php'
)
->dontTouch(
'routes', 'example_languages', 'database_connections_to_transact', 'strategies', 'laravel.middleware',
'postman.overrides', 'openapi.overrides', 'groups', 'examples.models_source'
Expand Down
6 changes: 4 additions & 2 deletions src/Commands/Upgrade.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Illuminate\Console\Command;
use Knuckles\Camel\Camel;
use Knuckles\Scribe\Configuration\PathConfig;
use Knuckles\Scribe\GroupedEndpoints\GroupedEndpointsFactory;
use Knuckles\Scribe\Scribe;
use Shalvah\Upgrader\Upgrader;
Expand Down Expand Up @@ -102,7 +103,8 @@ protected function migrateToConfigFileSort()
$this->info("We'll automatically import your current sorting into the config item `groups.order`.");

$defaultGroup = config($this->configName.".default_group");
$extractedEndpoints = GroupedEndpointsFactory::fromCamelDir($this->configName)->get();
$pathConfig = new PathConfig($this->configName);
$extractedEndpoints = GroupedEndpointsFactory::fromCamelDir($pathConfig)->get();

$order = array_map(function (array $group) {
return array_map(function (array $endpoint) {
Expand All @@ -112,7 +114,7 @@ protected function migrateToConfigFileSort()
$groupsOrder = array_keys($order);
$keyIndices = array_flip($groupsOrder);

$userDefinedEndpoints = Camel::loadUserDefinedEndpoints(Camel::camelDir($this->configName));
$userDefinedEndpoints = Camel::loadUserDefinedEndpoints(Camel::camelDir($pathConfig));

if ($userDefinedEndpoints) {
foreach ($userDefinedEndpoints as $endpoint) {
Expand Down
47 changes: 47 additions & 0 deletions src/Configuration/PathConfig.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

namespace Knuckles\Scribe\Configuration;

/**
* A home for path configurations. The important paths Scribe depends on.
*/
class PathConfig
{
public function __construct(
public string $configName = 'scribe',
// FOr lack of a better name, we'll call this `scribeDir`.
// It's sort of the cache dir, where Scribe stores its intermediate outputs.
protected ?string $scribeDir = null
)
{
if (is_null($this->scribeDir)) {
$this->scribeDir = ".{$this->configName}";
}
}

public function outputPath(string $resolvePath = null, string $separator = '/'): string
{
if (is_null($resolvePath)) {
return $this->configName;
}

return "{$this->configName}{$separator}{$resolvePath}";
}

public function configFileName(): string
{
return "{$this->configName}.php";
}

/**
* The directory where Scribe writes its intermediate output (default is .<config> ie .scribe)
*/
public function intermediateOutputPath(string $resolvePath = null, string $separator = '/'): string
{
if (is_null($resolvePath)) {
return $this->scribeDir;
}

return "{$this->scribeDir}{$separator}{$resolvePath}";
}
}
12 changes: 8 additions & 4 deletions src/Extracting/ApiDetails.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Knuckles\Scribe\Extracting;

use Knuckles\Scribe\Configuration\PathConfig;
use Knuckles\Scribe\Tools\ConsoleOutputUtils as c;
use Knuckles\Scribe\Tools\Utils as u;
use Knuckles\Scribe\Tools\DocumentationConfig;
Expand All @@ -23,11 +24,14 @@ class ApiDetails

private array $lastKnownFileContentHashes = [];

public function __construct(DocumentationConfig $config = null, bool $preserveUserChanges = true, string $docsName = 'scribe')
{
$this->markdownOutputPath = ".{$docsName}"; //.scribe by default
public function __construct(
PathConfig $paths,
DocumentationConfig $config = null,
bool $preserveUserChanges = true
) {
$this->markdownOutputPath = $paths->intermediateOutputPath(); //.scribe by default
// If no config is injected, pull from global. Makes testing easier.
$this->config = $config ?: new DocumentationConfig(config($docsName));
$this->config = $config ?: new DocumentationConfig(config($paths->configName));
$this->baseUrl = $this->config->get('base_url') ?? config('app.url');
$this->preserveUserChanges = $preserveUserChanges;

Expand Down
32 changes: 23 additions & 9 deletions src/GroupedEndpoints/GroupedEndpointsFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,48 @@
namespace Knuckles\Scribe\GroupedEndpoints;

use Knuckles\Scribe\Commands\GenerateDocumentation;
use Knuckles\Scribe\Configuration\PathConfig;
use Knuckles\Scribe\Matching\RouteMatcherInterface;

class GroupedEndpointsFactory
{
public function make(GenerateDocumentation $command, RouteMatcherInterface $routeMatcher, string $docsName = 'scribe'): GroupedEndpointsContract
{
public function make(
GenerateDocumentation $command,
RouteMatcherInterface $routeMatcher,
PathConfig $paths
): GroupedEndpointsContract {
if ($command->isForcing()) {
return static::fromApp($command, $routeMatcher, false, $docsName);
return static::fromApp(
command: $command,
routeMatcher: $routeMatcher,
preserveUserChanges: false,
paths: $paths
);
}

if ($command->shouldExtract()) {
return static::fromApp($command, $routeMatcher, true, $docsName);
return static::fromApp(
command: $command,
routeMatcher: $routeMatcher,
preserveUserChanges: true,
paths: $paths
);
}

return static::fromCamelDir($docsName);
return static::fromCamelDir($paths);
}

public static function fromApp(
GenerateDocumentation $command,
RouteMatcherInterface $routeMatcher,
bool $preserveUserChanges,
string $docsName = 'scribe'
PathConfig $paths
): GroupedEndpointsFromApp {
return new GroupedEndpointsFromApp($command, $routeMatcher, $preserveUserChanges, $docsName);
return new GroupedEndpointsFromApp($command, $routeMatcher, $paths, $preserveUserChanges);
}

public static function fromCamelDir(string $docsName = 'scribe'): GroupedEndpointsFromCamelDir
public static function fromCamelDir(PathConfig $paths): GroupedEndpointsFromCamelDir
{
return new GroupedEndpointsFromCamelDir($docsName);
return new GroupedEndpointsFromCamelDir($paths);
}
}
16 changes: 9 additions & 7 deletions src/GroupedEndpoints/GroupedEndpointsFromApp.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Knuckles\Camel\Extraction\ExtractedEndpointData;
use Knuckles\Camel\Output\OutputEndpointData;
use Knuckles\Scribe\Commands\GenerateDocumentation;
use Knuckles\Scribe\Configuration\PathConfig;
use Knuckles\Scribe\Exceptions\CouldntGetRouteDetails;
use Knuckles\Scribe\Extracting\ApiDetails;
use Knuckles\Scribe\Extracting\Extractor;
Expand All @@ -34,14 +35,15 @@ class GroupedEndpointsFromApp implements GroupedEndpointsContract
public static string $cacheDir;

public function __construct(
private GenerateDocumentation $command, private RouteMatcherInterface $routeMatcher,
private bool $preserveUserChanges = true, protected string $docsName = 'scribe'
)
{
private GenerateDocumentation $command,
private RouteMatcherInterface $routeMatcher,
protected PathConfig $paths,
private bool $preserveUserChanges = true
) {
$this->docConfig = $command->getDocConfig();

static::$camelDir = Camel::camelDir($this->docsName);
static::$cacheDir = Camel::cacheDir($this->docsName);
static::$camelDir = Camel::camelDir($this->paths);
static::$cacheDir = Camel::cacheDir($this->paths);
}

public function get(): array
Expand Down Expand Up @@ -282,7 +284,7 @@ protected function extractAndWriteApiDetailsToDisk(): void

protected function makeApiDetails(): ApiDetails
{
return new ApiDetails($this->docConfig, !$this->command->option('force'), $this->docsName);
return new ApiDetails($this->paths, $this->docConfig, !$this->command->option('force'));
}

/**
Expand Down
11 changes: 5 additions & 6 deletions src/GroupedEndpoints/GroupedEndpointsFromCamelDir.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,24 @@
namespace Knuckles\Scribe\GroupedEndpoints;

use Knuckles\Camel\Camel;
use Knuckles\Scribe\Configuration\PathConfig;

class GroupedEndpointsFromCamelDir implements GroupedEndpointsContract
{
protected string $docsName;

public function __construct(string $docsName = 'scribe')
public function __construct(protected PathConfig $paths)
{
$this->docsName = $docsName;
}

public function get(): array
{
if (!is_dir(Camel::camelDir($this->docsName))) {
if (!is_dir(Camel::camelDir($this->paths))) {
throw new \InvalidArgumentException(
"Can't use --no-extraction because there are no endpoints in the " . Camel::camelDir($this->docsName) . " directory."
"Can't use --no-extraction because there are no endpoints in the " . Camel::camelDir($this->paths) . " directory."
);
}

return Camel::loadEndpointsIntoGroups(Camel::camelDir($this->docsName));
return Camel::loadEndpointsIntoGroups(Camel::camelDir($this->paths));
}

public function hasEncounteredErrors(): bool
Expand Down
Loading
Loading