@jusoor/sdk
v0.1.0
Published
TypeScript SDK for the Jusoor shipping platform API
Downloads
138
Maintainers
Readme
@jusoor/sdk
TypeScript SDK for the Jusoor shipping platform API. Built on openapi-fetch for lightweight, type-safe API calls using native fetch.
Installation
npm install @jusoor/sdkQuick Start
API Key Authentication (for server-to-server / external integrations)
import { createClient } from '@jusoor/sdk';
const client = createClient({
baseUrl: 'https://api.jusoor.cloud',
apiKey: 'your-api-key',
});
// List shipments — fully typed params and response
const { data, error } = await client.shipments.list({ page: 1, limit: 20 });Bearer Token Authentication (for session-based / frontend apps)
import { createClient } from '@jusoor/sdk';
const client = createClient({
baseUrl: 'https://api.jusoor.cloud',
token: 'your-session-token',
});You can also pass a function (sync or async) that resolves the token dynamically:
const client = createClient({
baseUrl: 'https://api.jusoor.cloud',
token: () => getAccessToken(),
});Usage Examples
Create a Shipment
const { data, error } = await client.shipments.create({
carrierId: 'carrier-id',
recipientName: 'Ahmed',
recipientPhone: '+966500000000',
destCity: 'Riyadh',
destCountry: 'SA',
weightKg: '2.5',
shippingCost: '25.00',
paymentType: 'PREPAID',
});Get a Shipment
const { data, error } = await client.shipments.get('shipment-id');Track a Shipment
const { data, error } = await client.shipments.getTracking('shipment-id');Update a Shipment
const { data, error } = await client.shipments.update('shipment-id', {
carrierNotes: 'Handle with care',
});Cancel a Shipment
const { data, error } = await client.shipments.cancel('shipment-id');List Carriers
const { data, error } = await client.carriers.list();Addresses
// Create
const { data } = await client.addresses.create({
label: 'Warehouse',
city: 'Riyadh',
country: 'SA',
// ...
});
// Set as default
await client.addresses.setDefault('address-id');Webhooks
const { data } = await client.webhooks.create({
url: 'https://example.com/webhook',
events: ['shipment.created', 'shipment.delivered'],
});Error Handling
Non-2xx responses populate the error field in the response:
import { createClient, JusoorApiError, throwOnError } from '@jusoor/sdk';
const client = createClient({
baseUrl: 'https://api.jusoor.cloud',
apiKey: 'your-api-key',
});
// Pattern 1: Check error field
const { data, error } = await client.shipments.create({ ... });
if (error) {
console.error(error); // raw error body from the API
}
// Pattern 2: Throw on error (narrows data to non-nullable)
const result = await client.shipments.create({ ... });
throwOnError(result);
// result.data is now guaranteed to be definedJusoorApiError
When using throwOnError, errors are thrown as JusoorApiError instances:
try {
const result = await client.shipments.create({ ... });
throwOnError(result);
} catch (err) {
if (err instanceof JusoorApiError) {
console.error(err.status); // 400
console.error(err.message); // "Validation failed"
console.error(err.errors); // ["recipientName must not be empty", ...]
console.error(err.code); // optional error code
err.isValidationError; // 400 with validation errors
err.isUnauthorized; // 401
err.isForbidden; // 403
err.isNotFound; // 404
err.isRateLimited; // 429
}
}Raw Client (Escape Hatch)
For endpoints not covered by resource methods (e.g., Better Auth routes), use client.raw:
const { data } = await client.raw.GET('/api/auth/get-session');
const { data } = await client.raw.POST('/api/auth/sign-in/email', {
body: { email: '[email protected]', password: '...' },
});Custom Fetch (SSR / Node.js)
Pass a custom fetch implementation for server-side rendering or Node.js environments:
// React Router loader example
export async function loader({ request }: LoaderArgs) {
const client = createClient({
baseUrl: process.env.API_URL,
token: getSessionToken(request),
fetch: globalThis.fetch, // or any custom fetch
});
const { data } = await client.shipments.list();
return { shipments: data };
}Types
All request/response types are generated from the OpenAPI spec and exported:
import type { components, paths, operations } from '@jusoor/sdk';
// Use component schemas directly
type Shipment = components['schemas']['ShipmentEntity'];
type CreateShipmentDto = components['schemas']['CreateShipmentDto'];Available Resources
| Resource | Methods |
|---|---|
| client.shipments | list, get, create, update, cancel, getTracking |
| client.carriers | list, get, create, update, delete |
| client.addresses | list, get, create, update, delete, setDefault |
| client.customers | list, get, create, update, delete |
| client.shippingOrders | list, get, create, update, cancel |
| client.pickupRequests | list, get, create, update, delete, cancel |
| client.webhooks | list, get, create, update, delete, listDeliveries |
| client.stores | list, get, create, update, delete |
| client.wallets | get, create, update, listTransactions, getTransaction |
| client.subscriptions | getCurrent, subscribe, cancel, changePlan, renew, … |
| client.notifications | list, delete, markAsRead, markAllAsRead, getUnreadCount, … |
| client.activityLogs | list, get, create |
| client.reports | list, get, create, update, delete |
| client.raw | Direct access to GET, POST, PATCH, DELETE, PUT |
Development
Generate Types
Start the backend, then run:
bun run sdk:generateOverride the OpenAPI URL:
JUSOOR_BACKEND_OPENAPI_URL=http://localhost:4000/openapi.json bun run sdk:generateBuild
bun run --cwd packages/sdk build