Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 169 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,175 @@
# NullDrop SDK 🚀
# NullDrop SDK

**title**
Official TypeScript/JavaScript SDK for NullDrop file sharing service

[![TypeScript](https://img.shields.io/badge/TypeScript-5.1.0-blue)](https://www.typescriptlang.org/)
[![npm](https://img.shields.io/badge/npm-ready-green)](https://www.npmjs.com/)
[![License](https://img.shields.io/badge/license-GPL-blue)](LICENSE)
[![License](https://img.shields.io/badge/version-1.0.0-blue)](LICENSE)
[![API Version](https://img.shields.io/badge/API-v2-green)](https://docs.nulldrop.xyz/migrating-to-v2)

to do
## Features

- **API v2 by default** - Latest performance optimizations
- **Privacy Controls** - Public/private file uploads
- **Bulk Operations** - Upload and delete multiple files efficiently
- **Backward Compatible** - Full support for v1 API
- **Universal** - Works in browsers and Node.js
- **TypeScript** - Full type safety and IntelliSense
- **Error Handling** - Comprehensive error types and validation
- **Performance** - Built-in retry logic and request monitoring
- **Developer Friendly** - Fluent API with smart defaults

## Installation

```bash
npm install @nulldrop/sdk
```

## Quick Start

### Basic Usage (v2 API)

```javascript
import { NullDropClient } from '@nulldrop/sdk';

// Initialize client (v2 by default)
const client = new NullDropClient({
apiKey: 'your-api-key' // or set NULLDROP_API_KEY env var
});

// Upload a file with privacy control (v2 feature)
const result = await client.upload(file, { isPublic: false });
console.log(`Uploaded: ${result.filename} (Private: ${!result.isFilePublic()})`);

// Bulk upload multiple files (v2 feature)
const files = [file1, file2, file3];
const bulkResult = await client.uploadBulk(files, {
isPublic: true,
maxConcurrent: 3
});
console.log(`Uploaded ${bulkResult.totalUploaded} files successfully`);
```

### v1 API Compatibility

```javascript
// Explicitly use v1 API if needed
const clientV1 = new NullDropClient({
apiKey: 'your-api-key',
apiVersion: 'v1'
});

const result = await clientV1.upload(file); // v1 behavior
```

## What's New in v2

### Enhanced Upload Response
```javascript
const result = await client.upload(file, { isPublic: false });

// New v2 properties
console.log('Privacy:', result.isFilePublic()); // boolean
console.log('Performance:', result.getPerformanceMs()); // number (ms)
console.log('Formatted:', result.getFormattedPerformance()); // "45ms"
```

### Bulk Operations
```javascript
// Bulk Upload
const uploadResult = await client.uploadBulk(files, {
isPublic: false,
maxConcurrent: 3
});

// Bulk Delete
const deleteResult = await client.deleteBulk(fileIds, {
maxConcurrent: 5
});

console.log(`Success: ${uploadResult.totalUploaded}, Failed: ${uploadResult.totalFailed}`);
```

### Performance & Privacy
- **isPublic parameter**: Control file visibility
- **_perf field**: Request duration in milliseconds
- **Bulk operations**: Parallel processing for better performance
- **Backward compatible**: All v1 code continues to work


## Configuration

```javascript
const client = new NullDropClient({
apiKey: 'your-api-key', // Required (or NULLDROP_API_KEY env var)
apiVersion: 'v2', // 'v1' or 'v2' (default: v2)
baseUrl: 'https://nulldrop.xyz/api', // API base URL
timeout: 30000, // Request timeout (ms)
retryAttempts: 3, // Retry failed requests
debug: false // Enable debug logging
});
```

## API Methods

### Upload Operations
- `upload(file, options?)` - Upload single file with v2 options
- `uploadBulk(files, options?)` - Upload multiple files (v2 only)

### File Management
- `listFiles(options?)` - List uploaded files with pagination
- `getFile(fileId)` - Get file details
- `deleteFile(fileId)` - Delete single file
- `deleteBulk(fileIds, options?)` - Delete multiple files (v2 only)

### Utility Methods
- `getDownloadUrl(fileId)` - Get direct download URL
- `getShareUrl(fileId)` - Get shareable URL
- `fileExists(fileId)` - Check if file exists
- `getFileCount()` - Get total file count
- `getApiVersion()` - Get current API version
- `isV2Api()` - Check if using v2 API

## Error Handling

```javascript
import { ValidationError, AuthenticationError, RateLimitError } from '@nulldrop/sdk';

try {
const result = await client.upload(file);
} catch (error) {
if (error instanceof ValidationError) {
console.error('Validation failed:', error.message);
} else if (error instanceof AuthenticationError) {
console.error('Auth failed:', error.message);
} else if (error instanceof RateLimitError) {
console.error('Rate limited:', error.retryAfter);
}
}
```

## Environment Support

- √ **Node.js** 16+
- √ **Modern browsers** (Chrome, Firefox, Safari, Edge)
- √ **Web Workers**
- √ **TypeScript** 4.0+
- √ **ESM & CommonJS**


## Contributing

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request


## License

This project is licensed under the GPL License - see the [LICENSE](LICENSE) file for details.

---

**Made with ❤️ by [Null Tools](https://github.com/Null-Tools-Open)**
17 changes: 10 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
{
"name": "nulldrop-sdk",
"version": "1.0.0",
"name": "@nulldrop/sdk",
"version": "2.0.0",
"publishConfig": {
"access": "public"
},
"description": "Official SDK for Null Drop file upload service",
"main": "dist/index.js",
"module": "dist/index.esm.js",
Expand All @@ -27,16 +30,16 @@
"javascript",
"api-client"
],
"author": "Your Name",
"license": "MIT",
"author": "Null Tools",
"license": "GPL",
"repository": {
"type": "git",
"url": "https://github.com/yourusername/nulldrop-sdk.git"
"url": "https://github.com/Null-Tools-Open/nulldrop-sdk-js-ts.git"
},
"bugs": {
"url": "https://github.com/yourusername/nulldrop-sdk/issues"
"url": "https://github.com/Null-Tools-Open/nulldrop-sdk-js-ts/issues"
},
"homepage": "https://github.com/yourusername/nulldrop-sdk#readme",
"homepage": "https://github.com/Null-Tools-Open/nulldrop-sdk-js-ts#readme",
"files": [
"dist"
],
Expand Down
54 changes: 53 additions & 1 deletion src/client/FluentWrappers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ export class FluentUploadResult implements UploadResponse {
readonly downloadUrl: string;
readonly shareUrl: string;
readonly uploadedAt: string;
// v2 API fields
readonly isPublic?: boolean;
readonly _perf?: number;

constructor(private client: NullDropClient, result: UploadResponse) {
this.id = result.id;
Expand All @@ -20,6 +23,13 @@ export class FluentUploadResult implements UploadResponse {
this.downloadUrl = result.downloadUrl;
this.shareUrl = result.shareUrl;
this.uploadedAt = result.uploadedAt;
// v2 API fields
if (result.isPublic !== undefined) {
this.isPublic = result.isPublic;
}
if (result._perf !== undefined) {
this._perf = result._perf;
}
}

async getDetails(): Promise<FileDetails> {
Expand Down Expand Up @@ -75,8 +85,40 @@ export class FluentUploadResult implements UploadResponse {
return `${diffDays} day${diffDays > 1 ? 's' : ''} ago`;
}

/**
* Check if file is public (v2 API)
* @returns True if file is public, false if private, undefined if not available (v1 API)
*/
isFilePublic(): boolean | undefined {
return this.isPublic;
}

/**
* Get performance information (v2 API)
* @returns Request duration in milliseconds, undefined if not available (v1 API)
*/
getPerformanceMs(): number | undefined {
return this._perf;
}

/**
* Get formatted performance information (v2 API)
* @returns Formatted performance string or 'N/A' if not available
*/
getFormattedPerformance(): string {
return this._perf !== undefined ? `${this._perf}ms` : 'N/A';
}

/**
* Check if this result includes v2 API features
* @returns True if v2 features are available
*/
hasV2Features(): boolean {
return this.isPublic !== undefined || this._perf !== undefined;
}

toJSON(): UploadResponse {
return {
const result: UploadResponse = {
id: this.id,
filename: this.filename,
size: this.size,
Expand All @@ -85,5 +127,15 @@ export class FluentUploadResult implements UploadResponse {
shareUrl: this.shareUrl,
uploadedAt: this.uploadedAt
};

// Include v2 fields if available
if (this.isPublic !== undefined) {
result.isPublic = this.isPublic;
}
if (this._perf !== undefined) {
result._perf = this._perf;
}

return result;
}
}
Loading
Loading