Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8f06522
commit 40af56e
Showing
5 changed files
with
235 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
const frontendCookiesKey = "frontendCookies"; | ||
|
||
let inMemoryStorage = {}; | ||
|
||
function setKeyValue(key, value) { | ||
try { | ||
window.localStorage.setItem(key, value); | ||
} catch (err) { | ||
inMemoryStorage[key] = value; | ||
} | ||
} | ||
|
||
function getKeyValue(key) { | ||
try { | ||
return window.localStorage.getItem(key); | ||
} catch (err) { | ||
if (inMemoryStorage[key] === undefined) { | ||
return null; | ||
} else { | ||
return inMemoryStorage[key]; | ||
} | ||
} | ||
} | ||
|
||
function getCookiesFromStorage() { | ||
const cookiesFromStorage = getKeyValue(frontendCookiesKey); | ||
|
||
if (cookiesFromStorage === null) { | ||
setKeyValue(frontendCookiesKey, "[]"); | ||
return ""; | ||
} | ||
|
||
/** | ||
* Because we store cookies in local storage, we need to manually check | ||
* for expiry before returning all cookies | ||
*/ | ||
const cookieArrayInStorage = JSON.parse(cookiesFromStorage); | ||
let cookieArrayToReturn = []; | ||
|
||
for (let cookieIndex = 0; cookieIndex < cookieArrayInStorage.length; cookieIndex++) { | ||
const currentCookieString = cookieArrayInStorage[cookieIndex]; | ||
const parts = currentCookieString.split(";"); | ||
let expirationString = ""; | ||
|
||
for (let partIndex = 0; partIndex < parts.length; partIndex++) { | ||
const currentPart = parts[partIndex]; | ||
|
||
if (currentPart.toLocaleLowerCase().includes("expires=")) { | ||
expirationString = currentPart; | ||
break; | ||
} | ||
} | ||
|
||
if (expirationString !== "") { | ||
const expirationValueString = expirationString.split("=")[1]; | ||
const expirationDate = new Date(expirationValueString); | ||
const currentTimeInMillis = Date.now(); | ||
|
||
// if the cookie has expired, we skip it | ||
if (expirationDate.getTime() < currentTimeInMillis) { | ||
continue; | ||
} | ||
} | ||
|
||
cookieArrayToReturn.push(currentCookieString); | ||
} | ||
|
||
/** | ||
* After processing and removing expired cookies we need to update the cookies | ||
* in storage so we dont have to process the expired ones again | ||
*/ | ||
setKeyValue(frontendCookiesKey, JSON.stringify(cookieArrayToReturn)); | ||
|
||
return cookieArrayToReturn.join("; "); | ||
} | ||
|
||
function setCookieToStorage(cookieString) { | ||
const cookieName = cookieString.split(";")[0].split("=")[0]; | ||
const cookiesFromStorage = getKeyValue(frontendCookiesKey); | ||
let cookiesArray = []; | ||
|
||
if (cookiesFromStorage !== null) { | ||
const cookiesArrayFromStorage = JSON.parse(cookiesFromStorage); | ||
cookiesArray = cookiesArrayFromStorage; | ||
} | ||
|
||
let cookieIndex = -1; | ||
|
||
for (let i = 0; i < cookiesArray.length; i++) { | ||
const currentCookie = cookiesArray[i]; | ||
|
||
if (currentCookie.indexOf(`${cookieName}=`) !== -1) { | ||
cookieIndex = i; | ||
break; | ||
} | ||
} | ||
|
||
/** | ||
* If a cookie with the same name already exists (index != -1) then we | ||
* need to remove the old value and replace it with the new one. | ||
* | ||
* If it does not exist then simply add the new cookie | ||
*/ | ||
if (cookieIndex !== -1) { | ||
cookiesArray[cookieIndex] = cookieString; | ||
} else { | ||
cookiesArray.push(cookieString); | ||
} | ||
|
||
setKeyValue(frontendCookiesKey, JSON.stringify(cookiesArray)); | ||
} | ||
|
||
export default function getCookieHandler(original) { | ||
return { | ||
...original, | ||
getCookie: async function () { | ||
const cookies = getCookiesFromStorage(); | ||
return cookies; | ||
}, | ||
setCookie: async function (cookieString) { | ||
setCookieToStorage(cookieString); | ||
}, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
/** | ||
* This example app uses HashRouter from react-router-dom. The SuperTokens SDK relies on | ||
* some window properties like location hash, query params etc. Because HashRouter places | ||
* everything other than the website base in the location hash, we need to add custom | ||
* handling for some of the properties of the Window API | ||
*/ | ||
|
||
import Router from "next/router"; | ||
|
||
let inmemstorage = {}; | ||
|
||
export default function getWindowHandler(original) { | ||
return { | ||
...original, | ||
location: { | ||
...original.location, | ||
setHref: (href) => { | ||
Router.push(href); | ||
}, | ||
}, | ||
localStorage: { | ||
...original.localStorage, | ||
key: async (index) => { | ||
try { | ||
return window.localStorage.key(index); | ||
} catch (err) { | ||
return Object.keys(inmemstorage)[index]; | ||
} | ||
}, | ||
getItem: async (key) => { | ||
try { | ||
return window.localStorage.getItem(key); | ||
} catch (err) { | ||
return inmemstorage[key] === undefined ? null : inmemstorage[key]; | ||
} | ||
}, | ||
clear: async () => { | ||
try { | ||
return window.localStorage.clear(); | ||
} catch (err) { | ||
inmemstorage = {}; | ||
} | ||
}, | ||
removeItem: async (key) => { | ||
try { | ||
return window.localStorage.removeItem(key); | ||
} catch (err) { | ||
delete inmemstorage[key]; | ||
} | ||
}, | ||
setItem: async (key, value) => { | ||
try { | ||
return window.localStorage.setItem(key, value); | ||
} catch (err) { | ||
inmemstorage[key] = value; | ||
} | ||
}, | ||
keySync: (index) => { | ||
try { | ||
return window.localStorage.key(index); | ||
} catch (err) { | ||
return Object.keys(inmemstorage)[index]; | ||
} | ||
}, | ||
getItemSync: (key) => { | ||
try { | ||
return window.localStorage.getItem(key); | ||
} catch (err) { | ||
return inmemstorage[key] === undefined ? null : inmemstorage[key]; | ||
} | ||
}, | ||
clearSync: () => { | ||
try { | ||
return window.localStorage.clear(); | ||
} catch (err) { | ||
inmemstorage = {}; | ||
} | ||
}, | ||
removeItemSync: (key) => { | ||
try { | ||
return window.localStorage.removeItem(key); | ||
} catch (err) { | ||
delete inmemstorage[key]; | ||
} | ||
}, | ||
setItemSync: (key, value) => { | ||
try { | ||
return window.localStorage.setItem(key, value); | ||
} catch (err) { | ||
inmemstorage[key] = value; | ||
} | ||
}, | ||
}, | ||
}; | ||
} |