Skip to content
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## [Unreleased]

### Added

- `Innmind\Framework\Application::mapRoutes()`

## 4.0.2 - 2026-04-12

### Fixed
Expand Down
22 changes: 22 additions & 0 deletions src/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,11 @@ public function routes(string $routes): self
}

/**
* This wraps each route individually.
*
* This means that the code may be executed multiple times until it reaches
* the appropriate route.
*
* @psalm-mutation-free
*
* @param callable(Component<SideEffect, Response>, Container): Component<SideEffect, Response> $map
Expand All @@ -201,6 +206,23 @@ public function mapRoute(callable $map): self
return new self($this->app->mapRoute($map));
}

/**
* This wraps all routes as whole.
*
* This means that the code will be executed only once.
*
* @psalm-mutation-free
*
* @param callable(Component<SideEffect, Response>, Container): Component<SideEffect, Response> $map
*
* @return self<I, O>
*/
#[\NoDiscard]
public function mapRoutes(callable $map): self
{
return new self($this->app->mapRoutes($map));
}

/**
* @psalm-mutation-free
*
Expand Down
36 changes: 36 additions & 0 deletions src/Application/Async/Http.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ final class Http implements Implementation
* @param \Closure(OperatingSystem, Environment): Builder $container
* @param Sequence<callable(Pipe, Container): Component<SideEffect, Response>> $routes
* @param \Closure(Component<SideEffect, Response>, Container): Component<SideEffect, Response> $mapRoute
* @param \Closure(Component<SideEffect, Response>, Container): Component<SideEffect, Response> $mapRoutes
* @param Maybe<callable(ServerRequest, Container): Attempt<Response>> $notFound
* @param \Closure(ServerRequest, \Throwable, Container): Attempt<Response> $recover
*/
Expand All @@ -58,6 +59,7 @@ private function __construct(
private \Closure $container,
private Sequence $routes,
private \Closure $mapRoute,
private \Closure $mapRoutes,
private Maybe $notFound,
private \Closure $recover,
) {
Expand All @@ -77,6 +79,7 @@ public static function of(OperatingSystem $os): self
static fn() => Builder::new(),
Sequence::lazyStartingWith(),
static fn(Component $component) => $component,
static fn(Component $component) => $component,
$notFound,
static fn(ServerRequest $request, \Throwable $e) => Attempt::error($e),
);
Expand All @@ -101,6 +104,7 @@ static function(OperatingSystem $os, Environment $env) use ($previous, $map): ar
$this->container,
$this->routes,
$this->mapRoute,
$this->mapRoutes,
$this->notFound,
$this->recover,
);
Expand All @@ -125,6 +129,7 @@ static function(OperatingSystem $os, Environment $env) use ($previous, $map): ar
$this->container,
$this->routes,
$this->mapRoute,
$this->mapRoutes,
$this->notFound,
$this->recover,
);
Expand All @@ -147,6 +152,7 @@ public function service(Service $name, callable $definition): self
),
$this->routes,
$this->mapRoute,
$this->mapRoutes,
$this->notFound,
$this->recover,
);
Expand Down Expand Up @@ -182,6 +188,7 @@ public function route(callable $handle): self
$this->container,
($this->routes)($handle),
$this->mapRoute,
$this->mapRoutes,
$this->notFound,
$this->recover,
);
Expand All @@ -204,6 +211,30 @@ public function mapRoute(callable $map): self
$previous($component, $get),
$get,
),
$this->mapRoutes,
$this->notFound,
$this->recover,
);
}

/**
* @psalm-mutation-free
*/
#[\Override]
public function mapRoutes(callable $map): self
{
$previous = $this->mapRoutes;

return new self(
$this->os,
$this->map,
$this->container,
$this->routes,
$this->mapRoute,
static fn($component, $get) => $map(
$previous($component, $get),
$get,
),
$this->notFound,
$this->recover,
);
Expand All @@ -221,6 +252,7 @@ public function routeNotFound(callable $handle): self
$this->container,
$this->routes,
$this->mapRoute,
$this->mapRoutes,
Maybe::just($handle),
$this->recover,
);
Expand All @@ -240,6 +272,7 @@ public function recoverRouteError(callable $recover): self
$this->container,
$this->routes,
$this->mapRoute,
$this->mapRoutes,
$this->notFound,
static fn($request, $e, $container) => $previous($request, $e, $container)->recover(
static fn($e) => $recover($request, $e, $container),
Expand All @@ -255,6 +288,7 @@ public function run($input): Attempt
$routes = $this->routes;
$notFound = $this->notFound;
$mapRoute = $this->mapRoute;
$mapRoutes = $this->mapRoutes;
$recover = $this->recover;

$run = Commands::of(Serve::of(
Expand All @@ -265,6 +299,7 @@ static function(ServerRequest $request, OperatingSystem $os, Map $env) use (
$routes,
$notFound,
$mapRoute,
$mapRoutes,
$recover,
): Response {
$env = Environment::of($env);
Expand All @@ -275,6 +310,7 @@ static function(ServerRequest $request, OperatingSystem $os, Map $env) use (
->map(static fn($handle) => $handle($pipe, $container))
->map(static fn($component) => $mapRoute($component, $container));
$router = new Router(
static fn($component) => $mapRoutes($component, $container),
$routes,
$notFound->map(
static fn($handle) => static fn(ServerRequest $request) => $handle(
Expand Down
9 changes: 9 additions & 0 deletions src/Application/Cli.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,15 @@ public function mapRoute(callable $map): self
return $this;
}

/**
* @psalm-mutation-free
*/
#[\Override]
public function mapRoutes(callable $map): self
{
return $this;
}

/**
* @psalm-mutation-free
*/
Expand Down
35 changes: 35 additions & 0 deletions src/Application/Http.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ final class Http implements Implementation
* @param \Closure(OperatingSystem, Environment): Builder $container
* @param Sequence<callable(Pipe, Container): Component<SideEffect, Response>> $routes
* @param \Closure(Component<SideEffect, Response>, Container): Component<SideEffect, Response> $mapRoute
* @param \Closure(Component<SideEffect, Response>, Container): Component<SideEffect, Response> $mapRoutes
* @param Maybe<callable(ServerRequest, Container): Attempt<Response>> $notFound
* @param \Closure(ServerRequest, \Throwable, Container): Attempt<Response> $recover
*/
Expand All @@ -49,6 +50,7 @@ private function __construct(
private \Closure $container,
private Sequence $routes,
private \Closure $mapRoute,
private \Closure $mapRoutes,
private Maybe $notFound,
private \Closure $recover,
) {
Expand All @@ -68,6 +70,7 @@ public static function of(OperatingSystem $os, Environment $env): self
static fn() => Builder::new(),
Sequence::lazyStartingWith(),
static fn(Component $component) => $component,
static fn(Component $component) => $component,
$notFound,
static fn(ServerRequest $request, \Throwable $e) => Attempt::error($e),
);
Expand All @@ -86,6 +89,7 @@ public function mapEnvironment(callable $map): self
$this->container,
$this->routes,
$this->mapRoute,
$this->mapRoutes,
$this->notFound,
$this->recover,
);
Expand All @@ -104,6 +108,7 @@ public function mapOperatingSystem(callable $map): self
$this->container,
$this->routes,
$this->mapRoute,
$this->mapRoutes,
$this->notFound,
$this->recover,
);
Expand All @@ -126,6 +131,7 @@ public function service(Service $name, callable $definition): self
),
$this->routes,
$this->mapRoute,
$this->mapRoutes,
$this->notFound,
$this->recover,
);
Expand Down Expand Up @@ -161,6 +167,7 @@ public function route(callable $handle): self
$this->container,
($this->routes)($handle),
$this->mapRoute,
$this->mapRoutes,
$this->notFound,
$this->recover,
);
Expand All @@ -183,6 +190,30 @@ public function mapRoute(callable $map): self
$previous($component, $get),
$get,
),
$this->mapRoutes,
$this->notFound,
$this->recover,
);
}

/**
* @psalm-mutation-free
*/
#[\Override]
public function mapRoutes(callable $map): self
{
$previous = $this->mapRoutes;

return new self(
$this->os,
$this->env,
$this->container,
$this->routes,
$this->mapRoute,
static fn($component, $get) => $map(
$previous($component, $get),
$get,
),
$this->notFound,
$this->recover,
);
Expand All @@ -200,6 +231,7 @@ public function routeNotFound(callable $handle): self
$this->container,
$this->routes,
$this->mapRoute,
$this->mapRoutes,
Maybe::just($handle),
$this->recover,
);
Expand All @@ -219,6 +251,7 @@ public function recoverRouteError(callable $recover): self
$this->container,
$this->routes,
$this->mapRoute,
$this->mapRoutes,
$this->notFound,
static fn($request, $e, $container) => $previous($request, $e, $container)->recover(
static fn($e) => $recover($request, $e, $container),
Expand All @@ -231,13 +264,15 @@ public function run($input): Attempt
{
$container = ($this->container)($this->os, $this->env)->build();
$mapRoute = $this->mapRoute;
$mapRoutes = $this->mapRoutes;
$recover = $this->recover;
$pipe = Pipe::new();
$routes = $this
->routes
->map(static fn($handle) => $handle($pipe, $container))
->map(static fn($component) => $mapRoute($component, $container));
$router = new Router(
static fn($component) => $mapRoutes($component, $container),
$routes,
$this->notFound->map(
static fn($handle) => static fn(ServerRequest $request) => $handle(
Expand Down
9 changes: 9 additions & 0 deletions src/Application/Implementation.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,15 @@ public function route(callable $handle): self;
*/
public function mapRoute(callable $map): self;

/**
* @psalm-mutation-free
*
* @param callable(Component<SideEffect, Response>, Container): Component<SideEffect, Response> $map
*
* @return self<I, O>
*/
public function mapRoutes(callable $map): self;

/**
* @psalm-mutation-free
*
Expand Down
4 changes: 3 additions & 1 deletion src/Http/Router.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@
final class Router
{
/**
* @param \Closure(Component<SideEffect, Response>): Component<SideEffect, Response> $mapRoutes
* @param Sequence<Component<SideEffect, Response>> $routes
* @param Maybe<\Closure(ServerRequest): Attempt<Response>> $notFound
* @param \Closure(ServerRequest, \Throwable): Attempt<Response> $recover
*/
public function __construct(
private \Closure $mapRoutes,
private Sequence $routes,
private Maybe $notFound,
private \Closure $recover,
Expand All @@ -52,7 +54,7 @@ public function __invoke(ServerRequest $request): Attempt
* @psalm-suppress MixedArgumentTypeCoercion
*/
$route = Route::of(
Any::from($this->routes)
($this->mapRoutes)(Any::from($this->routes))
->mapError(static fn($e) => match (true) {
$e instanceof NoRouteProvided => new NotFound,
default => $e,
Expand Down
Loading
Loading