{"version":3,"sources":["../src/uploadFile/index.ts","../src/constants/file-types.ts","../src/request/node.ts","../src/request/browser.ts","../src/upload-client.ts"],"sourcesContent":["import NodeFormData from \"form-data\";\nimport { ALLOWED_MIME_TYPES, AllowedMimeType } from \"../constants/file-types\";\nimport {\n  InvalidFileError,\n  NetworkError,\n  UnauthorizedError,\n  UploadError,\n  BubblyStorageError,\n  ValidationError,\n} from \"../errors\";\nimport { UploadInput, BubblyStorageClientOptions } from \"../types\";\nimport { browserRequest, nodeRequest } from \"../request\";\n\ninterface UploadOptions extends BubblyStorageClientOptions {\n  apiUrl: string;\n}\n\ntype BrowserFormData = FormData;\n\nfunction validateFileType(mimeType: string) {\n  if (mimeType && !ALLOWED_MIME_TYPES.includes(mimeType as AllowedMimeType)) {\n    throw new InvalidFileError(\n      `File type '${mimeType}' is not allowed.\n      Allowed types: ${ALLOWED_MIME_TYPES.join(\", \")}\n      `\n    );\n  }\n}\n\nexport async function uploadFiles(\n  files: UploadInput | UploadInput[],\n  options: UploadOptions\n) {\n  const shouldUseBrowser = options.isBrowser;\n\n  let formData: BrowserFormData | NodeFormData;\n\n  if (shouldUseBrowser) {\n    formData = new FormData();\n  } else {\n    formData = new NodeFormData();\n  }\n\n  const fileArray = Array.isArray(files) ? files : [files];\n\n  for (const file of fileArray) {\n    if (typeof file === \"string\" && !shouldUseBrowser) {\n      validateFileType(file);\n\n      const { createReadStream } = await import(\"fs\");\n      const stream = createReadStream(file);\n      (formData as NodeFormData).append(\"files\", stream);\n    } else if (\n      Buffer.isBuffer(file) &&\n      !shouldUseBrowser &&\n      formData instanceof NodeFormData\n    ) {\n      const fileMetadata = file as any;\n      if (fileMetadata.type) {\n        validateFileType(fileMetadata.type);\n      }\n\n      formData.append(\"files\", file, {\n        filename: fileMetadata.name || \"file.bin\",\n        contentType: fileMetadata.type || \"application/octet-stream\",\n        knownLength: fileMetadata.size,\n      });\n    } else if (file instanceof Blob || file instanceof File) {\n      if (file instanceof File) {\n        validateFileType(file.type);\n      }\n      (formData as FormData).append(\"files\", file);\n    } else {\n      if (shouldUseBrowser && typeof file === \"string\") {\n        throw new InvalidFileError(\n          \"File paths are not supported when isBrowser is enabled. Use File objects instead.\"\n        );\n      } else if (shouldUseBrowser && file instanceof Buffer) {\n        throw new InvalidFileError(\n          \"Buffers are not supported when isBrowser is enabled\"\n        );\n      }\n      //throw new InvalidFileError(\"Invalid File\")\n    }\n  }\n\n  try {\n    const response = await (shouldUseBrowser ? browserRequest : nodeRequest)(\n      `${options.apiUrl}/files/upload`,\n      {\n        method: \"POST\",\n        headers: {\n          Authorization: `Bearer ${options.apiKey}`,\n        },\n        body: formData,\n      }\n    );\n\n    if (!response.ok) {\n      switch (response.status) {\n        case 400:\n          throw new ValidationError(\"Invalid request format\");\n        case 401:\n          throw new UnauthorizedError(\"Unathorized Access\");\n        case 413:\n          throw new UploadError(\"File size too large\");\n        case 503:\n          throw new NetworkError(\"Service temporarily unavailable\");\n        default:\n          throw new UploadError(\n            `Upload failed: ${response.status}\n            ${response.statusText}`\n          );\n      }\n    }\n\n    return response.json();\n  } catch (error) {\n    if (error instanceof BubblyStorageError) {\n      throw error;\n    }\n    throw new UploadError(\n      error instanceof Error ? error.message : \"Unknown error occurred\"\n    );\n  }\n}\n","export const ALLOWED_MIME_TYPES = [\n  // Images\n  \"image/jpeg\",\n  \"image/png\",\n  \"image/webp\",\n  \"image/svg+xml\",\n  \"image/gif\",\n\n  // Documents\n  \"application/pdf\", // PDF files\n  \"application/msword\", // .doc files\n  \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\", // .docx files\n\n  // Text files\n  \"text/plain\",\n  \"text/csv\",\n\n  // Archives\n  \"application/zip\",\n  \"application/x-zip-compressed\",\n  \"application/x-tar\",\n  \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\", // .xlsx\n  \"application/vnd.ms-excel\", // .xls\n  \"application/vnd.openxmlformats-officedocument.presentationml.presentation\", // .pptx\n\n  // Audio\n  \"audio/wav\",\n  \"audio/webm\",\n\n  // Video\n  \"video/mp4\",\n  \"video/webm\",\n] as const;\n\nexport type AllowedMimeType = (typeof ALLOWED_MIME_TYPES)[number];\n","import NodeFormData from \"form-data\";\nimport http, { IncomingMessage } from \"http\";\nimport https from \"https\";\nimport { UploadRequestOptions } from \"../types\";\n\nexport async function request(\n  url: string,\n  options: UploadRequestOptions\n): Promise<Response> {\n  const formData = options.body as NodeFormData;\n\n  const parsedUrl = new URL(url);\n\n  return new Promise((resolve, reject) => {\n    const requestOptions = {\n      method: options.method, //POST\n      hostname: parsedUrl.hostname, //\n      path: parsedUrl.pathname + parsedUrl.search,\n      port: parsedUrl.port || (parsedUrl.protocol === \"https: \" ? 443 : 80),\n      headers: {\n        ...options.headers,\n        ...(formData.getHeaders ? formData.getHeaders() : {}),\n      },\n    };\n\n    const isHttps = url.startsWith(\"https\");\n    const requestModule = isHttps ? https : http;\n\n    const req = requestModule.request(\n      requestOptions,\n      (res: IncomingMessage) => {\n        let data = \"\";\n\n        res.on(\"data\", (chunk) => {\n          data += chunk;\n        });\n\n        res.on(\"end\", () => {\n          const response = {\n            ok: res.statusCode\n              ? res.statusCode >= 200 && res.statusCode < 300\n              : false,\n            status: res.statusCode || 500,\n            statusText: res.statusMessage || \"\",\n            json: async () => JSON.parse(data),\n          } as Response;\n\n          resolve(response);\n        });\n      }\n    );\n\n    req.on(\"error\", (err) => {\n      reject(new Error(`Request failed: ${err.message}`));\n    });\n\n    if (formData && typeof formData.pipe === \"function\") {\n      formData.on(\"end\", () => {});\n\n      req.on(\"finish\", () => {});\n\n      formData.pipe(req);\n    } else {\n      req.end();\n    }\n\n    formData.on(\"error\", (err) => {\n      //console.error(\"FormData error\", err);\n      req.destroy();\n      reject(new Error(`FormData error: ${err.message}`));\n    });\n  });\n}\n","import type { UploadRequestOptions } from \"../types\";\n\nexport async function request(\n  url: string,\n  options: UploadRequestOptions\n): Promise<Response> {\n  return fetch(url, {\n    method: options.method,\n    headers: {\n      ...options.headers,\n    },\n    body: options.body as FormData, // Browser's native FormData\n  });\n}\n","import { UnauthorizedError } from \"./errors\";\nimport {\n  UploadInput,\n  BubblyStorageClientOptions,\n  UploadResponseType,\n} from \"./types\";\nimport { uploadFiles } from \"./uploadFile\";\n\nconst DEFAULT_API_URL = \"https://api.bubblystorage.com/v1\";\n\nexport class BubblyStorageClient {\n  private apiKey: string;\n  private apiUrl: string;\n  private isBrowser: boolean;\n\n  constructor(options: BubblyStorageClientOptions) {\n    if (!options.apiKey) throw new UnauthorizedError(\"API Key is required\");\n    this.apiKey = options.apiKey;\n    this.apiUrl = options.apiUrl || DEFAULT_API_URL;\n    this.isBrowser = options.isBrowser || false;\n  }\n\n  async uploadFiles(\n    files: UploadInput | UploadInput[]\n  ): Promise<UploadResponseType> {\n    return uploadFiles(files, {\n      apiKey: this.apiKey,\n      apiUrl: this.apiUrl,\n      isBrowser: this.isBrowser,\n    });\n  }\n}\n"],"mappings":"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","names":["NodeFormData","ALLOWED_MIME_TYPES","http","https","request","url","options","formData","parsedUrl","resolve","reject","requestOptions","req","res","data","chunk","response","err","request","url","options","validateFileType","mimeType","ALLOWED_MIME_TYPES","InvalidFileError","uploadFiles","files","options","shouldUseBrowser","formData","NodeFormData","fileArray","file","createReadStream","stream","fileMetadata","response","request","ValidationError","UnauthorizedError","UploadError","NetworkError","error","BubblyStorageError","DEFAULT_API_URL","BubblyStorageClient","options","UnauthorizedError","files","uploadFiles"]}