Skip to content

Commit f11536d

Browse files
committed
Add Flowpipe configuration, command for step creation, and YAML flow definition registry
1 parent 2bd4444 commit f11536d

File tree

8 files changed

+142
-7
lines changed

8 files changed

+142
-7
lines changed

composer.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
"php": "^8.3",
2323
"illuminate/support": "^12.19",
2424
"nesbot/carbon": "^3.10",
25-
"illuminate/contracts": "^12.0"
25+
"illuminate/contracts": "^12.0",
26+
"symfony/yaml": "^7.3"
2627
},
2728
"require-dev": {
2829
"laravel/pint": "^1.22",
@@ -92,4 +93,4 @@
9293
"pestphp/pest-plugin": true
9394
}
9495
}
95-
}
96+
}

src/Config/flowpipe.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,38 @@
33
declare(strict_types=1);
44

55
return [
6+
/*
7+
|--------------------------------------------------------------------------
8+
| Flow Definition Path
9+
|--------------------------------------------------------------------------
10+
|
11+
| This is where your YAML flow definitions live.
12+
| Relative to the base_path() of the Laravel app.
13+
|
14+
*/
15+
16+
'definitions_path' => 'flow_definitions',
17+
/*
18+
|--------------------------------------------------------------------------
19+
| Default Step Namespace
20+
|--------------------------------------------------------------------------
21+
|
22+
| This namespace will be prepended to step class names when resolving
23+
| strings like 'MyStep' into 'App\\Flowpipe\\Steps\\MyStep'.
24+
|
25+
*/
26+
27+
'step_namespace' => 'App\\Flowpipe\\Steps',
28+
29+
/*
30+
|--------------------------------------------------------------------------
31+
| Tracing Configuration
32+
|--------------------------------------------------------------------------
33+
|
34+
| This section configures the tracing functionality of Flowpipe.
35+
| You can enable or disable tracing and set the default tracer class.
36+
| */
37+
638
'tracing' => [
739
'enabled' => true,
840
'default' => Grazulex\LaravelFlowpipe\Tracer\BasicTracer::class,
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Grazulex\LaravelFlowpipe\Console\Commands;
6+
7+
use Illuminate\Console\GeneratorCommand;
8+
use Symfony\Component\Console\Input\InputArgument;
9+
10+
final class FlowpipeMakeStepCommand extends GeneratorCommand
11+
{
12+
protected $name = 'flowpipe:make-step';
13+
14+
protected $description = 'Create a new Flowpipe Step class';
15+
16+
protected $type = 'Step';
17+
18+
protected function getStub(): string
19+
{
20+
return __DIR__.'/stubs/step.stub';
21+
}
22+
23+
protected function getDefaultNamespace($rootNamespace): string
24+
{
25+
return $rootNamespace.'\\Flowpipe\\Steps';
26+
}
27+
28+
protected function getArguments(): array
29+
{
30+
return [
31+
['name', InputArgument::REQUIRED, 'The name of the Step class'],
32+
];
33+
}
34+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace {{ namespace }};
4+
5+
use Closure;
6+
use Grazulex\LaravelFlowpipe\Contracts\FlowStep;
7+
8+
final class {{ class }} implements FlowStep
9+
{
10+
public function handle(mixed $payload, Closure $next): mixed
11+
{
12+
// TODO: Add your logic here
13+
14+
return $next($payload);
15+
}
16+
}

src/LaravelFlowpipeServiceProvider.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,8 @@ public function boot(): void
2424
public function register(): void
2525
{
2626
$this->mergeConfigFrom(__DIR__.'/Config/flowpipe.php', 'flowpipe');
27+
$this->commands([
28+
Console\Commands\FlowpipeMakeStepCommand::class,
29+
]);
2730
}
2831
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Grazulex\LaravelFlowpipe\Registry;
6+
7+
use Illuminate\Support\Collection;
8+
use Illuminate\Support\Facades\File;
9+
use RuntimeException;
10+
use Symfony\Component\Yaml\Yaml;
11+
12+
final class FlowDefinitionRegistry
13+
{
14+
private string $path;
15+
16+
public function __construct(?string $path = null)
17+
{
18+
$this->path = base_path(config('flowpipe.definitions_path', 'flow_definitions'));
19+
}
20+
21+
public function list(): Collection
22+
{
23+
return collect(File::files($this->path))
24+
->filter(fn ($f) => str_ends_with($f->getFilename(), '.yaml'))
25+
->map(fn ($f) => $f->getFilenameWithoutExtension());
26+
}
27+
28+
public function get(string $name): array
29+
{
30+
$file = $this->path.'/'.$name.'.yaml';
31+
32+
if (! file_exists($file)) {
33+
throw new RuntimeException("Flow definition [$name] not found.");
34+
}
35+
36+
return Yaml::parseFile($file);
37+
}
38+
}

src/Steps/StepResolver.php

Whitespace-only changes.

src/Support/StepResolver.php

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,40 @@
66

77
use Closure;
88
use Grazulex\LaravelFlowpipe\Contracts\FlowStep;
9+
use Illuminate\Support\Str;
910
use InvalidArgumentException;
1011

1112
final class StepResolver
1213
{
1314
/**
14-
* Resolve a step given a Closure, instance, or class name.
15+
* Resolve a given step into a FlowStep instance or Closure.
1516
*/
1617
public static function resolve(FlowStep|Closure|string $step): FlowStep|Closure
1718
{
19+
// Already a usable instance
1820
if ($step instanceof Closure || $step instanceof FlowStep) {
1921
return $step;
2022
}
2123

22-
if (class_exists($step)) {
23-
$instance = app($step);
24+
// Try resolving by class name or configured namespace
25+
if (is_string($step)) {
26+
$class = class_exists($step)
27+
? $step
28+
: config('flowpipe.step_namespace', 'App\\Flowpipe\\Steps').'\\'.Str::studly($step);
29+
30+
if (! class_exists($class)) {
31+
throw new InvalidArgumentException("Step class [$class] does not exist.");
32+
}
33+
34+
$instance = app($class);
2435

2536
if (! $instance instanceof FlowStep) {
26-
throw new InvalidArgumentException("Resolved class [$step] must implement FlowStep.");
37+
throw new InvalidArgumentException("Resolved class [$class] must implement FlowStep.");
2738
}
2839

2940
return $instance;
3041
}
3142

32-
throw new InvalidArgumentException('Invalid step provided: '.gettype($step));
43+
throw new InvalidArgumentException('Invalid step type: '.gettype($step));
3344
}
3445
}

0 commit comments

Comments
 (0)