-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Create the Medusa API SDK as js-sdk package
- Loading branch information
Showing
12 changed files
with
560 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@medusajs/js-sdk": patch | ||
--- | ||
|
||
Introduce a js-sdk package for the Medusa API |
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
Empty file.
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,13 @@ | ||
module.exports = { | ||
transform: { | ||
"^.+\\.[jt]s?$": [ | ||
"ts-jest", | ||
{ | ||
tsconfig: "tsconfig.json", | ||
isolatedModules: true, | ||
}, | ||
], | ||
}, | ||
testEnvironment: `node`, | ||
moduleFileExtensions: [`js`, `ts`], | ||
} |
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,40 @@ | ||
{ | ||
"name": "@medusajs/js-sdk", | ||
"version": "0.0.1", | ||
"description": "SDK for the Medusa API", | ||
"main": "dist/index.js", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/medusajs/medusa", | ||
"directory": "packages/core/js-sdk" | ||
}, | ||
"engines": { | ||
"node": ">=16" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"files": [ | ||
"dist" | ||
], | ||
"author": "Medusa", | ||
"license": "MIT", | ||
"devDependencies": { | ||
"cross-env": "^5.2.1", | ||
"jest": "^29.6.3", | ||
"rimraf": "^5.0.1", | ||
"ts-jest": "^29.1.1", | ||
"typescript": "^5.1.6" | ||
}, | ||
"dependencies": { | ||
"@medusajs/types": "^1.11.16", | ||
"@medusajs/utils": "^1.11.9", | ||
"qs": "^6.12.1" | ||
}, | ||
"scripts": { | ||
"prepublishOnly": "cross-env NODE_ENV=production tsc --build", | ||
"build": "rimraf dist && tsc --build", | ||
"test": "jest --runInBand --bail --forceExit", | ||
"watch": "tsc --build --watch" | ||
} | ||
} |
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,8 @@ | ||
import { Client } from "../client" | ||
|
||
export class Admin { | ||
private client: Client | ||
constructor(client: Client) { | ||
this.client = client | ||
} | ||
} |
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,137 @@ | ||
import qs from "qs" | ||
import { ClientFetch, Config, FetchParams, Logger } from "./types" | ||
|
||
const isBrowser = () => typeof window !== "undefined" | ||
|
||
const toBase64 = (str: string) => { | ||
if (typeof window !== "undefined") { | ||
return window.btoa(str) | ||
} | ||
|
||
return Buffer.from(str).toString("base64") | ||
} | ||
|
||
const sanitizeHeaders = (headers: any) => { | ||
return { ...headers, Authorization: "<REDACTED>" } | ||
} | ||
|
||
// TODO: Add support for retries and timeouts | ||
export class Client { | ||
public fetch: ClientFetch | ||
private logger: Logger | ||
|
||
private DEFAULT_JWT_STORAGE_KEY = "medusa_auth_token" | ||
private token = "" | ||
|
||
constructor(config: Config) { | ||
const logger = config.logger || { | ||
error: console.error, | ||
warn: console.warn, | ||
info: console.info, | ||
debug: console.debug, | ||
} | ||
|
||
this.logger = { | ||
...logger, | ||
debug: config.debug ? logger.debug : () => {}, | ||
} | ||
|
||
this.fetch = this.initClient(config) | ||
} | ||
|
||
protected initClient(config: Config): ClientFetch { | ||
const defaultHeaders = { | ||
"Content-Type": "application/json", | ||
Accept: "application/json", | ||
...this.getApiKeyHeader(config), | ||
...this.getPublishableKeyHeader(config), | ||
...config.globalHeaders, | ||
} | ||
|
||
this.logger.debug( | ||
"Initiating Medusa client with default headers:\n", | ||
`${JSON.stringify(sanitizeHeaders(defaultHeaders), null, 2)}\n` | ||
) | ||
|
||
return ( | ||
input: FetchParams[0], | ||
init?: FetchParams[1] & { query?: Record<string, any> } | ||
) => { | ||
// We always want to fetch the up-to-date JWT token before firing off a request. | ||
const jwtToken = this.getJwtTokenHeader(config) | ||
|
||
const headers = init?.headers | ||
? { ...defaultHeaders, ...jwtToken, ...init.headers } | ||
: { ...defaultHeaders, ...jwtToken } | ||
|
||
let normalizedInput: RequestInfo | URL = input | ||
if (input instanceof URL || typeof input === "string") { | ||
normalizedInput = new URL(input, config.baseUrl) | ||
if (init?.query) { | ||
const existing = qs.parse(normalizedInput.search) | ||
const stringifiedQuery = qs.stringify({ existing, ...init.query }) | ||
normalizedInput.search = stringifiedQuery | ||
} | ||
} | ||
|
||
this.logger.debug( | ||
"Performing request to:\n", | ||
`URL: ${normalizedInput.toString()}\n`, | ||
`Headers: ${JSON.stringify(sanitizeHeaders(headers), null, 2)}\n` | ||
) | ||
|
||
// TODO: Make response a bit more user friendly (throw errors, return JSON if resp content type is json, etc.) | ||
return fetch(normalizedInput, { ...init, headers }).then((resp) => { | ||
this.logger.debug(`Received response with status ${resp.status}\n`) | ||
return resp | ||
}) | ||
} | ||
} | ||
|
||
protected getApiKeyHeader = ( | ||
config: Config | ||
): { Authorization: string } | {} => { | ||
return config.apiKey | ||
? { Authorization: "Basic " + toBase64(config.apiKey + ":") } | ||
: {} | ||
} | ||
|
||
protected getPublishableKeyHeader = ( | ||
config: Config | ||
): { "x-medusa-pub-key": string } | {} => { | ||
return config.publishableKey | ||
? { "x-medusa-pub-key": config.publishableKey } | ||
: {} | ||
} | ||
|
||
protected getJwtTokenHeader = ( | ||
config: Config | ||
): { Authorization: string } | {} => { | ||
const storageMethod = | ||
config.jwtToken?.storageMethod || (isBrowser() ? "local" : "memory") | ||
const storageKey = | ||
config.jwtToken?.storageKey || this.DEFAULT_JWT_STORAGE_KEY | ||
|
||
switch (storageMethod) { | ||
case "local": { | ||
if (!isBrowser()) { | ||
throw new Error("Local JWT storage is only available in the browser") | ||
} | ||
const token = window.localStorage.getItem(storageKey) | ||
return token ? { Authorization: `Bearer ${token}` } : {} | ||
} | ||
case "session": { | ||
if (!isBrowser()) { | ||
throw new Error( | ||
"Session JWT storage is only available in the browser" | ||
) | ||
} | ||
const token = window.sessionStorage.getItem(storageKey) | ||
return token ? { Authorization: `Bearer ${token}` } : {} | ||
} | ||
case "memory": { | ||
return this.token ? { Authorization: `Bearer ${this.token}` } : {} | ||
} | ||
} | ||
} | ||
} |
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,18 @@ | ||
import { Admin } from "./admin" | ||
import { Client } from "./client" | ||
import { Store } from "./store" | ||
import { Config } from "./types" | ||
|
||
class Medusa { | ||
public client: Client | ||
public admin: Admin | ||
public store: Store | ||
|
||
constructor(config: Config) { | ||
this.client = new Client(config) | ||
this.admin = new Admin(this.client) | ||
this.store = new Store(this.client) | ||
} | ||
} | ||
|
||
export default Medusa |
Oops, something went wrong.