feat(js-sdk): implement custom storage config to support react native (#11467)

* feat(js-sdk): implement custom storage config to support react native

* chore: add changeset

* feat(js-sdk): implement custom storage config to support react native

* chore: add changeset

* test:  add unit tests for custom storage
This commit is contained in:
Ranjith kumar
2025-02-18 08:38:23 +01:00
committed by GitHub
parent ee848bf0f4
commit 32ad13813b
5 changed files with 155 additions and 21 deletions
+33 -13
View File
@@ -175,15 +175,15 @@ export class Client {
return { stream: null, abort: abortFunc }
}
setToken(token: string) {
this.setToken_(token)
async setToken(token: string) {
await this.setToken_(token)
}
clearToken() {
this.clearToken_()
async clearToken() {
await this.clearToken_()
}
protected clearToken_() {
protected async clearToken_() {
const { storageMethod, storageKey } = this.getTokenStorageInfo_()
switch (storageMethod) {
case "local": {
@@ -194,6 +194,10 @@ export class Client {
window.sessionStorage.removeItem(storageKey)
break
}
case "custom": {
await this.config.auth?.storage?.removeItem(storageKey)
break
}
case "memory": {
this.token = ""
break
@@ -219,7 +223,7 @@ export class Client {
const headers = new Headers(defaultHeaders)
const customHeaders = {
...this.config.globalHeaders,
...this.getJwtHeader_(),
...(await this.getJwtHeader_()),
...init?.headers,
}
// We use `headers.set` in order to ensure headers are overwritten in a case-insensitive manner.
@@ -278,17 +282,17 @@ export class Client {
: {}
}
protected getJwtHeader_ = (): { Authorization: string } | {} => {
protected async getJwtHeader_(): Promise<{ Authorization: string } | {}> {
// If the user has requested for session storage, we don't want to send the JWT token in the header.
if (this.config.auth?.type === "session") {
return {}
}
const token = this.getToken_()
const token = await this.getToken_()
return token ? { Authorization: `Bearer ${token}` } : {}
}
protected setToken_ = (token: string) => {
protected async setToken_(token: string) {
const { storageMethod, storageKey } = this.getTokenStorageInfo_()
switch (storageMethod) {
case "local": {
@@ -299,6 +303,10 @@ export class Client {
window.sessionStorage.setItem(storageKey, token)
break
}
case "custom": {
await this.config.auth?.storage?.setItem(storageKey, token)
break
}
case "memory": {
this.token = token
break
@@ -306,7 +314,7 @@ export class Client {
}
}
protected getToken_ = () => {
protected async getToken_() {
const { storageMethod, storageKey } = this.getTokenStorageInfo_()
switch (storageMethod) {
case "local": {
@@ -315,17 +323,21 @@ export class Client {
case "session": {
return window.sessionStorage.getItem(storageKey)
}
case "custom": {
return await this.config.auth?.storage?.getItem(storageKey)
}
case "memory": {
return this.token
}
}
return
return null
}
protected getTokenStorageInfo_ = () => {
const hasLocal = hasStorage("localStorage")
const hasSession = hasStorage("sessionStorage")
const hasCustom = Boolean(this.config.auth?.storage)
const storageMethod =
this.config.auth?.jwtTokenStorageMethod ||
@@ -334,10 +346,13 @@ export class Client {
this.config.auth?.jwtTokenStorageKey || this.DEFAULT_JWT_STORAGE_KEY
if (!hasLocal && storageMethod === "local") {
throw new Error("Local JWT storage is only available in the browser")
this.throwError_("Local JWT storage is only available in the browser")
}
if (!hasSession && storageMethod === "session") {
throw new Error("Session JWT storage is only available in the browser")
this.throwError_("Session JWT storage is only available in the browser")
}
if (!hasCustom && storageMethod === "custom") {
this.throwError_("Custom storage was not provided in the config")
}
return {
@@ -345,4 +360,9 @@ export class Client {
storageKey,
}
}
protected throwError_(message: string) {
this.logger.error(message)
throw new Error(message)
}
}