feat(medusa-js): Register PublishableApiKey (#2616)

**What**
- register a publishable API key through `medusa-js` i.e. define the key that will be sent with each request

**How**
- introduce KeyManager class which is used to share keys between medusa-js objects.

**Usage**
1. Set the key through the `Medusa` config
2. Set the key through `KeyManager` dynamically:
```ts
import { KeyManager } from "medusa-js"

KeyManager.registerPublishableApiKey("pk_123")
```

---

RESOLVES CORE-794
This commit is contained in:
Frane Polić
2022-11-17 13:19:18 +01:00
committed by GitHub
parent f60267a494
commit 9eafde07fe
5 changed files with 65 additions and 2 deletions

View File

@@ -47,7 +47,7 @@ export class MedusaAPIError extends MedusaError {}
export class MedusaAuthenticationError extends MedusaError {}
/**
* MedusaPermissionErorr is raised when attempting to access a resource without permissions
* MedusaPermissionError is raised when attempting to access a resource without permissions
*/
export class MedusaPermissionError extends MedusaError {}

View File

@@ -17,6 +17,7 @@ import ReturnReasonsResource from "./resources/return-reasons"
import ReturnsResource from "./resources/returns"
import ShippingOptionsResource from "./resources/shipping-options"
import SwapsResource from "./resources/swaps"
import KeyManager from "./key-manager"
class Medusa {
private client: Client
@@ -63,8 +64,19 @@ class Medusa {
this.paymentMethods = new PaymentMethodsResource(this.client)
this.paymentCollections = new PaymentCollectionsResource(this.client)
}
/**
* Set a PublishableApiKey that will be sent with each request
* to define the scope of available resources.
*
* @param key - PublishableApiKey identifier
*/
setPublishableKey(key: string) {
KeyManager.registerPublishableApiKey(key)
}
}
export default Medusa
export { default as KeyManager } from "./key-manager"
export * from "./typings"

View File

@@ -0,0 +1,25 @@
/**
* `KeyManager` holds API keys in state.
*/
class KeyManager {
private publishableApiKey: string | null = null
/**
* Set a publishable api key to be sent with each request.
*/
public registerPublishableApiKey(key: string) {
this.publishableApiKey = key
}
/**
* Retrieve the publishable api key.
*/
public getPublishableApiKey() {
return this.publishableApiKey
}
}
/**
* Export singleton instance.
*/
export default new KeyManager()

View File

@@ -2,17 +2,22 @@ import axios, { AxiosError, AxiosInstance, AxiosRequestHeaders } from "axios"
import * as rax from "retry-axios"
import { v4 as uuidv4 } from "uuid"
import KeyManager from "./key-manager"
const unAuthenticatedAdminEndpoints = {
"/admin/auth": "POST",
"/admin/users/password-token": "POST",
"/admin/users/reset-password": "POST",
"/admin/invites/accept": "POST",
}
export interface Config {
baseUrl: string
maxRetries: number
apiKey?: string
publishableApiKey?: string
}
export interface RequestOptions {
timeout?: number
numberOfRetries?: number
@@ -123,6 +128,13 @@ class Client {
}
}
const publishableApiKey =
this.config.publishableApiKey || KeyManager.getPublishableApiKey()
if (publishableApiKey) {
defaultHeaders["x-publishable-api-key"] = publishableApiKey
}
// only add idempotency key, if we want to retry
if (this.config.maxRetries > 0 && method === "POST") {
defaultHeaders["Idempotency-Key"] = uuidv4()

View File

@@ -20,16 +20,30 @@ interface MedusaProviderProps {
baseUrl: string
queryClientProviderProps: QueryClientProviderProps
children: React.ReactNode
/**
* Authentication token
*/
apiKey?: string
/**
* PublishableApiKey identifier that defines the scope of resources
* available within the request
*/
publishableApiKey?: string
}
export const MedusaProvider = ({
queryClientProviderProps,
baseUrl,
apiKey,
publishableApiKey,
children,
}: MedusaProviderProps) => {
const medusaClient = new Medusa({ baseUrl, maxRetries: 0, apiKey })
const medusaClient = new Medusa({
baseUrl,
maxRetries: 0,
apiKey,
publishableApiKey,
})
return (
<QueryClientProvider {...queryClientProviderProps}>
<MedusaContext.Provider