@signskart/uploader 2.0.6 → 2.0.8
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/dist/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +37 -1
- package/dist/index.mjs.map +1 -1
- package/dist/server/index.js +2 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +2 -1
- package/dist/server/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var clientS3 = require('@aws-sdk/client-s3');
|
|
4
|
+
var s3RequestPresigner = require('@aws-sdk/s3-request-presigner');
|
|
5
|
+
|
|
3
6
|
// src/core/EventEmitter.ts
|
|
4
7
|
var EventEmitter = class {
|
|
5
8
|
constructor() {
|
|
@@ -181,10 +184,44 @@ var CloudinaryUploader = class extends BaseUploader {
|
|
|
181
184
|
});
|
|
182
185
|
}
|
|
183
186
|
};
|
|
187
|
+
function createS3PresignHandler(config) {
|
|
188
|
+
const s3 = new clientS3.S3Client({
|
|
189
|
+
region: config.region,
|
|
190
|
+
credentials: {
|
|
191
|
+
accessKeyId: config.accessKeyId,
|
|
192
|
+
secretAccessKey: config.secretAccessKey
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
return async function generatePresignedUpload({
|
|
196
|
+
fileName,
|
|
197
|
+
contentType,
|
|
198
|
+
folder
|
|
199
|
+
}) {
|
|
200
|
+
if (!fileName || !contentType) {
|
|
201
|
+
throw new Error("fileName and contentType are required");
|
|
202
|
+
}
|
|
203
|
+
const safeFileName = fileName.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
204
|
+
const key = `${folder || "uploads"}/${Date.now()}-${safeFileName}`;
|
|
205
|
+
const command = new clientS3.PutObjectCommand({
|
|
206
|
+
Bucket: config.bucket,
|
|
207
|
+
Key: key,
|
|
208
|
+
ContentType: contentType
|
|
209
|
+
});
|
|
210
|
+
const signedUrl = await s3RequestPresigner.getSignedUrl(s3, command, {
|
|
211
|
+
expiresIn: config.expiresIn ?? 300
|
|
212
|
+
});
|
|
213
|
+
return {
|
|
214
|
+
signedUrl,
|
|
215
|
+
key,
|
|
216
|
+
publicUrl: `${config.publicUrl}/${key}`
|
|
217
|
+
};
|
|
218
|
+
};
|
|
219
|
+
}
|
|
184
220
|
|
|
185
221
|
exports.CloudinaryUploader = CloudinaryUploader;
|
|
186
222
|
exports.S3Uploader = S3Uploader;
|
|
187
223
|
exports.UploadManager = UploadManager;
|
|
188
224
|
exports.UploadTask = UploadTask;
|
|
225
|
+
exports.createS3PresignHandler = createS3PresignHandler;
|
|
189
226
|
//# sourceMappingURL=index.js.map
|
|
190
227
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/EventEmitter.ts","../src/core/UploadTask.ts","../src/core/UploadManager.ts","../src/core/BaseUploader.ts","../src/providers/S3Uploader.ts","../src/providers/CloudinaryUploader.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["type Listener<T> = (payload: T) => void;\n\nexport class EventEmitter<T> {\n private listeners: Listener<T>[] = [];\n\n subscribe(listener: Listener<T>) {\n this.listeners.push(listener);\n return () => {\n this.listeners = this.listeners.filter(l => l !== listener);\n };\n }\n\n emit(payload: T) {\n this.listeners.forEach(listener => listener(payload));\n }\n}","import { BaseUploader } from './BaseUploader';\nimport { UploadOptions, UploadTaskState } from './types';\nimport { EventEmitter } from './EventEmitter';\n\nexport class UploadTask {\n public state: UploadTaskState;\n public events = new EventEmitter<UploadTaskState>();\n private abortController = new AbortController();\n private retries = 0;\n\n constructor(\n private uploader: BaseUploader,\n private options: UploadOptions,\n private maxRetries = 2,\n private retryDelay = 500\n ) {\n this.state = {\n id: crypto.randomUUID(),\n progress: 0,\n status: 'queued'\n };\n }\n\n async start(): Promise<void> {\n this.update({ status: 'uploading' });\n\n while (this.retries <= this.maxRetries) {\n try {\n const response = await this.uploader.upload(\n this.options,\n progress => this.update({ progress }),\n this.abortController.signal\n );\n\n this.update({ status: 'success', progress: 100, response });\n return;\n } catch (error: unknown) {\n if (this.abortController.signal.aborted) {\n this.update({ status: 'cancelled' });\n return;\n }\n\n const message = error instanceof Error ? error.message : 'Unknown upload error';\n\n if (this.retries >= this.maxRetries) {\n this.update({ status: 'error', error: message });\n return;\n }\n\n this.retries++;\n await this.sleep(this.retryDelay * Math.pow(2, this.retries - 1));\n }\n }\n }\n\n cancel() {\n this.abortController.abort();\n this.update({ status: 'cancelled' });\n }\n\n private update(update: Partial<UploadTaskState>) {\n this.state = { ...this.state, ...update };\n this.events.emit(this.state);\n }\n\n private sleep(ms: number) {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n}","import { BaseUploader } from './BaseUploader';\nimport { UploadOptions } from './types';\nimport { UploadTask } from './UploadTask';\n\nexport class UploadManager {\n private queue: UploadTask[] = [];\n private active = 0;\n\n constructor(private uploader: BaseUploader, private concurrency = 3) { }\n\n add(options: UploadOptions) {\n const task = new UploadTask(this.uploader, options);\n this.queue.push(task);\n this.process();\n return task;\n }\n\n private async process() {\n if (this.active >= this.concurrency) return;\n\n const next = this.queue.find(t => t.state.status === 'queued');\n if (!next) return;\n\n this.active++;\n await next.start();\n this.active--;\n this.process();\n }\n}","import { UploadOptions, UploadResponse } from './types';\n\nexport abstract class BaseUploader {\n abstract upload(options: UploadOptions, onProgress: (percent: number) => void, signal?: AbortSignal): Promise<UploadResponse>;\n}","import { BaseUploader } from '../core/BaseUploader';\nimport { UploadOptions, UploadResponse } from '../core/types';\n\ninterface S3Config {\n apiBaseUrl: string;\n publicUrl: string;\n}\n\nexport class S3Uploader extends BaseUploader {\n constructor(private config: S3Config) {\n super();\n }\n\n async upload(\n options: UploadOptions,\n onProgress: (percent: number) => void,\n signal?: AbortSignal\n ): Promise<UploadResponse> {\n const presignRes = await fetch(`${this.config.apiBaseUrl}/api/s3/presign-upload`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n fileName: options.fileName || options.file.name,\n folder: options.folder,\n contentType: options.file.type\n })\n });\n\n if (!presignRes.ok) throw new Error('Failed to get presigned URL');\n\n const { signedUrl, key } = await presignRes.json();\n\n if (!signedUrl || !key) throw new Error('Invalid presign response');\n\n return new Promise<UploadResponse>((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n\n xhr.upload.onprogress = event => {\n if (event.lengthComputable) {\n onProgress(Math.round((event.loaded / event.total) * 100));\n }\n };\n\n xhr.onload = () => {\n if (xhr.status === 200) {\n resolve({\n url: `${this.config.publicUrl}/${key}`,\n provider: 's3',\n key,\n });\n } else {\n reject(new Error(`S3 upload failed with status ${xhr.status}`));\n }\n };\n\n xhr.onerror = () => reject(new Error('S3 upload network error'));\n\n signal?.addEventListener('abort', () => {\n xhr.abort();\n reject(new Error('Upload cancelled'));\n });\n\n xhr.open('PUT', signedUrl);\n xhr.setRequestHeader('Content-Type', options.file.type);\n xhr.send(options.file);\n });\n }\n}","import { BaseUploader } from '../core/BaseUploader';\nimport { UploadOptions, UploadResponse } from '../core/types';\n\ninterface CloudinaryConfig {\n cloudName: string;\n uploadPreset: string;\n}\n\nexport class CloudinaryUploader extends BaseUploader {\n constructor(private config: CloudinaryConfig) {\n super();\n }\n\n async upload(\n options: UploadOptions,\n onProgress: (percent: number) => void\n ): Promise<UploadResponse> {\n const formData = new FormData();\n formData.append('file', options.file);\n formData.append('upload_preset', this.config.uploadPreset);\n formData.append('folder', options.folder);\n\n return new Promise((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n\n xhr.upload.onprogress = event => {\n if (event.lengthComputable) {\n onProgress(Math.round((event.loaded / event.total) * 100));\n }\n };\n\n xhr.onload = () => {\n const data = JSON.parse(xhr.responseText);\n if (xhr.status === 200 && data.secure_url) {\n resolve({ url: data.secure_url, provider: 'cloudinary' });\n } else {\n reject(new Error('Cloudinary upload failed'));\n }\n };\n\n xhr.onerror = () => reject(new Error('Cloudinary upload failed'));\n\n xhr.open('POST', `https://api.cloudinary.com/v1_1/${this.config.cloudName}/upload`);\n xhr.send(formData);\n });\n }\n}"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/EventEmitter.ts","../src/core/UploadTask.ts","../src/core/UploadManager.ts","../src/core/BaseUploader.ts","../src/providers/S3Uploader.ts","../src/providers/CloudinaryUploader.ts","../src/server/createS3PresignHandler.ts"],"names":["S3Client","PutObjectCommand","getSignedUrl"],"mappings":"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","file":"index.js","sourcesContent":["type Listener<T> = (payload: T) => void;\n\nexport class EventEmitter<T> {\n private listeners: Listener<T>[] = [];\n\n subscribe(listener: Listener<T>) {\n this.listeners.push(listener);\n return () => {\n this.listeners = this.listeners.filter(l => l !== listener);\n };\n }\n\n emit(payload: T) {\n this.listeners.forEach(listener => listener(payload));\n }\n}","import { BaseUploader } from './BaseUploader';\nimport { UploadOptions, UploadTaskState } from './types';\nimport { EventEmitter } from './EventEmitter';\n\nexport class UploadTask {\n public state: UploadTaskState;\n public events = new EventEmitter<UploadTaskState>();\n private abortController = new AbortController();\n private retries = 0;\n\n constructor(\n private uploader: BaseUploader,\n private options: UploadOptions,\n private maxRetries = 2,\n private retryDelay = 500\n ) {\n this.state = {\n id: crypto.randomUUID(),\n progress: 0,\n status: 'queued'\n };\n }\n\n async start(): Promise<void> {\n this.update({ status: 'uploading' });\n\n while (this.retries <= this.maxRetries) {\n try {\n const response = await this.uploader.upload(\n this.options,\n progress => this.update({ progress }),\n this.abortController.signal\n );\n\n this.update({ status: 'success', progress: 100, response });\n return;\n } catch (error: unknown) {\n if (this.abortController.signal.aborted) {\n this.update({ status: 'cancelled' });\n return;\n }\n\n const message = error instanceof Error ? error.message : 'Unknown upload error';\n\n if (this.retries >= this.maxRetries) {\n this.update({ status: 'error', error: message });\n return;\n }\n\n this.retries++;\n await this.sleep(this.retryDelay * Math.pow(2, this.retries - 1));\n }\n }\n }\n\n cancel() {\n this.abortController.abort();\n this.update({ status: 'cancelled' });\n }\n\n private update(update: Partial<UploadTaskState>) {\n this.state = { ...this.state, ...update };\n this.events.emit(this.state);\n }\n\n private sleep(ms: number) {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n}","import { BaseUploader } from './BaseUploader';\nimport { UploadOptions } from './types';\nimport { UploadTask } from './UploadTask';\n\nexport class UploadManager {\n private queue: UploadTask[] = [];\n private active = 0;\n\n constructor(private uploader: BaseUploader, private concurrency = 3) { }\n\n add(options: UploadOptions) {\n const task = new UploadTask(this.uploader, options);\n this.queue.push(task);\n this.process();\n return task;\n }\n\n private async process() {\n if (this.active >= this.concurrency) return;\n\n const next = this.queue.find(t => t.state.status === 'queued');\n if (!next) return;\n\n this.active++;\n await next.start();\n this.active--;\n this.process();\n }\n}","import { UploadOptions, UploadResponse } from './types';\n\nexport abstract class BaseUploader {\n abstract upload(options: UploadOptions, onProgress: (percent: number) => void, signal?: AbortSignal): Promise<UploadResponse>;\n}","import { BaseUploader } from '../core/BaseUploader';\nimport { UploadOptions, UploadResponse } from '../core/types';\n\ninterface S3Config {\n apiBaseUrl: string;\n publicUrl: string;\n}\n\nexport class S3Uploader extends BaseUploader {\n constructor(private config: S3Config) {\n super();\n }\n\n async upload(\n options: UploadOptions,\n onProgress: (percent: number) => void,\n signal?: AbortSignal\n ): Promise<UploadResponse> {\n const presignRes = await fetch(`${this.config.apiBaseUrl}/api/s3/presign-upload`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n fileName: options.fileName || options.file.name,\n folder: options.folder,\n contentType: options.file.type\n })\n });\n\n if (!presignRes.ok) throw new Error('Failed to get presigned URL');\n\n const { signedUrl, key } = await presignRes.json();\n\n if (!signedUrl || !key) throw new Error('Invalid presign response');\n\n return new Promise<UploadResponse>((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n\n xhr.upload.onprogress = event => {\n if (event.lengthComputable) {\n onProgress(Math.round((event.loaded / event.total) * 100));\n }\n };\n\n xhr.onload = () => {\n if (xhr.status === 200) {\n resolve({\n url: `${this.config.publicUrl}/${key}`,\n provider: 's3',\n key,\n });\n } else {\n reject(new Error(`S3 upload failed with status ${xhr.status}`));\n }\n };\n\n xhr.onerror = () => reject(new Error('S3 upload network error'));\n\n signal?.addEventListener('abort', () => {\n xhr.abort();\n reject(new Error('Upload cancelled'));\n });\n\n xhr.open('PUT', signedUrl);\n xhr.setRequestHeader('Content-Type', options.file.type);\n xhr.send(options.file);\n });\n }\n}","import { BaseUploader } from '../core/BaseUploader';\nimport { UploadOptions, UploadResponse } from '../core/types';\n\ninterface CloudinaryConfig {\n cloudName: string;\n uploadPreset: string;\n}\n\nexport class CloudinaryUploader extends BaseUploader {\n constructor(private config: CloudinaryConfig) {\n super();\n }\n\n async upload(\n options: UploadOptions,\n onProgress: (percent: number) => void\n ): Promise<UploadResponse> {\n const formData = new FormData();\n formData.append('file', options.file);\n formData.append('upload_preset', this.config.uploadPreset);\n formData.append('folder', options.folder);\n\n return new Promise((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n\n xhr.upload.onprogress = event => {\n if (event.lengthComputable) {\n onProgress(Math.round((event.loaded / event.total) * 100));\n }\n };\n\n xhr.onload = () => {\n const data = JSON.parse(xhr.responseText);\n if (xhr.status === 200 && data.secure_url) {\n resolve({ url: data.secure_url, provider: 'cloudinary' });\n } else {\n reject(new Error('Cloudinary upload failed'));\n }\n };\n\n xhr.onerror = () => reject(new Error('Cloudinary upload failed'));\n\n xhr.open('POST', `https://api.cloudinary.com/v1_1/${this.config.cloudName}/upload`);\n xhr.send(formData);\n });\n }\n}","import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';\nimport { getSignedUrl } from '@aws-sdk/s3-request-presigner';\n\nexport interface PresignConfig {\n region: string;\n accessKeyId: string;\n secretAccessKey: string;\n bucket: string;\n publicUrl: string;\n expiresIn?: number;\n}\n\nexport interface PresignRequest {\n fileName: string;\n contentType: string;\n folder?: string;\n}\n\nexport function createS3PresignHandler(config: PresignConfig) {\n const s3 = new S3Client({\n region: config.region,\n credentials: {\n accessKeyId: config.accessKeyId,\n secretAccessKey: config.secretAccessKey,\n },\n });\n\n return async function generatePresignedUpload({\n fileName,\n contentType,\n folder,\n }: PresignRequest) {\n if (!fileName || !contentType) {\n throw new Error('fileName and contentType are required');\n }\n\n const safeFileName = fileName.replace(/[^a-zA-Z0-9._-]/g, \"_\");\n const key = `${folder || 'uploads'}/${Date.now()}-${safeFileName}`;\n\n const command = new PutObjectCommand({\n Bucket: config.bucket,\n Key: key,\n ContentType: contentType,\n });\n\n const signedUrl = await getSignedUrl(s3, command, {\n expiresIn: config.expiresIn ?? 300,\n });\n\n return {\n signedUrl,\n key,\n publicUrl: `${config.publicUrl}/${key}`,\n };\n };\n}"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
|
|
2
|
+
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
|
|
3
|
+
|
|
1
4
|
// src/core/EventEmitter.ts
|
|
2
5
|
var EventEmitter = class {
|
|
3
6
|
constructor() {
|
|
@@ -179,7 +182,40 @@ var CloudinaryUploader = class extends BaseUploader {
|
|
|
179
182
|
});
|
|
180
183
|
}
|
|
181
184
|
};
|
|
185
|
+
function createS3PresignHandler(config) {
|
|
186
|
+
const s3 = new S3Client({
|
|
187
|
+
region: config.region,
|
|
188
|
+
credentials: {
|
|
189
|
+
accessKeyId: config.accessKeyId,
|
|
190
|
+
secretAccessKey: config.secretAccessKey
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
return async function generatePresignedUpload({
|
|
194
|
+
fileName,
|
|
195
|
+
contentType,
|
|
196
|
+
folder
|
|
197
|
+
}) {
|
|
198
|
+
if (!fileName || !contentType) {
|
|
199
|
+
throw new Error("fileName and contentType are required");
|
|
200
|
+
}
|
|
201
|
+
const safeFileName = fileName.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
202
|
+
const key = `${folder || "uploads"}/${Date.now()}-${safeFileName}`;
|
|
203
|
+
const command = new PutObjectCommand({
|
|
204
|
+
Bucket: config.bucket,
|
|
205
|
+
Key: key,
|
|
206
|
+
ContentType: contentType
|
|
207
|
+
});
|
|
208
|
+
const signedUrl = await getSignedUrl(s3, command, {
|
|
209
|
+
expiresIn: config.expiresIn ?? 300
|
|
210
|
+
});
|
|
211
|
+
return {
|
|
212
|
+
signedUrl,
|
|
213
|
+
key,
|
|
214
|
+
publicUrl: `${config.publicUrl}/${key}`
|
|
215
|
+
};
|
|
216
|
+
};
|
|
217
|
+
}
|
|
182
218
|
|
|
183
|
-
export { CloudinaryUploader, S3Uploader, UploadManager, UploadTask };
|
|
219
|
+
export { CloudinaryUploader, S3Uploader, UploadManager, UploadTask, createS3PresignHandler };
|
|
184
220
|
//# sourceMappingURL=index.mjs.map
|
|
185
221
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/EventEmitter.ts","../src/core/UploadTask.ts","../src/core/UploadManager.ts","../src/core/BaseUploader.ts","../src/providers/S3Uploader.ts","../src/providers/CloudinaryUploader.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["type Listener<T> = (payload: T) => void;\n\nexport class EventEmitter<T> {\n private listeners: Listener<T>[] = [];\n\n subscribe(listener: Listener<T>) {\n this.listeners.push(listener);\n return () => {\n this.listeners = this.listeners.filter(l => l !== listener);\n };\n }\n\n emit(payload: T) {\n this.listeners.forEach(listener => listener(payload));\n }\n}","import { BaseUploader } from './BaseUploader';\nimport { UploadOptions, UploadTaskState } from './types';\nimport { EventEmitter } from './EventEmitter';\n\nexport class UploadTask {\n public state: UploadTaskState;\n public events = new EventEmitter<UploadTaskState>();\n private abortController = new AbortController();\n private retries = 0;\n\n constructor(\n private uploader: BaseUploader,\n private options: UploadOptions,\n private maxRetries = 2,\n private retryDelay = 500\n ) {\n this.state = {\n id: crypto.randomUUID(),\n progress: 0,\n status: 'queued'\n };\n }\n\n async start(): Promise<void> {\n this.update({ status: 'uploading' });\n\n while (this.retries <= this.maxRetries) {\n try {\n const response = await this.uploader.upload(\n this.options,\n progress => this.update({ progress }),\n this.abortController.signal\n );\n\n this.update({ status: 'success', progress: 100, response });\n return;\n } catch (error: unknown) {\n if (this.abortController.signal.aborted) {\n this.update({ status: 'cancelled' });\n return;\n }\n\n const message = error instanceof Error ? error.message : 'Unknown upload error';\n\n if (this.retries >= this.maxRetries) {\n this.update({ status: 'error', error: message });\n return;\n }\n\n this.retries++;\n await this.sleep(this.retryDelay * Math.pow(2, this.retries - 1));\n }\n }\n }\n\n cancel() {\n this.abortController.abort();\n this.update({ status: 'cancelled' });\n }\n\n private update(update: Partial<UploadTaskState>) {\n this.state = { ...this.state, ...update };\n this.events.emit(this.state);\n }\n\n private sleep(ms: number) {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n}","import { BaseUploader } from './BaseUploader';\nimport { UploadOptions } from './types';\nimport { UploadTask } from './UploadTask';\n\nexport class UploadManager {\n private queue: UploadTask[] = [];\n private active = 0;\n\n constructor(private uploader: BaseUploader, private concurrency = 3) { }\n\n add(options: UploadOptions) {\n const task = new UploadTask(this.uploader, options);\n this.queue.push(task);\n this.process();\n return task;\n }\n\n private async process() {\n if (this.active >= this.concurrency) return;\n\n const next = this.queue.find(t => t.state.status === 'queued');\n if (!next) return;\n\n this.active++;\n await next.start();\n this.active--;\n this.process();\n }\n}","import { UploadOptions, UploadResponse } from './types';\n\nexport abstract class BaseUploader {\n abstract upload(options: UploadOptions, onProgress: (percent: number) => void, signal?: AbortSignal): Promise<UploadResponse>;\n}","import { BaseUploader } from '../core/BaseUploader';\nimport { UploadOptions, UploadResponse } from '../core/types';\n\ninterface S3Config {\n apiBaseUrl: string;\n publicUrl: string;\n}\n\nexport class S3Uploader extends BaseUploader {\n constructor(private config: S3Config) {\n super();\n }\n\n async upload(\n options: UploadOptions,\n onProgress: (percent: number) => void,\n signal?: AbortSignal\n ): Promise<UploadResponse> {\n const presignRes = await fetch(`${this.config.apiBaseUrl}/api/s3/presign-upload`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n fileName: options.fileName || options.file.name,\n folder: options.folder,\n contentType: options.file.type\n })\n });\n\n if (!presignRes.ok) throw new Error('Failed to get presigned URL');\n\n const { signedUrl, key } = await presignRes.json();\n\n if (!signedUrl || !key) throw new Error('Invalid presign response');\n\n return new Promise<UploadResponse>((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n\n xhr.upload.onprogress = event => {\n if (event.lengthComputable) {\n onProgress(Math.round((event.loaded / event.total) * 100));\n }\n };\n\n xhr.onload = () => {\n if (xhr.status === 200) {\n resolve({\n url: `${this.config.publicUrl}/${key}`,\n provider: 's3',\n key,\n });\n } else {\n reject(new Error(`S3 upload failed with status ${xhr.status}`));\n }\n };\n\n xhr.onerror = () => reject(new Error('S3 upload network error'));\n\n signal?.addEventListener('abort', () => {\n xhr.abort();\n reject(new Error('Upload cancelled'));\n });\n\n xhr.open('PUT', signedUrl);\n xhr.setRequestHeader('Content-Type', options.file.type);\n xhr.send(options.file);\n });\n }\n}","import { BaseUploader } from '../core/BaseUploader';\nimport { UploadOptions, UploadResponse } from '../core/types';\n\ninterface CloudinaryConfig {\n cloudName: string;\n uploadPreset: string;\n}\n\nexport class CloudinaryUploader extends BaseUploader {\n constructor(private config: CloudinaryConfig) {\n super();\n }\n\n async upload(\n options: UploadOptions,\n onProgress: (percent: number) => void\n ): Promise<UploadResponse> {\n const formData = new FormData();\n formData.append('file', options.file);\n formData.append('upload_preset', this.config.uploadPreset);\n formData.append('folder', options.folder);\n\n return new Promise((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n\n xhr.upload.onprogress = event => {\n if (event.lengthComputable) {\n onProgress(Math.round((event.loaded / event.total) * 100));\n }\n };\n\n xhr.onload = () => {\n const data = JSON.parse(xhr.responseText);\n if (xhr.status === 200 && data.secure_url) {\n resolve({ url: data.secure_url, provider: 'cloudinary' });\n } else {\n reject(new Error('Cloudinary upload failed'));\n }\n };\n\n xhr.onerror = () => reject(new Error('Cloudinary upload failed'));\n\n xhr.open('POST', `https://api.cloudinary.com/v1_1/${this.config.cloudName}/upload`);\n xhr.send(formData);\n });\n }\n}"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/EventEmitter.ts","../src/core/UploadTask.ts","../src/core/UploadManager.ts","../src/core/BaseUploader.ts","../src/providers/S3Uploader.ts","../src/providers/CloudinaryUploader.ts","../src/server/createS3PresignHandler.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["type Listener<T> = (payload: T) => void;\n\nexport class EventEmitter<T> {\n private listeners: Listener<T>[] = [];\n\n subscribe(listener: Listener<T>) {\n this.listeners.push(listener);\n return () => {\n this.listeners = this.listeners.filter(l => l !== listener);\n };\n }\n\n emit(payload: T) {\n this.listeners.forEach(listener => listener(payload));\n }\n}","import { BaseUploader } from './BaseUploader';\nimport { UploadOptions, UploadTaskState } from './types';\nimport { EventEmitter } from './EventEmitter';\n\nexport class UploadTask {\n public state: UploadTaskState;\n public events = new EventEmitter<UploadTaskState>();\n private abortController = new AbortController();\n private retries = 0;\n\n constructor(\n private uploader: BaseUploader,\n private options: UploadOptions,\n private maxRetries = 2,\n private retryDelay = 500\n ) {\n this.state = {\n id: crypto.randomUUID(),\n progress: 0,\n status: 'queued'\n };\n }\n\n async start(): Promise<void> {\n this.update({ status: 'uploading' });\n\n while (this.retries <= this.maxRetries) {\n try {\n const response = await this.uploader.upload(\n this.options,\n progress => this.update({ progress }),\n this.abortController.signal\n );\n\n this.update({ status: 'success', progress: 100, response });\n return;\n } catch (error: unknown) {\n if (this.abortController.signal.aborted) {\n this.update({ status: 'cancelled' });\n return;\n }\n\n const message = error instanceof Error ? error.message : 'Unknown upload error';\n\n if (this.retries >= this.maxRetries) {\n this.update({ status: 'error', error: message });\n return;\n }\n\n this.retries++;\n await this.sleep(this.retryDelay * Math.pow(2, this.retries - 1));\n }\n }\n }\n\n cancel() {\n this.abortController.abort();\n this.update({ status: 'cancelled' });\n }\n\n private update(update: Partial<UploadTaskState>) {\n this.state = { ...this.state, ...update };\n this.events.emit(this.state);\n }\n\n private sleep(ms: number) {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n}","import { BaseUploader } from './BaseUploader';\nimport { UploadOptions } from './types';\nimport { UploadTask } from './UploadTask';\n\nexport class UploadManager {\n private queue: UploadTask[] = [];\n private active = 0;\n\n constructor(private uploader: BaseUploader, private concurrency = 3) { }\n\n add(options: UploadOptions) {\n const task = new UploadTask(this.uploader, options);\n this.queue.push(task);\n this.process();\n return task;\n }\n\n private async process() {\n if (this.active >= this.concurrency) return;\n\n const next = this.queue.find(t => t.state.status === 'queued');\n if (!next) return;\n\n this.active++;\n await next.start();\n this.active--;\n this.process();\n }\n}","import { UploadOptions, UploadResponse } from './types';\n\nexport abstract class BaseUploader {\n abstract upload(options: UploadOptions, onProgress: (percent: number) => void, signal?: AbortSignal): Promise<UploadResponse>;\n}","import { BaseUploader } from '../core/BaseUploader';\nimport { UploadOptions, UploadResponse } from '../core/types';\n\ninterface S3Config {\n apiBaseUrl: string;\n publicUrl: string;\n}\n\nexport class S3Uploader extends BaseUploader {\n constructor(private config: S3Config) {\n super();\n }\n\n async upload(\n options: UploadOptions,\n onProgress: (percent: number) => void,\n signal?: AbortSignal\n ): Promise<UploadResponse> {\n const presignRes = await fetch(`${this.config.apiBaseUrl}/api/s3/presign-upload`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n fileName: options.fileName || options.file.name,\n folder: options.folder,\n contentType: options.file.type\n })\n });\n\n if (!presignRes.ok) throw new Error('Failed to get presigned URL');\n\n const { signedUrl, key } = await presignRes.json();\n\n if (!signedUrl || !key) throw new Error('Invalid presign response');\n\n return new Promise<UploadResponse>((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n\n xhr.upload.onprogress = event => {\n if (event.lengthComputable) {\n onProgress(Math.round((event.loaded / event.total) * 100));\n }\n };\n\n xhr.onload = () => {\n if (xhr.status === 200) {\n resolve({\n url: `${this.config.publicUrl}/${key}`,\n provider: 's3',\n key,\n });\n } else {\n reject(new Error(`S3 upload failed with status ${xhr.status}`));\n }\n };\n\n xhr.onerror = () => reject(new Error('S3 upload network error'));\n\n signal?.addEventListener('abort', () => {\n xhr.abort();\n reject(new Error('Upload cancelled'));\n });\n\n xhr.open('PUT', signedUrl);\n xhr.setRequestHeader('Content-Type', options.file.type);\n xhr.send(options.file);\n });\n }\n}","import { BaseUploader } from '../core/BaseUploader';\nimport { UploadOptions, UploadResponse } from '../core/types';\n\ninterface CloudinaryConfig {\n cloudName: string;\n uploadPreset: string;\n}\n\nexport class CloudinaryUploader extends BaseUploader {\n constructor(private config: CloudinaryConfig) {\n super();\n }\n\n async upload(\n options: UploadOptions,\n onProgress: (percent: number) => void\n ): Promise<UploadResponse> {\n const formData = new FormData();\n formData.append('file', options.file);\n formData.append('upload_preset', this.config.uploadPreset);\n formData.append('folder', options.folder);\n\n return new Promise((resolve, reject) => {\n const xhr = new XMLHttpRequest();\n\n xhr.upload.onprogress = event => {\n if (event.lengthComputable) {\n onProgress(Math.round((event.loaded / event.total) * 100));\n }\n };\n\n xhr.onload = () => {\n const data = JSON.parse(xhr.responseText);\n if (xhr.status === 200 && data.secure_url) {\n resolve({ url: data.secure_url, provider: 'cloudinary' });\n } else {\n reject(new Error('Cloudinary upload failed'));\n }\n };\n\n xhr.onerror = () => reject(new Error('Cloudinary upload failed'));\n\n xhr.open('POST', `https://api.cloudinary.com/v1_1/${this.config.cloudName}/upload`);\n xhr.send(formData);\n });\n }\n}","import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';\nimport { getSignedUrl } from '@aws-sdk/s3-request-presigner';\n\nexport interface PresignConfig {\n region: string;\n accessKeyId: string;\n secretAccessKey: string;\n bucket: string;\n publicUrl: string;\n expiresIn?: number;\n}\n\nexport interface PresignRequest {\n fileName: string;\n contentType: string;\n folder?: string;\n}\n\nexport function createS3PresignHandler(config: PresignConfig) {\n const s3 = new S3Client({\n region: config.region,\n credentials: {\n accessKeyId: config.accessKeyId,\n secretAccessKey: config.secretAccessKey,\n },\n });\n\n return async function generatePresignedUpload({\n fileName,\n contentType,\n folder,\n }: PresignRequest) {\n if (!fileName || !contentType) {\n throw new Error('fileName and contentType are required');\n }\n\n const safeFileName = fileName.replace(/[^a-zA-Z0-9._-]/g, \"_\");\n const key = `${folder || 'uploads'}/${Date.now()}-${safeFileName}`;\n\n const command = new PutObjectCommand({\n Bucket: config.bucket,\n Key: key,\n ContentType: contentType,\n });\n\n const signedUrl = await getSignedUrl(s3, command, {\n expiresIn: config.expiresIn ?? 300,\n });\n\n return {\n signedUrl,\n key,\n publicUrl: `${config.publicUrl}/${key}`,\n };\n };\n}"]}
|
package/dist/server/index.js
CHANGED
|
@@ -20,7 +20,8 @@ function createS3PresignHandler(config) {
|
|
|
20
20
|
if (!fileName || !contentType) {
|
|
21
21
|
throw new Error("fileName and contentType are required");
|
|
22
22
|
}
|
|
23
|
-
const
|
|
23
|
+
const safeFileName = fileName.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
24
|
+
const key = `${folder || "uploads"}/${Date.now()}-${safeFileName}`;
|
|
24
25
|
const command = new clientS3.PutObjectCommand({
|
|
25
26
|
Bucket: config.bucket,
|
|
26
27
|
Key: key,
|
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/server/createS3PresignHandler.ts"],"names":["S3Client","PutObjectCommand","getSignedUrl"],"mappings":";;;;;;AAkBO,SAAS,uBAAuB,MAAA,EAAuB;AAC1D,EAAA,MAAM,EAAA,GAAK,IAAIA,iBAAA,CAAS;AAAA,IACpB,QAAQ,MAAA,CAAO,MAAA;AAAA,IACf,WAAA,EAAa;AAAA,MACT,aAAa,MAAA,CAAO,WAAA;AAAA,MACpB,iBAAiB,MAAA,CAAO;AAAA;AAC5B,GACH,CAAA;AAED,EAAA,OAAO,eAAe,uBAAA,CAAwB;AAAA,IAC1C,QAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA,GACJ,EAAmB;AACf,IAAA,IAAI,CAAC,QAAA,IAAY,CAAC,WAAA,EAAa;AAC3B,MAAA,MAAM,IAAI,MAAM,uCAAuC,CAAA;AAAA,IAC3D;AAEA,IAAA,MAAM,GAAA,GAAM,GAAG,MAAA,IAAU,SAAS,IAAI,IAAA,CAAK,GAAA,EAAK,CAAA,CAAA,EAAI,
|
|
1
|
+
{"version":3,"sources":["../../src/server/createS3PresignHandler.ts"],"names":["S3Client","PutObjectCommand","getSignedUrl"],"mappings":";;;;;;AAkBO,SAAS,uBAAuB,MAAA,EAAuB;AAC1D,EAAA,MAAM,EAAA,GAAK,IAAIA,iBAAA,CAAS;AAAA,IACpB,QAAQ,MAAA,CAAO,MAAA;AAAA,IACf,WAAA,EAAa;AAAA,MACT,aAAa,MAAA,CAAO,WAAA;AAAA,MACpB,iBAAiB,MAAA,CAAO;AAAA;AAC5B,GACH,CAAA;AAED,EAAA,OAAO,eAAe,uBAAA,CAAwB;AAAA,IAC1C,QAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA,GACJ,EAAmB;AACf,IAAA,IAAI,CAAC,QAAA,IAAY,CAAC,WAAA,EAAa;AAC3B,MAAA,MAAM,IAAI,MAAM,uCAAuC,CAAA;AAAA,IAC3D;AAEA,IAAA,MAAM,YAAA,GAAe,QAAA,CAAS,OAAA,CAAQ,kBAAA,EAAoB,GAAG,CAAA;AAC7D,IAAA,MAAM,GAAA,GAAM,GAAG,MAAA,IAAU,SAAS,IAAI,IAAA,CAAK,GAAA,EAAK,CAAA,CAAA,EAAI,YAAY,CAAA,CAAA;AAEhE,IAAA,MAAM,OAAA,GAAU,IAAIC,yBAAA,CAAiB;AAAA,MACjC,QAAQ,MAAA,CAAO,MAAA;AAAA,MACf,GAAA,EAAK,GAAA;AAAA,MACL,WAAA,EAAa;AAAA,KAChB,CAAA;AAED,IAAA,MAAM,SAAA,GAAY,MAAMC,+BAAA,CAAa,EAAA,EAAI,OAAA,EAAS;AAAA,MAC9C,SAAA,EAAW,OAAO,SAAA,IAAa;AAAA,KAClC,CAAA;AAED,IAAA,OAAO;AAAA,MACH,SAAA;AAAA,MACA,GAAA;AAAA,MACA,SAAA,EAAW,CAAA,EAAG,MAAA,CAAO,SAAS,IAAI,GAAG,CAAA;AAAA,KACzC;AAAA,EACJ,CAAA;AACJ","file":"index.js","sourcesContent":["import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';\nimport { getSignedUrl } from '@aws-sdk/s3-request-presigner';\n\nexport interface PresignConfig {\n region: string;\n accessKeyId: string;\n secretAccessKey: string;\n bucket: string;\n publicUrl: string;\n expiresIn?: number;\n}\n\nexport interface PresignRequest {\n fileName: string;\n contentType: string;\n folder?: string;\n}\n\nexport function createS3PresignHandler(config: PresignConfig) {\n const s3 = new S3Client({\n region: config.region,\n credentials: {\n accessKeyId: config.accessKeyId,\n secretAccessKey: config.secretAccessKey,\n },\n });\n\n return async function generatePresignedUpload({\n fileName,\n contentType,\n folder,\n }: PresignRequest) {\n if (!fileName || !contentType) {\n throw new Error('fileName and contentType are required');\n }\n\n const safeFileName = fileName.replace(/[^a-zA-Z0-9._-]/g, \"_\");\n const key = `${folder || 'uploads'}/${Date.now()}-${safeFileName}`;\n\n const command = new PutObjectCommand({\n Bucket: config.bucket,\n Key: key,\n ContentType: contentType,\n });\n\n const signedUrl = await getSignedUrl(s3, command, {\n expiresIn: config.expiresIn ?? 300,\n });\n\n return {\n signedUrl,\n key,\n publicUrl: `${config.publicUrl}/${key}`,\n };\n };\n}"]}
|
package/dist/server/index.mjs
CHANGED
|
@@ -18,7 +18,8 @@ function createS3PresignHandler(config) {
|
|
|
18
18
|
if (!fileName || !contentType) {
|
|
19
19
|
throw new Error("fileName and contentType are required");
|
|
20
20
|
}
|
|
21
|
-
const
|
|
21
|
+
const safeFileName = fileName.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
22
|
+
const key = `${folder || "uploads"}/${Date.now()}-${safeFileName}`;
|
|
22
23
|
const command = new PutObjectCommand({
|
|
23
24
|
Bucket: config.bucket,
|
|
24
25
|
Key: key,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/server/createS3PresignHandler.ts"],"names":[],"mappings":";;;;AAkBO,SAAS,uBAAuB,MAAA,EAAuB;AAC1D,EAAA,MAAM,EAAA,GAAK,IAAI,QAAA,CAAS;AAAA,IACpB,QAAQ,MAAA,CAAO,MAAA;AAAA,IACf,WAAA,EAAa;AAAA,MACT,aAAa,MAAA,CAAO,WAAA;AAAA,MACpB,iBAAiB,MAAA,CAAO;AAAA;AAC5B,GACH,CAAA;AAED,EAAA,OAAO,eAAe,uBAAA,CAAwB;AAAA,IAC1C,QAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA,GACJ,EAAmB;AACf,IAAA,IAAI,CAAC,QAAA,IAAY,CAAC,WAAA,EAAa;AAC3B,MAAA,MAAM,IAAI,MAAM,uCAAuC,CAAA;AAAA,IAC3D;AAEA,IAAA,MAAM,GAAA,GAAM,GAAG,MAAA,IAAU,SAAS,IAAI,IAAA,CAAK,GAAA,EAAK,CAAA,CAAA,EAAI,
|
|
1
|
+
{"version":3,"sources":["../../src/server/createS3PresignHandler.ts"],"names":[],"mappings":";;;;AAkBO,SAAS,uBAAuB,MAAA,EAAuB;AAC1D,EAAA,MAAM,EAAA,GAAK,IAAI,QAAA,CAAS;AAAA,IACpB,QAAQ,MAAA,CAAO,MAAA;AAAA,IACf,WAAA,EAAa;AAAA,MACT,aAAa,MAAA,CAAO,WAAA;AAAA,MACpB,iBAAiB,MAAA,CAAO;AAAA;AAC5B,GACH,CAAA;AAED,EAAA,OAAO,eAAe,uBAAA,CAAwB;AAAA,IAC1C,QAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA,GACJ,EAAmB;AACf,IAAA,IAAI,CAAC,QAAA,IAAY,CAAC,WAAA,EAAa;AAC3B,MAAA,MAAM,IAAI,MAAM,uCAAuC,CAAA;AAAA,IAC3D;AAEA,IAAA,MAAM,YAAA,GAAe,QAAA,CAAS,OAAA,CAAQ,kBAAA,EAAoB,GAAG,CAAA;AAC7D,IAAA,MAAM,GAAA,GAAM,GAAG,MAAA,IAAU,SAAS,IAAI,IAAA,CAAK,GAAA,EAAK,CAAA,CAAA,EAAI,YAAY,CAAA,CAAA;AAEhE,IAAA,MAAM,OAAA,GAAU,IAAI,gBAAA,CAAiB;AAAA,MACjC,QAAQ,MAAA,CAAO,MAAA;AAAA,MACf,GAAA,EAAK,GAAA;AAAA,MACL,WAAA,EAAa;AAAA,KAChB,CAAA;AAED,IAAA,MAAM,SAAA,GAAY,MAAM,YAAA,CAAa,EAAA,EAAI,OAAA,EAAS;AAAA,MAC9C,SAAA,EAAW,OAAO,SAAA,IAAa;AAAA,KAClC,CAAA;AAED,IAAA,OAAO;AAAA,MACH,SAAA;AAAA,MACA,GAAA;AAAA,MACA,SAAA,EAAW,CAAA,EAAG,MAAA,CAAO,SAAS,IAAI,GAAG,CAAA;AAAA,KACzC;AAAA,EACJ,CAAA;AACJ","file":"index.mjs","sourcesContent":["import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';\nimport { getSignedUrl } from '@aws-sdk/s3-request-presigner';\n\nexport interface PresignConfig {\n region: string;\n accessKeyId: string;\n secretAccessKey: string;\n bucket: string;\n publicUrl: string;\n expiresIn?: number;\n}\n\nexport interface PresignRequest {\n fileName: string;\n contentType: string;\n folder?: string;\n}\n\nexport function createS3PresignHandler(config: PresignConfig) {\n const s3 = new S3Client({\n region: config.region,\n credentials: {\n accessKeyId: config.accessKeyId,\n secretAccessKey: config.secretAccessKey,\n },\n });\n\n return async function generatePresignedUpload({\n fileName,\n contentType,\n folder,\n }: PresignRequest) {\n if (!fileName || !contentType) {\n throw new Error('fileName and contentType are required');\n }\n\n const safeFileName = fileName.replace(/[^a-zA-Z0-9._-]/g, \"_\");\n const key = `${folder || 'uploads'}/${Date.now()}-${safeFileName}`;\n\n const command = new PutObjectCommand({\n Bucket: config.bucket,\n Key: key,\n ContentType: contentType,\n });\n\n const signedUrl = await getSignedUrl(s3, command, {\n expiresIn: config.expiresIn ?? 300,\n });\n\n return {\n signedUrl,\n key,\n publicUrl: `${config.publicUrl}/${key}`,\n };\n };\n}"]}
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@signskart/uploader",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.8",
|
|
4
4
|
"description": "Production-grade upload manager SDK with queue, progress tracking, retry logic, cancellation, and multi-provider support (S3, Cloudinary).",
|
|
5
5
|
"author": "Signskart",
|
|
6
6
|
"license": "MIT",
|
|
7
|
-
"main": "dist/index.cjs",
|
|
8
|
-
"module": "dist/index.js",
|
|
9
7
|
"types": "dist/index.d.ts",
|
|
10
8
|
"files": [
|
|
11
9
|
"dist"
|
|
12
10
|
],
|
|
11
|
+
"main": "dist/index.cjs",
|
|
12
|
+
"module": "dist/index.js",
|
|
13
13
|
"exports": {
|
|
14
14
|
".": {
|
|
15
15
|
"import": "./dist/index.js",
|