# ShippingDz 🚚 — La solution ultime pour la livraison en Algérie

**ShippingDz** is the first comprehensive Node.js library dedicated to the Algerian e-commerce market. It allows Algerian developers and store owners to connect their websites directly to **26+ local shipping providers** (Yalidine, Ecotrack, ZR Express, and more) using a single, unified tool.

---

### 🇩🇿 Pourquoi utiliser ShippingDz ? (Why use this?)

Integrating shipping in Algeria used to be a headache. Every courier had a different API, and most didn't work well with modern JavaScript frameworks. **ShippingDz fixes this:**

- **One Code for Everyone**: Stop writing custom code for every courier. Use one standard way to talk to Yalidine, Maystro, DHD, and 20+ others.
- **Modern Tech Stack**: Built for Node.js, React, and Next.js. No more fighting with old PHP scripts if your site is modern.
- **CORS Problem Solved**: By moving your shipping logic to the backend with this library, you never have to worry about browser CORS errors again.
- **Save Months of Work**: We've already done the hard work of reading documentation and testing APIs. You just focus on selling.

---

### 🌟 Acknowledgement & Credits

This project is a **JavaScript/Node.js port** of the excellent [CourierDZ](https://github.com/PiteurStudio/CourierDZ) PHP package developed by **[Piteur Studio](https://github.com/PiteurStudio)**.

We would like to thank **Nassim** and the **Piteur Studio** team for their hard work in mapping out the Algerian shipping ecosystem. This port aims to bring that same convenience to the modern JS ecosystem.

---

## Requirements

- Node.js 18+
- ESM support (`"type": "module"` in your `package.json`)

## Installation

### Method 1: Official NPM Package

you can install it simply with:

```bash
npm install shippingdz
```

### Method 2: Local / Manual (Pre-publication)

If you are using the source code directly (unreleased):

1.  **Download** the `ShippingDz` folder into your project's root.

2.  **Install it locally** via npm:
    ```bash
    # Run this from your main project folder (where your package.json is)
    npm install ./ShippingDz
    ```

3.  **Import in your code:**
    ```javascript
    import ShippingDz, { ShippingProvider } from "shippingdz";
    ```

---

## ⚖️ Terms of Use & Attribution

This project is open-source but subject to the following conditions:

1.  **Credit Required**: You must give credit to **Abdouh071** (the author of this port) and **Piteur Studio** (the authors of the original logic) in your project's documentation or credits.
2.  **Ownership**: You may not claim this project as your own. The copyright and intellectual property remain with the contributors.
3.  **Derivative Works**: If you modify the code, you must still maintain the original copyright notices and credits.

---

## Supported Providers (26)

| Provider                                                                                                                                                                                                                                                                     | Platform   | testCredentials | getRates | createOrder | getOrder | orderLabel |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | --------------- | -------- | ----------- | -------- | ---------- |
| **Yalidine**                                                                                                                                                                                                                                                                 | Yalidine   | ✅              | ✅       | ✅          | ✅       | ✅ (URL)   |
| **Yalitec**                                                                                                                                                                                                                                                                  | Yalidine   | ✅              | ✅       | ✅          | ✅       | ✅ (URL)   |
| **ZR Express**                                                                                                                                                                                                                                                               | Procolis   | ✅              | ✅       | ✅          | ✅       | ❌         |
| **Maystro Delivery**                                                                                                                                                                                                                                                         | Standalone | ✅              | ❌       | ✅          | ✅       | ✅ (PDF)   |
| **DHD, Conexlog, MsmGo, RexLivraison, RbLivraison, SpeedDelivery, Areex, Prest, RocketDelivery, Worldexpress, BaConsult, Packers, 48hr Livraison, MonoHub, Anderson Delivery, Golivri, Coyote Express, Salva Delivery, Distazero, Fret Direct, TSL Express, Negmar Express** | Ecotrack   | ✅              | ✅       | ✅          | ❌       | ✅ (PDF)   |

## Usage

### Initialize a Provider

```js
import ShippingDz, { ShippingProvider } from "shippingdz";

// Ecotrack providers (token only)
const provider = ShippingDz.provider(ShippingProvider.DHD, {
  token: "your-api-token",
});

// Yalidine / Yalitec (id + token)
const provider = ShippingDz.provider(ShippingProvider.YALIDINE, {
  id: "your-api-id",
  token: "your-api-token",
});

// Procolis / ZR Express (token + key)
const provider = ShippingDz.provider(ShippingProvider.ZREXPRESS, {
  token: "your-token",
  key: "your-key",
});

// Maystro Delivery (token only)
const provider = ShippingDz.provider(ShippingProvider.MAYSTRO_DELIVERY, {
  token: "your-api-token",
});
```

### Test Credentials

```js
const isValid = await provider.testCredentials();
console.log(isValid); // true or false
```

### Get Shipping Rates

```js
// All wilayas (Ecotrack / Procolis)
const rates = await provider.getRates();

// Filter by destination wilaya (wilaya 16 = Alger)
const rate = await provider.getRates(null, 16);

// From wilaya to wilaya (Yalidine only)
const rate = await provider.getRates(1, 16);
```

### Create an Order (Ecotrack example)

```js
const order = await provider.createOrder({
  nom_client: "Mohamed Salah",
  telephone: "0550123456",
  adresse: "Rue 39, Bab El Oued",
  commune: "Bab El Oued",
  code_wilaya: 16,
  montant: 2500,
  type: 1, // 1=Livraison, 2=Echange, 3=Pickup, 4=Recouvrement
});
```

### Create an Order (ZR Express / Procolis example)

```js
const order = await provider.createOrder({
  Tracking: "MY-REF-001",
  TypeLivraison: 0, // 0=Domicile, 1=Stopdesk
  TypeColis: 0,
  Confrimee: 1,
  Client: "Ahmed",
  MobileA: "0661234567",
  Adresse: "Rue Ben M'hidi",
  IDWilaya: "09",
  Commune: "Blida",
  Total: "3000",
  TProduit: "Chaussures",
  Source: "ShippingDz",
});
```

### Create an Order (Yalidine example)

```js
const order = await provider.createOrder({
  order_id: "MY-ORDER-123",
  from_wilaya_name: "Alger",
  firstname: "Karim",
  familyname: "Benali",
  contact_phone: "0770123456",
  address: "12 Rue Didouche Mourad",
  to_commune_name: "Oran",
  to_wilaya_name: "Oran",
  product_list: "T-shirt, Jean",
  price: 3500,
  do_insurance: false,
  declared_value: 3500,
  length: 30,
  width: 20,
  height: 5,
  weight: 1.2,
  freeshipping: false,
  is_stopdesk: false,
  has_exchange: false,
});
```

### Get Order Details

```js
const order = await provider.getOrder("MY-TRACKING-ID");
console.log(order);
```

### Get Shipping Label

```js
const label = await provider.orderLabel("MY-TRACKING-ID");

if (label.type === "pdf") {
  // label.data is a base64-encoded PDF string
  const buffer = Buffer.from(label.data, "base64");
  fs.writeFileSync("label.pdf", buffer);
} else if (label.type === "url") {
  // label.data is a direct URL
  console.log(label.data);
}
```

### Get Validation Rules

```js
const rules = provider.getCreateOrderValidationRules();
console.log(rules);
// { nom_client: 'required|string|max:255', ... }
```

### List All Providers

```js
const all = ShippingDz.providers();
// Returns array of metadata objects for all 26 providers
console.log(all);
```

## Error Handling

```js
import ShippingDz, { ShippingProvider, CredentialsException, HttpException, CreateOrderValidationException } from 'shippingdz';

try {
  const provider = ShippingDz.provider(ShippingProvider.DHD, { token: 'bad-token' });
  await provider.createOrder({ ... });
} catch (err) {
  if (err instanceof CredentialsException) {
    console.error('Invalid credentials:', err.message);
  } else if (err instanceof CreateOrderValidationException) {
    console.error('Validation failed:', err.message);
  } else if (err instanceof HttpException) {
    console.error('HTTP error:', err.message);
  }
}
```

## All Available Exceptions

| Exception                        | When thrown                              |
| -------------------------------- | ---------------------------------------- |
| `CredentialsException`           | Credentials are missing or malformed     |
| `HttpException`                  | An HTTP request to a provider API failed |
| `CreateOrderException`           | Provider rejected the order creation     |
| `CreateOrderValidationException` | Local validation of order data failed    |
| `InvalidProviderException`       | Unknown provider name was requested      |
| `TrackingIdNotFoundException`    | Tracking ID not found by provider        |
| `NotImplementedException`        | Method not yet implemented for provider  |
| `FunctionNotSupportedException`  | Method not supported by provider         |

## License

MIT
