From e0f0d8b3550e463e233a55a5b6a50675142e2e41 Mon Sep 17 00:00:00 2001 From: Yashaswi Agrawal Date: Mon, 6 Mar 2023 13:49:59 +0530 Subject: [PATCH 1/3] v2-alpha-upload feature addded --- src/interfaces/ImageKitOptions.ts | 1 + src/interfaces/UploadOptions.ts | 6 +++ src/interfaces/index.ts | 4 +- src/upload/index.ts | 26 ++++++++--- src/utils/request.ts | 71 +++++++++++++++++++++++++++++-- 5 files changed, 97 insertions(+), 11 deletions(-) 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..6c5e6f4 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} +} \ 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..0ca0e76 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) => { - generateSignatureToken(options.authenticationEndpoint).then((signaturObj) => { + 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,45 @@ export const request = ( }); } +export const getJwt = ( + authenticationEndpoint: string, + jwtRequestOptions: JwtRequestOptions +): Promise => { + return new Promise((resolve, reject) => { + var xhr = new XMLHttpRequest(); + xhr.timeout = 60000; + var urlObj = new URL(authenticationEndpoint); + urlObj.searchParams.set("t", Math.random().toString()); + xhr.open('POST', urlObj.toString()); + 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 { + var body = JSON.parse(xhr.responseText); + var 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 +161,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 && 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); } From 27f4566cb9f8779862aa66dd570351b6836cee90 Mon Sep 17 00:00:00 2001 From: Yashaswi Agrawal Date: Mon, 6 Mar 2023 13:52:15 +0530 Subject: [PATCH 2/3] 1.6.0-alpha.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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", From 2cbc6cb4262ba732debc458ab94636b3d377092d Mon Sep 17 00:00:00 2001 From: Yashaswi Agrawal Date: Mon, 6 Mar 2023 15:29:38 +0530 Subject: [PATCH 3/3] comments resolved --- src/interfaces/UploadOptions.ts | 2 +- src/utils/request.ts | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/interfaces/UploadOptions.ts b/src/interfaces/UploadOptions.ts index 6c5e6f4..17eb06a 100644 --- a/src/interfaces/UploadOptions.ts +++ b/src/interfaces/UploadOptions.ts @@ -108,5 +108,5 @@ export interface UploadOptions { export interface JwtRequestOptions { publicKey: string expire: number - uploadPayload:{[key: string]: Object} + uploadPayload: { [key: string]: Object | string | boolean } } \ No newline at end of file diff --git a/src/utils/request.ts b/src/utils/request.ts index 0ca0e76..bd9ecd1 100644 --- a/src/utils/request.ts +++ b/src/utils/request.ts @@ -65,7 +65,7 @@ export const request = ( return } - generateSignatureToken(options.authenticationEndpoint,).then((signaturObj) => { + generateSignatureToken(options.authenticationEndpoint).then((signaturObj) => { formData.append("signature", signaturObj.signature); formData.append("expire", String(signaturObj.expire)); formData.append("token", signaturObj.token); @@ -86,11 +86,9 @@ export const getJwt = ( jwtRequestOptions: JwtRequestOptions ): Promise => { return new Promise((resolve, reject) => { - var xhr = new XMLHttpRequest(); + const xhr = new XMLHttpRequest(); xhr.timeout = 60000; - var urlObj = new URL(authenticationEndpoint); - urlObj.searchParams.set("t", Math.random().toString()); - xhr.open('POST', urlObj.toString()); + xhr.open('POST', authenticationEndpoint); xhr.setRequestHeader("Content-type", "application/json"); xhr.ontimeout = function (e) { return reject(errorMessages.AUTH_ENDPOINT_TIMEOUT); @@ -101,8 +99,8 @@ export const getJwt = ( xhr.onload = function () { if (xhr.status === 200) { try { - var body = JSON.parse(xhr.responseText); - var obj = { + const body = JSON.parse(xhr.responseText); + const obj = { token: body.token } if (!obj.token) { @@ -165,7 +163,7 @@ export const uploadFile = ( apiVersion: undefined | string = undefined, ): Promise | Error> => { return new Promise((resolve, reject) => { - const uploadUrl = apiVersion && apiVersion === 'v2-alpha' ? 'https://upload.imagekit.io/api/v2-alpha/files/upload' : '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);