> ## Documentation Index
> Fetch the complete documentation index at: https://docs.apexxcloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# JavaScript SDK

> Documentation for ApexxCloud JavaScript SDK

## Installation

<CodeGroup>
  ```bash npm theme={null}
  npm install @apexxcloud/sdk-js
  ```

  ```bash yarn theme={null}
  yarn add @apexxcloud/sdk-js
  ```
</CodeGroup>

## Initialization

```javascript theme={null}
import ApexxCloud from "@apexxcloud/sdk-js";

const storage = new ApexxCloud({
  baseUrl: "https://api.apexxcloud.com", // optional
});
```

## Backend Implementation

Your backend needs to implement an endpoint that generates signed URLs. Here's an example using Node.js:

```javascript theme={null}
const ApexxCloud = require("@apexxcloud/sdk-node");

const storage = new ApexxCloud({
  accessKey: process.env.APEXXCLOUD_ACCESS_KEY,
  secretKey: process.env.APEXXCLOUD_SECRET_KEY,
  region: "bucket-region",
  bucket: "bucket-name",
});

app.post("/api/get-signed-url/:type", async (req, res) => {
  try {
    const { type } = req.params;
    const params = req.body; // Contains key, mimeType, totalParts, etc.

    const signedUrl = await storage.getSignedUrl(
      "your-bucket-name",
      params.key,
      {
        type: type,
        ...params,
      }
    );

    res.send(signedUrl);
  } catch (error) {
    res.status(500).send(error.message);
  }
});
```

The endpoint should handle these types of requests:

| Type              | Description               | Required Parameters                   | Example Response                                                         |
| ----------------- | ------------------------- | ------------------------------------- | ------------------------------------------------------------------------ |
| upload            | Single file upload        | key, mimeType                         | `https://api.apexxcloud.com/upload?signature=...`                        |
| start-multipart   | Start multipart upload    | key, totalParts, mimeType             | `https://api.apexxcloud.com/multipart/start?signature=...`               |
| uploadpart        | Upload individual part    | uploadId, partNumber, key, totalParts | `https://api.apexxcloud.com/multipart/{uploadId}/upload?signature=...`   |
| completemultipart | Complete multipart upload | uploadId, key                         | `https://api.apexxcloud.com/multipart/{uploadId}/complete?signature=...` |
| cancelmultipart   | Cancel multipart upload   | uploadId, key                         | `https://api.apexxcloud.com/multipart/{uploadId}/cancel?signature=...`   |

## File Upload

### Basic Upload

```javascript theme={null}
const controller = new AbortController();

// Function to get signed URLs from your backend
const getSignedUrl = async (type, params) => {
  const response = await fetch(`/api/get-signed-url/${type}`, {
    method: "POST",
    body: JSON.stringify(params),
  });
  return response.text();
};

try {
  const result = await storage.files.upload(getSignedUrl, file, {
    signal: controller.signal,

    onStart: (event) => {
      console.log("Upload started:", event);
      // event.type: 'start'
      // event.timestamp: Start time
      // event.file: {
      //   name: string,
      //   size: number,
      //   type: string
      // }
    },

    onProgress: (event) => {
      console.log(`Upload progress: ${event.progress}%`);
      // event.loaded: Bytes uploaded
      // event.total: Total bytes
      // event.progress: Percentage complete (0-100)
      // event.type: 'progress'
    },

    onComplete: (event) => {
      console.log("Upload completed:", event);
      // event.type: 'complete'
      // event.response: Server response
      // event.timestamp: Completion time
      // event.file: File metadata
    },

    onError: (event) => {
      console.error("Upload failed:", event);
      // event.type: 'error' | 'abort'
      // event.error: Error object
      // event.timestamp: Error time
      // event.status?: HTTP status code (if applicable)
    },
  });
} catch (error) {
  console.error("Upload failed:", error);
}

// To cancel the upload:
controller.abort();
```

### Multipart Upload

```javascript theme={null}
const controller = new AbortController();

try {
  const result = await storage.files.uploadMultipart(getSignedUrl, file, {
    signal: controller.signal,
    partSize: 5 * 1024 * 1024, // 5MB chunks (optional)
    concurrency: 3, // Number of concurrent uploads (optional)

    onProgress: (event) => {
      console.log(`Total progress: ${event.progress}%`);
      console.log(
        `Part ${event.part.number} progress: ${event.part.progress}%`
      );
      // event.loaded: Total bytes uploaded
      // event.total: Total file size
      // event.progress: Overall percentage
      // event.part: {
      //   number: Current part number
      //   progress: Current part progress (0-100)
      // }
    },

    onPartComplete: (part) => {
      console.log("Part completed:", part);
      // part.ETag: Part ETag from server
      // part.PartNumber: Completed part number
    },

    onComplete: (event) => {
      console.log("Upload completed:", event);
      // event.type: 'complete'
      // event.response: Server response
      // event.timestamp: Completion time
      // event.file: File metadata
    },

    onError: (event) => {
      console.error("Upload error:", event);
      // event.type: 'error' | 'abort'
      // event.error: Error object
      // event.phase: 'start' | 'upload' | 'complete' | 'cancel'
      // event.status?: HTTP status code (if applicable)
      // event.timestamp: Error time
    },
  });
} catch (error) {
  console.error("Upload failed:", error);
}
```

### Error Handling

The SDK provides detailed error information through the onError callback:

```javascript theme={null}
try {
  await storage.files.upload(getSignedUrl, file, {
    onError: (event) => {
      if (event.type === "abort") {
        console.log("Upload was cancelled");
      } else {
        console.error("Upload failed:", event.error.message);
        if (event.status) {
          console.error("HTTP Status:", event.status);
        }
        if (event.phase) {
          // For multipart uploads
          console.error("Failed during phase:", event.phase);
        }
      }
    },
  });
} catch (error) {
  console.error("Upload failed:", error.message);
}
```

### Multipart Upload Phases

The multipart upload process includes different phases where errors might occur:

| Phase    | Description                                   |
| -------- | --------------------------------------------- |
| start    | During the initialization of multipart upload |
| upload   | During the upload of individual parts         |
| complete | During the completion of multipart upload     |
| cancel   | During attempt to cancel a failed upload      |

## Image Transformations

The SDK provides a powerful image transformation API that allows you to modify images on-the-fly:

```javascript theme={null}
const storage = new ApexxCloud({
  accessId: "your-access-id",
  cdnUrl: "https://cdn.apexxcloud.com", // optional
});

// Basic transformations
const url = storage.transformimage
  .width(800)
  .height(600)
  .crop("fill")
  .quality("auto:good")
  .buildUrl("path/to/image.jpg");

// Chaining multiple transformations
const complexUrl = storage.transformimage
  .width(800)
  .height(600)
  .crop("fill")
  .chain()
  .blur(20)
  .grayscale()
  .buildUrl("path/to/image.jpg");

// Text overlay
const withText = storage.transformimage
  .text("Hello World", {
    font: "Arial",
    size: 32,
    color: "#FFFFFF",
    gravity: "center",
    opacity: 100,
  })
  .buildUrl("path/to/image.jpg");

// Image overlay
const withImage = storage.transformimage
  .overlay("path/to/logo.png", {
    type: "image",
    gravity: "southeast",
    x: 20,
    y: 20,
    width: 100,
    opacity: 80,
  })
  .buildUrl("path/to/image.jpg");
```

### Available Image Transformations

| Transformation | Method                        | Parameters             | Example                         |
| -------------- | ----------------------------- | ---------------------- | ------------------------------- |
| Width          | `width(value)`                | 1-5000px               | `.width(800)`                   |
| Height         | `height(value)`               | 1-5000px               | `.height(600)`                  |
| Crop           | `crop(mode)`                  | 'fill', 'fit', 'scale' | `.crop('fill')`                 |
| Quality        | `quality(value)`              | 1-100 or auto modes    | `.quality('auto:good')`         |
| Format         | `format(type)`                | 'auto', 'webp', 'jpeg' | `.format('webp')`               |
| Blur           | `blur(radius)`                | 1-100                  | `.blur(20)`                     |
| Grayscale      | `grayscale()`                 | -                      | `.grayscale()`                  |
| Background     | `background(color)`           | hex or 'transparent'   | `.background('#ff0000')`        |
| Border         | `border(width, style, color)` | width, style, color    | `.border(2, 'solid', '#000')`   |
| Radius         | `radius(value)`               | pixels or array        | `.radius(10)`                   |
| Opacity        | `opacity(value)`              | 0-100                  | `.opacity(50)`                  |
| Text Overlay   | `text(text, options)`         | text, options          | `.text('Hello', options)`       |
| Image Overlay  | `overlay(path, options)`      | path, options          | `.overlay('logo.png', options)` |

### Overlay Options

| Option        | Type   | Description        | Supported Types |
| ------------- | ------ | ------------------ | --------------- |
| `type`        | string | 'image' or 'video' | Video only      |
| `gravity`     | string | Position on target | All             |
| `x`           | number | Horizontal offset  | All             |
| `y`           | number | Vertical offset    | All             |
| `scale`       | number | Scale factor       | Image, Video    |
| `width`       | number | Width in pixels    | Image, Video    |
| `height`      | number | Height in pixels   | Image, Video    |
| `opacity`     | number | Opacity (0-100)    | All             |
| `aspectRatio` | string | Aspect ratio       | Image, Video    |

Text-specific options:

| Option  | Type   | Description         |
| ------- | ------ | ------------------- |
| `font`  | string | Font family name    |
| `size`  | number | Font size in pixels |
| `color` | string | Text color (hex)    |

## Video Transformations

Similar to images, you can transform videos:

```javascript theme={null}
// Basic video transformation
const videoUrl = storage.transformvideo
  .width(1280)
  .height(720)
  .format("mp4")
  .buildUrl("path/to/video.mp4");

// Generate video thumbnail
const thumbnailUrl = storage.transformvideo
  .thumbnail(5.0) // Seek to 5 seconds
  .width(400)
  .height(300)
  .crop("fill")
  .buildUrl("path/to/video.mp4");

// Text overlay
const withText = storage.transformvideo
  .text("Hello World", {
    font: "Arial",
    size: 32,
    color: "#FFFFFF",
    gravity: "center",
    opacity: 100,
  })
  .buildUrl("path/to/video.mp4");

// Image overlay
const withImage = storage.transformvideo
  .overlay("path/to/logo.png", {
    type: "image",
    gravity: "southeast",
    x: 20,
    y: 20,
    width: 100,
    opacity: 80,
  })
  .buildUrl("path/to/video.mp4");

// Video overlay (for videos only)
const withVideoOverlay = storage.transformvideo
  .overlay("path/to/overlay.mp4", {
    type: "video",
    gravity: "center",
    width: 200,
    height: 200,
    opacity: 70,
  })
  .buildUrl("path/to/video.mp4");
```

### Available Video Transformations

| Transformation | Method                   | Parameters            | Example                            |
| -------------- | ------------------------ | --------------------- | ---------------------------------- |
| Width          | `width(value)`           | 1-5000px              | `.width(1280)`                     |
| Height         | `height(value)`          | 1-5000px              | `.height(720)`                     |
| Format         | `format(type)`           | 'mp4', 'webm', 'mov'  | `.format('mp4')`                   |
| Thumbnail      | `thumbnail(seekOffset)`  | seconds               | `.thumbnail(5.0)`                  |
| Crop           | `crop(mode)`             | 'crop', 'fill', 'fit' | `.crop('fill')`                    |
| Background     | `background(color)`      | hex or 'blur'         | `.background('blur')`              |
| Text Overlay   | `text(text, options)`    | text, options         | `.text('Title', options)`          |
| Image Overlay  | `overlay(path, options)` | path, options         | `.overlay('logo.png', imageOpts)`  |
| Video Overlay  | `overlay(path, options)` | path, options         | `.overlay('intro.mp4', videoOpts)` |

### Overlay Options

| Option        | Type   | Description        | Supported Types |
| ------------- | ------ | ------------------ | --------------- |
| `type`        | string | 'image' or 'video' | Video only      |
| `gravity`     | string | Position on target | All             |
| `x`           | number | Horizontal offset  | All             |
| `y`           | number | Vertical offset    | All             |
| `scale`       | number | Scale factor       | Image, Video    |
| `width`       | number | Width in pixels    | Image, Video    |
| `height`      | number | Height in pixels   | Image, Video    |
| `opacity`     | number | Opacity (0-100)    | All             |
| `aspectRatio` | string | Aspect ratio       | Image, Video    |

Text-specific options:

| Option  | Type   | Description         |
| ------- | ------ | ------------------- |
| `font`  | string | Font family name    |
| `size`  | number | Font size in pixels |
| `color` | string | Text color (hex)    |

## Document Transformations

Transform and convert documents:

```javascript theme={null}
// Convert document format
const pdfUrl = storage.transformdocument
  .format("pdf")
  .quality("auto:high")
  .buildUrl("path/to/document.docx");

// Generate document thumbnail
const thumbnailUrl = storage.transformdocument
  .thumbnail(1) // First page
  .width(800)
  .height(1200)
  .buildUrl("path/to/document.pdf");
```

### Available Document Transformations

| Transformation | Method            | Parameters                               | Example                 |
| -------------- | ----------------- | ---------------------------------------- | ----------------------- |
| Format         | `format(type)`    | 'pdf', 'docx', 'xlsx', 'pptx'            | `.format('pdf')`        |
| Quality        | `quality(mode)`   | 'auto:high', 'auto:standard', 'auto:low' | `.quality('auto:high')` |
| Compress       | `compress(mode)`  | 'high', 'medium', 'low'                  | `.compress('medium')`   |
| Pages          | `pages(range)`    | number or range ('1-3,5-7')              | `.pages('1-3')`         |
| Thumbnail      | `thumbnail(page)` | Page number                              | `.thumbnail(1)`         |

### Chaining Transformations

You can chain multiple transformations together using the `chain()` method:

```javascript theme={null}
const url = storage.transformimage
  .width(800)
  .height(600)
  .crop("fill")
  .chain()
  .blur(20)
  .grayscale()
  .buildUrl("path/to/image.jpg");
```

Each transformation chain is applied sequentially, allowing for complex transformation pipelines.
