Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
b8969bb
feat(client): improve error handling
stainless-app[bot] Aug 20, 2025
8a3649a
feat(client): add streaming
stainless-app[bot] Aug 20, 2025
f977b9a
feat(client): use named parameters in methods
stainless-app[bot] Aug 20, 2025
ac66540
chore: readme improvements
stainless-app[bot] Aug 21, 2025
d8b47a2
feat(php): rename internal types
stainless-app[bot] Aug 21, 2025
47e2824
fix(client): elide null named parameters
stainless-app[bot] Aug 21, 2025
150660a
chore: intuitively order union types
stainless-app[bot] Aug 21, 2025
ff49892
chore: remove type aliases
stainless-app[bot] Aug 23, 2025
b45934c
chore: improve model annotations
stainless-app[bot] Aug 24, 2025
d5736cf
feat(php): differentiate null and omit
stainless-app[bot] Aug 26, 2025
39bcd29
fix: streaming internals
stainless-app[bot] Aug 26, 2025
26437b5
feat(refactor)!: clean up pagination, errors, as well as request methods
stainless-app[bot] Aug 26, 2025
666f374
feat(refactor)!: namespacing cleanup
stainless-app[bot] Aug 26, 2025
b306fa4
chore(internal): refactored internal codepaths
stainless-app[bot] Aug 27, 2025
041e76c
fix: basic pagination should work
stainless-app[bot] Aug 27, 2025
2e13643
fix: minor bugs
stainless-app[bot] Aug 27, 2025
961e540
feat!: pagination field rename, and basic streaming docs
stainless-app[bot] Aug 27, 2025
16e7c95
feat: ensure `->toArray()` benefits from structural typing
stainless-app[bot] Aug 27, 2025
92d9817
feat!: rename errors to exceptions
stainless-app[bot] Aug 27, 2025
11358ea
fix: add create release workflow
stainless-app[bot] Aug 27, 2025
607f49a
chore: remove `php-http/multipart-stream-builder` as a required depen…
stainless-app[bot] Aug 28, 2025
86ba48b
fix: remove inaccurate `license` field in composer.json
stainless-app[bot] Aug 28, 2025
95b27e8
chore(refactor): simplify base page interface
stainless-app[bot] Aug 28, 2025
4403319
chore: add additional php doc tags
stainless-app[bot] Aug 29, 2025
f1b303a
chore: refactor request options
stainless-app[bot] Aug 30, 2025
f38ec08
chore: simplify model initialization
stainless-app[bot] Aug 30, 2025
7f3730e
feat!: use builders for RequestOptions
stainless-app[bot] Aug 30, 2025
36dc0b6
chore(internal): refactor base client internals
stainless-app[bot] Sep 3, 2025
dd7855a
release: 0.1.0
stainless-app[bot] Sep 3, 2025
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
19 changes: 19 additions & 0 deletions .github/workflows/release-doctor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Release Doctor
on:
pull_request:
branches:
- main
workflow_dispatch:

jobs:
release_doctor:
name: release doctor
runs-on: ubuntu-latest
if: github.repository == 'CASParser/cas-parser-php' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next')

steps:
- uses: actions/checkout@v4

- name: Check release environment
run: |
bash ./bin/check-release-environment
8 changes: 4 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
*.swo
*.swp
composer.lock
docs/
.idea/
.php-cs-fixer.cache
.php-cs-fixer.php
.phpdoc/
.phpunit.cache
composer.lock
phpunit.xml
playground/
*.swo
*.swp
vendor/
8 changes: 7 additions & 1 deletion .php-cs-fixer.dist.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,11 @@
return (new Config())
->setParallelConfig(ParallelConfigFactory::detect())
->setFinder(Finder::create()->in([__DIR__.'/src', __DIR__.'/tests']))
->setRules(['@PhpCsFixer' => true, 'phpdoc_align' => false, 'new_with_parentheses' => ['named_class' => false]])
->setRules([
'@PhpCsFixer' => true,
'phpdoc_align' => false,
'new_with_parentheses' => ['named_class' => false],
'ordered_types' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'],
'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'],
])
;
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.0.2"
".": "0.1.0"
}
51 changes: 51 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,56 @@
# Changelog

## 0.1.0 (2025-09-03)

Full Changelog: [v0.0.2...v0.1.0](https://github.com/CASParser/cas-parser-php/compare/v0.0.2...v0.1.0)

### ⚠ BREAKING CHANGES

* use builders for RequestOptions
* rename errors to exceptions
* pagination field rename, and basic streaming docs
* **refactor:** namespacing cleanup
* **refactor:** clean up pagination, errors, as well as request methods

### Features

* **client:** add streaming ([8a3649a](https://github.com/CASParser/cas-parser-php/commit/8a3649ac38d283238cb78f183d88388d2220350f))
* **client:** improve error handling ([b8969bb](https://github.com/CASParser/cas-parser-php/commit/b8969bb06c1b5c4575ad2f0a25af16f2bb0f5c5f))
* **client:** use named parameters in methods ([f977b9a](https://github.com/CASParser/cas-parser-php/commit/f977b9a00b4f72c4d0add8e637baf699339b3707))
* ensure `->toArray()` benefits from structural typing ([16e7c95](https://github.com/CASParser/cas-parser-php/commit/16e7c9593a3216a1af73bd62b8c3d9561d2a05ad))
* pagination field rename, and basic streaming docs ([961e540](https://github.com/CASParser/cas-parser-php/commit/961e54000c4f7e50b2c2bdbed82ac08b4862450f))
* **php:** differentiate null and omit ([d5736cf](https://github.com/CASParser/cas-parser-php/commit/d5736cf656dd266165e262c6fe85a6bc0a12e5d9))
* **php:** rename internal types ([d8b47a2](https://github.com/CASParser/cas-parser-php/commit/d8b47a27256c7429058623b48624698804778320))
* **refactor:** clean up pagination, errors, as well as request methods ([26437b5](https://github.com/CASParser/cas-parser-php/commit/26437b521827b8cf5393feee1e8af173e18d7a22))
* **refactor:** namespacing cleanup ([666f374](https://github.com/CASParser/cas-parser-php/commit/666f37473888855fcc884cb9d851d43ce62aa75f))
* rename errors to exceptions ([92d9817](https://github.com/CASParser/cas-parser-php/commit/92d9817bf28718bfe5ecc6e61f6ed42abe4b0d4b))
* use builders for RequestOptions ([7f3730e](https://github.com/CASParser/cas-parser-php/commit/7f3730ee1d2081c219209b4cf06a9568af6b2559))


### Bug Fixes

* add create release workflow ([11358ea](https://github.com/CASParser/cas-parser-php/commit/11358ea756b190e7c2f459311f409f7ec6ddd255))
* basic pagination should work ([041e76c](https://github.com/CASParser/cas-parser-php/commit/041e76c9f5db339bd9834e609058b3b4edc865d3))
* **client:** elide null named parameters ([47e2824](https://github.com/CASParser/cas-parser-php/commit/47e28244783dd47d03f095cf0015aa947c0db5b8))
* minor bugs ([2e13643](https://github.com/CASParser/cas-parser-php/commit/2e13643e201a80bfb8d1ffbeea643133cb79701e))
* remove inaccurate `license` field in composer.json ([86ba48b](https://github.com/CASParser/cas-parser-php/commit/86ba48b8fc66042665d86362545915504f04011e))
* streaming internals ([39bcd29](https://github.com/CASParser/cas-parser-php/commit/39bcd29aa689ba5505428c732b63d07fc049c010))


### Chores

* add additional php doc tags ([4403319](https://github.com/CASParser/cas-parser-php/commit/44033196dc6699b911b64f473f95badc0f548c71))
* improve model annotations ([b45934c](https://github.com/CASParser/cas-parser-php/commit/b45934c91c079bc8eff6a3cfb53e8adab8927034))
* **internal:** refactor base client internals ([36dc0b6](https://github.com/CASParser/cas-parser-php/commit/36dc0b68f8706fe3bd5fcbb7f57c5487cbea2496))
* **internal:** refactored internal codepaths ([b306fa4](https://github.com/CASParser/cas-parser-php/commit/b306fa456c045ddd061225257fd4490e04099f12))
* intuitively order union types ([150660a](https://github.com/CASParser/cas-parser-php/commit/150660ae58f257d5faaa6f8cf7c4f9093e0bae2c))
* readme improvements ([ac66540](https://github.com/CASParser/cas-parser-php/commit/ac665402fa3edc84c13de25248d0b901e54aaab5))
* refactor request options ([f1b303a](https://github.com/CASParser/cas-parser-php/commit/f1b303add63f19005284bec65d3b5907d8f34372))
* **refactor:** simplify base page interface ([95b27e8](https://github.com/CASParser/cas-parser-php/commit/95b27e82468e3026ab7c6adad0af449ef2dd9355))
* remove `php-http/multipart-stream-builder` as a required dependency ([607f49a](https://github.com/CASParser/cas-parser-php/commit/607f49a7bfb66fc667c15ced3baaa556e1b689ab))
* remove type aliases ([ff49892](https://github.com/CASParser/cas-parser-php/commit/ff4989246f4c361a99aa1240db0b7c956fa5161d))
* simplify model initialization ([f38ec08](https://github.com/CASParser/cas-parser-php/commit/f38ec08395db6f5fcf1c8a8e2ccae49cd0e4537a))

## 0.0.2 (2025-08-18)

Full Changelog: [v0.0.1...v0.0.2](https://github.com/CASParser/cas-parser-php/compare/v0.0.1...v0.0.2)
Expand Down
91 changes: 42 additions & 49 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,88 +39,88 @@ To use this package, install via Composer by adding the following to your applic

## Usage

This library uses named parameters to specify optional arguments.
Parameters with a default value must be set by name.

```php
<?php

use CasParser\Client;
use CasParser\CasParser\CasParserSmartParseParams;

$client = new Client(apiKey: getenv("CAS_PARSER_API_KEY") ?: "My API Key");

$params = CasParserSmartParseParams::with(
password: "ABCDF", pdfURL: "https://your-cas-pdf-url-here.com"
);
$unifiedResponse = $client->casParser->smartParse($params);
$unifiedResponse = $client->casParser->smartParse();

var_dump($unifiedResponse->demat_accounts);
```

### Value Objects

It is recommended to use the static `with` constructor `Dog::with(name: "Joey")`
and named parameters to initialize value objects.

However, builders are also provided `(new Dog)->withName("Joey")`.

### Handling errors

When the library is unable to connect to the API, or if the API returns a non-success status code (i.e., 4xx or 5xx response), a subclass of `CasParser\Errors\APIError` will be thrown:
When the library is unable to connect to the API, or if the API returns a non-success status code (i.e., 4xx or 5xx response), a subclass of `CasParser\Core\Exceptions\APIException` will be thrown:

```php
<?php

use CasParser\CasParser\CasParserSmartParseParams;
use CasParser\Errors\APIConnectionError;
use CasParser\Core\Exceptions\APIConnectionException;

$params = CasParserSmartParseParams::with(
password: "ABCDF", pdfURL: "https://you-cas-pdf-url-here.com"
);
try {
$CasParser = $client->casParser->smartParse($params);
} catch (APIConnectionError $e) {
echo "The server could not be reached", PHP_EOL;
var_dump($e->getPrevious());
$unifiedResponse = $client->casParser->smartParse();
} catch (APIConnectionException $e) {
echo "The server could not be reached", PHP_EOL;
var_dump($e->getPrevious());
} catch (RateLimitError $_) {
echo "A 429 status code was received; we should back off a bit.", PHP_EOL;
echo "A 429 status code was received; we should back off a bit.", PHP_EOL;
} catch (APIStatusError $e) {
echo "Another non-200-range status code was received", PHP_EOL;
var_dump($e->status);
echo "Another non-200-range status code was received", PHP_EOL;
echo $e->getMessage();
}
```

Error codes are as follows:

| Cause | Error Type |
| ---------------- | -------------------------- |
| HTTP 400 | `BadRequestError` |
| HTTP 401 | `AuthenticationError` |
| HTTP 403 | `PermissionDeniedError` |
| HTTP 404 | `NotFoundError` |
| HTTP 409 | `ConflictError` |
| HTTP 422 | `UnprocessableEntityError` |
| HTTP 429 | `RateLimitError` |
| HTTP >= 500 | `InternalServerError` |
| Other HTTP error | `APIStatusError` |
| Timeout | `APITimeoutError` |
| Network error | `APIConnectionError` |
| Cause | Error Type |
| ---------------- | ------------------------------ |
| HTTP 400 | `BadRequestException` |
| HTTP 401 | `AuthenticationException` |
| HTTP 403 | `PermissionDeniedException` |
| HTTP 404 | `NotFoundException` |
| HTTP 409 | `ConflictException` |
| HTTP 422 | `UnprocessableEntityException` |
| HTTP 429 | `RateLimitException` |
| HTTP >= 500 | `InternalServerException` |
| Other HTTP error | `APIStatusException` |
| Timeout | `APITimeoutException` |
| Network error | `APIConnectionException` |

### Retries

Certain errors will be automatically retried 2 times by default, with a short exponential backoff.

Connection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict, 429 Rate Limit, >=500 Internal errors, and timeouts will all be retried by default.

You can use the `max_retries` option to configure or disable this:
You can use the `maxRetries` option to configure or disable this:

```php
<?php

use CasParser\Client;
use CasParser\RequestOptions;
use CasParser\CasParser\CasParserSmartParseParams;

// Configure the default for all requests:
$client = new Client(maxRetries: 0);
$params = CasParserSmartParseParams::with(
password: "ABCDF", pdfURL: "https://you-cas-pdf-url-here.com"
);

// Or, configure per-request:$result = $client
->casParser
->smartParse($params, new RequestOptions(maxRetries: 5));
// Or, configure per-request:

$result = $client->casParser->smartParse(
requestOptions: RequestOptions::with(maxRetries: 5)
);
```

## Advanced concepts
Expand All @@ -131,22 +131,15 @@ $params = CasParserSmartParseParams::with(

You can send undocumented parameters to any endpoint, and read undocumented response properties, like so:

Note: the `extra_` parameters of the same name overrides the documented parameters.
Note: the `extra*` parameters of the same name overrides the documented parameters.

```php
<?php

use CasParser\RequestOptions;
use CasParser\CasParser\CasParserSmartParseParams;

$params = CasParserSmartParseParams::with(
password: "ABCDF", pdfURL: "https://you-cas-pdf-url-here.com"
);
$unifiedResponse = $client
->casParser
->smartParse(
$params,
new RequestOptions(
$unifiedResponse = $client->casParser->smartParse(
requestOptions: RequestOptions::with(
extraQueryParams: ["my_query_parameter" => "value"],
extraBodyParams: ["my_body_parameter" => "value"],
extraHeaders: ["my-header" => "value"],
Expand Down
25 changes: 25 additions & 0 deletions bin/check-release-environment
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env bash

errors=()

if [ -z "${PACKAGIST_USERNAME}" ]; then
errors+=("The PACKAGIST_USERNAME secret has not been set. Please set it in either this repository's secrets or your organization secrets")
fi

if [ -z "${PACKAGIST_SAFE_KEY}" ]; then
errors+=("The PACKAGIST_SAFE_KEY secret has not been set. Please set it in either this repository's secrets or your organization secrets")
fi

lenErrors=${#errors[@]}

if [[ lenErrors -gt 0 ]]; then
echo -e "Found the following errors in the release environment:\n"

for error in "${errors[@]}"; do
echo -e "- $error\n"
done

exit 1
fi

echo "The environment is ready to push releases!"
7 changes: 2 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
{
"$schema": "https://getcomposer.org/schema.json",
"autoload": {
"files": [
"src/Client.php"
],
"files": ["src/Core.php", "src/Client.php"],
"psr-4": {
"CasParser\\": "src/"
}
Expand All @@ -25,13 +23,11 @@
"preferred-install": "dist",
"sort-packages": true
},
"license": "APACHE-2.0",
"description": "Cas Parser PHP SDK",
"name": "org-placeholder/cas-parser",
"require": {
"php": "^8.1",
"php-http/discovery": "^1",
"php-http/multipart-stream-builder": "^1",
"psr/http-client": "^1",
"psr/http-client-implementation": "^1",
"psr/http-factory-implementation": "^1",
Expand All @@ -48,6 +44,7 @@
"symfony/http-client": "^7"
},
"scripts": {
"build:docs": "curl --etag-save ./vendor/ag.etags --etag-compare ./vendor/ag.etags --create-dirs --remote-name --output-dir ./vendor/bin --no-progress-meter -- https://github.com/ApiGen/ApiGen/releases/latest/download/apigen.phar && php ./vendor/bin/apigen.phar --output docs -- src",
"lint": "./scripts/lint",
"test": "./scripts/test"
}
Expand Down
20 changes: 11 additions & 9 deletions src/CasGenerator/CasGeneratorGenerateCasParams.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@

use CasParser\CasGenerator\CasGeneratorGenerateCasParams\CasAuthority;
use CasParser\Core\Attributes\Api;
use CasParser\Core\Concerns\Model;
use CasParser\Core\Concerns\Params;
use CasParser\Core\Concerns\SdkModel;
use CasParser\Core\Concerns\SdkParams;
use CasParser\Core\Contracts\BaseModel;

/**
* This endpoint generates CAS (Consolidated Account Statement) documents by submitting a mailback request to the specified CAS authority.
* Currently only supports KFintech, with plans to support CAMS, CDSL, and NSDL in the future.
*
* @phpstan-type generate_cas_params = array{
* @see CasParser\CasGenerator->generateCas
*
* @phpstan-type cas_generator_generate_cas_params = array{
* email: string,
* fromDate: string,
* password: string,
Expand All @@ -25,8 +27,9 @@
*/
final class CasGeneratorGenerateCasParams implements BaseModel
{
use Model;
use Params;
/** @use SdkModel<cas_generator_generate_cas_params> */
use SdkModel;
use SdkParams;

/**
* Email address to receive the CAS document.
Expand Down Expand Up @@ -55,7 +58,7 @@ final class CasGeneratorGenerateCasParams implements BaseModel
/**
* CAS authority to generate the document from (currently only kfintech is supported).
*
* @var null|CasAuthority::* $casAuthority
* @var CasAuthority::*|null $casAuthority
*/
#[Api('cas_authority', enum: CasAuthority::class, optional: true)]
public ?string $casAuthority;
Expand Down Expand Up @@ -88,16 +91,15 @@ final class CasGeneratorGenerateCasParams implements BaseModel
*/
public function __construct()
{
self::introspect();
$this->unsetOptionalProperties();
$this->initialize();
}

/**
* Construct an instance from the required parameters.
*
* You must use named parameters to construct any parameters with a default value.
*
* @param null|CasAuthority::* $casAuthority
* @param CasAuthority::* $casAuthority
*/
public static function with(
string $email,
Expand Down
Loading
Loading