Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Nova Api Laravel Package

orca-services/nova-api

Expose Laravel Nova resources through a clean JSON API. Provides endpoints for models, authentication, filtering, and CRUD operations, making it easy to power mobile apps or external clients from your existing Nova admin.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and pin. Because the package is archived with effectively no user base, treat it as vendored code rather than a maintained dependency. Install with an exact constraint so a future Composer resolve can't surprise you:

composer require orca-services/nova-api:^1.0 --prefer-dist

Commit composer.lock. If the upstream tag you land on has no stable release you trust, pin the commit hash instead (dev-main#abc1234).

Publish the config first. Most PHP API clients of this shape ship a config/nova-api.php with base URL, credentials, and timeout values:

php artisan vendor:publish --provider="OrcaServices\NovaApi\NovaApiServiceProvider" --tag=config

Then move every secret out of the file and into .env:

NOVA_API_BASE_URL=https://api.example.com/
NOVA_API_TOKEN=
NOVA_API_TIMEOUT=10

If vendor:publish reports no publishable tags, read src/ directly — with a one-star package the README is usually thinner than the code, and the constructor signature of the main client class is the real documentation.

Where to look first, in order:

  1. src/ for the client class (usually NovaApiClient or similar) — its constructor tells you what config it actually consumes.
  2. The ServiceProvider in src/ — confirms whether it registers a singleton, aliases a facade, and whether extra.laravel.providers in composer.json gives you auto-discovery. Archived packages frequently predate or misconfigure auto-discovery, so verify php artisan about lists the provider.
  3. src/Exceptions/ — the exception hierarchy determines every catch block you write later.
  4. README.md last, for the two or three usage snippets that are probably still accurate.

First use case. The realistic day-one win is a single read call you can validate against a real response — a health/ping endpoint if one exists, otherwise the simplest GET the client exposes. Bootstrap it in tinker before writing any application code:

$client = app(\OrcaServices\NovaApi\NovaApiClient::class);
dump($client->getSomething(['id' => 1]));

If that returns a parsed array or DTO rather than a raw Guzzle Response, you know the client does its own deserialization and you can skip most of the plumbing below.

Implementation Patterns

Wrap the client, don't inject it everywhere. Since the package is archived, you want one seam you control. Put a thin repository/action class in front of it:

namespace App\Services;

use OrcaServices\NovaApi\NovaApiClient;

class NovaGateway
{
    public function __construct(private NovaApiClient $client) {}

    public function findCustomer(string $id): ?array
    {
        try {
            return $this->client->getCustomer($id);
        } catch (\OrcaServices\NovaApi\Exceptions\NotFoundException) {
            return null;
        }
    }
}

Bind it as a singleton in AppServiceProvider so connection state and Guzzle's handler stack are reused per request/worker:

$this->app->singleton(NovaGateway::class, fn ($app) => new NovaGateway(
    $app->make(NovaApiClient::class)
));

When (not if) you need to patch the client, you swap the binding or extend NovaGateway — you never edit vendor code.

Push calls into jobs. NOVA-style APIs are typically external, slow, and rate-limited; keep them off the request cycle. A queued job with $tries, $backoff, and $timeout set gives you retry semantics for free:

class SyncNovaCustomer implements ShouldQueue
{
    public $tries = 5;
    public $backoff = [10, 30, 120, 600];

    public function __construct(public string $customerId) {}

    public function handle(NovaGateway $nova): void
    {
        $data = $nova->findCustomer($this->customerId);
        // persist to Eloquent, dispatch follow-ups, etc.
    }
}

Be careful with $timeout versus the client's own HTTP timeout — the job timeout must be larger, or the worker kills the process before Guzzle returns.

Normalize responses into your own DTOs or models immediately. Don't let raw API arrays leak into views or controllers. Map once, at the boundary:

$customer = NovaCustomer::updateOrCreate(
    ['external_id' => $data['id']],
    ['name' => $data['name'], 'status' => $data['status']],
);

This is your insurance policy: if the archived client breaks against an API change, only the mapper needs attention.

Test with a fake handler, not the network. Inject a Guzzle MockHandler (or, if the client is built on Laravel's HTTP client, use Http::fake()). Either way, test through NovaGateway, asserting on your DTOs rather than the client's internals:

Http::fake([
    'api.example.com/customers/*' => Http::response(['id' => '42', 'name' => 'ACME'], 200),
]);

$this->assertSame('ACME', app(NovaGateway::class)->findCustomer('42')->name);

Add one contract test against a sandbox environment, tagged and excluded from CI by default, so you find out about upstream drift on your own schedule rather than during a deploy.

Cache reads aggressively. External API calls in a loop are the most common performance mistake here. Cache per-entity with a short TTL and invalidate on write:

return Cache::remember("nova:customer:{$id}", now()->addMinutes(15), fn () => $this->client->getCustomer($id));

Log the correlation data, not the payload. Log method, path, status, duration, and any request ID header the API returns. Full response bodies will eventually contain PII and blow up your log storage.

Gotchas and Tips

It is archived — plan for abandonment. One star and zero dependents means no one is triaging issues, and any bug you hit is yours. Before adopting, budget half a day to read src/ end to end. If the surface area you need is small, seriously consider writing a 200-line client against the NOVA API docs with Laravel's Http client instead: you get first-class fakes, retries, and middleware, and you own the maintenance either way. Forking the package into app/Support/NovaApi or a private VCS repo is the middle path and the sane default if you must keep its DTOs and exception types.

Guzzle and PHP version constraints will bite. Older API clients pin guzzlehttp/guzzle:^6, which conflicts with Laravel 10+ projects and modern PHP. Check composer.json's require block before installing; if it conflicts, that's the fork-and-bump moment, and it is usually a one-line change.

Auto-discovery is unreliable in low-traffic packages. If app(NovaApiClient::class) throws a binding error, the provider isn't registered. Add it explicitly to bootstrap/providers.php (Laravel 11+) or config/app.php (older). Also verify the provider's provides() and defer flags — a misconfigured deferred provider can serve a stale client after config:cache.

Never trust the config file with env() calls. If the published config uses env('NOVA_API_TOKEN') directly and you later run php artisan config:cache, it works — but if the package reads env() outside the config file, it will return null in production and nowhere else. Grep the source for env( and move any hits into config keys you control.

Exception granularity is usually poor. Expect a catch-all NovaApiException wrapping Guzzle's RequestException, with getPrevious() holding the real status code. Wrap once, extract the status code defensively, and translate to your own exceptions:

catch (\OrcaServices\NovaApi\Exceptions\NovaApiException $e) {
    $status = $e->getPrevious()?->getResponse()?->getStatusCode();
    // 429 => throw a rate-limit-specific exception, 404 => null, else rethrow
}

Set timeouts explicitly, including connect. Client defaults are frequently 0 (infinite). Override in your gateway or a Guzzle middleware: connect_timeout of 3s, timeout of 10s for reads, longer for anything that writes bulk data. Pair with retry on 429/5xx only — never blind-retry non-idempotent POSTs unless the API supports an idempotency key.

Watch for shared mutable state in long-running workers. If the client stores a token or "last response" on the instance, a singleton plus Octane/queue workers can leak state between requests. If you see that pattern in src/, bind as scoped instead of singleton.

Extension points are limited, so prefer composition. Subclassing the client to add logging or auth-refresh tends to break on minor upgrades. Instead, use Guzzle middleware pushed onto the client's handler stack (if exposed) or decorate your own NovaGateway. If the client exposes a setHttpClient()-style setter, use it to inject a preconfigured Guzzle instance — that's the cleanest hook these packages usually offer.

Document your fork. If you patch vendor code or fork, leave a FORK.md noting the upstream commit, the patches applied, and why. This package will not tell you what changed, and future-you will not remember.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib