Skip to content

Getting Started

crisp-oquent is a fetch-only TypeScript API client that speaks the Spatie laravel-query-builder URL contract.

If your Laravel API uses QueryBuilder::for(...)->allowedFilters(...), you can use crisp-oquent on the JavaScript side and avoid hand-writing query strings entirely.

Why crisp-oquent?

  • Zero dependencies. Bundle size is what your build process minifies it to. No Axios.
  • TypeScript-first. Strict mode, ships its own .d.ts. Generic Model<T> for typed attributes.
  • 1:1 Spatie URL contract. Every laravel-query-builder v7 feature has a typed builder method.
  • Filter Groups (#1060) included. Client-side shorthand for AllowedFilter::groupOr / groupAnd (Spatie v7.3.0).
  • Laravel-aware. Resource paginated payloads, HttpError.isValidationError, 422 → validationErrors.

Requirements

  • Node ≥ 18 (uses native fetch)
  • Backend: Laravel + Spatie laravel-query-builder ≥ 7.0 (Filter Groups need ≥ 7.3.0)

Install

bash
npm install @bir-tan/crisp-oquent
bash
pnpm add @bir-tan/crisp-oquent
bash
yarn add @bir-tan/crisp-oquent

Configure once at app boot

ts
import { CrispOquentConfig } from '@bir-tan/crisp-oquent';

CrispOquentConfig.initialize({
  baseUri: 'https://api.example.com',
});

CrispOquentConfig.setBearerToken(localStorage.getItem('token'));

In Nuxt 3, this lives in a plugin (plugins/crisp-oquent.client.ts). In Next.js, your root layout. In Vue/React SPAs, main.ts / index.tsx.

Define your first model

ts
import { Model } from '@bir-tan/crisp-oquent';

export class User extends Model {
  static override uri = '/users';

  declare id?: number;
  declare name?: string;
  declare email?: string;
  declare created_at?: string;
}

uri is the path appended to baseUri. The declare fields give you typed attribute access through the proxy.

Run your first query

ts
const users = await User.crispy()
  .filter('status', 'active')
  .sortByDesc('created_at')
  .paginate(1, 25);

users.items;        // User[]
users.currentPage;  // 1
users.total;        // 137

That call emits:

http
GET https://api.example.com/users?filter[status]=active&sort=-created_at&page=1&per_page=25
Accept: application/json
Authorization: Bearer <token>

Continue to Filtering →