Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
78f945e
refactor: migrar constantes a backed enums de php 8.1 (Fase 1)
macarthuror Oct 11, 2026
1e01491
refactor: implementar lazy loading y eliminar require_once en entrypo…
macarthuror Oct 11, 2026
ba28944
refactor: implementar cliente HTTP global agnóstico con psr-18 (Fases…
macarthuror Oct 11, 2026
eb74684
refactor: aplicar composición y strict_types en recursos, eliminando …
macarthuror Oct 11, 2026
da1e69c
feat: implementar jerarquía granular de excepciones (Fase 5)
macarthuror Oct 11, 2026
0432e3b
build: instalar symfony/yaml para generador OpenAPI en Fase 6
macarthuror Oct 11, 2026
fb42d1f
feat(enums): generar enums inline desde OpenAPI preservando los exist…
macarthuror Oct 11, 2026
6a28586
feat(models): auto-generar DTOs con métodos fromArray/toArray desde O…
macarthuror Oct 11, 2026
2e1fd84
refactor(http): cambiar JSON parser para usar JSON_THROW_ON_ERROR y r…
macarthuror Oct 11, 2026
6ee92c6
refactor(resources): integrar DTOs generados en Customers y Products …
macarthuror Oct 11, 2026
65b0518
build(deps-dev): remover symfony/yaml tras completar la generación de…
macarthuror Oct 11, 2026
dbf169d
Fase 7: Refactorización y estabilización de la suite de pruebas (PHPU…
macarthuror Oct 11, 2026
e72a3e9
refactor: Migración a Pest y refactorización global de suite
macarthuror Oct 11, 2026
a0fc6f0
chore: update .gitignore to include temporary files and agent directo…
macarthuror Oct 11, 2026
b024acf
refactor: Implementa Mejores Prácticas de Pest (Expectation API y toT…
macarthuror Oct 11, 2026
d297aa7
feat(tests): añadir pruebas completas para Receipts y Retentions" -m …
macarthuror Oct 11, 2026
af5c4d5
feat(tests): añadir cobertura exhaustiva para Customers e Invoices
macarthuror Oct 11, 2026
1bfcf7b
feat(tests): implementar pruebas CRUD para Organizations y Webhooks
macarthuror Oct 11, 2026
a50fdc4
fix(catalogs): corregir parámetros de búsqueda y añadir check en Tools
macarthuror Oct 11, 2026
fbe2060
test(catalogs): añadir cobertura para endpoints de catálogos y herram…
macarthuror Oct 11, 2026
517fbd4
chore: añadir Makefile para ejecución simplificada de pruebas
macarthuror Oct 11, 2026
d976799
chore: actualizar dependencias y limpiar archivos de ejemplo
macarthuror Oct 11, 2026
8f13dd9
fix(gitignore): previeme mandar archivos temporales del lint
macarthuror Oct 11, 2026
633f413
fix(gitignore): previeme mandar archivos temporales del lint
macarthuror Oct 11, 2026
47a5fad
build: add strict linting configuration (PHPStan, Pint, Rector, Makef…
macarthuror Oct 11, 2026
0cb6b8f
fix(http): enforce strict array return types on HttpClient methods
macarthuror Oct 11, 2026
ea78f83
fix(enums): correct value type mismatch in PaymentInputTipoCadPagoEnum
macarthuror Oct 11, 2026
91539f9
style: apply PSR-12 and strict_types to all files via Laravel Pint
macarthuror Oct 11, 2026
85096c5
delete: archivos ya no necesarios
macarthuror Oct 11, 2026
865e6f8
feat(deploy): add standalone ZIP build step for deployment
macarthuror Oct 11, 2026
f12e0f1
fix: phpstan baseline
macarthuror Oct 11, 2026
5ad2a74
fix: update .gitignore to correct temporary files entry
macarthuror Oct 11, 2026
000d378
refactor(models): improve DTO type hinting and strict types
macarthuror Oct 11, 2026
abcccc2
refactor(resources): enforce strong typing for resource method parame…
macarthuror Oct 11, 2026
0824f21
test: migrate test assertions and mocks for strictly typed DTOs
macarthuror Oct 11, 2026
deb6911
chore: remove outdated PR notes
macarthuror Oct 11, 2026
59b2881
docs: update documentation and version for SDK release
macarthuror Oct 11, 2026
342ee94
build: update dependencies and static analysis tools
macarthuror Oct 11, 2026
70b70c9
refactor(core): update main client and exceptions for strict typing
macarthuror Oct 11, 2026
5ed04db
docs: add AI agent guidelines and framework-specific examples
macarthuror Oct 11, 2026
c63928d
refactor(models): expand DTO properties, casting, and ArrayAccess com…
macarthuror Oct 13, 2026
00e7369
refactor(resources): declare strong return types and DTO hydration ac…
macarthuror Oct 13, 2026
c72b95d
test(products): add comprehensive Pest tests for Products resource
macarthuror Oct 13, 2026
2d7b523
test(resources): update assertions and add tests for typed DTO respon…
macarthuror Oct 13, 2026
f4081f8
build(phpstan): tighten parameter phpDoc checks and document level 9 …
macarthuror Oct 13, 2026
9478cc8
docs(agents): update guidelines for API response handling and backwar…
macarthuror Oct 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
46 changes: 46 additions & 0 deletions .agents/skills/create-api-resource/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
name: create-api-resource
description: Generates a new API Resource (DTOs, Resource Class, Methods, and Pest tests) using the official Facturapi OpenAPI specification.
---

# Create API Resource Skill

Use this skill whenever you need to add a new API resource or endpoint to the Facturapi PHP SDK.

## 1. Single Source of Truth (OpenAPI Spec)

**CRITICAL RULE:** Do NOT search for a local `.yaml` file. The SDK does not ship with a downloaded OpenAPI spec to prevent it from becoming stale.

You MUST dynamically fetch the live OpenAPI specification using the following URL:
`https://docs.facturapi.io/redocusaurus/api-es.yaml`

Use your `read_url_content` or HTTP fetching tool to read the schema.

## 2. Generate the DTO (Data Transfer Object)

Once you understand the schema for the requested resource:
- Create a strictly typed DTO class inside `src/Models/`.
- The class must enforce `declare(strict_types=1);`.
- All properties should map to the JSON response fields exactly, but they must be strongly typed (e.g., `public string $id`, `public ?array $address`).
- Avoid using associative arrays for the return models. All new endpoints must return these strictly typed DTOs.

## 3. Generate the Resource Class

- Create a new Resource class in `src/Resources/` (e.g., `src/Resources/NewResource.php`).
- Extend `BaseResource` if applicable, or accept `FacturapiHttpClient` in the constructor.
- Add the necessary CRUD methods (`create`, `retrieve`, `all`, `delete`, etc.).
- Ensure all methods return the corresponding DTO or an array of DTOs, NEVER generic arrays.
- Handle nested structures carefully (e.g. `$response['data']` -> loop -> instantiate DTOs).

## 4. Register the Endpoint

- Open `src/Facturapi.php`.
- Add a new method (not a property!) to expose the new resource (e.g., `public function newResource(): NewResource`).
- Ensure the method utilizes lazy instantiation to avoid memory bloat.

## 5. Scaffold Tests

- Create a new Pest test file in `tests/` (e.g., `tests/NewResourceTest.php`).
- Use Pest v3's Expectation API (`expect()->toBe()`). Do NOT use PHPUnit assertions.
- Use the global helper `mockResponse(string $body, int $status = 200)` to mock the API responses instead of relying on a live network connection.
- Group the tests in a logical `describe('NewResource', function () { ... });` block.
42 changes: 36 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: CI
name: CI Strict Linter & Tests

on:
push:
Expand All @@ -7,18 +7,48 @@ on:
pull_request:
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
lint-and-analyze:
name: Lint & Static Analysis
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
coverage: none
tools: composer:v2

- name: Install dependencies
uses: ramsey/composer-install@v3

- name: Audit dependencies
run: composer audit

- name: Check Code Style (Pint)
run: composer format:test

- name: Static Analysis (PHPStan)
run: composer analyze

tests:
name: PHP ${{ matrix.php-version }}
needs: lint-and-analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php-version: ['8.2', '8.4']

php-version: ['8.2', '8.3', '8.4', '8.5']
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All @@ -31,7 +61,7 @@ jobs:
tools: composer:v2

- name: Install dependencies
run: composer install --no-interaction --prefer-dist
uses: ramsey/composer-install@v3

- name: Run test suite
run: ./vendor/bin/phpunit --configuration phpunit.xml
- name: Run test suite (Pest)
run: composer test
17 changes: 17 additions & 0 deletions .github/workflows/deploy-on-main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,22 @@ jobs:
git tag "$TAG"
git push origin "$TAG"

- name: Build Standalone ZIP
if: steps.version.outputs.should_deploy == 'true'
run: |
mkdir -p build-standalone
cp -r src build-standalone/
cp composer.json build-standalone/

cd build-standalone
composer require guzzlehttp/guzzle --no-interaction
composer install --no-dev --optimize-autoloader --no-interaction

echo "<?php require_once __DIR__ . '/vendor/autoload.php';" > autoload.php

zip -r ../facturapi-php-standalone.zip src vendor autoload.php
cd ..

- name: Create GitHub release
id: release
if: steps.version.outputs.should_deploy == 'true'
Expand All @@ -105,6 +121,7 @@ jobs:
tag_name: ${{ steps.version.outputs.tag }}
name: ${{ steps.version.outputs.tag }}
body_path: RELEASE_NOTES.md
files: facturapi-php-standalone.zip

- name: Notify Slack (success)
if: steps.version.outputs.should_deploy == 'true' && steps.release.outcome == 'success'
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,8 @@ composer.lock
/.idea/
.DS_Store
.phpunit.cache/

# temporary files
/tmp/
/tmps/
/build/
79 changes: 79 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Antigravity Agents Guidelines (AGENTS.md)

Welcome to the **Facturapi PHP SDK** project. This file provides critical context, coding standards, and instructions for AI agents working on this codebase.

## 1. Project Context & Domain Overview

- **Project**: `facturapi/facturapi-php`
- **Domain**: Official PHP SDK for [Facturapi](https://www.facturapi.io), a Mexican electronic invoicing (CFDI) API.
- **Architecture**: A standard SDK composition model. The main entry point is the `Facturapi\Facturapi` class, which acts as a factory that instantiates and exposes various API resources (e.g., Customers, Invoices, Products).

## 2. Tech Stack & Coding Standards

- **Language**: PHP >= 8.2
- **Autoloading**: PSR-4 (`Facturapi\` mapped to `src/`, `Facturapi\Tests\` mapped to `tests/`)
- **Strict Typing**: Use strict types always (`declare(strict_types=1);` at the top of every file). All properties, parameters, and returns must be strongly typed.
- **Style**: Follow PSR-12 standard conventions.
- **Dependencies**: Managed via Composer (`composer.json`). The SDK must remain completely framework-agnostic.
- **Static Analysis**: Enforced at **PHPStan Level 9** (`composer run analyze`). Code additions or refactors must pass with 0 errors without introducing artificial `ignoreErrors` in `phpstan.neon`.

## 3. Important SDK Concepts (Architecture)

- **HTTP Client**:
- The SDK relies on PSR-18 (HTTP Client) and PSR-17 (HTTP Factories).
- Internally, all requests are routed through `Facturapi\Http\FacturapiHttpClient`.
- The client is strictly **framework-agnostic** and uses `php-http/discovery` to automatically find available HTTP clients in the user's project (like Guzzle or Symfony HTTP). Do not tightly couple code to Guzzle.
- **Exceptions**:
- Errors from the API are intercepted and wrapped by the SDK into a **granular exception hierarchy**.
- All exceptions extend `Facturapi\Exceptions\FacturapiException`.
- Specific errors throw their respective child classes (e.g., `BadRequestException` for 400, `UnauthorizedException` for 401, `UnprocessableEntityException` for 422).
- **DTOs and Enums (Strictly Typed)**:
- **IMPORTANT**: The SDK v5 migration is COMPLETE. ALL API endpoints now return strictly typed Data Transfer Objects (DTOs) and Enums.
- Agents MUST NEVER write code assuming associative arrays for resource responses. Always use object property syntax (e.g., `$customer->legal_name`).
- **Backward Compatibility via `\ArrayAccess`**: Certain nested DTOs (e.g., `CommonAddressProperties`) intentionally implement `\ArrayAccess` to ensure seamless backward compatibility with legacy array-style access (e.g., `$customer->address['zip']`). Agents must preserve these interfaces and not remove them.
- **API Endpoints (Methods vs Properties)**:
- API interactions are handled through resource classes located in `src/Resources/`.
- Resource classes MUST be accessed via **methods** (e.g., `$facturapi->customers()`, `$facturapi->invoices()`).
- DO NOT use magic properties (e.g., `$facturapi->Customers`), as this syntax is deprecated and will trigger an undefined property error.
- **Statelessness (Long-Running Processes)**:
- The SDK is 100% compatible with long-running processes (FrankenPHP, RoadRunner, Swoole) and may be resolved as a Singleton in frameworks like Laravel Octane.
- Agents MUST NOT introduce request-specific state into the `Facturapi` or `FacturapiHttpClient` classes, as this will cause memory leaks or cross-tenant data bleed.

## 4. Testing Instructions (Pest v3)

- **Framework**: We strictly use **Pest v3** (`pestphp/pest`). PHPUnit is completely deprecated in this project.
- **Configuration & Setup**:
- The test suite uses `tests/TestCase.php` and `tests/Pest.php` to globally inject a `FakeHttpClient` and a `Facturapi` instance into every test via `setUp()`.
- Inside any test, the API is available as `test()->facturapi` (or `$this->facturapi`).
- **Mocking Responses**:
- Do NOT manually instantiate `FakeHttpClient`.
- Always use the global helper function `mockResponse(string $body, int $status = 200, array $headers = [])` at the beginning of the test.
- **Assertions (Expectation API)**:
- Do NOT use static PHPUnit assertions (like `self::assertSame` or `self::assertTrue`).
- You MUST use Pest's Expectation API: `expect($result)->toBe(...)`, `expect($array)->toBeArray()`, `expect($string)->toContain(...)`.
- **Exception Testing**:
- Do NOT use `try/catch` blocks or `self::fail()` to test exceptions.
- Use Pest's `toThrow` method passing a closure to validate internal exception data:
```php
expect(fn () => $invoices->cancel('inv_123'))
->toThrow(function (FacturapiException $exception) {
expect($exception->getStatusCode())->toBe(409);
});
```
- **Grouping**: Always group related endpoints inside logical `describe('ResourceName', function () { ... });` blocks.

## 5. Overview of `.agents` Skills

This project contains customized AI skills to automate repetitive tasks and enforce SDK architectural standards. When working on related tasks, agents should refer to these skills:

- **SDK Maintenance & Code Generation**: `create-api-resource`
_Use this skill whenever you need to add a new API endpoint, DTO, and Pest tests to the SDK. It explains how to scaffold the entire pipeline._

**CRITICAL - OpenAPI Single Source of Truth**:
The SDK does NOT store a local `.yaml` file. Whenever you need to read the Facturapi OpenAPI specification, you MUST fetch it directly from the live documentation site:
`https://docs.facturapi.io/redocusaurus/api-es.yaml`
Do not attempt to search for `tmp/api-es.yaml` or any local variant.

---

CO-CREATED BY INCREDE < @increde - @macarthuror>
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [5.0.0] - 2026-10-11

### Changed

- **BREAKING CHANGE**: All API resources now return strictly typed DTOs and Enums instead of generic associative arrays.
- **BREAKING CHANGE**: API resources are now accessed via methods (e.g. `$facturapi->customers()`) instead of magic properties (e.g. `$facturapi->Customers`).
- **BREAKING CHANGE**: Changed the internal HTTP client implementation (requires PSR-18 compatible client).
- **BREAKING CHANGE**: Required PHP version is strictly enforced to PHP >= 8.2.

## [4.8.0] 2026-09-04

### Added
Expand Down
30 changes: 30 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
.PHONY: install test test-coverage clean format analyze lint pre-commit

# Instala las dependencias del proyecto usando Composer
install:
composer install

# Corre todos los tests con Pest
test:
./vendor/bin/pest

# Corre todos los tests mostrando el reporte de cobertura (requiere PCOV o Xdebug habilitado)
test-coverage:
./vendor/bin/pest --coverage

# Elimina las dependencias instaladas (útil para limpiar el entorno)
clean:
rm -rf vendor composer.lock

# Comandos de linting y análisis
format:
composer format

analyze:
composer analyze

lint:
composer lint

# Corre las herramientas de formato, análisis y tests (ideal para antes de un commit)
pre-commit: format analyze test
Loading