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
30 changes: 27 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,16 @@ Keep the architecture centered on a small set of clear responsibilities:
- `Setup`: the explicit SDK-user setup and hackability surface exposed through
`Api::setup()`.
- `Runtime`: the internal configured runtime used by resources for configuration
access and request execution.
access, request identity, and request execution.
- `Resource`: an immutable endpoint group and the primary SDK-author workflow.
- `Endpoint`: an immutable builder for request-local query, header, and body
options.
- `RequestOptions`: the request-local query, header, and body state carried by an
endpoint.
- `Context`: the effective SDK config and response-graph capabilities passed
through response mapping and hydration.
- `Resolver`: the explicit, response-graph-scoped API for following linked
resources and pagination while reusing the originating runtime.
- `Response`: the decoded/raw response wrapper and mapping surface.
- `Entity`: the optional contract for typed response data objects.

Expand Down Expand Up @@ -94,8 +98,20 @@ cache, hooks, decoding, and error handling.
options merge, before serialization.
- Authentication strategies must be explicit. Multiple strategies compose
through `auth()->chain(...)` rather than relying on implicit precedence.
- Keep entities as response data/value objects by default. Do not introduce
hidden network calls, lazy loading, or transparent proxy behavior.
- Keep entities as response data/value objects by default. SDK authors may add
purpose-built relationship or pagination methods that explicitly defer a
request through the context resolver. Do not introduce transparent proxy
behavior, automatic property loading, or network calls from ordinary value
accessors.
- Resolver requests must reuse the originating runtime pipeline, including
current setup, config overrides, authentication, plugins, API-level cache,
hooks, decoding, and error handling. Request-local endpoint modifiers are not
inherited by followed links.
- Resolver memoization is scoped to one response graph. Memoize SDK responses by
request identity rather than sharing mapped entities or leaking state across
independent top-level requests.
- Treat query parameters already present in API-provided links as authoritative.
Apply missing API defaults without replacing or reparsing link queries.
- Keep API-specific vocabulary in concrete SDK packages. Concepts such as
includes, selects, filters, and pagination should build on generic resource
primitives rather than enter the base package without broad applicability.
Expand Down Expand Up @@ -128,6 +144,7 @@ Maintain support for the package's core capabilities:
- Query and header defaults.
- Base URL and path construction.
- Response decoding and transformation.
- Explicit linked-response resolution and response-graph memoization.
- Error handling.
- Test utilities for SDK authors where they provide clear value.

Expand All @@ -154,6 +171,8 @@ Documentation should explain:
- How to create and configure a simple SDK.
- How to author resources and request options.
- How to map responses to entities, collections, and envelopes.
- How entities and envelopes can explicitly resolve linked resources and
pagination through their hydration context.
- How to configure authentication, clients, factories, cache, logging, plugins,
hooks, and errors.
- How to create API-specific fluent helpers on top of generic primitives.
Expand Down Expand Up @@ -186,6 +205,11 @@ For scoped or pipeline behavior, verify isolation and propagation explicitly:
- Hooks, errors, responses, and hydration observe the same effective context.
- Cache behavior does not leak request-local state.
- Independent fluent modifiers compose correctly.
- Resolver requests use the same effective runtime pipeline as their originating
response.
- Resolver memoization is isolated by response graph and avoids duplicate
requests without sharing mapped objects.
- Linked URL query precedence and request identity match documented behavior.

## Downstream Validation

Expand Down
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,13 @@ SDK packages may still require or suggest concrete PSR-18 and PSR-17 implementat
- [Resource Authoring](docs/04-resource-authoring.md): deeper guide for resource methods, query/header options, request bodies, entity mapping, collections, envelopes, and API-specific resource chains.
- [Resources](docs/05-resources.md): resource classes and endpoint request helpers.
- [Responses](docs/06-responses.md): decoded data, raw responses, entities, collections, envelopes, and context.
- [Authentication](docs/07-authentication.md): configure bearer, basic, header, query, HTTPlug, and custom authentication.
- [HTTP Client](docs/08-http-client.md): configure PSR-18 clients and PSR-17 factories.
- [Cache](docs/09-cache.md): configure PSR-6 HTTP response caching.
- [Logging](docs/10-logging.md): configure PSR-3 logging and HTTP/cache log output.
- [Plugins](docs/11-plugins.md): configure HTTPlug middleware and priority ordering.
- [Hooks](docs/12-hooks.md): run SDK-author callbacks around requests and responses.
- [Resolver](docs/07-resolver.md): follow linked entities, collections, and pagination through the configured SDK runtime.
- [Authentication](docs/08-authentication.md): configure bearer, basic, header, query, HTTPlug, and custom authentication.
- [HTTP Client](docs/09-http-client.md): configure PSR-18 clients and PSR-17 factories.
- [Cache](docs/10-cache.md): configure PSR-6 HTTP response caching.
- [Logging](docs/11-logging.md): configure PSR-3 logging and HTTP/cache log output.
- [Plugins](docs/12-plugins.md): configure HTTPlug middleware and priority ordering.
- [Hooks](docs/13-hooks.md): run SDK-author callbacks around requests and responses.

## Upgrading

Expand Down
8 changes: 4 additions & 4 deletions UPGRADE-3.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ $this->auth()->bearer($token);

Use `chain()` only when an API requires multiple authentication rules on the same request.

See [Authentication](docs/07-authentication.md), [HTTP Client](docs/08-http-client.md), [Cache](docs/09-cache.md), [Logging](docs/10-logging.md), [Plugins](docs/11-plugins.md), and [Hooks](docs/12-hooks.md) for details.
See [Authentication](docs/08-authentication.md), [HTTP Client](docs/09-http-client.md), [Cache](docs/10-cache.md), [Logging](docs/11-logging.md), [Plugins](docs/12-plugins.md), and [Hooks](docs/13-hooks.md) for details.

## Defaults And Endpoint Overrides

Expand All @@ -121,7 +121,7 @@ use ProgrammatorDev\Api\Builder\CacheBuilder;

return $this
->endpoint()
->cache(fn (CacheBuilder $cache) => $cache->defaultTtl(60))
->withCache(fn (CacheBuilder $cache) => $cache->defaultTtl(60))
->get('/live')
->collection(Event::class, key: 'data');
```
Expand All @@ -143,7 +143,7 @@ API cache config < endpoint cache defaults < resource withCache override

The base package provides the generic override mechanism. API-specific fluent helpers, such as `withIncludes()` or `withStatus()`, should live in the concrete SDK.

See [Resource Authoring: API-Specific Resource Chains](docs/04-resource-authoring.md#api-specific-resource-chains), [Resources: Resource Cache Overrides](docs/05-resources.md#resource-cache-overrides), [Cache: Endpoint Defaults](docs/09-cache.md#endpoint-defaults), and [Cache: Resource Overrides](docs/09-cache.md#resource-overrides) for details.
See [Resource Authoring: API-Specific Resource Chains](docs/04-resource-authoring.md#api-specific-resource-chains), [Resources: Resource Cache Overrides](docs/05-resources.md#resource-cache-overrides), [Cache: Endpoint Defaults](docs/10-cache.md#endpoint-defaults), and [Cache: Resource Overrides](docs/10-cache.md#resource-overrides) for details.

## Setup Is The Escape Hatch

Expand Down Expand Up @@ -177,7 +177,7 @@ The package uses PHP-HTTP discovery for PSR-18 clients and PSR-17 factories. Whe

SDK authors may still require or suggest concrete implementations when they want control over the default HTTP stack.

See [HTTP Client: SDK Author Defaults](docs/08-http-client.md#sdk-author-defaults) and [HTTP Client: SDK User Overrides](docs/08-http-client.md#sdk-user-overrides) for details.
See [HTTP Client: SDK Author Defaults](docs/09-http-client.md#sdk-author-defaults) and [HTTP Client: SDK User Overrides](docs/09-http-client.md#sdk-user-overrides) for details.

## API-Specific Behavior Belongs In SDKs

Expand Down
13 changes: 7 additions & 6 deletions docs/00-index.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,13 @@ SDK packages may still require or suggest concrete PSR-18 and PSR-17 implementat
- [Resource Authoring](04-resource-authoring.md): deeper guide for resource methods, query/header options, request bodies, entity mapping, collections, envelopes, and API-specific resource chains.
- [Resources](05-resources.md): resource classes and endpoint request helpers.
- [Responses](06-responses.md): decoded data, raw responses, entities, collections, envelopes, and context.
- [Authentication](07-authentication.md): configure bearer, basic, header, query, HTTPlug, and custom authentication.
- [HTTP Client](08-http-client.md): configure PSR-18 clients and PSR-17 factories.
- [Cache](09-cache.md): configure PSR-6 HTTP response caching.
- [Logging](10-logging.md): configure PSR-3 logging and HTTP/cache log output.
- [Plugins](11-plugins.md): configure HTTPlug middleware and priority ordering.
- [Hooks](12-hooks.md): run SDK-author callbacks around requests and responses.
- [Resolver](07-resolver.md): follow linked entities, collections, and pagination through the configured SDK runtime.
- [Authentication](08-authentication.md): configure bearer, basic, header, query, HTTPlug, and custom authentication.
- [HTTP Client](09-http-client.md): configure PSR-18 clients and PSR-17 factories.
- [Cache](10-cache.md): configure PSR-6 HTTP response caching.
- [Logging](11-logging.md): configure PSR-3 logging and HTTP/cache log output.
- [Plugins](12-plugins.md): configure HTTPlug middleware and priority ordering.
- [Hooks](13-hooks.md): run SDK-author callbacks around requests and responses.

## Upgrading

Expand Down
12 changes: 6 additions & 6 deletions docs/03-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ Authentication is applied automatically to outgoing requests.

Calling another auth helper replaces the previous authentication. Use `chain()` when multiple authentication rules are required.

See [Authentication](07-authentication.md) for helper methods, HTTPlug authentication objects, and custom auth callbacks.
See [Authentication](08-authentication.md) for helper methods, HTTPlug authentication objects, and custom auth callbacks.

### `hooks()`

Expand All @@ -225,7 +225,7 @@ $this->hooks()->afterResponse($hook);

Hooks are SDK-author extension points. They run around the raw HTTP request and response, before response decoding and error handling.

See [Hooks](12-hooks.md) for hook context objects, return values, and priority behavior.
See [Hooks](13-hooks.md) for hook context objects, return values, and priority behavior.

### `plugins()`

Expand All @@ -241,7 +241,7 @@ $this->plugins()->add($plugin, priority: 16);

Higher priority plugins run earlier. Same-priority plugins are preserved in insertion order.

See [Plugins](11-plugins.md) for internal plugin order and priority guidance.
See [Plugins](12-plugins.md) for internal plugin order and priority guidance.

### `cache()`

Expand All @@ -258,7 +258,7 @@ $this
->methods(['GET', 'HEAD']);
```

See [Cache](09-cache.md) for cache options and plugin order.
See [Cache](10-cache.md) for cache options and plugin order.

### `client()`

Expand All @@ -281,7 +281,7 @@ $this
->streamFactory($streamFactory);
```

See [HTTP Client](08-http-client.md) for client and factory configuration.
See [HTTP Client](09-http-client.md) for client and factory configuration.

### `logger()`

Expand All @@ -297,7 +297,7 @@ $this
->formatter($formatter);
```

See [Logging](10-logging.md) for logger formatting and cache logging.
See [Logging](11-logging.md) for logger formatting and cache logging.

## Response Handling

Expand Down
4 changes: 4 additions & 0 deletions docs/04-resource-authoring.md
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,10 @@ final class UserEnvelope implements EnvelopeInterface

Keep context usage focused on hydration decisions. Entities should still be data/value objects by default and should not perform hidden network calls.

When an API exposes relationships or pagination as links, an SDK author can opt
into explicit request-backed methods through the context resolver. See
[Resolver](07-resolver.md).

## Resource-Local Configuration

> **Available since version 3.1.0.**
Expand Down
6 changes: 4 additions & 2 deletions docs/05-resources.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,13 +238,15 @@ SDK authors can configure endpoint-specific cache defaults on the endpoint build
```php
return $this
->endpoint()
->cache(fn (CacheBuilder $cache) => $cache->defaultTtl(60))
->withCache(fn (CacheBuilder $cache) => $cache->defaultTtl(60))
->get('/users')
->collection(User::class, key: 'data');
```

Endpoint cache defaults are immutable and apply only to that request. They require API-level cache configuration because the global cache setup provides the PSR-6 pool.

`Endpoint::cache()` is deprecated since version 3.2.0. Use `Endpoint::withCache()` instead.

## Resource Cache Overrides

`withCache()` lets SDK users override cache behavior for one resource chain while keeping query, headers, body, and verbs inside `Endpoint`.
Expand All @@ -258,7 +260,7 @@ $users = $api

This override is immutable and applies only to the chained resource instance. It requires API-level cache configuration because the global cache setup provides the PSR-6 pool.

See [Cache](09-cache.md) for endpoint cache defaults, merge order, and the API-level cache requirement.
See [Cache](10-cache.md) for endpoint cache defaults, merge order, and the API-level cache requirement.

## Navigation

Expand Down
17 changes: 15 additions & 2 deletions docs/06-responses.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public static function fromResponse(Response $response, ?Context $context = null

## `Context`

`Context` carries SDK config into response mapping.
`Context` carries SDK config and response resolution into response mapping.

SDK users do not fetch context from `Response`. The package passes context into entity and envelope hydration methods:

Expand All @@ -133,6 +133,19 @@ this returns the effective API configuration plus its resource-local overrides.
The same effective configuration is available to hooks and error handlers for
that request. See [Resource-Local Configuration](04-resource-authoring.md#resource-local-configuration).

### `resolver()`

```php
resolver(): ResolverInterface
```

Returns the response-graph resolver provided by the API runtime. It can follow
linked entities, collections, and pagination through the configured SDK runtime.
Calling it outside an API runtime request throws `RuntimeException`.

See [Resolver](07-resolver.md) for linked-resource authoring, request behavior,
and memoization scope.

## `ErrorContext`

`ErrorContext` is passed to configured error handlers.
Expand Down Expand Up @@ -173,4 +186,4 @@ It exposes:
## Navigation

- Previous: [Resources](05-resources.md)
- Next: [Authentication](07-authentication.md)
- Next: [Resolver](07-resolver.md)
Loading