mikes-php-image-handler 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +77 -0
- package/package.json +15 -0
- package/src/index.ts +100 -0
- package/tsconfig.json +13 -0
package/README.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# mikes-php-image-handler
|
|
2
|
+
|
|
3
|
+
A Node.js client for uploading and managing images on a custom PHP image server. It allows you to seamlessly upload images from a backend server (e.g. Express, Next.js) to a remote PHP server that optimizes them and stores them efficiently.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install mikes-php-image-handler
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage Example
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
const { VampireImageClient } = require('mikes-php-image-handler');
|
|
15
|
+
const fs = require('fs');
|
|
16
|
+
|
|
17
|
+
// Initialize the client
|
|
18
|
+
const imageClient = new VampireImageClient({
|
|
19
|
+
baseUrl: 'https://img.miketsak.gr',
|
|
20
|
+
apiKey: 'your_api_key_here'
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
async function run() {
|
|
24
|
+
// 1. Upload an Image
|
|
25
|
+
const fileBuffer = fs.readFileSync('./test-image.jpg');
|
|
26
|
+
// For buffers, you must provide a filename so the server knows the extension
|
|
27
|
+
const uploadResult = await imageClient.uploadImage(fileBuffer, 'test-image.jpg');
|
|
28
|
+
|
|
29
|
+
if (uploadResult.success) {
|
|
30
|
+
console.log('Image uploaded successfully!');
|
|
31
|
+
console.log('URL:', uploadResult.url);
|
|
32
|
+
} else {
|
|
33
|
+
console.error('Upload failed:', uploadResult.error);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// 2. Delete an Image
|
|
37
|
+
if (uploadResult.success) {
|
|
38
|
+
const deleteResult = await imageClient.deleteImage(uploadResult.filename);
|
|
39
|
+
if (deleteResult.success) {
|
|
40
|
+
console.log('Image deleted successfully!');
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
run();
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## API Reference
|
|
49
|
+
|
|
50
|
+
### `new VampireImageClient(options)`
|
|
51
|
+
- `options.baseUrl`: The URL of your PHP image API (e.g., `https://img.miketsak.gr`).
|
|
52
|
+
- `options.apiKey`: The secret API key used for authentication.
|
|
53
|
+
|
|
54
|
+
### `uploadImage(file, filename?)`
|
|
55
|
+
- `file`: Can be a `Buffer`, a `Blob`, or a `File` object.
|
|
56
|
+
- `filename`: Required if `file` is a Buffer. Represents the original name of the file (e.g., `avatar.png`).
|
|
57
|
+
- **Returns**: A Promise resolving to an object `{ success: boolean, url?: string, filename?: string, error?: string }`.
|
|
58
|
+
|
|
59
|
+
### `deleteImage(filename)`
|
|
60
|
+
- `filename`: The name of the file on the remote server to delete (e.g., `img_669cdb8a4f.jpg`).
|
|
61
|
+
- **Returns**: A Promise resolving to an object `{ success: boolean, message?: string, error?: string }`.
|
|
62
|
+
|
|
63
|
+
## License
|
|
64
|
+
ISC
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export interface VampireImageClientOptions {
|
|
2
|
+
apiKey: string;
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
}
|
|
5
|
+
export interface UploadResponse {
|
|
6
|
+
success?: boolean;
|
|
7
|
+
url?: string;
|
|
8
|
+
filename?: string;
|
|
9
|
+
error?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface DeleteResponse {
|
|
12
|
+
success?: boolean;
|
|
13
|
+
message?: string;
|
|
14
|
+
error?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare class VampireImageClient {
|
|
17
|
+
private apiKey;
|
|
18
|
+
private baseUrl;
|
|
19
|
+
constructor(options: VampireImageClientOptions);
|
|
20
|
+
private getHeaders;
|
|
21
|
+
/**
|
|
22
|
+
* Upload an image to the PHP server.
|
|
23
|
+
* @param file A standard File or Blob object (from browser)
|
|
24
|
+
* @param filename Optional filename (mainly for Node.js usage where Blob might not have a name)
|
|
25
|
+
*/
|
|
26
|
+
uploadImage(file: Blob, filename?: string): Promise<UploadResponse>;
|
|
27
|
+
/**
|
|
28
|
+
* Delete an image by its filename
|
|
29
|
+
* @param filename The exact filename (e.g., 'img_123.jpg')
|
|
30
|
+
*/
|
|
31
|
+
deleteImage(filename: string): Promise<DeleteResponse>;
|
|
32
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.VampireImageClient = void 0;
|
|
4
|
+
class VampireImageClient {
|
|
5
|
+
apiKey;
|
|
6
|
+
baseUrl;
|
|
7
|
+
constructor(options) {
|
|
8
|
+
this.apiKey = options.apiKey;
|
|
9
|
+
this.baseUrl = options.baseUrl.replace(/\/$/, '');
|
|
10
|
+
}
|
|
11
|
+
getHeaders(isFormData = false) {
|
|
12
|
+
const headers = {
|
|
13
|
+
'Authorization': `Bearer ${this.apiKey}`
|
|
14
|
+
};
|
|
15
|
+
if (!isFormData) {
|
|
16
|
+
headers['Content-Type'] = 'application/json';
|
|
17
|
+
}
|
|
18
|
+
return headers;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Upload an image to the PHP server.
|
|
22
|
+
* @param file A standard File or Blob object (from browser)
|
|
23
|
+
* @param filename Optional filename (mainly for Node.js usage where Blob might not have a name)
|
|
24
|
+
*/
|
|
25
|
+
async uploadImage(file, filename) {
|
|
26
|
+
const formData = new FormData();
|
|
27
|
+
if (filename) {
|
|
28
|
+
formData.append('image', file, filename);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
formData.append('image', file);
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
const response = await fetch(`${this.baseUrl}/upload`, {
|
|
35
|
+
method: 'POST',
|
|
36
|
+
headers: this.getHeaders(true),
|
|
37
|
+
body: formData
|
|
38
|
+
});
|
|
39
|
+
if (!response.ok) {
|
|
40
|
+
const text = await response.text();
|
|
41
|
+
throw new Error(`Upload failed with status ${response.status}: ${text}`);
|
|
42
|
+
}
|
|
43
|
+
const data = await response.json();
|
|
44
|
+
return data;
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
return {
|
|
48
|
+
error: error instanceof Error ? error.message : String(error)
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Delete an image by its filename
|
|
54
|
+
* @param filename The exact filename (e.g., 'img_123.jpg')
|
|
55
|
+
*/
|
|
56
|
+
async deleteImage(filename) {
|
|
57
|
+
try {
|
|
58
|
+
const response = await fetch(`${this.baseUrl}/delete`, {
|
|
59
|
+
method: 'DELETE',
|
|
60
|
+
headers: this.getHeaders(),
|
|
61
|
+
body: JSON.stringify({ filename })
|
|
62
|
+
});
|
|
63
|
+
if (!response.ok) {
|
|
64
|
+
const text = await response.text();
|
|
65
|
+
throw new Error(`Delete failed with status ${response.status}: ${text}`);
|
|
66
|
+
}
|
|
67
|
+
const data = await response.json();
|
|
68
|
+
return data;
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
return {
|
|
72
|
+
error: error instanceof Error ? error.message : String(error)
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.VampireImageClient = VampireImageClient;
|
package/package.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mikes-php-image-handler",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A Node.js client for uploading and managing images on a custom PHP image server.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"watch": "tsc -w"
|
|
10
|
+
},
|
|
11
|
+
"devDependencies": {
|
|
12
|
+
"typescript": "^5.0.0",
|
|
13
|
+
"@types/node": "^20.0.0"
|
|
14
|
+
}
|
|
15
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
export interface VampireImageClientOptions {
|
|
2
|
+
apiKey: string;
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface UploadResponse {
|
|
7
|
+
success?: boolean;
|
|
8
|
+
url?: string;
|
|
9
|
+
filename?: string;
|
|
10
|
+
error?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface DeleteResponse {
|
|
14
|
+
success?: boolean;
|
|
15
|
+
message?: string;
|
|
16
|
+
error?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class VampireImageClient {
|
|
20
|
+
private apiKey: string;
|
|
21
|
+
private baseUrl: string;
|
|
22
|
+
|
|
23
|
+
constructor(options: VampireImageClientOptions) {
|
|
24
|
+
this.apiKey = options.apiKey;
|
|
25
|
+
this.baseUrl = options.baseUrl.replace(/\/$/, '');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
private getHeaders(isFormData = false): HeadersInit {
|
|
29
|
+
const headers: HeadersInit = {
|
|
30
|
+
'Authorization': `Bearer ${this.apiKey}`
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
if (!isFormData) {
|
|
34
|
+
headers['Content-Type'] = 'application/json';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return headers;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Upload an image to the PHP server.
|
|
42
|
+
* @param file A standard File or Blob object (from browser)
|
|
43
|
+
* @param filename Optional filename (mainly for Node.js usage where Blob might not have a name)
|
|
44
|
+
*/
|
|
45
|
+
async uploadImage(file: Blob, filename?: string): Promise<UploadResponse> {
|
|
46
|
+
const formData = new FormData();
|
|
47
|
+
|
|
48
|
+
if (filename) {
|
|
49
|
+
formData.append('image', file, filename);
|
|
50
|
+
} else {
|
|
51
|
+
formData.append('image', file);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
const response = await fetch(`${this.baseUrl}/upload`, {
|
|
56
|
+
method: 'POST',
|
|
57
|
+
headers: this.getHeaders(true),
|
|
58
|
+
body: formData
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
if (!response.ok) {
|
|
62
|
+
const text = await response.text();
|
|
63
|
+
throw new Error(`Upload failed with status ${response.status}: ${text}`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const data: UploadResponse = await response.json();
|
|
67
|
+
return data;
|
|
68
|
+
} catch (error) {
|
|
69
|
+
return {
|
|
70
|
+
error: error instanceof Error ? error.message : String(error)
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Delete an image by its filename
|
|
77
|
+
* @param filename The exact filename (e.g., 'img_123.jpg')
|
|
78
|
+
*/
|
|
79
|
+
async deleteImage(filename: string): Promise<DeleteResponse> {
|
|
80
|
+
try {
|
|
81
|
+
const response = await fetch(`${this.baseUrl}/delete`, {
|
|
82
|
+
method: 'DELETE',
|
|
83
|
+
headers: this.getHeaders(),
|
|
84
|
+
body: JSON.stringify({ filename })
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
if (!response.ok) {
|
|
88
|
+
const text = await response.text();
|
|
89
|
+
throw new Error(`Delete failed with status ${response.status}: ${text}`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const data: DeleteResponse = await response.json();
|
|
93
|
+
return data;
|
|
94
|
+
} catch (error) {
|
|
95
|
+
return {
|
|
96
|
+
error: error instanceof Error ? error.message : String(error)
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es2022",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"declaration": true,
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"strict": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"forceConsistentCasingInFileNames": true
|
|
11
|
+
},
|
|
12
|
+
"include": ["src/**/*"]
|
|
13
|
+
}
|