diff --git a/package-lock.json b/package-lock.json index 40d6d1e..74fe73f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "imagekit-javascript", - "version": "1.5.4", + "version": "1.6.0-alpha.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index cef6c5d..356387e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "imagekit-javascript", - "version": "1.5.4", + "version": "1.6.0-alpha.0", "description": "Javascript SDK for using ImageKit.io in the browser", "main": "dist/imagekit.cjs.js", "module": "dist/imagekit.esm.js", diff --git a/src/interfaces/ImageKitOptions.ts b/src/interfaces/ImageKitOptions.ts index 2ba4bcd..a7d5b6b 100644 --- a/src/interfaces/ImageKitOptions.ts +++ b/src/interfaces/ImageKitOptions.ts @@ -6,4 +6,5 @@ export interface ImageKitOptions { publicKey?: string; authenticationEndpoint?: string; transformationPosition?: TransformationPosition; + apiVersion?: string } \ No newline at end of file diff --git a/src/interfaces/UploadOptions.ts b/src/interfaces/UploadOptions.ts index 24f18ec..17eb06a 100644 --- a/src/interfaces/UploadOptions.ts +++ b/src/interfaces/UploadOptions.ts @@ -104,3 +104,9 @@ export interface UploadOptions { */ xhr?: XMLHttpRequest } + +export interface JwtRequestOptions { + publicKey: string + expire: number + uploadPayload: { [key: string]: Object | string | boolean } +} \ No newline at end of file diff --git a/src/interfaces/index.ts b/src/interfaces/index.ts index 50afe5c..4264fe6 100644 --- a/src/interfaces/index.ts +++ b/src/interfaces/index.ts @@ -1,7 +1,7 @@ import { ImageKitOptions } from "./ImageKitOptions"; import { TransformationPosition } from "./Transformation"; -import { UploadOptions } from "./UploadOptions"; +import { UploadOptions, JwtRequestOptions } from "./UploadOptions"; import { UploadResponse, FileType } from "./UploadResponse"; import { UrlOptions } from "./UrlOptions"; -export type { ImageKitOptions, TransformationPosition, UploadOptions, UploadResponse, FileType, UrlOptions }; +export type { ImageKitOptions, TransformationPosition, UploadOptions, UploadResponse, FileType, UrlOptions, JwtRequestOptions }; diff --git a/src/upload/index.ts b/src/upload/index.ts index 8fabb9b..1871666 100644 --- a/src/upload/index.ts +++ b/src/upload/index.ts @@ -1,7 +1,7 @@ import errorMessages from "../constants/errorMessages"; import respond from "../utils/respond"; import { request } from "../utils/request"; -import { ImageKitOptions, UploadOptions, UploadResponse } from "../interfaces"; +import { ImageKitOptions, UploadOptions, UploadResponse, JwtRequestOptions } from "../interfaces"; export const upload = ( xhr: XMLHttpRequest, @@ -9,6 +9,12 @@ export const upload = ( options: ImageKitOptions, callback?: (err: Error | null, response: UploadResponse | null) => void, ) => { + + if (!uploadOptions) { + respond(true, errorMessages.INVALID_UPLOAD_OPTIONS, callback); + return; + } + if (!uploadOptions.file) { respond(true, errorMessages.MISSING_UPLOAD_FILE_PARAMETER, callback); return; @@ -29,6 +35,12 @@ export const upload = ( return; } + const reqPayload: JwtRequestOptions = { + publicKey: options.publicKey, + expire: 3600, + uploadPayload: {}, + } + var formData = new FormData(); let key: keyof typeof uploadOptions; for (key in uploadOptions) { @@ -37,20 +49,24 @@ export const upload = ( formData.append('file', uploadOptions.file, String(uploadOptions.fileName)); } else if (key === "tags" && Array.isArray(uploadOptions.tags)) { formData.append('tags', uploadOptions.tags.join(",")); + reqPayload.uploadPayload[key] = uploadOptions.tags.join(","); } else if (key === "responseFields" && Array.isArray(uploadOptions.responseFields)) { formData.append('responseFields', uploadOptions.responseFields.join(",")); + reqPayload.uploadPayload[key] = uploadOptions.responseFields.join(","); } else if (key === "extensions" && Array.isArray(uploadOptions.extensions)) { formData.append('extensions', JSON.stringify(uploadOptions.extensions)); + reqPayload.uploadPayload[key] = JSON.stringify(uploadOptions.extensions); } else if (key === "customMetadata" && typeof uploadOptions.customMetadata === "object" && !Array.isArray(uploadOptions.customMetadata) && uploadOptions.customMetadata !== null) { formData.append('customMetadata', JSON.stringify(uploadOptions.customMetadata)); - } else if(uploadOptions[key] !== undefined) { + reqPayload.uploadPayload[key] = JSON.stringify(uploadOptions.customMetadata); + } else if (uploadOptions[key] !== undefined) { formData.append(key, String(uploadOptions[key])); + if (key !== 'file') + reqPayload.uploadPayload[key] = String(uploadOptions[key]); } } } - formData.append("publicKey", options.publicKey); - - request(xhr, formData, { ...options, authenticationEndpoint: options.authenticationEndpoint }, callback); + request(xhr, formData, reqPayload, { ...options, authenticationEndpoint: options.authenticationEndpoint }, callback); }; diff --git a/src/utils/request.ts b/src/utils/request.ts index dc351f2..bd9ecd1 100644 --- a/src/utils/request.ts +++ b/src/utils/request.ts @@ -1,6 +1,6 @@ import respond from "../utils/respond"; import errorMessages from "../constants/errorMessages" -import { ImageKitOptions, UploadResponse } from "../interfaces"; +import { ImageKitOptions, UploadResponse, JwtRequestOptions } from "../interfaces"; import IKResponse from "../interfaces/IKResponse"; interface SignatureResponse { @@ -9,6 +9,10 @@ interface SignatureResponse { token: string } +interface JwtResponse { + token: string +} + function getResponseHeaderMap(xhr: XMLHttpRequest) { const headers: Record = {}; const responseHeaders = xhr.getAllResponseHeaders(); @@ -41,13 +45,31 @@ const addResponseHeadersAndBody = (body: any, xhr: XMLHttpRequest): IKResponse void) => { + if (options.apiVersion === 'v2-alpha') { + + getJwt(options.authenticationEndpoint, jwtRequestOptions).then((tokenObj) => { + formData.append("token", tokenObj.token); + + uploadFile(uploadFileXHR, formData, options.apiVersion).then((result) => { + return respond(false, result, callback); + }, (ex) => { + return respond(true, ex, callback); + }); + }, (ex) => { + return respond(true, ex, callback); + }); + return + } + generateSignatureToken(options.authenticationEndpoint).then((signaturObj) => { formData.append("signature", signaturObj.signature); formData.append("expire", String(signaturObj.expire)); formData.append("token", signaturObj.token); + formData.append("publicKey", String(options.publicKey)); uploadFile(uploadFileXHR, formData).then((result) => { return respond(false, result, callback); @@ -59,6 +81,43 @@ export const request = ( }); } +export const getJwt = ( + authenticationEndpoint: string, + jwtRequestOptions: JwtRequestOptions +): Promise => { + return new Promise((resolve, reject) => { + const xhr = new XMLHttpRequest(); + xhr.timeout = 60000; + xhr.open('POST', authenticationEndpoint); + xhr.setRequestHeader("Content-type", "application/json"); + xhr.ontimeout = function (e) { + return reject(errorMessages.AUTH_ENDPOINT_TIMEOUT); + }; + xhr.onerror = function () { + return reject(errorMessages.AUTH_ENDPOINT_NETWORK_ERROR); + } + xhr.onload = function () { + if (xhr.status === 200) { + try { + const body = JSON.parse(xhr.responseText); + const obj = { + token: body.token + } + if (!obj.token) { + return reject(errorMessages.AUTH_INVALID_RESPONSE); + } + return resolve(obj); + } catch (ex) { + return reject(errorMessages.AUTH_INVALID_RESPONSE); + } + } else { + return reject(errorMessages.AUTH_INVALID_RESPONSE); + } + }; + xhr.send(JSON.stringify(jwtRequestOptions)); + }); +} + export const generateSignatureToken = ( authenticationEndpoint: string ): Promise => { @@ -100,10 +159,12 @@ export const generateSignatureToken = ( export const uploadFile = ( uploadFileXHR: XMLHttpRequest, - formData: FormData + formData: FormData, + apiVersion: undefined | string = undefined, ): Promise | Error> => { return new Promise((resolve, reject) => { - uploadFileXHR.open('POST', 'https://upload.imagekit.io/api/v1/files/upload'); + const uploadUrl = apiVersion === 'v2-alpha' ? 'https://upload.imagekit.io/api/v2-alpha/files/upload' : 'https://upload.imagekit.io/api/v1/files/upload' + uploadFileXHR.open('POST', uploadUrl); uploadFileXHR.onerror = function (e) { return reject(errorMessages.UPLOAD_ENDPOINT_NETWORK_ERROR); }