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
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ If a package does not have CLAUDE.md:

- follow root rules only
- do NOT invent architecture
- ask instead of guessing

## Development principles

Expand Down
30 changes: 27 additions & 3 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,23 +65,36 @@ Delivered:

### 0.9.x — Platform readiness & API stabilization

Focus: stabilizing core APIs, improving extensibility, and preparing dfsync for production-scale usage and future SaaS integration.
Focus: stabilizing core APIs, improving extensibility, and preparing `@dfsync/client` for production-scale usage and future SaaS integration.

Planned features:

- stable validation API (finalized `responseSchema` contract)
- validation must run after response parsing
- validation must not affect retry logic
- validation adapters must follow a consistent interface
- validation adapters (starting with `zod`)
- serializer / parser extensibility (custom request/response handling)
- adapters must be lightweight wrappers
- must not introduce runtime dependencies into core
- must not change validation execution flow
- serializer / parser extensibility
- must integrate into existing request/response pipeline
- must not bypass error handling or validation stages
- must preserve default JSON behavior when not configured
- improved retry model:
- retry budget (`maxElapsedMs`)
- jitter support
- advanced retry conditions
- must remain backward compatible with existing retry behavior
- must preserve Retry-After handling
- finalized error model:
- `HttpError`
- `NetworkError`
- `TimeoutError`
- `AbortError`
- `ValidationError`
- must preserve backward compatibility
- must not change existing error inheritance unexpectedly
- extended error metadata:
- `requestId`
- `attempt`
Expand All @@ -92,9 +105,20 @@ Planned features:
- auth provider interface
- validation adapter interface
- retry policy interface
- operation naming support (`operationName` for requests)
- must be minimal and explicit
- must not expose internal implementation details
- must be version-stable
- operation naming support (`operationName`)
- must be part of request context
- must be available in hooks and telemetry
- documentation restructuring (use-case oriented)

Constraints:

- no breaking changes in public API within 0.9.x
- avoid over-engineering in extensibility APIs
- new features must not introduce significant runtime overhead

### 1.0.x — Stable core & production readiness

Focus: delivering a stable, well-documented, and production-ready API with long-term support guarantees.
Expand Down
96 changes: 75 additions & 21 deletions packages/client/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,42 @@

This package provides a reliable HTTP client for service-to-service communication.

It is designed for backend services, microservices, workers, and integration services that need predictable HTTP communication.

## Scope

- Node.js / TypeScript HTTP client
- Focus on predictable request lifecycle
- Used in microservices and integrations
- Service-to-service communication
- Predictable request lifecycle
- Consistent error handling
- Retry behavior with observability metadata
- Optional response validation
- Idempotency support for safer integrations

This package is NOT a browser-first data fetching library and should not introduce UI or frontend state-management concerns.

## Architecture

Core flow:

1. createExecutionContext
2. applyRequestMetadata (headers, requestId)
3. fetch
2. applyRequestMetadata
- headers
- requestId / correlation metadata
- idempotency metadata when configured
3. execute fetch
4. parseResponse
5. error handling (HttpError / NetworkError / etc.)
6. response validation (if configured)
7. hooks execution
5. classify result
- successful HTTP response
- retryable HTTP response
- non-retryable HTTP error
- network error
6. run retry logic when applicable
7. run response validation (if configured) only for successful responses
8. run lifecycle hooks
9. return parsed response or throw a `DfsyncError` (or one of its subclasses)

Do not refactor the request pipeline unless the task explicitly requires it.

## Key principles

Expand All @@ -27,37 +46,66 @@ Core flow:
- All internal errors must extend `DfsyncError`
- NEVER wrap `DfsyncError` into `NetworkError`
- Preserve original error types
- Preserve useful error metadata
- Do not hide the original cause when available
- Do not introduce generic `Error` when a specific `DfsyncError` subclass already exists

### Validation

- Runs only after successful HTTP responses
- Throws `ValidationError`
- MUST NOT trigger retries
- Validation runs only after successful HTTP responses
- Validation must run after response parsing
- Validation errors throw `ValidationError`
- Validation errors MUST NOT trigger retries
- Validation errors are contract errors, not transport errors
- Do not treat validation failures as `NetworkError` or retryable HTTP errors

### Retry

- Applies only to:
- Retry applies only to:
- network errors
- 5xx responses
- 429 responses
- Must remain predictable
- Retry must remain predictable
- Preserve existing retry metadata
- Preserve existing Retry-After behavior
- Do not add custom retry loops outside the existing retry flow
- Do not retry validation errors
- Do not retry non-idempotent requests unless explicitly supported by the configured behavior

### Idempotency

- Idempotency is part of integration safety
- Idempotency keys must not overwrite user-provided headers unexpectedly
- Idempotency behavior must be explicit and predictable
- Idempotency should support safe retries without changing existing retry semantics
- Do not generate idempotency keys for every request unless the feature explicitly requires it

### Hooks

- Do NOT change existing hook signatures
- New fields must be optional
- New hook fields must be optional
- Preserve backward compatibility
- Hooks should receive metadata, not mutate core control flow unexpectedly
- Prefer extending hook context over introducing new hook types

### Tests

- Use Vitest
- Integration tests for request lifecycle
- Unit tests for isolated logic
- Use `getFirstMockCall` from testUtils
- Use helpers from testUtils if they can help, especially `getFirstMockCall`
- Add regression tests for error classification
- Add tests for retry vs validation behavior
- Add tests for idempotency headers when relevant

## Code style

- Follow existing structure in src/core
- Follow existing structure in `src/core`
- Do NOT introduce new layers
- Prefer extending existing flow
- Keep implementation small and explicit
- Avoid clever abstractions
- Avoid broad refactors in feature PRs

## Important

Expand All @@ -66,18 +114,24 @@ Do NOT:
- refactor request pipeline
- change retry behavior unless task explicitly requires it
- introduce new abstractions
- change public API casually
- change hook signatures
- wrap `DfsyncError` (or its subclasses) into generic `Error`
- use generic `Error` when a specific `DfsyncError` subclass should be used
- make validation retryable
- silently overwrite user headers

## When implementing features

- Keep PRs small and focused
- One concern per PR
- Preserve backward compatibility
- Add tests before or together with behavior changes
- Update README/examples when public behavior changes
- Update the root `examples/node-basic` when it becomes outdated or when new public functionality is added

## Current focus

Release: 0.8.x — Integration safety

Areas:
Release: 0.9.x — Platform readiness & API stabilization

- response validation
- idempotency
- safe retries
Always check the root `ROADMAP.md` before making release-related changes.
Loading