ipsocode / hypervel-cin7
Cin7 Core API client for Hypervel, built on hypervel/saloon
Requires
- hypervel/components: 0.4.x-dev
Requires (Dev)
- brianium/paratest: ^7.24
- fakerphp/faker: ^1.24
- friendsofphp/php-cs-fixer: ^3.57.2
- hypervel/testbench: ^0.4
- mockery/mockery: ^1.6
- phpstan/phpstan: ^2.2.15
- phpunit/phpunit: >=13.0.3 <13.4
- symfony/yaml: ^8.0.12
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
A Cin7 Core API client for
Hypervel, built on hypervel/saloon.
Warning
Development only — do not use this package in production until Hypervel 0.4 is released.
It is built for Hypervel 0.4, which has no release yet: 0.4 exists only as the
0.4.x-dev branch of hypervel/components,
and this package is developed and tested against that moving branch. Until 0.4
ships, anything here can change without a deprecation period — the API, the
configuration and the requests it sends included. Use it to evaluate or to
build against Hypervel 0.4, and pin the version you tested.
use Ipsocode\Cin7\Cin7Connector; public function __construct(private readonly Cin7Connector $cin7) {} // GET customer?page=1&limit=100 $customers = $this->cin7->customer()->get()->json();
What this is
Cin7 Core — formerly DEAR Inventory — exposes a REST API at
inventory.dearsystems.com. This package is a client for it that is safe to run
in long-lived Swoole workers: one shared connector, a bounded retry when Cin7
throttles (429 or 503), and rate limiting through the framework's rate limiter,
all on hypervel/saloon.
This is an independent package. It is not affiliated with or endorsed by Cin7.
Requirements
- PHP 8.4 or newer (CI runs 8.4 and 8.5)
- Hypervel 0.4, which today means
hypervel/componentsat0.4.x-dev. The package requireshypervel/componentsitself rather than its split packages. - A Cin7 Core account with API access — its account ID and an application key
Installation
The package is not on Packagist, so add this repository to your application's Composer repositories first:
composer config repositories.hypervel-cin7 vcs https://github.com/ipsocode/hypervel-cin7 composer require ipsocode/hypervel-cin7 php artisan vendor:publish --tag=cin7-config
Hypervel 0.4 is only available as a dev branch, so your application's
composer.json must already allow it: "minimum-stability": "dev" together
with "prefer-stable": true. Tags are not re-tested as 0.4.x-dev moves on,
and neither is main between changes: each change is tested against the
0.4.x-dev of its day before it merges. To pick up changes as they land,
require ipsocode/hypervel-cin7:dev-main instead. Each release's notes,
breaking changes first, are on the
Releases page.
The service provider (Ipsocode\Cin7\Cin7ServiceProvider) is discovered
through the package's extra.hypervel block, and hypervel/saloon's own
provider through the components manifest, so there is nothing to register and
no Saloon wiring to do. Publishing the config is optional: the packaged defaults
are merged in either way. The credentials go in your environment:
CIN7_ACCOUNT_ID= CIN7_APPLICATION_KEY=
Every configuration key, with its environment variable and default, is in docs/configuration.md.
Usage
Inject Cin7Connector and call a resource accessor.
use Ipsocode\Cin7\Cin7Connector; public function __construct(private readonly Cin7Connector $cin7) {} // GET customer?page=1&limit=100 $all = $this->cin7->customer()->get()->json(); // POST customer, raw JSON body, no page/limit $new = $this->cin7->customer()->post(['Name' => 'ACME'])->json(); // PUT customer, body carries ID $this->cin7->customer()->put(['ID' => $guid, 'Name' => 'ACME Ltd']); // Every customer, across all pages foreach ($this->cin7->customer()->paginate()->items() as $customer) { // … }
Each connector holds only readonly scalars and is never mutated per request, so
sharing one instance across coroutines for a worker's lifetime is safe.
Injecting Cin7Connector gives the default connection.
For a second account, such as a sandbox, add it under connections in
config/cin7.php and ask Cin7Manager for it by name:
use Ipsocode\Cin7\Cin7Manager; $sandbox = app(Cin7Manager::class)->connection('sandbox');
Each connection throttles on its own, as docs/connector.md describes.
Documentation
- docs/configuration.md — every configuration key with its environment variable and default, publishing the config, and when the values are read.
- docs/resources.md — the accessor tree, the conventions every resource and request follows, and adding a new resource method.
- docs/requests.md — the three request bases and the request lines they send, the wire protocol, the exceptions a failed call throws, and the bounded throttling retry.
- docs/data.md — the typed request and response bodies: the conventions every data class follows, the class behind each path, and the empty-collection rule.
- docs/pagination.md — walking every page of a listing or sending the pages concurrently, and how the last page is worked out from Cin7's list envelope.
- docs/connector.md — the shared connector, its transport and timeouts, rate limiting and the choice of limiter store, and the throttling cooldown.
- docs/sync.md — the optional scheduled copy of Cin7's records
in one local table: the modules and their order, how a pull works, the
schedule, the
cin7:synccommand and reading the table. - docs/testing.md — faking Cin7 in the tests of an
application that uses the package, with the shipped
Cin7Fakebuilders for list envelopes and the Error Model, and how the package's own suite is built.
What this package deliberately does not do
-
No caching. Response caching, cache-key shape and cache-hit logging semantics are consumer policy;
Cacheable/HasCachingcan be adopted later once a second consumer's needs are known. The sync, a local copy of Cin7's records, is a separate, opt-in table: off by default, it creates no table and runs no query. -
No mandatory DTOs. Arrays work everywhere: a write takes an array body and
json()returns the decoded array. Typed data objects are an additive layer on top (docs/data.md), shown here for a customer:use Ipsocode\Cin7\Data\Customer\CustomerPostData; // The fields the reference requires must be given; of the rest, only the keys you set are sent. $response = $cin7->customer()->post(CustomerPostData::from([ 'Name' => 'ACME', 'Status' => 'Active', 'Currency' => 'GBP', 'PaymentTerm' => '30 days', 'AccountReceivable' => '610', 'RevenueAccount' => '200', 'TaxRule' => 'Tax Exempt', ])); $customer = $response->dto(); // CustomerData $customers = $cin7->customer()->get()->dto(); // list<CustomerData>
-
No request logging. Instrumentation writes consumer-owned models.
Contributing
The development setup, the checks CI runs, the coroutine-safety rules every change is held to, and how releases are cut are in CONTRIBUTING.md. Report security issues privately, as described in SECURITY.md, rather than in a public issue.
Credits
The wire protocol, the endpoint table and the page-defaults helper derive from
eighteen73/dear-api, by Umair
Mahmood and its contributors, which is MIT-licensed. The client itself is
written on hypervel/saloon and is not a copy of that code. LICENSE carries
its copyright notice alongside this package's.
License
MIT. See LICENSE.