Rename namespace to Tezmanian and prepare for Packagist
PHP Composer / build (push) Successful in 31s
PHP Composer / build (push) Successful in 31s
- Namespace Tez\Utils -> Tezmanian\Utils, package tez/* -> tezmanian/* - Add keywords, homepage, authors and support metadata - Drop VCS repositories (resolved via Packagist) - Remove stale composer.lock, set license holder
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2026 Development
|
Copyright (c) 2026 René Halberstadt
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||||
associated documentation files (the "Software"), to deal in the Software without restriction, including
|
associated documentation files (the "Software"), to deal in the Software without restriction, including
|
||||||
|
|||||||
@@ -1,13 +1,20 @@
|
|||||||
# tez-utils-fn
|
# tez-utils-fn
|
||||||
|
|
||||||
|
[](https://github.com/tezmanian/tez-utils-fn/actions/workflows/php.yml)
|
||||||
|
[](https://packagist.org/packages/tezmanian/utils-fn)
|
||||||
|
[](https://packagist.org/packages/tezmanian/utils-fn)
|
||||||
|
[](LICENSE)
|
||||||
|
|
||||||
Functional programming primitives for PHP: pipelines, composition, memoization, partial application, once-guards, retry with backoff, and tap for side-effects. PHP 8.3+, no dependencies.
|
Functional programming primitives for PHP: pipelines, composition, memoization, partial application, once-guards, retry with backoff, and tap for side-effects. PHP 8.3+, no dependencies.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
composer require tez/utils-fn
|
composer require tezmanian/utils-fn
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Package: [`tezmanian/utils-fn`](https://packagist.org/packages/tezmanian/utils-fn) · Namespace: `Tezmanian\Utils\Fn`
|
||||||
|
|
||||||
## Components
|
## Components
|
||||||
|
|
||||||
| Class | Purpose |
|
| Class | Purpose |
|
||||||
@@ -27,7 +34,7 @@ composer require tez/utils-fn
|
|||||||
Passes a value through an ordered sequence of callables left-to-right. Each stage receives the output of the previous one.
|
Passes a value through an ordered sequence of callables left-to-right. Each stage receives the output of the previous one.
|
||||||
|
|
||||||
```php
|
```php
|
||||||
use Tez\Utils\Fn\Pipeline;
|
use Tezmanian\Utils\Fn\Pipeline;
|
||||||
|
|
||||||
// Immediate execution
|
// Immediate execution
|
||||||
Pipeline::process(
|
Pipeline::process(
|
||||||
@@ -58,7 +65,7 @@ Right-to-left composition — the mathematical counterpart to `Pipeline`. The ri
|
|||||||
`Compose::build(f, g, h)` is equivalent to `Pipeline::build(h, g, f)`.
|
`Compose::build(f, g, h)` is equivalent to `Pipeline::build(h, g, f)`.
|
||||||
|
|
||||||
```php
|
```php
|
||||||
use Tez\Utils\Fn\Compose;
|
use Tezmanian\Utils\Fn\Compose;
|
||||||
|
|
||||||
// Immediate execution — applies right-to-left: trim → strtolower → str_replace
|
// Immediate execution — applies right-to-left: trim → strtolower → str_replace
|
||||||
Compose::apply(
|
Compose::apply(
|
||||||
@@ -87,7 +94,7 @@ $process(' FOO BAR '); // 'foo-bar'
|
|||||||
Wraps a callable and caches its return value per unique argument signature. `null` return values are cached correctly and do not trigger a second invocation.
|
Wraps a callable and caches its return value per unique argument signature. `null` return values are cached correctly and do not trigger a second invocation.
|
||||||
|
|
||||||
```php
|
```php
|
||||||
use Tez\Utils\Fn\Memoize;
|
use Tezmanian\Utils\Fn\Memoize;
|
||||||
|
|
||||||
$expensiveCalc = Memoize::wrap(function (int $n): int {
|
$expensiveCalc = Memoize::wrap(function (int $n): int {
|
||||||
// called only once per unique $n
|
// called only once per unique $n
|
||||||
@@ -116,7 +123,7 @@ $expensiveCalc(5); // computed again
|
|||||||
Executes a callable exactly once. Every subsequent call returns the cached return value without re-invoking the callable. Each `Once` instance is independent.
|
Executes a callable exactly once. Every subsequent call returns the cached return value without re-invoking the callable. Each `Once` instance is independent.
|
||||||
|
|
||||||
```php
|
```php
|
||||||
use Tez\Utils\Fn\Once;
|
use Tezmanian\Utils\Fn\Once;
|
||||||
|
|
||||||
$init = Once::wrap(function (): string {
|
$init = Once::wrap(function (): string {
|
||||||
// executed only on the first call
|
// executed only on the first call
|
||||||
@@ -140,7 +147,7 @@ $once(); // null — from cache, callable NOT called again
|
|||||||
Pre-fills the leading arguments of a callable and returns a new `Closure` that accepts the remaining arguments.
|
Pre-fills the leading arguments of a callable and returns a new `Closure` that accepts the remaining arguments.
|
||||||
|
|
||||||
```php
|
```php
|
||||||
use Tez\Utils\Fn\Partial;
|
use Tezmanian\Utils\Fn\Partial;
|
||||||
|
|
||||||
$multiply = fn(int $a, int $b): int => $a * $b;
|
$multiply = fn(int $a, int $b): int => $a * $b;
|
||||||
|
|
||||||
@@ -172,7 +179,7 @@ $pipeline('hello'); // '>>> HELLO'
|
|||||||
Retries a callable on exception. Supports linear and exponential backoff, exception allowlists (`only`), and exception blocklists (`except`). Throws the last exception when all attempts are exhausted.
|
Retries a callable on exception. Supports linear and exponential backoff, exception allowlists (`only`), and exception blocklists (`except`). Throws the last exception when all attempts are exhausted.
|
||||||
|
|
||||||
```php
|
```php
|
||||||
use Tez\Utils\Fn\Retry;
|
use Tezmanian\Utils\Fn\Retry;
|
||||||
|
|
||||||
// Basic retry — up to 3 attempts (default)
|
// Basic retry — up to 3 attempts (default)
|
||||||
$result = Retry::run(fn() => fetchFromApi());
|
$result = Retry::run(fn() => fetchFromApi());
|
||||||
@@ -212,8 +219,8 @@ Executes a side-effect callable on a value and returns the value unchanged. The
|
|||||||
Useful for logging, debugging, or triggering side-effects inside a pipeline without breaking the chain.
|
Useful for logging, debugging, or triggering side-effects inside a pipeline without breaking the chain.
|
||||||
|
|
||||||
```php
|
```php
|
||||||
use Tez\Utils\Fn\Tap;
|
use Tezmanian\Utils\Fn\Tap;
|
||||||
use Tez\Utils\Fn\Pipeline;
|
use Tezmanian\Utils\Fn\Pipeline;
|
||||||
|
|
||||||
Tap::value('hello', fn($v) => strtoupper($v)); // 'hello' — callable return discarded
|
Tap::value('hello', fn($v) => strtoupper($v)); // 'hello' — callable return discarded
|
||||||
|
|
||||||
@@ -232,6 +239,15 @@ $pipeline = Pipeline::build(
|
|||||||
- PHP 8.3+
|
- PHP 8.3+
|
||||||
- No runtime dependencies
|
- No runtime dependencies
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make build && make install
|
||||||
|
make ci # audit, PHPStan, code style, tests
|
||||||
|
```
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT
|
MIT — see [LICENSE](LICENSE).
|
||||||
|
|
||||||
|
Author: René Halberstadt
|
||||||
|
|||||||
+21
-3
@@ -1,16 +1,34 @@
|
|||||||
{
|
{
|
||||||
"name": "tez/utils-fn",
|
"name": "tezmanian/utils-fn",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"description": "Functional programming primitives for PHP: pipelines, composition, memoization, partial application, once-guards, retry with backoff, and tap for side-effects. PHP 8.3+, no dependencies.",
|
"description": "Functional programming primitives for PHP: pipelines, composition, memoization, partial application, once-guards, retry with backoff, and tap for side-effects. PHP 8.3+, no dependencies.",
|
||||||
|
"keywords": [
|
||||||
|
"functional",
|
||||||
|
"pipeline",
|
||||||
|
"memoize",
|
||||||
|
"retry",
|
||||||
|
"php"
|
||||||
|
],
|
||||||
|
"homepage": "https://github.com/tezmanian/tez-utils-fn",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "René Halberstadt",
|
||||||
|
"email": "tezmanian@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/tezmanian/tez-utils-fn/issues",
|
||||||
|
"source": "https://github.com/tezmanian/tez-utils-fn"
|
||||||
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Tez\\Utils\\Fn\\": "src/"
|
"Tezmanian\\Utils\\Fn\\": "src/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload-dev": {
|
"autoload-dev": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Tez\\Utils\\Tests\\Fn\\": "tests/"
|
"Tezmanian\\Utils\\Tests\\Fn\\": "tests/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Tez\Utils\Fn;
|
namespace Tezmanian\Utils\Fn;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Combines callables using right-to-left mathematical composition (f∘g∘h).
|
* Combines callables using right-to-left mathematical composition (f∘g∘h).
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Tez\Utils\Fn;
|
namespace Tezmanian\Utils\Fn;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wraps a callable and caches its return value per unique argument signature.
|
* Wraps a callable and caches its return value per unique argument signature.
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Tez\Utils\Fn;
|
namespace Tezmanian\Utils\Fn;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wraps a callable so it is executed exactly once.
|
* Wraps a callable so it is executed exactly once.
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Tez\Utils\Fn;
|
namespace Tezmanian\Utils\Fn;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pre-fills the leading arguments of a callable and returns a new Closure
|
* Pre-fills the leading arguments of a callable and returns a new Closure
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Tez\Utils\Fn;
|
namespace Tezmanian\Utils\Fn;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pipes a value through an ordered sequence of callables left-to-right.
|
* Pipes a value through an ordered sequence of callables left-to-right.
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Tez\Utils\Fn;
|
namespace Tezmanian\Utils\Fn;
|
||||||
|
|
||||||
final class Retry
|
final class Retry
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Tez\Utils\Fn;
|
namespace Tezmanian\Utils\Fn;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes a side-effect callable on a value and returns the value unchanged.
|
* Executes a side-effect callable on a value and returns the value unchanged.
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Tez\Utils\Tests\Fn;
|
namespace Tezmanian\Utils\Tests\Fn;
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Tez\Utils\Fn\Compose;
|
use Tezmanian\Utils\Fn\Compose;
|
||||||
|
|
||||||
final class ComposeTest extends TestCase
|
final class ComposeTest extends TestCase
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Tez\Utils\Tests\Fn;
|
namespace Tezmanian\Utils\Tests\Fn;
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Tez\Utils\Fn\Memoize;
|
use Tezmanian\Utils\Fn\Memoize;
|
||||||
|
|
||||||
final class MemoizeTest extends TestCase
|
final class MemoizeTest extends TestCase
|
||||||
{
|
{
|
||||||
@@ -109,7 +109,7 @@ final class MemoizeTest extends TestCase
|
|||||||
});
|
});
|
||||||
|
|
||||||
self::assertSame(3, $memoized(1, 2));
|
self::assertSame(3, $memoized(1, 2));
|
||||||
self::assertSame(3, $memoized(1, 2));
|
self::assertSame(3, $memoized(1, 2)); // @phpstan-ignore staticMethod.alreadyNarrowedType
|
||||||
self::assertSame(5, $memoized(2, 3));
|
self::assertSame(5, $memoized(2, 3));
|
||||||
self::assertSame(2, $calls);
|
self::assertSame(2, $calls);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Tez\Utils\Tests\Fn;
|
namespace Tezmanian\Utils\Tests\Fn;
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Tez\Utils\Fn\Once;
|
use Tezmanian\Utils\Fn\Once;
|
||||||
|
|
||||||
final class OnceTest extends TestCase
|
final class OnceTest extends TestCase
|
||||||
{
|
{
|
||||||
@@ -45,7 +45,7 @@ final class OnceTest extends TestCase
|
|||||||
$once = Once::wrap(fn(): string => 'hello');
|
$once = Once::wrap(fn(): string => 'hello');
|
||||||
|
|
||||||
self::assertSame('hello', $once());
|
self::assertSame('hello', $once());
|
||||||
self::assertSame('hello', $once());
|
self::assertSame('hello', $once()); // @phpstan-ignore staticMethod.alreadyNarrowedType
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testNullReturnIsCachedCorrectly(): void
|
public function testNullReturnIsCachedCorrectly(): void
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Tez\Utils\Tests\Fn;
|
namespace Tezmanian\Utils\Tests\Fn;
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Tez\Utils\Fn\Partial;
|
use Tezmanian\Utils\Fn\Partial;
|
||||||
|
|
||||||
final class PartialTest extends TestCase
|
final class PartialTest extends TestCase
|
||||||
{
|
{
|
||||||
@@ -64,7 +64,7 @@ final class PartialTest extends TestCase
|
|||||||
{
|
{
|
||||||
$addPrefix = Partial::apply(fn(string $prefix, string $s) => $prefix . $s, '>>> ');
|
$addPrefix = Partial::apply(fn(string $prefix, string $s) => $prefix . $s, '>>> ');
|
||||||
|
|
||||||
$pipeline = \Tez\Utils\Fn\Pipeline::build(
|
$pipeline = \Tezmanian\Utils\Fn\Pipeline::build(
|
||||||
'strtoupper',
|
'strtoupper',
|
||||||
$addPrefix,
|
$addPrefix,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Tez\Utils\Tests\Fn;
|
namespace Tezmanian\Utils\Tests\Fn;
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Tez\Utils\Fn\Pipeline;
|
use Tezmanian\Utils\Fn\Pipeline;
|
||||||
|
|
||||||
final class PipelineTest extends TestCase
|
final class PipelineTest extends TestCase
|
||||||
{
|
{
|
||||||
|
|||||||
+2
-2
@@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Tez\Utils\Tests\Fn;
|
namespace Tezmanian\Utils\Tests\Fn;
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Tez\Utils\Fn\Retry;
|
use Tezmanian\Utils\Fn\Retry;
|
||||||
|
|
||||||
final class RetryTest extends TestCase
|
final class RetryTest extends TestCase
|
||||||
{
|
{
|
||||||
|
|||||||
+2
-2
@@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Tez\Utils\Tests\Fn;
|
namespace Tezmanian\Utils\Tests\Fn;
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Tez\Utils\Fn\Tap;
|
use Tezmanian\Utils\Fn\Tap;
|
||||||
|
|
||||||
final class TapTest extends TestCase
|
final class TapTest extends TestCase
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user