diff --git a/packages/medusa-js/src/error.ts b/packages/medusa-js/src/error.ts index 089ba54664..22bac5baef 100644 --- a/packages/medusa-js/src/error.ts +++ b/packages/medusa-js/src/error.ts @@ -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 {} diff --git a/packages/medusa-js/src/index.ts b/packages/medusa-js/src/index.ts index cd527c7b49..f813c06068 100644 --- a/packages/medusa-js/src/index.ts +++ b/packages/medusa-js/src/index.ts @@ -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" diff --git a/packages/medusa-js/src/key-manager.ts b/packages/medusa-js/src/key-manager.ts new file mode 100644 index 0000000000..412cd72527 --- /dev/null +++ b/packages/medusa-js/src/key-manager.ts @@ -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() diff --git a/packages/medusa-js/src/request.ts b/packages/medusa-js/src/request.ts index dd230b32f8..20194fd5e4 100644 --- a/packages/medusa-js/src/request.ts +++ b/packages/medusa-js/src/request.ts @@ -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() diff --git a/packages/medusa-react/src/contexts/medusa.tsx b/packages/medusa-react/src/contexts/medusa.tsx index 4e02ccb193..193839c42a 100644 --- a/packages/medusa-react/src/contexts/medusa.tsx +++ b/packages/medusa-react/src/contexts/medusa.tsx @@ -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 (