@reactionary/medusa 0.10.50 → 0.10.52
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.
|
@@ -28,8 +28,11 @@ import {
|
|
|
28
28
|
Reactionary,
|
|
29
29
|
success
|
|
30
30
|
} from "@reactionary/core";
|
|
31
|
+
import { FetchError } from "@medusajs/js-sdk";
|
|
31
32
|
import {} from "@medusajs/types";
|
|
32
33
|
import createDebug from "debug";
|
|
34
|
+
import { MedusaAdminAPI } from "../core/client.js";
|
|
35
|
+
import { MedusaCachedPluginListSchema } from "../schema/medusa.schema.js";
|
|
33
36
|
import {
|
|
34
37
|
handleProviderError
|
|
35
38
|
} from "../utils/medusa-helpers.js";
|
|
@@ -51,7 +54,87 @@ class MedusaCartCapability extends CartCapability {
|
|
|
51
54
|
* example: this.includedFields = [includedFields, '+discounts.*'].join(',');
|
|
52
55
|
*/
|
|
53
56
|
includedFields = ["+items.*", "+items.adjustments.*", "+shipping_methods.adjustments.*"].join(",");
|
|
57
|
+
/**
|
|
58
|
+
* Fields requested when listing owned carts, both via the cart-ownership
|
|
59
|
+
* endpoint and via the session-tracked fallback. Every entry must be in
|
|
60
|
+
* the allowed field set of both routes; `customer.id` stands in for
|
|
61
|
+
* `customer_id`, which is not an allowed field (see normalizeOwnedCart).
|
|
62
|
+
*/
|
|
63
|
+
ownedCartListFields = ["id", "updated_at", "metadata", "items.id", "customer.id"].join(",");
|
|
64
|
+
/** Sort order for the server-side owned-carts listing. */
|
|
65
|
+
ownedCartListOrder = "-updated_at";
|
|
66
|
+
/**
|
|
67
|
+
* Package name of the optional backend plugin that serves
|
|
68
|
+
* `GET /store/customers/me/carts` (a logged-in customer's open carts).
|
|
69
|
+
*/
|
|
70
|
+
cartOwnershipPluginName = "@solteq-excom/medusa-cart-ownership";
|
|
71
|
+
/**
|
|
72
|
+
* How long a backend's plugin list stays cached. Bounds how late a newly
|
|
73
|
+
* (un)installed cart-ownership plugin is noticed.
|
|
74
|
+
*/
|
|
75
|
+
pluginDetectionTtlSeconds = 900;
|
|
54
76
|
async listCarts(payload) {
|
|
77
|
+
let data = null;
|
|
78
|
+
if (await this.shouldUseOwnershipEndpoint(payload)) {
|
|
79
|
+
data = await this.listCartsViaOwnershipEndpoint(payload);
|
|
80
|
+
}
|
|
81
|
+
data ??= await this.listCartsFromSession(payload);
|
|
82
|
+
return success(this.factory.parseCartPaginatedSearchResult(this.context, data, payload));
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* The server-side owned-carts listing only applies to a logged-in
|
|
86
|
+
* customer's own carts: a company bucket and anonymous/guest carts are
|
|
87
|
+
* only known to the session, and the backend only serves the route when
|
|
88
|
+
* the cart-ownership plugin is installed.
|
|
89
|
+
*/
|
|
90
|
+
async shouldUseOwnershipEndpoint(payload) {
|
|
91
|
+
if (payload.search.company) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
if (this.context.session.identityContext.identity.type !== "Registered") {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
return await this.isCartOwnershipPluginEnabled();
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Lists the customer's open carts through the cart-ownership plugin's
|
|
101
|
+
* `GET /store/customers/me/carts`. Returns null when the backend turns
|
|
102
|
+
* out not to serve the route after all (404: plugin configured but not
|
|
103
|
+
* built; 401: the token is no longer valid), so the caller falls back to
|
|
104
|
+
* the session-tracked list. Other errors are real backend faults and
|
|
105
|
+
* propagate.
|
|
106
|
+
*/
|
|
107
|
+
async listCartsViaOwnershipEndpoint(payload) {
|
|
108
|
+
const client = await this.getClient();
|
|
109
|
+
const { pageNumber, pageSize } = payload.search.paginationOptions;
|
|
110
|
+
try {
|
|
111
|
+
const response = await client.client.fetch("/store/customers/me/carts", {
|
|
112
|
+
method: "GET",
|
|
113
|
+
query: {
|
|
114
|
+
fields: this.ownedCartListFields,
|
|
115
|
+
limit: pageSize,
|
|
116
|
+
offset: (pageNumber - 1) * pageSize,
|
|
117
|
+
order: this.ownedCartListOrder
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
return {
|
|
121
|
+
items: response.carts.map((cart) => this.normalizeOwnedCart(cart)),
|
|
122
|
+
totalCount: response.count
|
|
123
|
+
};
|
|
124
|
+
} catch (err) {
|
|
125
|
+
if (this.shouldFallBackToSessionList(err)) {
|
|
126
|
+
debug("Owned-carts endpoint unavailable, falling back to session-tracked carts:", err);
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
throw err;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Lists carts from the ids tracked in the session: the behavior from
|
|
134
|
+
* before the cart-ownership plugin existed, and still the only source for
|
|
135
|
+
* anonymous/guest carts and company buckets.
|
|
136
|
+
*/
|
|
137
|
+
async listCartsFromSession(payload) {
|
|
55
138
|
const client = await this.getClient();
|
|
56
139
|
const sessionData = this.medusaApi.getSessionData();
|
|
57
140
|
let cartCollection = payload.search.company ? sessionData.allOwnedCarts?.[payload.search.company.taxIdentifier] : sessionData.allOwnedCarts?.["_me"];
|
|
@@ -61,18 +144,58 @@ class MedusaCartCapability extends CartCapability {
|
|
|
61
144
|
} else {
|
|
62
145
|
cartCollection = [];
|
|
63
146
|
}
|
|
64
|
-
const
|
|
65
|
-
const allPromises = cartCollection.map((cartIdentifier) => client.store.cart.retrieve(cartIdentifier.key, { fields: shortFields }));
|
|
147
|
+
const allPromises = cartCollection.map((cartIdentifier) => client.store.cart.retrieve(cartIdentifier.key, { fields: this.ownedCartListFields }));
|
|
66
148
|
const responses = await Promise.all(allPromises);
|
|
67
149
|
const carts = responses.map((response) => response.cart).filter((cart) => !!cart);
|
|
68
|
-
return
|
|
69
|
-
this.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
150
|
+
return {
|
|
151
|
+
items: carts.map((cart) => this.normalizeOwnedCart(cart)),
|
|
152
|
+
totalCount
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* The factory reads `customer_id`, but only the `customer.id` relation is
|
|
157
|
+
* an allowed list field, so copy it over when `customer_id` itself wasn't
|
|
158
|
+
* returned.
|
|
159
|
+
*/
|
|
160
|
+
normalizeOwnedCart(cart) {
|
|
161
|
+
return { ...cart, customer_id: cart.customer_id ?? cart.customer?.id };
|
|
162
|
+
}
|
|
163
|
+
/** A 404 (route not served) or 401 (token no longer valid) degrades to the session list. */
|
|
164
|
+
shouldFallBackToSessionList(err) {
|
|
165
|
+
return err instanceof FetchError && (err.status === 404 || err.status === 401);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Checks whether the backend has the cart-ownership plugin, by its name in
|
|
169
|
+
* core's `GET /admin/plugins`. Detection must never break cart listing, so
|
|
170
|
+
* any failure just reports the plugin as absent.
|
|
171
|
+
*/
|
|
172
|
+
async isCartOwnershipPluginEnabled() {
|
|
173
|
+
const plugins = await this.fetchEnabledPlugins();
|
|
174
|
+
return plugins.includes(this.cartOwnershipPluginName);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* The backend's configured plugin list, kept in the reactionary cache
|
|
178
|
+
* (shared across sessions) so not every request re-asks the admin API.
|
|
179
|
+
* Failures are not cached: a plugin-less answer from here only costs the
|
|
180
|
+
* fallback behavior, while caching a transient failure would hide the
|
|
181
|
+
* plugin for a whole TTL.
|
|
182
|
+
*/
|
|
183
|
+
async fetchEnabledPlugins() {
|
|
184
|
+
const cacheKey = `medusa:plugins:${this.config.apiUrl}`;
|
|
185
|
+
const cached = await this.cache.get(cacheKey, MedusaCachedPluginListSchema);
|
|
186
|
+
if (cached) {
|
|
187
|
+
return cached.plugins;
|
|
188
|
+
}
|
|
189
|
+
try {
|
|
190
|
+
const adminClient = await new MedusaAdminAPI(this.config, this.context).getClient();
|
|
191
|
+
const response = await adminClient.client.fetch("/admin/plugins", { method: "GET" });
|
|
192
|
+
const plugins = response.plugins.map((plugin) => plugin.name);
|
|
193
|
+
await this.cache.put(cacheKey, { plugins }, { ttlSeconds: this.pluginDetectionTtlSeconds, dependencyIds: [] });
|
|
194
|
+
return plugins;
|
|
195
|
+
} catch (err) {
|
|
196
|
+
debug("Failed to list backend plugins:", err);
|
|
197
|
+
return [];
|
|
198
|
+
}
|
|
76
199
|
}
|
|
77
200
|
async getById(payload) {
|
|
78
201
|
try {
|
|
@@ -218,6 +341,21 @@ class MedusaCartCapability extends CartCapability {
|
|
|
218
341
|
}
|
|
219
342
|
};
|
|
220
343
|
}
|
|
344
|
+
/**
|
|
345
|
+
* Session tracking is skipped for a logged-in customer's own carts when
|
|
346
|
+
* the backend has the cart-ownership plugin: the backend attributes the
|
|
347
|
+
* cart to the customer at creation and lists it server-side. Anonymous
|
|
348
|
+
* carts and company buckets are still only known to the session.
|
|
349
|
+
*/
|
|
350
|
+
async shouldTrackOwnedCartInSession(payload) {
|
|
351
|
+
if (payload.company) {
|
|
352
|
+
return true;
|
|
353
|
+
}
|
|
354
|
+
if (this.context.session.identityContext.identity.type !== "Registered") {
|
|
355
|
+
return true;
|
|
356
|
+
}
|
|
357
|
+
return !await this.isCartOwnershipPluginEnabled();
|
|
358
|
+
}
|
|
221
359
|
addCartToOwnedList(cartIdentifier, companyId) {
|
|
222
360
|
const sessionData = this.medusaApi.getSessionData();
|
|
223
361
|
const companyIdToUse = companyId ? companyId.taxIdentifier : "_me";
|
|
@@ -233,6 +371,30 @@ class MedusaCartCapability extends CartCapability {
|
|
|
233
371
|
}
|
|
234
372
|
this.medusaApi.setSessionData(sessionData);
|
|
235
373
|
}
|
|
374
|
+
/**
|
|
375
|
+
* Removes every trace of a cart from the session: the active cart marker
|
|
376
|
+
* (when it points at this cart) and the entry in every owned-carts
|
|
377
|
+
* collection. Used when a cart turns out to be deleted or stale upstream.
|
|
378
|
+
*/
|
|
379
|
+
pruneCartFromSession(cartKey) {
|
|
380
|
+
const sessionData = this.medusaApi.getSessionData();
|
|
381
|
+
if (sessionData.activeCartId?.key === cartKey) {
|
|
382
|
+
delete sessionData.activeCartId;
|
|
383
|
+
this.medusaApi.setSessionData({ activeCartId: void 0 });
|
|
384
|
+
}
|
|
385
|
+
if (sessionData.allOwnedCarts) {
|
|
386
|
+
const prunedCollections = Object.fromEntries(
|
|
387
|
+
Object.entries(sessionData.allOwnedCarts).map(([collection, carts]) => [
|
|
388
|
+
collection,
|
|
389
|
+
carts.filter((cart) => cart.key !== cartKey)
|
|
390
|
+
])
|
|
391
|
+
);
|
|
392
|
+
this.medusaApi.setSessionData({ allOwnedCarts: prunedCollections });
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
isNotFoundError(err) {
|
|
396
|
+
return err instanceof FetchError && err.status === 404;
|
|
397
|
+
}
|
|
236
398
|
removeCartFromOwnedList(cartIdentifier, company) {
|
|
237
399
|
const sessionData = this.medusaApi.getSessionData();
|
|
238
400
|
const companyIdToUse = company ? company.taxIdentifier : "_me";
|
|
@@ -253,7 +415,9 @@ class MedusaCartCapability extends CartCapability {
|
|
|
253
415
|
}
|
|
254
416
|
);
|
|
255
417
|
if (response.cart) {
|
|
256
|
-
|
|
418
|
+
if (await this.shouldTrackOwnedCartInSession(payload)) {
|
|
419
|
+
this.addCartToOwnedList(this.factory.parseCartIdentifier(this.context, response.cart), payload.company);
|
|
420
|
+
}
|
|
257
421
|
this.medusaApi.setSessionData({
|
|
258
422
|
activeCartId: this.factory.parseCartIdentifier(this.context, response.cart)
|
|
259
423
|
});
|
|
@@ -329,18 +493,23 @@ class MedusaCartCapability extends CartCapability {
|
|
|
329
493
|
}
|
|
330
494
|
}
|
|
331
495
|
if (activeCartId) {
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
496
|
+
let remoteCart;
|
|
497
|
+
try {
|
|
498
|
+
const response = await client.store.cart.retrieve(activeCartId.key, { fields: "id,region_id" });
|
|
499
|
+
remoteCart = response.cart;
|
|
500
|
+
} catch (retrieveError) {
|
|
501
|
+
if (!this.isNotFoundError(retrieveError)) {
|
|
502
|
+
throw retrieveError;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
if (!remoteCart) {
|
|
506
|
+
this.pruneCartFromSession(activeCartId.key);
|
|
338
507
|
return error({
|
|
339
508
|
type: "NotFound",
|
|
340
509
|
identifier: activeCartId
|
|
341
510
|
});
|
|
342
511
|
}
|
|
343
|
-
return success(this.factory.parseCartIdentifier(this.context,
|
|
512
|
+
return success(this.factory.parseCartIdentifier(this.context, remoteCart));
|
|
344
513
|
}
|
|
345
514
|
return error({
|
|
346
515
|
type: "NotFound",
|
|
@@ -359,13 +528,7 @@ class MedusaCartCapability extends CartCapability {
|
|
|
359
528
|
const client = await this.getClient();
|
|
360
529
|
const medusaId = payload.cart;
|
|
361
530
|
if (medusaId.key) {
|
|
362
|
-
|
|
363
|
-
if (sessionData.activeCartId) {
|
|
364
|
-
delete sessionData.activeCartId;
|
|
365
|
-
this.medusaApi.setSessionData({
|
|
366
|
-
activeCartId: void 0
|
|
367
|
-
});
|
|
368
|
-
}
|
|
531
|
+
this.pruneCartFromSession(medusaId.key);
|
|
369
532
|
}
|
|
370
533
|
const cartResponse = await client.store.cart.retrieve(medusaId.key);
|
|
371
534
|
if (cartResponse.cart) {
|
|
@@ -374,9 +537,11 @@ class MedusaCartCapability extends CartCapability {
|
|
|
374
537
|
}
|
|
375
538
|
}
|
|
376
539
|
return success(void 0);
|
|
377
|
-
} catch (
|
|
378
|
-
|
|
379
|
-
|
|
540
|
+
} catch (err) {
|
|
541
|
+
if (this.isNotFoundError(err)) {
|
|
542
|
+
return success(void 0);
|
|
543
|
+
}
|
|
544
|
+
handleProviderError("delete cart", err);
|
|
380
545
|
}
|
|
381
546
|
}
|
|
382
547
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reactionary/medusa",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.52",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"types": "./src/index.d.ts",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@medusajs/js-sdk": "^2.13.3",
|
|
13
|
-
"@reactionary/core": "0.10.
|
|
13
|
+
"@reactionary/core": "0.10.52",
|
|
14
14
|
"debug": "^4.4.3",
|
|
15
15
|
"@medusajs/types": "^2.13.3",
|
|
16
16
|
"zod": "4.1.9"
|
package/schema/medusa.schema.js
CHANGED
|
@@ -11,6 +11,9 @@ const MedusaRegionSchema = z.looseObject({
|
|
|
11
11
|
name: z.string(),
|
|
12
12
|
currency_code: z.string()
|
|
13
13
|
});
|
|
14
|
+
const MedusaCachedPluginListSchema = z.looseObject({
|
|
15
|
+
plugins: z.array(z.string())
|
|
16
|
+
});
|
|
14
17
|
const MedusaSessionSchema = z.looseObject({
|
|
15
18
|
activeCartId: MedusaCartIdentifierSchema.optional(),
|
|
16
19
|
allOwnedCarts: z.record(z.string(), z.array(MedusaCartIdentifierSchema)).optional(),
|
|
@@ -20,6 +23,7 @@ const MedusaSessionSchema = z.looseObject({
|
|
|
20
23
|
selectedRegion: MedusaRegionSchema.optional()
|
|
21
24
|
});
|
|
22
25
|
export {
|
|
26
|
+
MedusaCachedPluginListSchema,
|
|
23
27
|
MedusaCartIdentifierSchema,
|
|
24
28
|
MedusaOrderIdentifierSchema,
|
|
25
29
|
MedusaRegionSchema,
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import type { Cache, CartFactory, CartFactoryCartOutput, CartFactoryIdentifierOutput, CartFactoryWithOutput, CartMutationApplyCoupon, CartMutationChangeCurrency, CartMutationCreateCart, CartMutationDeleteCart, CartMutationItemAdd, CartMutationItemQuantityChange, CartMutationItemRemove, CartMutationRemoveCoupon, CartMutationRenameCart, CartPaginatedSearchResult, CartQueryById, CartQueryList, CompanyIdentifier, NotFoundError, RequestContext, Result } from '@reactionary/core';
|
|
2
2
|
import { CartCapability } from '@reactionary/core';
|
|
3
|
+
import type { StoreCart } from '@medusajs/types';
|
|
3
4
|
import { type StoreAddCartLineItem, type StoreCartAddPromotion, type StoreCartRemovePromotion, type StoreCreateCart, type StoreUpdateCart, type StoreUpdateCartLineItem } from '@medusajs/types';
|
|
4
|
-
import type
|
|
5
|
-
import type { MedusaCartFactory } from '../factories/cart/cart.factory.js';
|
|
5
|
+
import { type MedusaAPI } from '../core/client.js';
|
|
6
|
+
import type { MedusaCartFactory, ParseMedusaCartPaginatedSearchResultInput } from '../factories/cart/cart.factory.js';
|
|
6
7
|
import type { MedusaConfiguration } from '../schema/configuration.schema.js';
|
|
7
|
-
import type
|
|
8
|
+
import { type MedusaCartIdentifier } from '../schema/medusa.schema.js';
|
|
9
|
+
/**
|
|
10
|
+
* A cart as returned when the `customer.id` relation field is requested;
|
|
11
|
+
* `StoreCart` itself has no `customer` property.
|
|
12
|
+
*/
|
|
13
|
+
interface MedusaOwnedCart extends StoreCart {
|
|
14
|
+
customer?: {
|
|
15
|
+
id: string;
|
|
16
|
+
} | null;
|
|
17
|
+
}
|
|
8
18
|
export declare class MedusaCartCapability<TFactory extends CartFactory = MedusaCartFactory> extends CartCapability<CartFactoryCartOutput<TFactory>, CartFactoryIdentifierOutput<TFactory>> {
|
|
9
19
|
medusaApi: MedusaAPI;
|
|
10
20
|
protected config: MedusaConfiguration;
|
|
@@ -16,8 +26,71 @@ export declare class MedusaCartCapability<TFactory extends CartFactory = MedusaC
|
|
|
16
26
|
* example: this.includedFields = [includedFields, '+discounts.*'].join(',');
|
|
17
27
|
*/
|
|
18
28
|
protected includedFields: string;
|
|
29
|
+
/**
|
|
30
|
+
* Fields requested when listing owned carts, both via the cart-ownership
|
|
31
|
+
* endpoint and via the session-tracked fallback. Every entry must be in
|
|
32
|
+
* the allowed field set of both routes; `customer.id` stands in for
|
|
33
|
+
* `customer_id`, which is not an allowed field (see normalizeOwnedCart).
|
|
34
|
+
*/
|
|
35
|
+
protected ownedCartListFields: string;
|
|
36
|
+
/** Sort order for the server-side owned-carts listing. */
|
|
37
|
+
protected ownedCartListOrder: string;
|
|
38
|
+
/**
|
|
39
|
+
* Package name of the optional backend plugin that serves
|
|
40
|
+
* `GET /store/customers/me/carts` (a logged-in customer's open carts).
|
|
41
|
+
*/
|
|
42
|
+
protected cartOwnershipPluginName: string;
|
|
43
|
+
/**
|
|
44
|
+
* How long a backend's plugin list stays cached. Bounds how late a newly
|
|
45
|
+
* (un)installed cart-ownership plugin is noticed.
|
|
46
|
+
*/
|
|
47
|
+
protected pluginDetectionTtlSeconds: number;
|
|
19
48
|
constructor(config: MedusaConfiguration, cache: Cache, context: RequestContext, medusaApi: MedusaAPI, factory: CartFactoryWithOutput<TFactory>);
|
|
20
49
|
listCarts(payload: CartQueryList): Promise<Result<CartPaginatedSearchResult>>;
|
|
50
|
+
/**
|
|
51
|
+
* The server-side owned-carts listing only applies to a logged-in
|
|
52
|
+
* customer's own carts: a company bucket and anonymous/guest carts are
|
|
53
|
+
* only known to the session, and the backend only serves the route when
|
|
54
|
+
* the cart-ownership plugin is installed.
|
|
55
|
+
*/
|
|
56
|
+
protected shouldUseOwnershipEndpoint(payload: CartQueryList): Promise<boolean>;
|
|
57
|
+
/**
|
|
58
|
+
* Lists the customer's open carts through the cart-ownership plugin's
|
|
59
|
+
* `GET /store/customers/me/carts`. Returns null when the backend turns
|
|
60
|
+
* out not to serve the route after all (404: plugin configured but not
|
|
61
|
+
* built; 401: the token is no longer valid), so the caller falls back to
|
|
62
|
+
* the session-tracked list. Other errors are real backend faults and
|
|
63
|
+
* propagate.
|
|
64
|
+
*/
|
|
65
|
+
protected listCartsViaOwnershipEndpoint(payload: CartQueryList): Promise<ParseMedusaCartPaginatedSearchResultInput | null>;
|
|
66
|
+
/**
|
|
67
|
+
* Lists carts from the ids tracked in the session: the behavior from
|
|
68
|
+
* before the cart-ownership plugin existed, and still the only source for
|
|
69
|
+
* anonymous/guest carts and company buckets.
|
|
70
|
+
*/
|
|
71
|
+
protected listCartsFromSession(payload: CartQueryList): Promise<ParseMedusaCartPaginatedSearchResultInput>;
|
|
72
|
+
/**
|
|
73
|
+
* The factory reads `customer_id`, but only the `customer.id` relation is
|
|
74
|
+
* an allowed list field, so copy it over when `customer_id` itself wasn't
|
|
75
|
+
* returned.
|
|
76
|
+
*/
|
|
77
|
+
protected normalizeOwnedCart(cart: MedusaOwnedCart): StoreCart;
|
|
78
|
+
/** A 404 (route not served) or 401 (token no longer valid) degrades to the session list. */
|
|
79
|
+
protected shouldFallBackToSessionList(err: unknown): boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Checks whether the backend has the cart-ownership plugin, by its name in
|
|
82
|
+
* core's `GET /admin/plugins`. Detection must never break cart listing, so
|
|
83
|
+
* any failure just reports the plugin as absent.
|
|
84
|
+
*/
|
|
85
|
+
protected isCartOwnershipPluginEnabled(): Promise<boolean>;
|
|
86
|
+
/**
|
|
87
|
+
* The backend's configured plugin list, kept in the reactionary cache
|
|
88
|
+
* (shared across sessions) so not every request re-asks the admin API.
|
|
89
|
+
* Failures are not cached: a plugin-less answer from here only costs the
|
|
90
|
+
* fallback behavior, while caching a transient failure would hide the
|
|
91
|
+
* plugin for a whole TTL.
|
|
92
|
+
*/
|
|
93
|
+
protected fetchEnabledPlugins(): Promise<string[]>;
|
|
21
94
|
getById(payload: CartQueryById): Promise<Result<CartFactoryCartOutput<TFactory>, NotFoundError>>;
|
|
22
95
|
/**
|
|
23
96
|
* Extension point for the `add` operation to control the payload sent to Medusa when adding an item to the cart. By default, it only includes the variant ID and quantity, but you can override it to include more fields as needed.
|
|
@@ -35,7 +108,21 @@ export declare class MedusaCartCapability<TFactory extends CartFactory = MedusaC
|
|
|
35
108
|
* @returns
|
|
36
109
|
*/
|
|
37
110
|
protected createCartPayload(payload: CartMutationCreateCart): Promise<StoreCreateCart>;
|
|
111
|
+
/**
|
|
112
|
+
* Session tracking is skipped for a logged-in customer's own carts when
|
|
113
|
+
* the backend has the cart-ownership plugin: the backend attributes the
|
|
114
|
+
* cart to the customer at creation and lists it server-side. Anonymous
|
|
115
|
+
* carts and company buckets are still only known to the session.
|
|
116
|
+
*/
|
|
117
|
+
protected shouldTrackOwnedCartInSession(payload: CartMutationCreateCart): Promise<boolean>;
|
|
38
118
|
protected addCartToOwnedList(cartIdentifier: MedusaCartIdentifier, companyId?: CompanyIdentifier): void;
|
|
119
|
+
/**
|
|
120
|
+
* Removes every trace of a cart from the session: the active cart marker
|
|
121
|
+
* (when it points at this cart) and the entry in every owned-carts
|
|
122
|
+
* collection. Used when a cart turns out to be deleted or stale upstream.
|
|
123
|
+
*/
|
|
124
|
+
protected pruneCartFromSession(cartKey: string): void;
|
|
125
|
+
protected isNotFoundError(err: unknown): boolean;
|
|
39
126
|
protected removeCartFromOwnedList(cartIdentifier: MedusaCartIdentifier, company?: CompanyIdentifier): void;
|
|
40
127
|
createCart(payload: CartMutationCreateCart): Promise<Result<CartFactoryCartOutput<TFactory>>>;
|
|
41
128
|
remove(payload: CartMutationItemRemove): Promise<Result<CartFactoryCartOutput<TFactory>>>;
|
|
@@ -77,3 +164,4 @@ export declare class MedusaCartCapability<TFactory extends CartFactory = MedusaC
|
|
|
77
164
|
auth: import("@medusajs/js-sdk").Auth;
|
|
78
165
|
}>;
|
|
79
166
|
}
|
|
167
|
+
export {};
|
|
@@ -13,6 +13,13 @@ export declare const MedusaRegionSchema: z.ZodObject<{
|
|
|
13
13
|
name: z.ZodString;
|
|
14
14
|
currency_code: z.ZodString;
|
|
15
15
|
}, z.core.$loose>;
|
|
16
|
+
/**
|
|
17
|
+
* Cache entry shape for a backend's configured plugin list, as reported by
|
|
18
|
+
* core's `GET /admin/plugins`.
|
|
19
|
+
*/
|
|
20
|
+
export declare const MedusaCachedPluginListSchema: z.ZodObject<{
|
|
21
|
+
plugins: z.ZodArray<z.ZodString>;
|
|
22
|
+
}, z.core.$loose>;
|
|
16
23
|
export declare const MedusaSessionSchema: z.ZodObject<{
|
|
17
24
|
activeCartId: z.ZodOptional<z.ZodObject<{
|
|
18
25
|
key: z.ZodString;
|
|
@@ -37,5 +44,6 @@ export declare const MedusaSessionSchema: z.ZodObject<{
|
|
|
37
44
|
}, z.core.$loose>;
|
|
38
45
|
export type MedusaCartIdentifier = InferType<typeof MedusaCartIdentifierSchema>;
|
|
39
46
|
export type MedusaOrderIdentifier = z.infer<typeof MedusaOrderIdentifierSchema>;
|
|
47
|
+
export type MedusaCachedPluginList = z.infer<typeof MedusaCachedPluginListSchema>;
|
|
40
48
|
export type MedusaSession = z.infer<typeof MedusaSessionSchema>;
|
|
41
49
|
export type MedusaRegion = z.infer<typeof MedusaRegionSchema>;
|