Skip to content

Tags: seatplus/esi-client

Tags

4.1.2

Toggle 4.1.2's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
chore: add strict_types and fix strict-mode type errors (#32)

- Add declare(strict_types=1) to all 20 source files
- Fix EsiClient::invoke() — cast Guzzle Uri to string before GuzzleFetcher::call()
- Fix EsiClient::buildDataUri() — cast (string) $data[$match] for str_replace
- Fix EsiClient::getConfiguration() return type — add int|null to union
  (EsiConfiguration properties include int fields e.g. esi_port)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

4.1.1

Toggle 4.1.1's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
ci: add structured coverage CI (100% min) (#31)

* ci: add structured coverage CI matching eveapi pattern

- formats.yml: bump PHP to 8.5, add FORK_MEM_PER_PROC=107374182400 to
  prevent pokio race condition on type coverage checks
- tests.yml: restructure to 3-shard matrix + all-tests-pass gate +
  separate coverage job (pcov) with --min=100
- composer.json: add --min=100 to test:unit-coverage script

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: resolve deprecation warnings for PHP 8.5

- Replace abandoned fzaninotto/faker with fakerphp/faker ^1.23
- Upgrade kevinrob/guzzle-cache-middleware ^4 -> ^6 (fixes implicit
  nullable params deprecated in PHP 8.4+)
- Fix faker property accesses to method calls: randomNumber/md5/sha1
- Remove ReflectionMethod::setAccessible(true) call (deprecated since
  PHP 8.5, no-op since PHP 8.1)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: upgrade kevinrob/guzzle-cache-middleware to ^7.0

Latest stable release (2025-09-04). v6 would have been sufficient to
fix the PHP 8.5 implicit-nullable deprecation, but there is no reason
to stop short of the latest version.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

4.1.0

Toggle 4.1.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat: propagate X-ESI-Error-Limit-Reset through EsiResponse and EsiCl…

…ient (#28)

- EsiResponse: add `error_limit_reset` property parsed from X-ESI-Error-Limit-Reset header
- EsiClient::invoke(): map error_limit_remain/reset into EsiRawResponse so callers
  (RecordingEsiClient in eveapi) can track the global error budget
- GuzzleFetcher: pass retryAfter to EsiErrorLimitedException from X-Esi-Error-Limit-Reset header
- composer.json: bump seatplus/esi-schema to ^1.3 (adds errorLimitRemaining/Reset to EsiRawResponse)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

4.0.0

Toggle 4.0.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
feat: ESI rate-limit support + typed SDK with OAS3 generator (#22)

* remove spatie/data-transfer-object dependency

* Fix styling

* Fix/badges (#18)

* update batches

* update workflow for branch renaming

* improve coverage

* Update PHP version requirement to 8.3 and add Rector/rector in require-dev.

* Update GuzzleFetcherTest for Carbon\Carbon::now() usage.

* Add VerifyAccessTokenTest.php and VerifyAccessToken.php files for token verification.

* Refactored UpdateRefreshTokenService constructor for dependency injection.

* Create JwtService class with methods to decode JWT and parse JWKS.

* Create Null Logger Test

* Refactor __set method to return void and remove unnecessary return statement.

* Refactor getErrorMessage method to return string directly.

* Refactor EsiConfiguration to use new instance singleton pattern.

* Refactor CheckAccess to use EsiConfiguration instead of Configuration.

* Update RotatingFileLogger to use EsiConfiguration singleton for logger setup.

* Refactor EsiClient invoke method for better error handling and readability.

* Refactor GuzzleFetcher constructor for better dependency injection.

* Add method to make $method lowercase before checking URI.

* Remove outdated interface implementation and add method to reset the instance.

* improve export format

* Add unit test for LaravelFileCacheMiddleware returning CacheMiddleware instance.

* Add EsiResponseTest with parsing and handling methods.

* lint

* Lint: enforce type declaration in GuzzleFetcher and EsiResponse methods.

* rector

* lint

* Workflow update

* Update code climate badges for maintainability and test coverage.

* Refactor RotatingFileLoggerTest.php for log level functionality. (#19)

* Refactor RotatingFileLoggerTest.php for log level functionality.

* lint

* fix: upgrade firebase/php-jwt from v5 to v6 (#20)

* fix: upgrade firebase/php-jwt from v5 to v6

- Bump composer requirement from ^5.4 to ^6.0
- Remove $allowed_algs parameter from JwtService::decodeJWT() — v6
  embeds the algorithm inside Key objects; JWT::decode() no longer
  accepts a third argument
- Update VerifyAccessToken to drop the ['RS256'] third argument
- Update JwtServiceTest to use new Key($secret, 'HS256') instead of
  plain string keys
- Update VerifyAccessTokenTest mock expectations to match new 2-arg
  decodeJWT() signature

Resolves security advisories PKSA-y2cr-5h3j-g3ys and PKSA-2kqm-ps5x-s4f5

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ci: update deprecated actions (checkout v4, codeclimate v9)

- actions/checkout@v2 -> @v4
- paambaati/codeclimate-action@v2.6.0 -> @v9.0.0

Old versions crash with Node.js 20+ runners.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ci: replace broken codeclimate-action with direct pest run

codeclimate.com/downloads/test-reporter returns 404 — the reporter
binary has been removed upstream. Drop paambaati/codeclimate-action
and run tests directly via pest --coverage --ci --min=100.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: upgrade firebase/php-jwt to ^7.0

v6.x is also affected by PKSA-y2cr-5h3j-g3ys, so bump to ^7.0 which
is unaffected. v7 enforces minimum key lengths (HS256: 32 bytes,
RSA: 2048 bits) — update tests accordingly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* style: apply pint fixes for updated ruleset

New pint version enforces fully_qualified_strict_types,
ordered_imports, and other rules across existing files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: add logs, .phpunit.cache to .gitignore

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: pin phpstan <1.12.28 to fix pest-plugin-type-coverage incompatibility

phpstan 1.12.28+ changed RuleErrorTransformer::transform() signature
breaking pest-plugin-type-coverage v3.x. Pin to <1.12.28 until the
plugin is upgraded to v4 (which requires pest v4).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: upgrade pest to v4 to resolve phpstan incompatibility

pest-plugin-type-coverage v3.x was incompatible with phpstan 1.12.28+
due to a changed RuleErrorTransformer::transform() signature.
Upgrading to pest v4 + pest-plugin-type-coverage v4 resolves this
properly without needing a phpstan version pin.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ci: add pull_request trigger and composer.json path to formats workflow

Also update actions/checkout to v4.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: pin phpstan <1.12.28 (pest-plugin-type-coverage v4 still broken)

pest-plugin-type-coverage v4 calls PHPStan\RuleErrorTransformer::transform()
with an array for arg #3, but phpstan 1.12.28+ changed that parameter
to strictly require string. Both v3 and v4 of the plugin are affected.
This is an upstream bug — track: https://github.com/pestphp/pest-plugin-type-coverage

Pin until a fixed release of pest-plugin-type-coverage ships.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: upgrade to PHPUnit 12 / PHPStan 2 / Rector 2 for Pest 4 compatibility

- Bump phpstan/phpstan ^1.12 → ^2.1.46 to match pest-plugin-type-coverage
  v4 API (RuleErrorTransformer::transform signature changed in PHPStan 2)
- Bump rector/rector ^1.2 → ^2.0 (rector 1.x requires PHPStan 1.x)
- Update phpunit.xml.dist schema to PHPUnit 12.5 (<coverage> element was
  removed from the schema; keeping it caused a validation WARN that with
  failOnWarning=true became a fatal test failure)
- Move coverage report flags to test:unit-coverage CLI script
- Set failOnWarning=false (schema warnings from missing optional drivers
  should not be fatal)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ci: remove pull_request trigger and composer.json path from formats workflow

* ci: add pull_request trigger for 3.x branch in formats workflow

* feat: ESI rate-limit support + EsiResponse ArrayObject refactor

- Add EsiRateLimitedException (HTTP 429) with retryAfter from Retry-After header
- Add EsiErrorLimitedException (HTTP 420) with default retryAfter of 60s
- GuzzleFetcher: throw specific exceptions for 429/420 instead of generic RequestFailedException
- GuzzleFetcher: send X-Compatibility-Date header when EsiConfiguration::compatibility_date is set
- GuzzleFetcher: log X-Ratelimit-Remaining alongside X-Esi-Error-Limit-Remain
- EsiResponse: drop extends ArrayObject; add public object $data with @deprecated __get/__isset bridge
- EsiResponse: parse X-Ratelimit-Group/Limit/Remaining/Used and Retry-After headers
- EsiResponse: add isRateLimitLow() helper (returns true when remaining < 10% of limit)
- EsiConfiguration: add public ?string $compatibility_date = null
- All tests pass: 73 assertions, 100% type coverage, PHPStan clean, Pint clean

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat: parse ratelimit window seconds from X-Ratelimit-Limit header

Parse the '15m' window part of '1800/15m' into ratelimitWindowSeconds
(e.g. 900 for 15m). This enables Phase 2 proactive rate-limit middleware
to calculate the correct dispatch rate (limit / window).

Supports s/m/h unit suffixes; null when header is absent or has no '/'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: bump PHP requirement to ^8.5, add typed constants

- Require PHP ^8.5 (skipping 8.4, targeting current stable)
- Add typed class constants (const string) in VerifyAccessToken and
  UpdateRefreshTokenService — required for 100% type coverage on PHP 8.5
- Update CI workflows: php-version 8.3 → 8.5, add 4.x to trigger branches
- Update composer.lock for PHP 8.5 compatible deps

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: add version 4.0.0 field for path-repo dev workaround

Required so eveapi's path repository can satisfy the ^4.0 constraint
while PR #22 is unmerged. Must be removed after the tag is published.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat!: remove deprecated EsiResponse __get/__isset shim

Magic property access bridge dropped for v4. All eveapi callers now
use ->data->property directly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs: update README with usage, DTO contract, and rate-limit notes

- Replace outdated echo $character_info usage example with proper
  EsiResponse consumption pattern
- Document that response shapes are the consumer's responsibility
  (transport-only contract)
- Show eveapi DTO pattern: XxxResponse::from($response->data)
- Document ESI 1800-token/15-min rate limit and that throttling is
  handled by eveapi Horizon middleware

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat: add EsiResult<T>, withToken(), and 30 resource stubs (typed SDK scaffold)

- EsiResult<T> readonly class wraps typed data + pages + isCachedLoad
- EsiClient::withToken(string): static for fluent authenticated calls
- 30 resource factory methods on EsiClient (one per ESI tag group)
- AbstractResource base class + 30 generated stub classes
- EsiClient::$authentication changed from readonly to allow clone+reassign

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(generator): body params in invoke, constant interpolation in header comment

- buildInvokeCall: pass body params (in:body) as 6th arg to invoke()
- buildMethodSignature: resolve type from schema.type for body params, use mixed type
- generateResourceFile: fix {ESI_COMPATIBILITY_DATE} constant not interpolated in heredoc — pre-assign to $compatDate variable

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* test(esi-client): add tests for EsiResult and generated resources

- EsiResultTest: constructor defaults, explicit pages/cached, fromResponse
  with object body, X-Pages extraction, X-Kevinrob-Cache HIT/MISS
- GeneratedResourcesTest: withToken() immutability, resource factory methods
  (characters/alliance/universe), typed DTO assertion on character endpoint,
  paginated asset endpoint with page count, cached-load propagation via HIT header
- Helper makeAuthedClient() mocks CheckAccess::can() to avoid JWT decode
  on authenticated endpoints in unit tests

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat: rewrite generator for OpenAPI 3.1 YAML spec

- bin/generate.php now fetches from esi.evetech.net/meta/openapi.yaml
- Uses symfony/yaml for parsing (avoid native yaml_parse dependency)
- DTO class names now match schema names directly (e.g. CharactersDetail)
- Flat namespace: Responses/{SchemaName}.php (no tag subdirs)
- Typed method params: CharacterID x-common-model resolves to int
- Fixed: nullable mixed becomes mixed (PHP 8.4+ compliance)
- Fixed: array_map with cast for array<primitive> return types
- Added resources for 3 new tag groups: CorporationProjects, FreelanceJobs, Meta
- EsiClient: added corporationProjects(), freelanceJobs(), meta() methods
- Updated tests to use new DTO class names

PHPStan: 0 errors. All 87 tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: remove stale Clones/ subdirectory leftover from Swagger 2.0 generator

The Clones/ subdirectory was missed in the cleanup when switching to
the OAS3 flat-namespace generator. The replacement file
CharactersCharacterIdClonesGet.php already exists at the correct path.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(generator): defensive ?? fallbacks in from() for all required fields

CCP has been observed changing ESI response fields without bumping the
compatibility date (e.g. active_skill_level on 2026-02-27). Previously,
required fields in from() did $data->field directly — a TypeError if
ESI silently drops the field.

Now all required primitive fields use a type-safe cast + zero fallback:
  (int)($data->field ?? 0)
  (string)($data->field ?? '')
  (bool)($data->field ?? false)
  (float)($data->field ?? 0.0)
  (array)($data->field ?? [])

Required object (DTO) fields fall back to an empty stdClass so ::from()
still runs rather than crashing on property access.

Optional fields already used ?? and are unchanged.

PHPStan: 0 errors. All 87 tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat: integrate seatplus/esi-schema, return DTOs directly from object endpoints

- Require seatplus/esi-schema:1.x-dev (VCS from github.com/seatplus/esi-schema)
- Delete src/Generated/Responses/ — all DTOs now come from seatplus/esi-schema
- Generator: no longer generates DTO files, only Resources
- Generator: all DTO imports changed to Seatplus\EsiSchema\Responses\*
- Object endpoints (single-object responses) now return the DTO directly
  instead of wrapping in EsiResult<T>. The DTO extends AbstractEsiDto
  so $dto->isCachedLoad and $dto->pages are available on the result.
- Paginated array endpoints keep EsiResult<array<T>> (pages metadata required)
- Update tests to reflect new return types
- Update README: compatibility date notice + new SDK usage examples
- ESI compatibility date: 2025-12-16 and forward

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: delete obsolete tools/ folder, bump Rector target to PHP_85

- Remove tools/swagger_download.php, tools/get_endpoints_and_scopes.php,
  tools/esi.json — all artefacts of the old Swagger 2.0 workflow; the
  generator now fetches OAS3 YAML directly from ESI
- rector.php: PHP_83 → PHP_85 (SetList::PHP_85 confirmed present)
- rector.php: replace tools path with bin (tools deleted, bin has generator)
- Rector dry-run: 0 changes — codebase already fully PHP 8.5 compatible

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat: implement EsiTransportInterface, delete Generated/Resources

- EsiClient now implements Seatplus\EsiSchema\Contracts\EsiTransportInterface
- invoke() returns EsiRawResponse (wrapping GuzzleFetcher EsiResponse)
  converting: data, isCachedLoad(), pages → EsiRawResponse properties
- All resource factory methods updated to return Seatplus\EsiSchema\Resources\*
- Deleted src/Generated/Resources/ (34 files) — now live in esi-schema
- Deleted bin/generate.php — single generator now in esi-schema
- Updated composer.json: esi-schema dev-fix/ci-phpunit-config (pending PR merge)
- Updated tests: EsiClientTest expects EsiRawResponse from invoke()
- Updated tests: GeneratedResourcesTest uses esi-schema Resources + EsiResult
- All 89 tests pass, PHPStan clean, 100% type coverage

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: remove $version from invoke() — always uses 'latest'

Aligned with EsiTransportInterface change: version parameter removed
since compatibility_date header handles versioning now. buildDataUri()
hardcodes 'latest' in the URL path.

Updated EsiClientTest to reflect /latest/ in expected URI.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* refactor: remove dead EsiClient\EsiResult

Resources now use Seatplus\EsiSchema\EsiResult::fromRaw() — the
EsiClient\EsiResult (which used fromResponse(EsiResponse)) is no
longer referenced by anything. Removing it eliminates the confusion
of two nearly-identical EsiResult classes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat: populate cursor and rate-limit fields in EsiRawResponse from invoke()

- Lower PHP requirement to ^8.3 (no PHP 8.5 features used yet)
- EsiClient::invoke() now propagates rateLimitRemaining, rateLimitUsed,
  retryAfter from EsiResponse headers into EsiRawResponse
- Detects cursor token in response body and populates EsiRawResponse::cursor
  (for x-pagination: cursor routes like freelance-jobs, projects)
- 3 new tests covering rate-limit propagation and cursor extraction

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: bump PHP requirement to ^8.5, Carbon to ^3.0

PHP 8.5 released and available. No code changes required — the package
already uses PHP 8.3+ features only (typed class constants).

- composer.json: PHP ^8.3 → ^8.5
- composer.json: nesbot/carbon ^2.53 → ^3.0 (required for Laravel 13 compat)
- tests/Unit/EsiClientTest.php: pint binary_operator_spaces fix

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: use seatplus/esi-schema ^1.0 stable release from Packagist

- Switch from dev-feat/typed-operation-meta branch alias to stable ^1.0
- Remove VCS repository override (package is on Packagist)
- Remove minimum-stability: dev and prefer-stable (no longer needed)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* test: add coverage for all EsiClient factory methods; remove dead code in EsiResponse

- Add data-provider test covering all 30 remaining factory methods on
  EsiClient (calendar, clones, contacts, … meta) to reach 100% line coverage
- Remove unreachable $window === null guard in parseRatelimitWindowSeconds():
  the str_contains() check above guarantees explode() always yields index [1],
  making the null branch dead code and untestable

Fixes CI code-coverage failure (was 90.5 %, now 100.0 %)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: lower PHP requirement from ^8.5 to ^8.2

The source only uses PHP 8.1 features (readonly properties,
new-in-initializers). All runtime deps (Carbon ^3.0, monolog ^3.7,
guzzle-cache-middleware ^4.0) support PHP 8.1+. PHP 8.1 is EOL, so

- require.php: ^8.5 → ^8.2
- remove unused symfony/yaml dev dependency (leftover from esi-schema
  codegen work; never referenced in esi-client source or tests)
- ci: php-version 8.5 → 8.2 in both tests.yml and formats.yml

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: remove hardcoded version from composer.json

Packagist derives the version from git tags. A hardcoded "version"
field overrides tag detection and would pin the package permanently
at 4.0.0 regardless of future tags.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: raise PHP requirement to ^8.3

pestphp/pest ^4.0 and seatplus/esi-schema 1.0.0 both require php ^8.3,
making 8.2 uninstallable. ^8.3 is the correct minimum — still well below
the previous ^8.5.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* refactor: replace CheckAccess with assertScope() — delete 250-line hardcoded scope map (#25)

* refactor: replace CheckAccess with assertScope() from EsiTransportInterface

Scope enforcement now lives where scope is defined. Each generated execute()
calls $transport->assertScope(self::REQUIRED_SCOPE) before any HTTP call.
The transport (EsiClient) implements the check against the JWT token.

Changes:
- EsiClient: implement assertScope(?string $scope): void
  - null = public endpoint → no-op
  - non-null = must be present in JWT scopes → ScopeAccessDeniedException
- EsiClient: remove CheckAccess wiring from constructor and withToken()
- EsiClient: remove hasAccess() pre-flight from invoke()
- EsiScopeAccessDeniedException: now extends ScopeAccessDeniedException
  from esi-schema for backward compatibility
- Delete CheckAccess.php (250-line hardcoded scope map — no longer needed)
- Delete CheckAccessTest.php (replaced by assertScope tests in EsiClientTest)
- Bump seatplus/esi-schema: ^1.1 (requires assertScope in EsiTransportInterface)
- Update GeneratedResourcesTest: use real JWT tokens, remove CheckAccess mock
- Update EsiClientTest: replace access-denied test with assertScope tests

Requires seatplus/esi-schema ^1.1 (PR #4).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: use dev-feat/assert-scope alias until esi-schema 1.1.0 is tagged

Until esi-schema PR #4 is merged and 1.1.0 tagged on Packagist,
use the branch dev alias so CI can resolve the dependency.

Will be reverted to ^1.1 once tag exists.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: trigger CI — add assertScope docblock, watch composer.json in formats workflow

- Add docblock to EsiClient::assertScope() explaining null semantics
- Update formats.yml to also trigger on composer.json changes and
  pull_request targeting feat/esi-rate-limit-overhaul

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: remove minimum-stability=dev — explicit dev-branch constraint is sufficient

Explicit dev-* constraints override minimum-stability per-package, so
setting minimum-stability=dev globally was unnecessary and caused
pest-plugin-type-coverage to resolve a dev build instead of stable.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: use stable seatplus/esi-schema ^1.1 (1.1.0 now tagged on Packagist)

Replaces the temporary dev-feat/assert-scope alias now that esi-schema
PR #4 has been merged and tagged 1.1.0.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: remove feature branch name from formats.yml pull_request trigger

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: drop EsiScopeAccessDeniedException — use ScopeAccessDeniedException from esi-schema directly

No backwards compatibility needed. Callers should catch
Seatplus\EsiSchema\Contracts\ScopeAccessDeniedException.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: remove /latest/ URL prefix — use server+path per ESI OpenAPI 3.1 spec

The ESI OpenAPI 3.1 spec (esi.evetech.net/meta/openapi.yaml) defines:
  servers: [url: https://esi.evetech.net]
  paths:  /alliances, /characters/{character_id}/assets, …

No version prefix anywhere. Versioning is handled by X-Compatibility-Date
header (already sent by GuzzleFetcher). The /latest/ prefix was a Swagger 2.0
basePath artifact.

Changes:
- buildDataUri(): /{path}/ instead of /latest/{path}/
- EsiConfiguration: default compatibility_date to '2025-12-16'
  (matches esi-schema generation date; update when regenerating)
- Update tests accordingly

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* style: apply Spatie coding guidelines across all source files

- Strings: replace sprintf() and . concatenation with string interpolation
  throughout EsiRateLimitedException, EsiErrorLimitedException, EsiClient,
  GuzzleFetcher, UpdateRefreshTokenService, EsiResponse, RotatingFileLogger
- Fix latent bug: logFetcherActivity used %F with number_format result,
  double-formatting the float (0.12 → 0.120000); interpolation uses the
  number_format string directly
- Docblocks: remove duplicate docblock on EsiClient::assertScope(); remove
  useless 'FileLogger constructor.' description from RotatingFileLogger
- Comments: remove inline comments that restate the code they precede
- Naming: rename private snake_case members in EsiResponse to camelCase
  (get_data→getData, error_message→errorMessage, expires_at→expiresAt,
  cache_loaded→cacheLoaded)
- Constructor: expand UpdateRefreshTokenService single-line constructor to
  multi-line promoted-parameter style (one param per line, trailing comma)

All 113 tests pass, Pint clean.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: herpaderpaldent <herpaderpaldent@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

3.1.0

Toggle 3.1.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
fix: upgrade firebase/php-jwt to ^7.0 (v6 also vulnerable) (#21)

* fix: upgrade firebase/php-jwt to ^7.0

v6.x is also affected by PKSA-y2cr-5h3j-g3ys, so bump to ^7.0 which
is unaffected. v7 enforces minimum key lengths (HS256: 32 bytes,
RSA: 2048 bits) — update tests accordingly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* style: apply pint fixes for updated ruleset

New pint version enforces fully_qualified_strict_types,
ordered_imports, and other rules across existing files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: add logs, .phpunit.cache to .gitignore

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: pin phpstan <1.12.28 to fix pest-plugin-type-coverage incompatibility

phpstan 1.12.28+ changed RuleErrorTransformer::transform() signature
breaking pest-plugin-type-coverage v3.x. Pin to <1.12.28 until the
plugin is upgraded to v4 (which requires pest v4).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: upgrade pest to v4 to resolve phpstan incompatibility

pest-plugin-type-coverage v3.x was incompatible with phpstan 1.12.28+
due to a changed RuleErrorTransformer::transform() signature.
Upgrading to pest v4 + pest-plugin-type-coverage v4 resolves this
properly without needing a phpstan version pin.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ci: add pull_request trigger and composer.json path to formats workflow

Also update actions/checkout to v4.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: pin phpstan <1.12.28 (pest-plugin-type-coverage v4 still broken)

pest-plugin-type-coverage v4 calls PHPStan\RuleErrorTransformer::transform()
with an array for arg #3, but phpstan 1.12.28+ changed that parameter
to strictly require string. Both v3 and v4 of the plugin are affected.
This is an upstream bug — track: https://github.com/pestphp/pest-plugin-type-coverage

Pin until a fixed release of pest-plugin-type-coverage ships.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: upgrade to PHPUnit 12 / PHPStan 2 / Rector 2 for Pest 4 compatibility

- Bump phpstan/phpstan ^1.12 → ^2.1.46 to match pest-plugin-type-coverage
  v4 API (RuleErrorTransformer::transform signature changed in PHPStan 2)
- Bump rector/rector ^1.2 → ^2.0 (rector 1.x requires PHPStan 1.x)
- Update phpunit.xml.dist schema to PHPUnit 12.5 (<coverage> element was
  removed from the schema; keeping it caused a validation WARN that with
  failOnWarning=true became a fatal test failure)
- Move coverage report flags to test:unit-coverage CLI script
- Set failOnWarning=false (schema warnings from missing optional drivers
  should not be fatal)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* ci: remove pull_request trigger and composer.json path from formats workflow

* ci: add pull_request trigger for 3.x branch in formats workflow

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

3.0.0

Toggle 3.0.0's commit message
Update code climate badges for maintainability and test coverage.

2.0.0

Toggle 2.0.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
Fix/badges (#18)

* update batches

* update workflow for branch renaming

* improve coverage

1.0.1

Toggle 1.0.1's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
fix/getScopes (#17)

* ensure that returned scopes are always array

* Fix styling

Co-authored-by: herpaderpaldent <herpaderpaldent@users.noreply.github.com>

1.0.0

Toggle 1.0.0's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
Merge pull request #15 from seatplus/develop

update kevinrob/guzzle-cache-middleware

0.10.1

Toggle 0.10.1's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
Merge pull request #14 from seatplus/develop

Throw Error On UpdateRequests and Workflow Rename