diff --git a/src/MarcSync/MarcSyncv1.0.lua b/src/MarcSync/MarcSyncv1.1.lua similarity index 84% rename from src/MarcSync/MarcSyncv1.0.lua rename to src/MarcSync/MarcSyncv1.1.lua index 4fa246a..0184bfb 100644 --- a/src/MarcSync/MarcSyncv1.0.lua +++ b/src/MarcSync/MarcSyncv1.1.lua @@ -8,31 +8,33 @@ local tokens = { local Utils = require(script.Parent.Utils) local MarcSyncClient = {} +local Types = require(script.Parent.Types) + MarcSyncClient.getVersion = function(self:typeof(MarcSyncClient), clientId: number?):string self:_checkInstallation() local url = "" if clientId then url = "/"..clientId end - local result = Utils.makeHTTPRequest("GET", "https://api.marcsync.dev/v0/utils/version"..url); + local result = Utils.makeHTTPRequest("", "GET", "https://api.marcsync.dev/v0/utils/version"..url, nil, nil, self._options); return result["version"] end MarcSyncClient.createCollection = function(self:typeof(MarcSyncClient), collectionName: string):typeof(require(script.Parent.Objects.Collection).new()) if not self._accessToken then error("[MarcSync] Please set a Token before using MarcSync.") end if not collectionName then error("No CollectionName Provided") end - local result = Utils.makeHTTPRequest("collection", "POST", "https://api.marcsync.dev/v0/collection/"..collectionName, {}, self._accessToken); + local result = Utils.makeHTTPRequest("collection", "POST", "https://api.marcsync.dev/v0/collection/"..collectionName, {}, self._accessToken, self._options); if not result["success"] then error(result["errorMessage"]) end - result = require(script.Parent.Objects.Collection).new(collectionName, self._accessToken) + result = require(script.Parent.Objects.Collection).new(collectionName, self._accessToken, self._options) return result end MarcSyncClient.fetchCollection = function(self:typeof(MarcSyncClient), collectionName: string):typeof(require(script.Parent.Objects.Collection).new()) self:_checkInstallation() if not collectionName then error("No CollectionName Provided") end - local result = Utils.makeHTTPRequest("collection", "GET", "https://api.marcsync.dev/v0/collection/"..collectionName, {}, self._accessToken); + local result = Utils.makeHTTPRequest("collection", "GET", "https://api.marcsync.dev/v0/collection/"..collectionName, {}, self._accessToken, self._options); if not result["success"] then error(result["errorMessage"]) end - result = require(script.Parent.Objects.Collection).new(collectionName, self._accessToken) + result = require(script.Parent.Objects.Collection).new(collectionName, self._accessToken, self._options) return result end @@ -40,15 +42,16 @@ MarcSyncClient.getCollection = function(self:typeof(MarcSyncClient), collectionN if typeof(self) ~= "table" then error("Please use : instead of .") end self:_checkInstallation() if not collectionName then error("No CollectionName Provided") end - return require(script.Parent.Objects.Collection).new(collectionName, self._accessToken) + return require(script.Parent.Objects.Collection).new(collectionName, self._accessToken, self._options) end return { - new = function(accessToken: string):typeof(MarcSyncClient) + new = function(accessToken: string, options: Types.ClientOptions?):typeof(MarcSyncClient) if not accessToken then warn("Token not provided while creating a new MarcSync Object.") end if not tokens[accessToken] then warn("Token provided for creating a new MarcSync Object not Found in Token Table, using it as token instead.") else accessToken = tokens[accessToken] end local self = {} self._accessToken = accessToken + self._options = options or {retryCount = 3} self._checkInstallation = function() if not self then error("Please Setup MarcSync before using MarcSync.") end if not self._accessToken then error("[MarcSync] Please set a Token before using MarcSync.") end diff --git a/src/MarcSync/Objects/Collection.lua b/src/MarcSync/Objects/Collection.lua index 435d7b7..ccb5667 100644 --- a/src/MarcSync/Objects/Collection.lua +++ b/src/MarcSync/Objects/Collection.lua @@ -7,11 +7,11 @@ local Collection = {} Collection.createEntry = function(self:typeof(Collection), data:Types.EntryData):typeof(Entry.new()) if not self._collectionName then error("[MarcSync: Collection] Invalid Object created or trying to access an destroied object.") end - local result = Utils.makeHTTPRequest("entry", "POST", "https://api.marcsync.dev/v0/entries/"..self._collectionName, {["data"]=data}, self._accessToken); + local result = Utils.makeHTTPRequest("entry", "POST", "https://api.marcsync.dev/v0/entries/"..self._collectionName, {["data"]=data}, self._accessToken, self._options); if result["success"] and result["objectId"] then data["_id"] = result["objectId"] - result = require(script.Parent.Entry).new(self._collectionName, data, self._accessToken) + result = require(script.Parent.Entry).new(self._collectionName, data, self._accessToken, self._options) else error(result["errorMessage"]) end @@ -21,7 +21,7 @@ end Collection.updateEntries = function(self:typeof(Collection), filters:Types.EntryData, data:Types.EntryData):number if not self._collectionName then error("[MarcSync: Collection] Invalid Object created or trying to access an destroied object.") end - local result = Utils.makeHTTPRequest("entry", "PUT", "https://api.marcsync.dev/v0/entries/"..self._collectionName, {["filters"]=filters,["data"]=data}, self._accessToken); + local result = Utils.makeHTTPRequest("entry", "PUT", "https://api.marcsync.dev/v0/entries/"..self._collectionName, {["filters"]=filters,["data"]=data}, self._accessToken, self._options); if not result["success"] then error(result["errorMessage"]) end return result["modifiedEntries"] @@ -30,11 +30,11 @@ end Collection.getEntries = function(self:typeof(Collection), filters:Types.EntryData):{[number]:typeof(Entry.new())} if not self._collectionName then error("[MarcSync: Collection] Invalid Object created or trying to access an destroied object.") end if not filters then filters = {} end - local result = Utils.makeHTTPRequest("entry", "DELETE", "https://api.marcsync.dev/v0/entries/"..self._collectionName.."?isQuery=true", {["filters"]=filters}, self._accessToken); + local result = Utils.makeHTTPRequest("entry", "DELETE", "https://api.marcsync.dev/v0/entries/"..self._collectionName.."?isQuery=true", {["filters"]=filters}, self._accessToken, self._options); if result["success"] and result["entries"] then local _result = {} for index,entry in pairs(result["entries"]) do - _result[index] = require(script.Parent.Entry).new(self._collectionName, entry, self._accessToken) + _result[index] = require(script.Parent.Entry).new(self._collectionName, entry, self._accessToken, self._options) end result = _result else @@ -46,7 +46,7 @@ end Collection.deleteEntries = function(self:typeof(Collection), filters:Types.EntryData):number if not self._collectionName then error("[MarcSync: Collection] Invalid Object created or trying to access an destroied object.") end - local result = Utils.makeHTTPRequest("DELETE", "https://api.marcsync.dev/v0/entries/"..self._collectionName, {["filters"]=filters}, self._accessToken); + local result = Utils.makeHTTPRequest("DELETE", "https://api.marcsync.dev/v0/entries/"..self._collectionName, {["filters"]=filters}, self._accessToken, self._options); if not result["success"] then error(result["errorMessage"]) end return result["deletedEntries"] @@ -54,16 +54,17 @@ end Collection.drop = function(self:typeof(Collection)) if not self._collectionName then error("[MarcSync: Collection] Invalid Object created or trying to access an destroied object.") end - local result = Utils.makeHTTPRequest("collection", "DELETE", "https://api.marcsync.dev/v0/collection/"..self._collectionName, {}, self._accessToken); + local result = Utils.makeHTTPRequest("collection", "DELETE", "https://api.marcsync.dev/v0/collection/"..self._collectionName, {}, self._accessToken, self._options); if not result["success"] then error(result["errorMessage"]) end self = nil end return { - new = function(collectionName: string, accessToken: string):typeof(Collection) + new = function(collectionName: string, accessToken: string, options: Types.ClientOptions):typeof(Collection) local self = {} self._collectionName = collectionName self._accessToken = accessToken + self._options = options self = setmetatable(self, { __index = Collection diff --git a/src/MarcSync/Objects/Entry.lua b/src/MarcSync/Objects/Entry.lua index 1bc4e5d..f53631a 100644 --- a/src/MarcSync/Objects/Entry.lua +++ b/src/MarcSync/Objects/Entry.lua @@ -14,7 +14,7 @@ Entry.getValues = function(self:typeof(Entry)):Types.EntryData end Entry.updateValues = function(self:typeof(Entry), data:Types.EntryData):number - local result = Utils.makeHTTPRequest("entry", "PUT", "https://api.marcsync.dev/v0/entries/"..self._tableId, {["filters"]={["_id"]=self._objectId},["data"]=data}, self._accessToken); + local result = Utils.makeHTTPRequest("entry", "PUT", "https://api.marcsync.dev/v0/entries/"..self._tableId, {["filters"]={["_id"]=self._objectId},["data"]=data}, self._accessToken, self._options); if result["success"] and result["modifiedEntries"] and result["modifiedEntries"] > 0 then for i,v in pairs(data) do @@ -29,7 +29,7 @@ end Entry.delete = function(self:typeof(Entry)) if typeof(self) ~= "table" then error("Please use : instead of .") end - local result = Utils.makeHTTPRequest("entry", "DELETE", "https://api.marcsync.dev/v0/entries/"..self._tableId, {["filters"]={["_id"]=self._objectId}}, self._accessToken); + local result = Utils.makeHTTPRequest("entry", "DELETE", "https://api.marcsync.dev/v0/entries/"..self._tableId, {["filters"]={["_id"]=self._objectId}}, self._accessToken, self._options); if not result["success"] then error(result["errorMessage"]) end self = nil @@ -37,13 +37,14 @@ Entry.delete = function(self:typeof(Entry)) end return { - new = function(tableId:string, entryData:Types.EntryData, accessToken:string):typeof(Entry) + new = function(tableId:string, entryData:Types.EntryData, accessToken:string, options: Types.ClientOptions):typeof(Entry) if not tableId or not entryData or not entryData["_id"] or not accessToken then error("[MarcSync: Entry] Tried creating invalid Entry Object.") end local self = {} self._tableId = tableId self._entryData = entryData self._objectId = entryData["_id"] self._accessToken = accessToken + self._options = options self = setmetatable(self, { __index = Entry diff --git a/src/MarcSync/Types.lua b/src/MarcSync/Types.lua index 835be36..b8f26b2 100644 --- a/src/MarcSync/Types.lua +++ b/src/MarcSync/Types.lua @@ -4,4 +4,8 @@ export type EntryData = { [string]: any } +export type ClientOptions = { + retryCount: number +} + return types \ No newline at end of file diff --git a/src/MarcSync/Utils.lua b/src/MarcSync/Utils.lua index 194e2b2..bd242ec 100644 --- a/src/MarcSync/Utils.lua +++ b/src/MarcSync/Utils.lua @@ -3,8 +3,9 @@ local CollectionError = require(script.Parent.Errors.Collection) local EntryError = require(script.Parent.Errors.Entry) local HttpService = game:GetService("HttpService") +local Types = require(script.Parent.Types) -function errorHandler(type: string, resultBody: any, resultObject: {}) +function errorHandler(callInformation: {}, resultBody: any, resultObject: {}, retryCount: number) local Error; if typeof(resultBody) == typeof({}) and resultBody["message"] then Error = resultBody["message"] @@ -14,30 +15,39 @@ function errorHandler(type: string, resultBody: any, resultObject: {}) Error = "An Unexpected Error occoured." end - if type == "collection" then - if resultObject["StatusCode"] == 401 then + local statusCode = resultObject["StatusCode"] + if callInformation.type == "collection" then + if statusCode == 401 then Error = AuthorizationError.InvalidAccessToken("InvalidAccessToken") - elseif resultObject["StatusCode"] == 404 then + elseif statusCode == 404 then Error = CollectionError.CollectionNotFound("CollectionNotFound") - elseif resultObject["StatusCode"] == 400 then + elseif statusCode == 400 then Error = CollectionError.CollectionAlreadyExists("CollectionAlreadyExists") end - elseif type == "entry" then - if resultObject["StatusCode"] == 401 then + elseif callInformation.type == "entry" then + if statusCode == 401 then Error = AuthorizationError.InvalidAccessToken("InvalidAccessToken") - elseif resultObject["StatusCode"] == 404 then + elseif statusCode == 404 then Error = CollectionError.CollectionNotFound("CollectionNotFound") - elseif resultObject["StatusCode"] == 400 then + elseif statusCode == 400 then Error = EntryError.InvalidEntryData("InvalidEntryData") end end + if(statusCode ~= 400 and statusCode ~= 401) then + if retryCount > 0 then + warn("[MarcSync HTTPRequest Handler] MarcSync HTTP Request failed with error: "..Error.." and status code: "..statusCode..". Retrying Request. ("..retryCount..") retries left") + task.wait(3) + return require(script.Parent.Utils).makeHTTPRequest(callInformation.type, callInformation.method, callInformation.url, callInformation.body, callInformation.authorization, {retryCount = retryCount - 1}) + end + end + return {["success"] = false, ["errorMessage"] = Error} end local utils = {} -function utils.makeHTTPRequest(type: string, method: string, url: string, body: {}, authorization: string):{["success"]: boolean, ["message"]: string} +function utils.makeHTTPRequest(type: string, method: string, url: string, body: {}, authorization: string, options: Types.ClientOptions):{["success"]: boolean, ["message"]: string} local resultObj; local resultBody; local success = pcall(function() @@ -54,7 +64,13 @@ function utils.makeHTTPRequest(type: string, method: string, url: string, body: if resultBody["warning"] then warn('[MarcSync HTTPRequest Handler] MarcSync HTTP Request returned warning for URL "'..url..'" with body: "'..HttpService:JSONEncode(body)..'": '..resultBody["warning"]) end return resultBody end - return errorHandler(type, resultBody, resultObj) + return errorHandler({ + type = type, + method = method, + url = url, + body = body, + authorization = authorization + }, resultBody, resultObj, options.retryCount) end return utils \ No newline at end of file