@mercurjs/client 2.3.8-canary.3 → 2.3.9-canary.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +84 -2
- package/dist/index.mjs +148 -8
- package/package.json +6 -4
package/dist/index.d.mts
CHANGED
|
@@ -8,10 +8,92 @@ type InferOutput<TResponse> = TResponse extends MedusaResponse<infer Output> ? O
|
|
|
8
8
|
type HttpMethod = "GET" | "POST" | "DELETE";
|
|
9
9
|
type ChildKeys<T> = Exclude<keyof T, HttpMethod | "__esModule">;
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Token storage and request authentication for the client.
|
|
13
|
+
*
|
|
14
|
+
* A token store keeps one credential under one key and survives reloads
|
|
15
|
+
* through `localStorage` when it exists, falling back to memory on the server
|
|
16
|
+
* or when storage is blocked. An auth scheme turns stores into the headers a
|
|
17
|
+
* Mercur API expects, resolved freshly on every request.
|
|
18
|
+
*/
|
|
19
|
+
type TokenStorage = {
|
|
20
|
+
getItem(key: string): string | null;
|
|
21
|
+
setItem(key: string, value: string): void;
|
|
22
|
+
removeItem(key: string): void;
|
|
23
|
+
};
|
|
24
|
+
type TokenStore = {
|
|
25
|
+
readonly key: string;
|
|
26
|
+
get(): string | null;
|
|
27
|
+
set(token: string): void;
|
|
28
|
+
clear(): void;
|
|
29
|
+
/** Called with the new value after every `set` and `clear`, in this tab. */
|
|
30
|
+
subscribe(listener: (token: string | null) => void): () => void;
|
|
31
|
+
};
|
|
32
|
+
declare function createTokenStore(key: string, storage?: TokenStorage): TokenStore;
|
|
33
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
34
|
+
type Credential = string | null | undefined;
|
|
35
|
+
/** One way of authenticating a request. Several can be combined in `ClientOptions.auth`. */
|
|
36
|
+
type AuthScheme = {
|
|
37
|
+
type: "bearer";
|
|
38
|
+
token: TokenStore | (() => MaybePromise<Credential>);
|
|
39
|
+
} | {
|
|
40
|
+
type: "api-key";
|
|
41
|
+
key: TokenStore | (() => MaybePromise<Credential>);
|
|
42
|
+
} | {
|
|
43
|
+
type: "publishable-key";
|
|
44
|
+
key: TokenStore | (() => MaybePromise<Credential>);
|
|
45
|
+
} | {
|
|
46
|
+
type: "header";
|
|
47
|
+
name: string;
|
|
48
|
+
value: TokenStore | (() => MaybePromise<Credential>);
|
|
49
|
+
};
|
|
50
|
+
type AuthOption = TokenStore | AuthScheme | AuthScheme[];
|
|
51
|
+
/** The session token of an admin or vendor panel user, as `Authorization: Bearer`. */
|
|
52
|
+
declare const bearerAuth: (token: TokenStore | (() => MaybePromise<Credential>)) => AuthScheme;
|
|
53
|
+
/** A secret API key (`sk_…`), sent the way Medusa expects it: HTTP Basic with the key as the user. */
|
|
54
|
+
declare const apiKeyAuth: (key: TokenStore | (() => MaybePromise<Credential>)) => AuthScheme;
|
|
55
|
+
/** A publishable API key (`pk_…`) for the Store API. */
|
|
56
|
+
declare const publishableKeyAuth: (key: TokenStore | (() => MaybePromise<Credential>)) => AuthScheme;
|
|
57
|
+
/** Any other credential header, e.g. the vendor panel's active seller. */
|
|
58
|
+
declare const headerAuth: (name: string, value: TokenStore | (() => MaybePromise<Credential>)) => AuthScheme;
|
|
59
|
+
declare function resolveAuthHeaders(auth: AuthOption | undefined): Promise<Record<string, string>>;
|
|
60
|
+
/** Clears every token store the auth option reads from; used after a 401. */
|
|
61
|
+
declare function clearAuthStores(auth: AuthOption | undefined): void;
|
|
62
|
+
/**
|
|
63
|
+
* The stores the admin and vendor panels keep their sessions in. A plugin's
|
|
64
|
+
* dashboard code reads the same session by using the same store, so it never
|
|
65
|
+
* has to know the storage key.
|
|
66
|
+
*/
|
|
67
|
+
declare const ADMIN_TOKEN_KEY = "mercur_admin_auth_token";
|
|
68
|
+
declare const VENDOR_TOKEN_KEY = "mercur_vendor_auth_token";
|
|
69
|
+
declare const VENDOR_SELLER_KEY = "mercur_vendor_seller_id";
|
|
70
|
+
declare const adminTokenStore: TokenStore;
|
|
71
|
+
declare const vendorTokenStore: TokenStore;
|
|
72
|
+
declare const vendorSellerStore: TokenStore;
|
|
73
|
+
/** Auth for anything that talks to `/admin/*` as the signed-in panel user. */
|
|
74
|
+
declare const adminAuth: () => AuthScheme[];
|
|
75
|
+
/** Auth for `/vendor/*` as the signed-in seller member, scoped to the active seller. */
|
|
76
|
+
declare const vendorAuth: () => AuthScheme[];
|
|
77
|
+
|
|
11
78
|
type ClientOptions = {
|
|
12
79
|
baseUrl: string;
|
|
13
80
|
fetchOptions?: RequestInit;
|
|
14
|
-
|
|
81
|
+
/**
|
|
82
|
+
* How requests authenticate: a token store (sent as a bearer token), one
|
|
83
|
+
* scheme, or several. Resolved on every request, so a token set after the
|
|
84
|
+
* client was created is picked up by the next call.
|
|
85
|
+
*/
|
|
86
|
+
auth?: AuthOption;
|
|
87
|
+
/** Extra headers computed per request, on top of `auth`. */
|
|
88
|
+
headers?: () => Record<string, string> | Promise<Record<string, string>>;
|
|
89
|
+
/**
|
|
90
|
+
* Runs when the API answers 401. By default the bearer token stores in
|
|
91
|
+
* `auth` are cleared so the panel falls back to its login screen.
|
|
92
|
+
*/
|
|
93
|
+
onUnauthorized?: (error: {
|
|
94
|
+
status: number;
|
|
95
|
+
message: string;
|
|
96
|
+
}) => void;
|
|
15
97
|
};
|
|
16
98
|
type AddParamsToFn<Fn, TParams> = keyof TParams extends never ? Fn : Fn extends (input?: infer TInput) => infer TOutput ? (input: (TInput extends Record<string, any> ? Omit<TInput, 'fetchOptions'> : {}) & TParams & {
|
|
17
99
|
fetchOptions?: RequestInit;
|
|
@@ -59,4 +141,4 @@ declare class ClientError extends Error {
|
|
|
59
141
|
}
|
|
60
142
|
declare function createClient(options: ClientOptions): any;
|
|
61
143
|
|
|
62
|
-
export { ClientError, type InferClient, type InferClientInput, type InferClientOutput, createClient };
|
|
144
|
+
export { ADMIN_TOKEN_KEY, type AuthOption, type AuthScheme, ClientError, type InferClient, type InferClientInput, type InferClientOutput, type TokenStorage, type TokenStore, VENDOR_SELLER_KEY, VENDOR_TOKEN_KEY, adminAuth, adminTokenStore, apiKeyAuth, bearerAuth, clearAuthStores, createClient, createTokenStore, headerAuth, publishableKeyAuth, resolveAuthHeaders, vendorAuth, vendorSellerStore, vendorTokenStore };
|
package/dist/index.mjs
CHANGED
|
@@ -75,6 +75,123 @@ function createRecursiveProxy(callback, path = []) {
|
|
|
75
75
|
// src/utils.ts
|
|
76
76
|
var kebabCase = (string) => string.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
|
|
77
77
|
|
|
78
|
+
// src/auth.ts
|
|
79
|
+
var memoryStorage = () => {
|
|
80
|
+
const map = /* @__PURE__ */ new Map();
|
|
81
|
+
return {
|
|
82
|
+
getItem: (key) => {
|
|
83
|
+
var _a;
|
|
84
|
+
return (_a = map.get(key)) != null ? _a : null;
|
|
85
|
+
},
|
|
86
|
+
setItem: (key, value) => void map.set(key, value),
|
|
87
|
+
removeItem: (key) => void map.delete(key)
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
var resolveStorage = (storage) => {
|
|
91
|
+
if (storage) return storage;
|
|
92
|
+
try {
|
|
93
|
+
if (typeof localStorage !== "undefined") {
|
|
94
|
+
localStorage.getItem("__mercur_probe__");
|
|
95
|
+
return localStorage;
|
|
96
|
+
}
|
|
97
|
+
} catch (e) {
|
|
98
|
+
}
|
|
99
|
+
return memoryStorage();
|
|
100
|
+
};
|
|
101
|
+
function createTokenStore(key, storage) {
|
|
102
|
+
const backing = resolveStorage(storage);
|
|
103
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
104
|
+
const notify = (token) => listeners.forEach((l) => l(token));
|
|
105
|
+
return {
|
|
106
|
+
key,
|
|
107
|
+
get() {
|
|
108
|
+
try {
|
|
109
|
+
return backing.getItem(key);
|
|
110
|
+
} catch (e) {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
set(token) {
|
|
115
|
+
try {
|
|
116
|
+
backing.setItem(key, token);
|
|
117
|
+
} catch (e) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
notify(token);
|
|
121
|
+
},
|
|
122
|
+
clear() {
|
|
123
|
+
try {
|
|
124
|
+
backing.removeItem(key);
|
|
125
|
+
} catch (e) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
notify(null);
|
|
129
|
+
},
|
|
130
|
+
subscribe(listener) {
|
|
131
|
+
listeners.add(listener);
|
|
132
|
+
return () => void listeners.delete(listener);
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
var read = (source) => typeof source === "function" ? source() : source.get();
|
|
137
|
+
var isTokenStore = (value) => typeof value === "object" && value !== null && "get" in value && "subscribe" in value;
|
|
138
|
+
var toBase64 = (value) => typeof btoa === "function" ? btoa(value) : Buffer.from(value, "utf8").toString("base64");
|
|
139
|
+
var bearerAuth = (token) => ({ type: "bearer", token });
|
|
140
|
+
var apiKeyAuth = (key) => ({ type: "api-key", key });
|
|
141
|
+
var publishableKeyAuth = (key) => ({ type: "publishable-key", key });
|
|
142
|
+
var headerAuth = (name, value) => ({ type: "header", name, value });
|
|
143
|
+
function resolveAuthHeaders(auth) {
|
|
144
|
+
return __async(this, null, function* () {
|
|
145
|
+
if (!auth) return {};
|
|
146
|
+
const schemes = isTokenStore(auth) ? [bearerAuth(auth)] : Array.isArray(auth) ? auth : [auth];
|
|
147
|
+
const headers = {};
|
|
148
|
+
for (const scheme of schemes) {
|
|
149
|
+
switch (scheme.type) {
|
|
150
|
+
case "bearer": {
|
|
151
|
+
const token = yield read(scheme.token);
|
|
152
|
+
if (token) headers.Authorization = `Bearer ${token}`;
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
case "api-key": {
|
|
156
|
+
const key = yield read(scheme.key);
|
|
157
|
+
if (key) headers.Authorization = `Basic ${toBase64(`${key}:`)}`;
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
case "publishable-key": {
|
|
161
|
+
const key = yield read(scheme.key);
|
|
162
|
+
if (key) headers["x-publishable-api-key"] = key;
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
case "header": {
|
|
166
|
+
const value = yield read(scheme.value);
|
|
167
|
+
if (value) headers[scheme.name] = value;
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return headers;
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
function clearAuthStores(auth) {
|
|
176
|
+
if (!auth) return;
|
|
177
|
+
const schemes = isTokenStore(auth) ? [bearerAuth(auth)] : Array.isArray(auth) ? auth : [auth];
|
|
178
|
+
for (const scheme of schemes) {
|
|
179
|
+
const source = scheme.type === "bearer" ? scheme.token : scheme.type === "header" ? scheme.value : scheme.key;
|
|
180
|
+
if (isTokenStore(source) && scheme.type === "bearer") source.clear();
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
var ADMIN_TOKEN_KEY = "mercur_admin_auth_token";
|
|
184
|
+
var VENDOR_TOKEN_KEY = "mercur_vendor_auth_token";
|
|
185
|
+
var VENDOR_SELLER_KEY = "mercur_vendor_seller_id";
|
|
186
|
+
var adminTokenStore = createTokenStore(ADMIN_TOKEN_KEY);
|
|
187
|
+
var vendorTokenStore = createTokenStore(VENDOR_TOKEN_KEY);
|
|
188
|
+
var vendorSellerStore = createTokenStore(VENDOR_SELLER_KEY);
|
|
189
|
+
var adminAuth = () => [bearerAuth(adminTokenStore)];
|
|
190
|
+
var vendorAuth = () => [
|
|
191
|
+
bearerAuth(vendorTokenStore),
|
|
192
|
+
headerAuth("x-seller-id", vendorSellerStore)
|
|
193
|
+
];
|
|
194
|
+
|
|
78
195
|
// src/index.ts
|
|
79
196
|
var ClientError = class extends Error {
|
|
80
197
|
constructor(message, statusText, status, code) {
|
|
@@ -112,8 +229,8 @@ var toFormData = (payload) => {
|
|
|
112
229
|
return formData;
|
|
113
230
|
};
|
|
114
231
|
function createClient(options) {
|
|
115
|
-
const { baseUrl, fetchOptions: defaultFetchOptions, headers: resolveHeaders } = options;
|
|
116
|
-
return createRecursiveProxy((path, args) => {
|
|
232
|
+
const { baseUrl, fetchOptions: defaultFetchOptions, headers: resolveHeaders, auth, onUnauthorized } = options;
|
|
233
|
+
return createRecursiveProxy((path, args) => __async(null, null, function* () {
|
|
117
234
|
var _a;
|
|
118
235
|
const action = path.pop();
|
|
119
236
|
const input = (_a = args[0]) != null ? _a : {};
|
|
@@ -153,28 +270,51 @@ function createClient(options) {
|
|
|
153
270
|
if (!isMultipart) {
|
|
154
271
|
defaultHeaders["Content-Type"] = "application/json";
|
|
155
272
|
}
|
|
156
|
-
const headers = new Headers(__spreadValues(__spreadValues(__spreadValues(__spreadValues({}, defaultHeaders), defaultFetchOptions == null ? void 0 : defaultFetchOptions.headers), resolveHeaders == null ? void 0 : resolveHeaders()), inputFetchOptions == null ? void 0 : inputFetchOptions.headers));
|
|
273
|
+
const headers = new Headers(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues({}, defaultHeaders), defaultFetchOptions == null ? void 0 : defaultFetchOptions.headers), yield resolveAuthHeaders(auth)), yield resolveHeaders == null ? void 0 : resolveHeaders()), inputFetchOptions == null ? void 0 : inputFetchOptions.headers));
|
|
157
274
|
return fetch(url, __spreadProps(__spreadValues(__spreadValues({}, defaultFetchOptions), inputFetchOptions), {
|
|
158
275
|
method,
|
|
159
276
|
body,
|
|
160
277
|
headers
|
|
161
278
|
})).then((response) => __async(null, null, function* () {
|
|
162
|
-
var _a2, _b2;
|
|
279
|
+
var _a2, _b2, _c;
|
|
163
280
|
if (response.status >= 300) {
|
|
164
281
|
const jsonError = yield response.json().catch(() => ({}));
|
|
282
|
+
if (response.status === 401) {
|
|
283
|
+
const message = (_a2 = jsonError.message) != null ? _a2 : response.statusText;
|
|
284
|
+
if (onUnauthorized) {
|
|
285
|
+
onUnauthorized({ status: 401, message });
|
|
286
|
+
} else {
|
|
287
|
+
clearAuthStores(auth);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
165
290
|
throw new ClientError(
|
|
166
|
-
(
|
|
291
|
+
(_b2 = jsonError.message) != null ? _b2 : response.statusText,
|
|
167
292
|
response.statusText,
|
|
168
293
|
response.status,
|
|
169
294
|
typeof jsonError.code === "string" ? jsonError.code : void 0
|
|
170
295
|
);
|
|
171
296
|
}
|
|
172
|
-
const isJsonRequest = (
|
|
297
|
+
const isJsonRequest = (_c = headers.get("accept")) == null ? void 0 : _c.includes("application/json");
|
|
173
298
|
return isJsonRequest ? yield response.json() : response;
|
|
174
299
|
}));
|
|
175
|
-
});
|
|
300
|
+
}));
|
|
176
301
|
}
|
|
177
302
|
export {
|
|
303
|
+
ADMIN_TOKEN_KEY,
|
|
178
304
|
ClientError,
|
|
179
|
-
|
|
305
|
+
VENDOR_SELLER_KEY,
|
|
306
|
+
VENDOR_TOKEN_KEY,
|
|
307
|
+
adminAuth,
|
|
308
|
+
adminTokenStore,
|
|
309
|
+
apiKeyAuth,
|
|
310
|
+
bearerAuth,
|
|
311
|
+
clearAuthStores,
|
|
312
|
+
createClient,
|
|
313
|
+
createTokenStore,
|
|
314
|
+
headerAuth,
|
|
315
|
+
publishableKeyAuth,
|
|
316
|
+
resolveAuthHeaders,
|
|
317
|
+
vendorAuth,
|
|
318
|
+
vendorSellerStore,
|
|
319
|
+
vendorTokenStore
|
|
180
320
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mercurjs/client",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.9-canary.1",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/mercurjs/mercur",
|
|
@@ -32,17 +32,19 @@
|
|
|
32
32
|
"scripts": {
|
|
33
33
|
"typecheck": "tsc --noEmit",
|
|
34
34
|
"dev": "tsup --watch",
|
|
35
|
-
"build": "tsup"
|
|
35
|
+
"build": "tsup",
|
|
36
|
+
"test": "vitest run"
|
|
36
37
|
},
|
|
37
38
|
"dependencies": {
|
|
38
39
|
"@tanstack/react-query": "^5.64.2",
|
|
39
40
|
"qs": "^6.12.1"
|
|
40
41
|
},
|
|
41
42
|
"devDependencies": {
|
|
42
|
-
"@medusajs/framework": "2.
|
|
43
|
+
"@medusajs/framework": "2.22.0",
|
|
43
44
|
"@types/qs": "^6.9.18",
|
|
44
45
|
"tsup": "^8.5.0",
|
|
45
|
-
"typescript": "5.9.3"
|
|
46
|
+
"typescript": "5.9.3",
|
|
47
|
+
"vitest": "^3.2.4"
|
|
46
48
|
},
|
|
47
49
|
"peerDependencies": {
|
|
48
50
|
"typescript": ">=4.8.0"
|