medusa-services 1.1.0

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.
Files changed (89) hide show
  1. package/dist/auth.d.ts +29 -0
  2. package/dist/auth.d.ts.map +1 -0
  3. package/dist/auth.js +80 -0
  4. package/dist/cart.d.ts +148 -0
  5. package/dist/cart.d.ts.map +1 -0
  6. package/dist/cart.js +156 -0
  7. package/dist/categories.d.ts +20 -0
  8. package/dist/categories.d.ts.map +1 -0
  9. package/dist/categories.js +36 -0
  10. package/dist/collections.d.ts +27 -0
  11. package/dist/collections.d.ts.map +1 -0
  12. package/dist/collections.js +36 -0
  13. package/dist/contact-action.d.ts +18 -0
  14. package/dist/contact-action.d.ts.map +1 -0
  15. package/dist/contact-action.js +42 -0
  16. package/dist/customer.d.ts +59 -0
  17. package/dist/customer.d.ts.map +1 -0
  18. package/dist/customer.js +68 -0
  19. package/dist/facebook-login.d.ts +37 -0
  20. package/dist/facebook-login.d.ts.map +1 -0
  21. package/dist/facebook-login.js +146 -0
  22. package/dist/fulfillment.d.ts +33 -0
  23. package/dist/fulfillment.d.ts.map +1 -0
  24. package/dist/fulfillment.js +43 -0
  25. package/dist/gift-wrap.d.ts +30 -0
  26. package/dist/gift-wrap.d.ts.map +1 -0
  27. package/dist/gift-wrap.js +29 -0
  28. package/dist/google-login.d.ts +37 -0
  29. package/dist/google-login.d.ts.map +1 -0
  30. package/dist/google-login.js +150 -0
  31. package/dist/guest.d.ts +46 -0
  32. package/dist/guest.d.ts.map +1 -0
  33. package/dist/guest.js +91 -0
  34. package/dist/index.d.ts +29 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +28 -0
  37. package/dist/locales.d.ts +13 -0
  38. package/dist/locales.d.ts.map +1 -0
  39. package/dist/locales.js +13 -0
  40. package/dist/medusa-auth.d.ts +17 -0
  41. package/dist/medusa-auth.d.ts.map +1 -0
  42. package/dist/medusa-auth.js +25 -0
  43. package/dist/middleware.d.ts +13 -0
  44. package/dist/middleware.d.ts.map +1 -0
  45. package/dist/middleware.js +36 -0
  46. package/dist/orders.d.ts +105 -0
  47. package/dist/orders.d.ts.map +1 -0
  48. package/dist/orders.js +139 -0
  49. package/dist/payment.d.ts +55 -0
  50. package/dist/payment.d.ts.map +1 -0
  51. package/dist/payment.js +68 -0
  52. package/dist/product-detail.d.ts +30 -0
  53. package/dist/product-detail.d.ts.map +1 -0
  54. package/dist/product-detail.js +94 -0
  55. package/dist/product-listing.d.ts +81 -0
  56. package/dist/product-listing.d.ts.map +1 -0
  57. package/dist/product-listing.js +189 -0
  58. package/dist/products.d.ts +41 -0
  59. package/dist/products.d.ts.map +1 -0
  60. package/dist/products.js +141 -0
  61. package/dist/recently-viewed.d.ts +14 -0
  62. package/dist/recently-viewed.d.ts.map +1 -0
  63. package/dist/recently-viewed.js +59 -0
  64. package/dist/regions.d.ts +37 -0
  65. package/dist/regions.d.ts.map +1 -0
  66. package/dist/regions.js +30 -0
  67. package/dist/related-products.d.ts +30 -0
  68. package/dist/related-products.d.ts.map +1 -0
  69. package/dist/related-products.js +99 -0
  70. package/dist/returns.d.ts +75 -0
  71. package/dist/returns.d.ts.map +1 -0
  72. package/dist/returns.js +105 -0
  73. package/dist/reviews.d.ts +135 -0
  74. package/dist/reviews.d.ts.map +1 -0
  75. package/dist/reviews.js +202 -0
  76. package/dist/store-api.d.ts +20 -0
  77. package/dist/store-api.d.ts.map +1 -0
  78. package/dist/store-api.js +55 -0
  79. package/dist/swaps.d.ts +33 -0
  80. package/dist/swaps.d.ts.map +1 -0
  81. package/dist/swaps.js +39 -0
  82. package/dist/variants.d.ts +17 -0
  83. package/dist/variants.d.ts.map +1 -0
  84. package/dist/variants.js +8 -0
  85. package/dist/wishlist.d.ts +65 -0
  86. package/dist/wishlist.d.ts.map +1 -0
  87. package/dist/wishlist.js +149 -0
  88. package/middleware.ts +54 -0
  89. package/package.json +174 -0
@@ -0,0 +1,202 @@
1
+ /**
2
+ * medusa-review-rating Store API helpers.
3
+ * @see package README (store routes under /store)
4
+ */
5
+ function readEnv(name) {
6
+ try {
7
+ return process.env?.[name];
8
+ }
9
+ catch {
10
+ return undefined;
11
+ }
12
+ }
13
+ /**
14
+ * Medusa store URL + publishable key from common Next.js / Node env vars.
15
+ */
16
+ export function getMedusaReviewsClientOptionsFromEnv() {
17
+ const backendUrl = readEnv('NEXT_PUBLIC_MEDUSA_BACKEND_URL') ||
18
+ readEnv('MEDUSA_BACKEND_URL') ||
19
+ 'http://localhost:9000';
20
+ const publishableApiKey = readEnv('NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY') || '';
21
+ return { backendUrl, publishableApiKey };
22
+ }
23
+ function normalizeAuth(authorization) {
24
+ const t = authorization.trim();
25
+ if (t.toLowerCase().startsWith('bearer '))
26
+ return t;
27
+ return `Bearer ${t}`;
28
+ }
29
+ function storeOrigin(options) {
30
+ return options.backendUrl.replace(/\/$/, '');
31
+ }
32
+ function buildPublicHeaders(options) {
33
+ return {
34
+ 'x-publishable-api-key': options.publishableApiKey,
35
+ ...options.headers,
36
+ };
37
+ }
38
+ function buildAuthHeaders(options) {
39
+ return {
40
+ 'Content-Type': 'application/json',
41
+ 'x-publishable-api-key': options.publishableApiKey,
42
+ Authorization: normalizeAuth(options.authorization),
43
+ ...options.headers,
44
+ };
45
+ }
46
+ async function parseErrorMessage(response, fallbackPrefix) {
47
+ const data = await response.json().catch(() => ({}));
48
+ const msg = typeof data.message === 'string'
49
+ ? data.message
50
+ : typeof data.error === 'string'
51
+ ? data.error
52
+ : `${fallbackPrefix} (${response.status})`;
53
+ return msg;
54
+ }
55
+ /**
56
+ * GET /store/ratings — all product ratings, or filter by product_id.
57
+ */
58
+ export async function medusaListRatings(options, query) {
59
+ const params = new URLSearchParams();
60
+ if (query?.product_id)
61
+ params.set('product_id', query.product_id);
62
+ const qs = params.toString();
63
+ const url = `${storeOrigin(options)}/store/ratings${qs ? `?${qs}` : ''}`;
64
+ const response = await fetch(url, {
65
+ method: 'GET',
66
+ headers: {
67
+ 'Content-Type': 'application/json',
68
+ ...buildPublicHeaders(options),
69
+ },
70
+ });
71
+ if (!response.ok) {
72
+ throw new Error(await parseErrorMessage(response, 'List ratings failed'));
73
+ }
74
+ const data = (await response.json());
75
+ return { rating: data.rating ?? [] };
76
+ }
77
+ /**
78
+ * GET /store/products/:id/rating
79
+ */
80
+ export async function medusaGetProductRatingSummary(productId, options) {
81
+ const url = `${storeOrigin(options)}/store/products/${encodeURIComponent(productId)}/rating`;
82
+ const response = await fetch(url, { method: 'GET', headers: buildPublicHeaders(options) });
83
+ if (!response.ok) {
84
+ throw new Error(await parseErrorMessage(response, 'Rating request failed'));
85
+ }
86
+ const data = (await response.json());
87
+ const r = data.rating ?? {};
88
+ return {
89
+ averageRating: typeof r.average_rating === 'number' ? r.average_rating : 0,
90
+ totalReviews: typeof r.total_reviews === 'number' ? r.total_reviews : 0,
91
+ };
92
+ }
93
+ /**
94
+ * GET /store/products/:id/reviews
95
+ */
96
+ export async function medusaListProductReviews(productId, options, query) {
97
+ const params = new URLSearchParams();
98
+ if (query?.status)
99
+ params.set('status', query.status);
100
+ if (query?.limit != null)
101
+ params.set('limit', String(query.limit));
102
+ if (query?.offset != null)
103
+ params.set('offset', String(query.offset));
104
+ const qs = params.toString();
105
+ const url = `${storeOrigin(options)}/store/products/${encodeURIComponent(productId)}/reviews${qs ? `?${qs}` : ''}`;
106
+ const response = await fetch(url, { method: 'GET', headers: buildPublicHeaders(options) });
107
+ if (!response.ok) {
108
+ throw new Error(await parseErrorMessage(response, 'List reviews failed'));
109
+ }
110
+ return response.json();
111
+ }
112
+ /**
113
+ * POST /store/reviews
114
+ */
115
+ export async function medusaSubmitReview(body, options) {
116
+ const url = `${storeOrigin(options)}/store/reviews`;
117
+ const response = await fetch(url, {
118
+ method: 'POST',
119
+ headers: buildAuthHeaders(options),
120
+ body: JSON.stringify(body),
121
+ });
122
+ if (!response.ok) {
123
+ throw new Error(await parseErrorMessage(response, 'Submit review failed'));
124
+ }
125
+ return response.json();
126
+ }
127
+ /**
128
+ * PUT /store/reviews/:id
129
+ */
130
+ export async function medusaUpdateReview(reviewId, body, options) {
131
+ const url = `${storeOrigin(options)}/store/reviews/${encodeURIComponent(reviewId)}`;
132
+ const response = await fetch(url, {
133
+ method: 'PUT',
134
+ headers: buildAuthHeaders(options),
135
+ body: JSON.stringify(body),
136
+ });
137
+ if (!response.ok) {
138
+ throw new Error(await parseErrorMessage(response, 'Update review failed'));
139
+ }
140
+ return response.json();
141
+ }
142
+ // --- Single review (store) ---
143
+ /**
144
+ * GET /store/reviews/:id
145
+ */
146
+ export async function medusaGetStoreReview(reviewId, options) {
147
+ const url = `${storeOrigin(options)}/store/reviews/${encodeURIComponent(reviewId)}`;
148
+ const response = await fetch(url, { method: 'GET', headers: buildPublicHeaders(options) });
149
+ if (!response.ok) {
150
+ throw new Error(await parseErrorMessage(response, 'Get review failed'));
151
+ }
152
+ return response.json();
153
+ }
154
+ /**
155
+ * GET /store/reviews/me
156
+ */
157
+ export async function medusaListCustomerReviews(options, query) {
158
+ const params = new URLSearchParams();
159
+ if (query?.product_id)
160
+ params.set('product_id', query.product_id);
161
+ if (query?.status)
162
+ params.set('status', query.status);
163
+ const qs = params.toString();
164
+ const url = `${storeOrigin(options)}/store/reviews/me${qs ? `?${qs}` : ''}`;
165
+ const response = await fetch(url, { method: 'GET', headers: buildAuthHeaders(options) });
166
+ if (!response.ok) {
167
+ throw new Error(await parseErrorMessage(response, 'List customer reviews failed'));
168
+ }
169
+ return response.json();
170
+ }
171
+ /**
172
+ * GET /store/products/:id/reviews/me
173
+ */
174
+ export async function medusaListCustomerProductReviews(productId, options) {
175
+ const url = `${storeOrigin(options)}/store/products/${encodeURIComponent(productId)}/reviews/me`;
176
+ const response = await fetch(url, { method: 'GET', headers: buildAuthHeaders(options) });
177
+ if (!response.ok) {
178
+ throw new Error(await parseErrorMessage(response, 'List customer product reviews failed'));
179
+ }
180
+ return response.json();
181
+ }
182
+ /**
183
+ * POST /store/upload — multipart FormData with `files` field(s).
184
+ * Do not set Content-Type; the runtime sets the boundary.
185
+ */
186
+ export async function medusaUploadStoreFiles(formData, options) {
187
+ const url = `${storeOrigin(options)}/store/upload`;
188
+ const response = await fetch(url, {
189
+ method: 'POST',
190
+ headers: {
191
+ 'x-publishable-api-key': options.publishableApiKey,
192
+ Authorization: normalizeAuth(options.authorization),
193
+ ...options.headers,
194
+ },
195
+ body: formData,
196
+ });
197
+ if (!response.ok) {
198
+ throw new Error(await parseErrorMessage(response, 'Upload failed'));
199
+ }
200
+ const data = (await response.json());
201
+ return { files: data.files ?? [] };
202
+ }
@@ -0,0 +1,20 @@
1
+ export interface MedusaStoreClientOptions {
2
+ backendUrl: string;
3
+ publishableApiKey: string;
4
+ /**
5
+ * Send cookies (e.g. `_medusa_cart_id`, customer session) on cross-origin requests.
6
+ * @default "include"
7
+ */
8
+ credentials?: RequestCredentials;
9
+ /** Optional Bearer JWT (e.g. logged-in customer). */
10
+ authorization?: string;
11
+ headers?: Record<string, string>;
12
+ }
13
+ /** @deprecated Use MedusaStoreClientOptions */
14
+ export type MedusaStoreCartClientOptions = MedusaStoreClientOptions;
15
+ export declare function buildStoreHeaders(options: MedusaStoreClientOptions): Record<string, string>;
16
+ export declare function parseStoreErrorMessage(response: Response, label?: string): Promise<string>;
17
+ export declare function storeFetch(path: string, options: MedusaStoreClientOptions, init: RequestInit): Promise<Response>;
18
+ export declare function fieldsQuery(fields?: string, defaultFields?: string): string;
19
+ export declare function parseStoreJson<T>(response: Response, label?: string): Promise<T>;
20
+ //# sourceMappingURL=store-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store-api.d.ts","sourceRoot":"","sources":["../store-api.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,wBAAwB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,qDAAqD;IACrD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAED,+CAA+C;AAC/C,MAAM,MAAM,4BAA4B,GAAG,wBAAwB,CAAC;AAYpE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAU3F;AAED,wBAAsB,sBAAsB,CACxC,QAAQ,EAAE,QAAQ,EAClB,KAAK,SAAkB,GACxB,OAAO,CAAC,MAAM,CAAC,CASjB;AAED,wBAAsB,UAAU,CAC5B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,wBAAwB,EACjC,IAAI,EAAE,WAAW,GAClB,OAAO,CAAC,QAAQ,CAAC,CAWnB;AAED,wBAAgB,WAAW,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAM3E;AAED,wBAAsB,cAAc,CAAC,CAAC,EAClC,QAAQ,EAAE,QAAQ,EAClB,KAAK,SAAkB,GACxB,OAAO,CAAC,CAAC,CAAC,CAKZ"}
@@ -0,0 +1,55 @@
1
+ function normalizeBackendUrl(backendUrl) {
2
+ return backendUrl.replace(/\/$/, "");
3
+ }
4
+ function normalizeAuth(authorization) {
5
+ const t = authorization.trim();
6
+ if (t.toLowerCase().startsWith("bearer "))
7
+ return t;
8
+ return `Bearer ${t}`;
9
+ }
10
+ export function buildStoreHeaders(options) {
11
+ const headers = {
12
+ "Content-Type": "application/json",
13
+ "x-publishable-api-key": options.publishableApiKey,
14
+ ...options.headers,
15
+ };
16
+ if (options.authorization) {
17
+ headers.Authorization = normalizeAuth(options.authorization);
18
+ }
19
+ return headers;
20
+ }
21
+ export async function parseStoreErrorMessage(response, label = "Store request") {
22
+ const data = await response.json().catch(() => ({}));
23
+ const msg = typeof data.message === "string"
24
+ ? data.message
25
+ : typeof data.error === "string"
26
+ ? data.error
27
+ : `${label} failed (${response.status})`;
28
+ return msg;
29
+ }
30
+ export async function storeFetch(path, options, init) {
31
+ const url = `${normalizeBackendUrl(options.backendUrl)}/store${path}`;
32
+ const credentials = options.credentials ?? "include";
33
+ return fetch(url, {
34
+ ...init,
35
+ credentials,
36
+ headers: {
37
+ ...buildStoreHeaders(options),
38
+ ...init.headers,
39
+ },
40
+ });
41
+ }
42
+ export function fieldsQuery(fields, defaultFields) {
43
+ const f = fields?.trim() || defaultFields || "";
44
+ if (!f)
45
+ return "";
46
+ const params = new URLSearchParams();
47
+ params.set("fields", f);
48
+ return `?${params.toString()}`;
49
+ }
50
+ export async function parseStoreJson(response, label = "Store request") {
51
+ if (!response.ok) {
52
+ throw new Error(await parseStoreErrorMessage(response, label));
53
+ }
54
+ return response.json();
55
+ }
@@ -0,0 +1,33 @@
1
+ import { type MedusaStoreClientOptions } from "./store-api";
2
+ export interface CreateSwapPayload {
3
+ order_id: string;
4
+ return_items: Array<Record<string, unknown>>;
5
+ new_items: Array<Record<string, unknown>>;
6
+ reason?: string;
7
+ note?: string;
8
+ }
9
+ export interface StoreSwapListResponse {
10
+ swaps?: Array<Record<string, unknown>>;
11
+ count?: number;
12
+ swap?: Record<string, unknown>;
13
+ [key: string]: unknown;
14
+ }
15
+ /**
16
+ * POST /store/swaps
17
+ */
18
+ export declare function medusaSwapCreate(payload: CreateSwapPayload, options: MedusaStoreClientOptions): Promise<Record<string, unknown>>;
19
+ /**
20
+ * POST /store/guest-orders/:id/swaps
21
+ */
22
+ export declare function medusaSwapCreateGuest(orderId: string, payload: Omit<CreateSwapPayload, "order_id">, options: MedusaStoreClientOptions): Promise<Record<string, unknown>>;
23
+ /**
24
+ * GET /store/swaps
25
+ */
26
+ export declare function medusaSwapList(options: MedusaStoreClientOptions, query?: {
27
+ order_id?: string;
28
+ }): Promise<StoreSwapListResponse>;
29
+ /**
30
+ * GET /store/guest-orders/:id/swaps
31
+ */
32
+ export declare function medusaSwapListGuest(orderId: string, options: MedusaStoreClientOptions): Promise<StoreSwapListResponse>;
33
+ //# sourceMappingURL=swaps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swaps.d.ts","sourceRoot":"","sources":["../swaps.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,KAAK,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAExF,MAAM,WAAW,iBAAiB;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC7C,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IAClC,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAClC,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,wBAAwB,GAClC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAOlC;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACvC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAAE,UAAU,CAAC,EAC5C,OAAO,EAAE,wBAAwB,GAClC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAQlC;AAED;;GAEG;AACH,wBAAsB,cAAc,CAChC,OAAO,EAAE,wBAAwB,EACjC,KAAK,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9B,OAAO,CAAC,qBAAqB,CAAC,CAQhC;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACrC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,wBAAwB,GAClC,OAAO,CAAC,qBAAqB,CAAC,CAOhC"}
package/dist/swaps.js ADDED
@@ -0,0 +1,39 @@
1
+ import { parseStoreJson, storeFetch } from "./store-api";
2
+ /**
3
+ * POST /store/swaps
4
+ */
5
+ export async function medusaSwapCreate(payload, options) {
6
+ const response = await storeFetch("/swaps", options, {
7
+ method: "POST",
8
+ body: JSON.stringify(payload),
9
+ });
10
+ const data = await parseStoreJson(response, "Swap create request");
11
+ return (data.swap ?? data);
12
+ }
13
+ /**
14
+ * POST /store/guest-orders/:id/swaps
15
+ */
16
+ export async function medusaSwapCreateGuest(orderId, payload, options) {
17
+ const response = await storeFetch(`/guest-orders/${encodeURIComponent(orderId)}/swaps`, options, { method: "POST", body: JSON.stringify(payload) });
18
+ const data = await parseStoreJson(response, "Guest swap create request");
19
+ return (data.swap ?? data);
20
+ }
21
+ /**
22
+ * GET /store/swaps
23
+ */
24
+ export async function medusaSwapList(options, query) {
25
+ const params = new URLSearchParams();
26
+ if (query?.order_id) {
27
+ params.set("order_id", query.order_id);
28
+ }
29
+ const path = params.toString() ? `/swaps?${params.toString()}` : "/swaps";
30
+ const response = await storeFetch(path, options, { method: "GET" });
31
+ return parseStoreJson(response, "Swap list request");
32
+ }
33
+ /**
34
+ * GET /store/guest-orders/:id/swaps
35
+ */
36
+ export async function medusaSwapListGuest(orderId, options) {
37
+ const response = await storeFetch(`/guest-orders/${encodeURIComponent(orderId)}/swaps`, options, { method: "GET" });
38
+ return parseStoreJson(response, "Guest swap list request");
39
+ }
@@ -0,0 +1,17 @@
1
+ import { type MedusaStoreClientOptions } from "./store-api";
2
+ export interface StoreProductVariant {
3
+ id: string;
4
+ title?: string;
5
+ sku?: string;
6
+ [key: string]: unknown;
7
+ }
8
+ export interface StoreProductVariantResponse {
9
+ variant: StoreProductVariant;
10
+ }
11
+ /**
12
+ * GET /store/product-variants/:id
13
+ */
14
+ export declare function medusaVariantRetrieve(variantId: string, options: MedusaStoreClientOptions, query?: {
15
+ fields?: string;
16
+ }): Promise<StoreProductVariantResponse>;
17
+ //# sourceMappingURL=variants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"variants.d.ts","sourceRoot":"","sources":["../variants.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2C,KAAK,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAErG,MAAM,WAAW,mBAAmB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,2BAA2B;IACxC,OAAO,EAAE,mBAAmB,CAAC;CAChC;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACvC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,wBAAwB,EACjC,KAAK,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5B,OAAO,CAAC,2BAA2B,CAAC,CAOtC"}
@@ -0,0 +1,8 @@
1
+ import { fieldsQuery, parseStoreJson, storeFetch } from "./store-api";
2
+ /**
3
+ * GET /store/product-variants/:id
4
+ */
5
+ export async function medusaVariantRetrieve(variantId, options, query) {
6
+ const response = await storeFetch(`/product-variants/${encodeURIComponent(variantId)}${fieldsQuery(query?.fields, "*images")}`, options, { method: "GET" });
7
+ return parseStoreJson(response, "Variant retrieve request");
8
+ }
@@ -0,0 +1,65 @@
1
+ export interface WishlistServiceOptions {
2
+ storageKey?: string;
3
+ }
4
+ /**
5
+ * Local-first wishlist (guest / no API).
6
+ * medusa-product-helper Store routes require a logged-in customer.
7
+ */
8
+ export declare const wishlistService: {
9
+ getAll(options?: WishlistServiceOptions): string[];
10
+ isInWishlist(productId: string, options?: WishlistServiceOptions): boolean;
11
+ add(productId: string, options?: WishlistServiceOptions): string[];
12
+ remove(productId: string, options?: WishlistServiceOptions): string[];
13
+ toggle(productId: string, options?: WishlistServiceOptions): {
14
+ ids: string[];
15
+ isWishlisted: boolean;
16
+ };
17
+ };
18
+ export interface MedusaWishlistClientOptions {
19
+ backendUrl: string;
20
+ publishableApiKey: string;
21
+ /** Customer JWT, or full `Bearer …` value (required for store wishlist routes) */
22
+ authorization: string;
23
+ /** Optional extra headers */
24
+ headers?: Record<string, string>;
25
+ }
26
+ export interface MedusaWishlistItemResponse {
27
+ id: string;
28
+ customer_id: string;
29
+ product_id: string;
30
+ created_at?: string;
31
+ updated_at?: string;
32
+ }
33
+ export interface MedusaAddWishlistResponse {
34
+ wishlist_item: MedusaWishlistItemResponse;
35
+ }
36
+ /**
37
+ * POST /store/wishlist — add product (idempotent).
38
+ */
39
+ export declare function medusaWishlistAdd(productId: string, options: MedusaWishlistClientOptions): Promise<MedusaAddWishlistResponse>;
40
+ /**
41
+ * DELETE /store/wishlist/:product_id
42
+ */
43
+ export declare function medusaWishlistRemove(productId: string, options: MedusaWishlistClientOptions): Promise<{
44
+ success: boolean;
45
+ }>;
46
+ export type MedusaWishlistListEntry = {
47
+ product_id: string;
48
+ } | {
49
+ id: string;
50
+ product_id: string;
51
+ product?: Record<string, unknown>;
52
+ created_at?: string;
53
+ };
54
+ export interface MedusaGetWishlistResponse {
55
+ wishlist: MedusaWishlistListEntry[];
56
+ }
57
+ /**
58
+ * GET /store/wishlist — optional include_details=true for full product payloads.
59
+ */
60
+ export declare function medusaWishlistGet(options: MedusaWishlistClientOptions, query?: {
61
+ includeDetails?: boolean;
62
+ }): Promise<MedusaGetWishlistResponse>;
63
+ /** Product IDs from GET /store/wishlist (both response shapes). */
64
+ export declare function medusaWishlistProductIds(response: MedusaGetWishlistResponse): string[];
65
+ //# sourceMappingURL=wishlist.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wishlist.d.ts","sourceRoot":"","sources":["../wishlist.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,sBAAsB;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAwCD;;;GAGG;AACH,eAAO,MAAM,eAAe;qBACP,sBAAsB,GAAG,MAAM,EAAE;4BAI1B,MAAM,YAAY,sBAAsB,GAAG,OAAO;mBAI3D,MAAM,YAAY,sBAAsB,GAAG,MAAM,EAAE;sBAQhD,MAAM,YAAY,sBAAsB,GAAG,MAAM,EAAE;sBAOnD,MAAM,YAAY,sBAAsB,GAAG;QAAE,GAAG,EAAE,MAAM,EAAE,CAAC;QAAC,YAAY,EAAE,OAAO,CAAA;KAAE;CAOxG,CAAC;AAIF,MAAM,WAAW,2BAA2B;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kFAAkF;IAClF,aAAa,EAAE,MAAM,CAAC;IACtB,6BAA6B;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAiCD,MAAM,WAAW,0BAA0B;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,yBAAyB;IACtC,aAAa,EAAE,0BAA0B,CAAC;CAC7C;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACnC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,2BAA2B,GACrC,OAAO,CAAC,yBAAyB,CAAC,CAapC;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACtC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,2BAA2B,GACrC,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAa/B;AAED,MAAM,MAAM,uBAAuB,GAC7B;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,GACtB;IACI,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAER,MAAM,WAAW,yBAAyB;IACtC,QAAQ,EAAE,uBAAuB,EAAE,CAAC;CACvC;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACnC,OAAO,EAAE,2BAA2B,EACpC,KAAK,CAAC,EAAE;IAAE,cAAc,CAAC,EAAE,OAAO,CAAA;CAAE,GACrC,OAAO,CAAC,yBAAyB,CAAC,CAkBpC;AAED,mEAAmE;AACnE,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,yBAAyB,GAAG,MAAM,EAAE,CAEtF"}
@@ -0,0 +1,149 @@
1
+ const DEFAULT_WISHLIST_STORAGE_KEY = "medusa_pdp_wishlist";
2
+ function getStorageKey(options) {
3
+ return options?.storageKey || DEFAULT_WISHLIST_STORAGE_KEY;
4
+ }
5
+ function canUseStorage() {
6
+ return typeof window !== "undefined" && !!window.localStorage;
7
+ }
8
+ function sanitizeIds(value) {
9
+ if (!Array.isArray(value))
10
+ return [];
11
+ return value.filter((id) => typeof id === "string" && id.trim() !== "");
12
+ }
13
+ function readWishlistIds(options) {
14
+ if (!canUseStorage())
15
+ return [];
16
+ try {
17
+ const raw = window.localStorage.getItem(getStorageKey(options));
18
+ if (!raw)
19
+ return [];
20
+ const parsed = JSON.parse(raw);
21
+ return sanitizeIds(parsed);
22
+ }
23
+ catch {
24
+ return [];
25
+ }
26
+ }
27
+ function writeWishlistIds(ids, options) {
28
+ if (!canUseStorage())
29
+ return;
30
+ try {
31
+ window.localStorage.setItem(getStorageKey(options), JSON.stringify(ids));
32
+ }
33
+ catch {
34
+ // Ignore storage errors (quota/private mode)
35
+ }
36
+ }
37
+ /**
38
+ * Local-first wishlist (guest / no API).
39
+ * medusa-product-helper Store routes require a logged-in customer.
40
+ */
41
+ export const wishlistService = {
42
+ getAll(options) {
43
+ return readWishlistIds(options);
44
+ },
45
+ isInWishlist(productId, options) {
46
+ return readWishlistIds(options).includes(productId);
47
+ },
48
+ add(productId, options) {
49
+ const current = readWishlistIds(options);
50
+ if (current.includes(productId))
51
+ return current;
52
+ const next = [productId, ...current];
53
+ writeWishlistIds(next, options);
54
+ return next;
55
+ },
56
+ remove(productId, options) {
57
+ const current = readWishlistIds(options);
58
+ const next = current.filter((id) => id !== productId);
59
+ writeWishlistIds(next, options);
60
+ return next;
61
+ },
62
+ toggle(productId, options) {
63
+ const current = readWishlistIds(options);
64
+ const exists = current.includes(productId);
65
+ const next = exists ? current.filter((id) => id !== productId) : [productId, ...current];
66
+ writeWishlistIds(next, options);
67
+ return { ids: next, isWishlisted: !exists };
68
+ },
69
+ };
70
+ function normalizeAuth(authorization) {
71
+ const t = authorization.trim();
72
+ if (t.toLowerCase().startsWith("bearer "))
73
+ return t;
74
+ return `Bearer ${t}`;
75
+ }
76
+ function wishlistStoreBaseUrl(backendUrl) {
77
+ return `${backendUrl.replace(/\/$/, "")}/store/wishlist`;
78
+ }
79
+ function buildStoreHeaders(options) {
80
+ const headers = {
81
+ "Content-Type": "application/json",
82
+ "x-publishable-api-key": options.publishableApiKey,
83
+ Authorization: normalizeAuth(options.authorization),
84
+ ...options.headers,
85
+ };
86
+ return headers;
87
+ }
88
+ async function parseErrorMessage(response) {
89
+ const data = await response.json().catch(() => ({}));
90
+ const msg = typeof data.message === "string"
91
+ ? data.message
92
+ : typeof data.error === "string"
93
+ ? data.error
94
+ : `Wishlist request failed (${response.status})`;
95
+ return msg;
96
+ }
97
+ /**
98
+ * POST /store/wishlist — add product (idempotent).
99
+ */
100
+ export async function medusaWishlistAdd(productId, options) {
101
+ const url = wishlistStoreBaseUrl(options.backendUrl);
102
+ const response = await fetch(url, {
103
+ method: "POST",
104
+ headers: buildStoreHeaders(options),
105
+ body: JSON.stringify({ product_id: productId }),
106
+ });
107
+ if (!response.ok) {
108
+ throw new Error(await parseErrorMessage(response));
109
+ }
110
+ return response.json();
111
+ }
112
+ /**
113
+ * DELETE /store/wishlist/:product_id
114
+ */
115
+ export async function medusaWishlistRemove(productId, options) {
116
+ const base = wishlistStoreBaseUrl(options.backendUrl);
117
+ const url = `${base}/${encodeURIComponent(productId)}`;
118
+ const response = await fetch(url, {
119
+ method: "DELETE",
120
+ headers: buildStoreHeaders(options),
121
+ });
122
+ if (!response.ok) {
123
+ throw new Error(await parseErrorMessage(response));
124
+ }
125
+ return response.json();
126
+ }
127
+ /**
128
+ * GET /store/wishlist — optional include_details=true for full product payloads.
129
+ */
130
+ export async function medusaWishlistGet(options, query) {
131
+ const params = new URLSearchParams();
132
+ if (query?.includeDetails) {
133
+ params.set("include_details", "true");
134
+ }
135
+ const qs = params.toString();
136
+ const url = `${wishlistStoreBaseUrl(options.backendUrl)}${qs ? `?${qs}` : ""}`;
137
+ const response = await fetch(url, {
138
+ method: "GET",
139
+ headers: buildStoreHeaders(options),
140
+ });
141
+ if (!response.ok) {
142
+ throw new Error(await parseErrorMessage(response));
143
+ }
144
+ return response.json();
145
+ }
146
+ /** Product IDs from GET /store/wishlist (both response shapes). */
147
+ export function medusaWishlistProductIds(response) {
148
+ return response.wishlist.map((entry) => entry.product_id).filter(Boolean);
149
+ }
package/middleware.ts ADDED
@@ -0,0 +1,54 @@
1
+ /** Edge-safe Medusa store fetches (no Node SDK). */
2
+
3
+ export interface MedusaMiddlewareClientOptions {
4
+ backendUrl: string;
5
+ publishableApiKey: string;
6
+ }
7
+
8
+ function normalizeBackendUrl(backendUrl: string): string {
9
+ return backendUrl.replace(/\/$/, "");
10
+ }
11
+
12
+ export async function medusaListRegions(
13
+ options: MedusaMiddlewareClientOptions,
14
+ init?: RequestInit
15
+ ): Promise<{ regions: unknown[] }> {
16
+ const url = `${normalizeBackendUrl(options.backendUrl)}/store/regions`;
17
+ const response = await fetch(url, {
18
+ ...init,
19
+ headers: {
20
+ "x-publishable-api-key": options.publishableApiKey,
21
+ ...(init?.headers as Record<string, string> | undefined),
22
+ },
23
+ });
24
+
25
+ const json = (await response.json()) as { regions?: unknown[]; message?: string };
26
+ if (!response.ok) {
27
+ throw new Error(json.message || "Failed to fetch regions");
28
+ }
29
+ return { regions: json.regions ?? [] };
30
+ }
31
+
32
+ export async function medusaMergeCarts(
33
+ options: MedusaMiddlewareClientOptions & {
34
+ authorization: string;
35
+ cartId?: string;
36
+ },
37
+ init?: RequestInit
38
+ ): Promise<Response> {
39
+ const url = `${normalizeBackendUrl(options.backendUrl)}/store/carts/merge`;
40
+ return fetch(url, {
41
+ method: "POST",
42
+ ...init,
43
+ headers: {
44
+ "Content-Type": "application/json",
45
+ "x-publishable-api-key": options.publishableApiKey,
46
+ Authorization: options.authorization.startsWith("Bearer ")
47
+ ? options.authorization
48
+ : `Bearer ${options.authorization}`,
49
+ ...(init?.headers as Record<string, string> | undefined),
50
+ },
51
+ body: options.cartId ? JSON.stringify({ cart_id: options.cartId }) : init?.body,
52
+ cache: init?.cache ?? "no-store",
53
+ });
54
+ }