@reactionary/medusa 0.6.3
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/README.md +11 -0
- package/capabilities/cart.capability.js +517 -0
- package/capabilities/category.capability.js +216 -0
- package/capabilities/checkout.capability.js +533 -0
- package/capabilities/identity.capability.js +128 -0
- package/capabilities/inventory.capability.js +142 -0
- package/capabilities/order-search.capability.js +161 -0
- package/capabilities/order.capability.js +179 -0
- package/capabilities/price.capability.js +120 -0
- package/capabilities/product-associations.capability.js +148 -0
- package/capabilities/product-recommendations.capability.js +116 -0
- package/capabilities/product-search.capability.js +177 -0
- package/capabilities/product.capability.js +252 -0
- package/capabilities/profile.capability.js +333 -0
- package/core/client.js +269 -0
- package/core/initialize.js +290 -0
- package/core/initialize.types.js +13 -0
- package/factories/cart/cart.factory.js +17 -0
- package/factories/category/category.factory.js +17 -0
- package/factories/checkout/checkout.factory.js +22 -0
- package/factories/identity/identity.factory.js +12 -0
- package/factories/index.js +12 -0
- package/factories/inventory/inventory.factory.js +12 -0
- package/factories/order/order.factory.js +12 -0
- package/factories/order-search/order-search.factory.js +12 -0
- package/factories/price/price.factory.js +12 -0
- package/factories/product/product.factory.js +12 -0
- package/factories/product-associations/product-associations.factory.js +12 -0
- package/factories/product-search/product-search.factory.js +12 -0
- package/factories/profile/profile.factory.js +12 -0
- package/index.js +17 -0
- package/package.json +17 -0
- package/schema/capabilities.schema.js +43 -0
- package/schema/configuration.schema.js +11 -0
- package/schema/medusa.schema.js +26 -0
- package/src/capabilities/cart.capability.d.ts +100 -0
- package/src/capabilities/category.capability.d.ts +36 -0
- package/src/capabilities/checkout.capability.d.ts +88 -0
- package/src/capabilities/identity.capability.d.ts +13 -0
- package/src/capabilities/inventory.capability.d.ts +21 -0
- package/src/capabilities/order-search.capability.d.ts +53 -0
- package/src/capabilities/order.capability.d.ts +49 -0
- package/src/capabilities/price.capability.d.ts +16 -0
- package/src/capabilities/product-associations.capability.d.ts +19 -0
- package/src/capabilities/product-recommendations.capability.d.ts +41 -0
- package/src/capabilities/product-search.capability.d.ts +45 -0
- package/src/capabilities/product.capability.d.ts +32 -0
- package/src/capabilities/profile.capability.d.ts +39 -0
- package/src/core/client.d.ts +81 -0
- package/src/core/initialize.d.ts +5 -0
- package/src/core/initialize.types.d.ts +108 -0
- package/src/factories/cart/cart.factory.d.ts +9 -0
- package/src/factories/category/category.factory.d.ts +9 -0
- package/src/factories/checkout/checkout.factory.d.ts +11 -0
- package/src/factories/identity/identity.factory.d.ts +7 -0
- package/src/factories/index.d.ts +12 -0
- package/src/factories/inventory/inventory.factory.d.ts +7 -0
- package/src/factories/order/order.factory.d.ts +7 -0
- package/src/factories/order-search/order-search.factory.d.ts +7 -0
- package/src/factories/price/price.factory.d.ts +9 -0
- package/src/factories/product/product.factory.d.ts +7 -0
- package/src/factories/product-associations/product-associations.factory.d.ts +7 -0
- package/src/factories/product-search/product-search.factory.d.ts +7 -0
- package/src/factories/profile/profile.factory.d.ts +7 -0
- package/src/index.d.ts +17 -0
- package/src/schema/capabilities.schema.d.ts +116 -0
- package/src/schema/configuration.schema.d.ts +9 -0
- package/src/schema/medusa.schema.d.ts +33 -0
- package/src/test/test-utils.d.ts +2 -0
- package/src/utils/medusa-helpers.d.ts +35 -0
- package/test/test-utils.js +12 -0
- package/utils/medusa-helpers.js +72 -0
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
4
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
5
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
6
|
+
if (decorator = decorators[i])
|
|
7
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
+
if (kind && result)
|
|
9
|
+
__defProp(target, key, result);
|
|
10
|
+
return result;
|
|
11
|
+
};
|
|
12
|
+
import {
|
|
13
|
+
ProfileCapability,
|
|
14
|
+
Reactionary,
|
|
15
|
+
ProfileSchema,
|
|
16
|
+
ProfileMutationUpdateSchema,
|
|
17
|
+
ProfileMutationAddShippingAddressSchema,
|
|
18
|
+
ProfileMutationUpdateShippingAddressSchema,
|
|
19
|
+
ProfileMutationRemoveShippingAddressSchema,
|
|
20
|
+
ProfileMutationMakeShippingAddressDefaultSchema,
|
|
21
|
+
ProfileMutationSetBillingAddressSchema,
|
|
22
|
+
success,
|
|
23
|
+
ProfileQueryByIdSchema,
|
|
24
|
+
error
|
|
25
|
+
} from "@reactionary/core";
|
|
26
|
+
import createDebug from "debug";
|
|
27
|
+
const debug = createDebug("reactionary:medusa:profile");
|
|
28
|
+
class MedusaProfileCapability extends ProfileCapability {
|
|
29
|
+
constructor(config, cache, context, medusaApi, factory) {
|
|
30
|
+
super(cache, context);
|
|
31
|
+
this.medusaApi = medusaApi;
|
|
32
|
+
this.config = config;
|
|
33
|
+
this.factory = factory;
|
|
34
|
+
}
|
|
35
|
+
config;
|
|
36
|
+
includedFields = ["+metadata.*"];
|
|
37
|
+
factory;
|
|
38
|
+
async getById(payload) {
|
|
39
|
+
debug("getById", payload);
|
|
40
|
+
const client = await this.medusaApi.getClient();
|
|
41
|
+
const customerResponse = await client.store.customer.retrieve({ fields: this.includedFields.join(",") });
|
|
42
|
+
if (!customerResponse.customer) {
|
|
43
|
+
return error({
|
|
44
|
+
identifier: payload.identifier,
|
|
45
|
+
type: "NotFound"
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
const model = this.parseSingle(customerResponse.customer);
|
|
49
|
+
return success(model);
|
|
50
|
+
}
|
|
51
|
+
updatePayload(payload) {
|
|
52
|
+
const updateData = {};
|
|
53
|
+
if (payload.phone !== void 0) {
|
|
54
|
+
updateData.phone = payload.phone;
|
|
55
|
+
}
|
|
56
|
+
return updateData;
|
|
57
|
+
}
|
|
58
|
+
async update(payload) {
|
|
59
|
+
debug("update", payload);
|
|
60
|
+
const client = await this.medusaApi.getClient();
|
|
61
|
+
const customerResponse = await client.store.customer.retrieve({ fields: this.includedFields.join(",") });
|
|
62
|
+
if (!customerResponse.customer) {
|
|
63
|
+
return error({
|
|
64
|
+
type: "NotFound",
|
|
65
|
+
identifier: payload.identifier
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
const customer = customerResponse.customer;
|
|
69
|
+
const updatedResponse = await client.store.customer.update(this.updatePayload(payload), { fields: this.includedFields.join(",") });
|
|
70
|
+
const model = this.parseSingle(updatedResponse.customer);
|
|
71
|
+
return success(model);
|
|
72
|
+
}
|
|
73
|
+
addShippingAddressPayload(payload) {
|
|
74
|
+
return this.createMedusaAddress(payload.address);
|
|
75
|
+
}
|
|
76
|
+
async addShippingAddress(payload) {
|
|
77
|
+
debug("addShippingAddress", payload);
|
|
78
|
+
const client = await this.medusaApi.getClient();
|
|
79
|
+
const customer = await client.store.customer.retrieve({ fields: this.includedFields.join(",") });
|
|
80
|
+
if (!customer.customer) {
|
|
81
|
+
return error({
|
|
82
|
+
type: "NotFound",
|
|
83
|
+
identifier: payload.identifier
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
const existingAddress = customer.customer.addresses.find((addr) => addr.address_name === payload.address.identifier.nickName);
|
|
87
|
+
if (existingAddress) {
|
|
88
|
+
return error({
|
|
89
|
+
type: "InvalidInput",
|
|
90
|
+
error: "Address with the same nickname already exists"
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
const response = await client.store.customer.createAddress(this.addShippingAddressPayload(payload), { fields: this.includedFields.join(",") });
|
|
94
|
+
if (!response.customer) {
|
|
95
|
+
return error({
|
|
96
|
+
type: "InvalidInput",
|
|
97
|
+
error: "Failed to add shipping address"
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
const model = this.parseSingle(response.customer);
|
|
101
|
+
return success(model);
|
|
102
|
+
}
|
|
103
|
+
updateShippingAddressPayload(payload) {
|
|
104
|
+
return this.createMedusaAddress(payload.address);
|
|
105
|
+
}
|
|
106
|
+
async updateShippingAddress(payload) {
|
|
107
|
+
debug("updateShippingAddress", payload);
|
|
108
|
+
const client = await this.medusaApi.getClient();
|
|
109
|
+
const customer = await client.store.customer.retrieve({ fields: this.includedFields.join(",") });
|
|
110
|
+
if (!customer.customer) {
|
|
111
|
+
return error({
|
|
112
|
+
type: "NotFound",
|
|
113
|
+
identifier: payload.identifier
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
const existingAddress = customer.customer.addresses.find((addr) => addr.address_name === payload.address.identifier.nickName);
|
|
117
|
+
if (!existingAddress) {
|
|
118
|
+
return error({
|
|
119
|
+
type: "NotFound",
|
|
120
|
+
identifier: payload.address.identifier
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
const response = await client.store.customer.updateAddress(existingAddress.id, this.updateShippingAddressPayload(payload), { fields: this.includedFields.join(",") });
|
|
124
|
+
if (!response.customer) {
|
|
125
|
+
return error({
|
|
126
|
+
type: "InvalidInput",
|
|
127
|
+
error: "Failed to add shipping address"
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
const model = this.parseSingle(response.customer);
|
|
131
|
+
return success(model);
|
|
132
|
+
}
|
|
133
|
+
async removeShippingAddress(payload) {
|
|
134
|
+
debug("removeShippingAddress", payload);
|
|
135
|
+
const client = await this.medusaApi.getClient();
|
|
136
|
+
const customer = await client.store.customer.retrieve({ fields: this.includedFields.join(",") });
|
|
137
|
+
if (!customer.customer) {
|
|
138
|
+
return error({
|
|
139
|
+
type: "NotFound",
|
|
140
|
+
identifier: payload.identifier
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
const existingAddress = customer.customer.addresses.find((addr) => addr.address_name === payload.addressIdentifier.nickName);
|
|
144
|
+
if (!existingAddress) {
|
|
145
|
+
return error({
|
|
146
|
+
type: "NotFound",
|
|
147
|
+
identifier: payload.addressIdentifier
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
const response = await client.store.customer.deleteAddress(existingAddress.id, { fields: this.includedFields.join(",") });
|
|
151
|
+
if (!response.deleted) {
|
|
152
|
+
return error({
|
|
153
|
+
type: "InvalidInput",
|
|
154
|
+
error: "Failed to delete shipping address"
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
const customerAfterDelete = await client.store.customer.retrieve({ fields: this.includedFields.join(",") });
|
|
158
|
+
const model = this.parseSingle(customerAfterDelete.customer);
|
|
159
|
+
return success(model);
|
|
160
|
+
}
|
|
161
|
+
makeShippingAddressDefaultPayload(payload) {
|
|
162
|
+
return {
|
|
163
|
+
is_default_shipping: true
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
async makeShippingAddressDefault(payload) {
|
|
167
|
+
debug("makeShippingAddressDefault", payload);
|
|
168
|
+
const client = await this.medusaApi.getClient();
|
|
169
|
+
const customer = await client.store.customer.retrieve({ fields: this.includedFields.join(",") });
|
|
170
|
+
if (!customer.customer) {
|
|
171
|
+
return error({
|
|
172
|
+
type: "NotFound",
|
|
173
|
+
identifier: payload.identifier
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
const existingAddress = customer.customer.addresses.find((addr) => addr.address_name === payload.addressIdentifier.nickName);
|
|
177
|
+
if (!existingAddress) {
|
|
178
|
+
return error({
|
|
179
|
+
type: "NotFound",
|
|
180
|
+
identifier: payload.addressIdentifier
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
const response = await client.store.customer.updateAddress(
|
|
184
|
+
existingAddress.id,
|
|
185
|
+
this.makeShippingAddressDefaultPayload(payload),
|
|
186
|
+
{ fields: this.includedFields.join(",") }
|
|
187
|
+
);
|
|
188
|
+
const model = this.parseSingle(response.customer);
|
|
189
|
+
return success(model);
|
|
190
|
+
}
|
|
191
|
+
setBillingAddressPayload(payload) {
|
|
192
|
+
const newAddr = this.createMedusaAddress(payload.address);
|
|
193
|
+
newAddr.is_default_billing = true;
|
|
194
|
+
return newAddr;
|
|
195
|
+
}
|
|
196
|
+
async setBillingAddress(payload) {
|
|
197
|
+
debug("setBillingAddress", payload);
|
|
198
|
+
const client = await this.medusaApi.getClient();
|
|
199
|
+
const customerResponse = await client.store.customer.retrieve({ fields: this.includedFields.join(",") });
|
|
200
|
+
if (!customerResponse.customer) {
|
|
201
|
+
return error({
|
|
202
|
+
type: "NotFound",
|
|
203
|
+
identifier: payload.identifier
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
let customer = customerResponse.customer;
|
|
207
|
+
const existingAddressWithNickname = customer.addresses.find((addr) => addr.address_name === payload.address.identifier.nickName);
|
|
208
|
+
if (existingAddressWithNickname && !existingAddressWithNickname.is_default_billing) {
|
|
209
|
+
return error({
|
|
210
|
+
type: "InvalidInput",
|
|
211
|
+
error: "Another address with the same nickname already exists"
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
const newAddr = this.setBillingAddressPayload(payload);
|
|
215
|
+
const existingBillingAddress = customer.addresses.find((addr) => addr.is_default_billing);
|
|
216
|
+
if (existingBillingAddress) {
|
|
217
|
+
const updateAddressResponse = await client.store.customer.updateAddress(existingBillingAddress.id, newAddr, { fields: this.includedFields.join(",") });
|
|
218
|
+
customer = updateAddressResponse.customer;
|
|
219
|
+
} else {
|
|
220
|
+
const createAddressResponse = await client.store.customer.createAddress(newAddr, { fields: this.includedFields.join(",") });
|
|
221
|
+
customer = createAddressResponse.customer;
|
|
222
|
+
}
|
|
223
|
+
const model = this.parseSingle(customer);
|
|
224
|
+
return success(model);
|
|
225
|
+
}
|
|
226
|
+
createMedusaAddress(address) {
|
|
227
|
+
return {
|
|
228
|
+
address_name: address.identifier.nickName,
|
|
229
|
+
first_name: address.firstName,
|
|
230
|
+
last_name: address.lastName,
|
|
231
|
+
address_1: address.streetAddress,
|
|
232
|
+
address_2: address.streetNumber,
|
|
233
|
+
city: address.city,
|
|
234
|
+
province: address.region,
|
|
235
|
+
postal_code: address.postalCode,
|
|
236
|
+
country_code: address.countryCode
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
parseAddress(address) {
|
|
240
|
+
return {
|
|
241
|
+
identifier: {
|
|
242
|
+
nickName: address.address_name || ""
|
|
243
|
+
},
|
|
244
|
+
firstName: address.first_name || "",
|
|
245
|
+
lastName: address.last_name || "",
|
|
246
|
+
streetAddress: address.address_1 || "",
|
|
247
|
+
streetNumber: address.address_2 || "",
|
|
248
|
+
city: address.city || "",
|
|
249
|
+
region: address.province || "",
|
|
250
|
+
postalCode: address.postal_code || "",
|
|
251
|
+
countryCode: address.country_code || ""
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
parseSingle(customer) {
|
|
255
|
+
const email = customer.email;
|
|
256
|
+
const emailVerified = customer.metadata?.["email_verified"] === "true";
|
|
257
|
+
const phone = customer.phone || "";
|
|
258
|
+
const phoneVerified = customer.metadata?.["phone_verified"] === "true";
|
|
259
|
+
const addresses = customer.addresses || [];
|
|
260
|
+
let billingAddress = void 0;
|
|
261
|
+
let shippingAddress = void 0;
|
|
262
|
+
const existingBillingAddress = customer.addresses.find((addr) => addr.is_default_billing);
|
|
263
|
+
if (existingBillingAddress) {
|
|
264
|
+
billingAddress = this.parseAddress(existingBillingAddress);
|
|
265
|
+
}
|
|
266
|
+
const existingShippingAddress = customer.addresses.find((addr) => addr.is_default_shipping);
|
|
267
|
+
if (existingShippingAddress) {
|
|
268
|
+
shippingAddress = this.parseAddress(existingShippingAddress);
|
|
269
|
+
}
|
|
270
|
+
const alternateShippingAddresses = [];
|
|
271
|
+
alternateShippingAddresses.push(...addresses.filter((x) => !(x.is_default_billing || x.is_default_shipping)).map((addr) => this.parseAddress(addr)));
|
|
272
|
+
const result = {
|
|
273
|
+
identifier: {
|
|
274
|
+
userId: customer.id
|
|
275
|
+
},
|
|
276
|
+
email,
|
|
277
|
+
emailVerified,
|
|
278
|
+
phone,
|
|
279
|
+
phoneVerified,
|
|
280
|
+
billingAddress,
|
|
281
|
+
shippingAddress,
|
|
282
|
+
alternateShippingAddresses,
|
|
283
|
+
createdAt: new Date(customer.created_at || "").toISOString(),
|
|
284
|
+
updatedAt: new Date(customer.updated_at || "").toISOString()
|
|
285
|
+
};
|
|
286
|
+
return this.factory.parseProfile(this.context, result);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
__decorateClass([
|
|
290
|
+
Reactionary({
|
|
291
|
+
inputSchema: ProfileQueryByIdSchema,
|
|
292
|
+
outputSchema: ProfileSchema
|
|
293
|
+
})
|
|
294
|
+
], MedusaProfileCapability.prototype, "getById", 1);
|
|
295
|
+
__decorateClass([
|
|
296
|
+
Reactionary({
|
|
297
|
+
inputSchema: ProfileMutationUpdateSchema,
|
|
298
|
+
outputSchema: ProfileSchema
|
|
299
|
+
})
|
|
300
|
+
], MedusaProfileCapability.prototype, "update", 1);
|
|
301
|
+
__decorateClass([
|
|
302
|
+
Reactionary({
|
|
303
|
+
inputSchema: ProfileMutationAddShippingAddressSchema,
|
|
304
|
+
outputSchema: ProfileSchema
|
|
305
|
+
})
|
|
306
|
+
], MedusaProfileCapability.prototype, "addShippingAddress", 1);
|
|
307
|
+
__decorateClass([
|
|
308
|
+
Reactionary({
|
|
309
|
+
inputSchema: ProfileMutationUpdateShippingAddressSchema,
|
|
310
|
+
outputSchema: ProfileSchema
|
|
311
|
+
})
|
|
312
|
+
], MedusaProfileCapability.prototype, "updateShippingAddress", 1);
|
|
313
|
+
__decorateClass([
|
|
314
|
+
Reactionary({
|
|
315
|
+
inputSchema: ProfileMutationRemoveShippingAddressSchema,
|
|
316
|
+
outputSchema: ProfileSchema
|
|
317
|
+
})
|
|
318
|
+
], MedusaProfileCapability.prototype, "removeShippingAddress", 1);
|
|
319
|
+
__decorateClass([
|
|
320
|
+
Reactionary({
|
|
321
|
+
inputSchema: ProfileMutationMakeShippingAddressDefaultSchema,
|
|
322
|
+
outputSchema: ProfileSchema
|
|
323
|
+
})
|
|
324
|
+
], MedusaProfileCapability.prototype, "makeShippingAddressDefault", 1);
|
|
325
|
+
__decorateClass([
|
|
326
|
+
Reactionary({
|
|
327
|
+
inputSchema: ProfileMutationSetBillingAddressSchema,
|
|
328
|
+
outputSchema: ProfileSchema
|
|
329
|
+
})
|
|
330
|
+
], MedusaProfileCapability.prototype, "setBillingAddress", 1);
|
|
331
|
+
export {
|
|
332
|
+
MedusaProfileCapability
|
|
333
|
+
};
|
package/core/client.js
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import { Admin, Auth, Client, Store } from "@medusajs/js-sdk";
|
|
2
|
+
import {
|
|
3
|
+
AnonymousIdentitySchema,
|
|
4
|
+
Reactionary,
|
|
5
|
+
RegisteredIdentitySchema
|
|
6
|
+
} from "@reactionary/core";
|
|
7
|
+
import createDebug from "debug";
|
|
8
|
+
import {
|
|
9
|
+
MedusaSessionSchema
|
|
10
|
+
} from "../index.js";
|
|
11
|
+
const debug = createDebug("reactionary:medusa");
|
|
12
|
+
const SESSION_KEY = "MEDUSA_PROVIDER";
|
|
13
|
+
class RequestContextTokenStore {
|
|
14
|
+
constructor(context, keyPrefix = "__x") {
|
|
15
|
+
this.context = context;
|
|
16
|
+
this.keyPrefix = keyPrefix;
|
|
17
|
+
}
|
|
18
|
+
getItem(key) {
|
|
19
|
+
if (this.context.session[SESSION_KEY] === void 0) {
|
|
20
|
+
this.context.session[SESSION_KEY] = {};
|
|
21
|
+
}
|
|
22
|
+
const retVal = this.context.session[SESSION_KEY] ? this.context.session[SESSION_KEY][this.keyPrefix + "_" + key] || null : null;
|
|
23
|
+
if (debug.enabled) {
|
|
24
|
+
debug(
|
|
25
|
+
`Getting token item for key: ${this.keyPrefix + "_" + key} - Found: ${retVal ? "Yes" : "No"}`
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
return Promise.resolve(retVal);
|
|
29
|
+
}
|
|
30
|
+
setItem(key, value) {
|
|
31
|
+
if (this.context.session[SESSION_KEY] === void 0) {
|
|
32
|
+
this.context.session[SESSION_KEY] = {};
|
|
33
|
+
}
|
|
34
|
+
if (debug.enabled) {
|
|
35
|
+
debug(
|
|
36
|
+
`Setting token item for key: ${this.keyPrefix + "_" + key} - Value: ${value}`
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
this.context.session[SESSION_KEY][this.keyPrefix + "_" + key] = value;
|
|
40
|
+
return Promise.resolve();
|
|
41
|
+
}
|
|
42
|
+
removeItem(key) {
|
|
43
|
+
if (this.context.session[SESSION_KEY] === void 0) {
|
|
44
|
+
this.context.session[SESSION_KEY] = {};
|
|
45
|
+
}
|
|
46
|
+
if (debug.enabled) {
|
|
47
|
+
debug(`Removing token item for key: ${this.keyPrefix + "_" + key}`);
|
|
48
|
+
}
|
|
49
|
+
delete this.context.session[SESSION_KEY][this.keyPrefix + "_" + key];
|
|
50
|
+
return Promise.resolve();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
class Medusa {
|
|
54
|
+
client;
|
|
55
|
+
admin;
|
|
56
|
+
store;
|
|
57
|
+
auth;
|
|
58
|
+
constructor(config) {
|
|
59
|
+
this.client = new Client(config);
|
|
60
|
+
this.admin = new Admin(this.client);
|
|
61
|
+
this.store = new Store(this.client);
|
|
62
|
+
this.auth = new Auth(this.client, config);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
class MedusaAdminAPI {
|
|
66
|
+
config;
|
|
67
|
+
client;
|
|
68
|
+
context;
|
|
69
|
+
constructor(config, context) {
|
|
70
|
+
this.config = config;
|
|
71
|
+
this.context = context;
|
|
72
|
+
console.log(
|
|
73
|
+
"MedusaAdminClient config:",
|
|
74
|
+
this.config,
|
|
75
|
+
"Debug enabled:",
|
|
76
|
+
debug.enabled
|
|
77
|
+
);
|
|
78
|
+
this.client = new Medusa({
|
|
79
|
+
baseUrl: this.config.apiUrl,
|
|
80
|
+
apiKey: this.config.adminApiKey,
|
|
81
|
+
debug: true
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
async getClient() {
|
|
85
|
+
return this.client;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
class MedusaAPI {
|
|
89
|
+
config;
|
|
90
|
+
client;
|
|
91
|
+
context;
|
|
92
|
+
constructor(config, context) {
|
|
93
|
+
this.config = config;
|
|
94
|
+
this.context = context;
|
|
95
|
+
console.log(
|
|
96
|
+
"MedusaClient config:",
|
|
97
|
+
this.config,
|
|
98
|
+
"Debug enabled:",
|
|
99
|
+
debug.enabled
|
|
100
|
+
);
|
|
101
|
+
this.client = void 0;
|
|
102
|
+
}
|
|
103
|
+
async getActiveRegion() {
|
|
104
|
+
const session = this.getSessionData();
|
|
105
|
+
if (session.selectedRegion) {
|
|
106
|
+
return session.selectedRegion;
|
|
107
|
+
}
|
|
108
|
+
const regions = await (await this.getClient()).store.region.list();
|
|
109
|
+
const allRegions = [];
|
|
110
|
+
for (const region of regions.regions) {
|
|
111
|
+
allRegions.push({
|
|
112
|
+
id: region.id,
|
|
113
|
+
name: region.name,
|
|
114
|
+
currency_code: region.currency_code
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
const selectedRegion = allRegions.find(
|
|
118
|
+
(r) => r.currency_code === this.context.languageContext.currencyCode.toLowerCase()
|
|
119
|
+
) || allRegions[0];
|
|
120
|
+
this.context.languageContext.currencyCode = (selectedRegion || allRegions[0]).currency_code.toUpperCase();
|
|
121
|
+
this.setSessionData({
|
|
122
|
+
allRegions,
|
|
123
|
+
selectedRegion
|
|
124
|
+
});
|
|
125
|
+
return selectedRegion;
|
|
126
|
+
}
|
|
127
|
+
async resolveProductForSKU(sku) {
|
|
128
|
+
const adminClient = await new MedusaAdminAPI(
|
|
129
|
+
this.config,
|
|
130
|
+
this.context
|
|
131
|
+
).getClient();
|
|
132
|
+
const productsResponse = await adminClient.admin.product.list({
|
|
133
|
+
limit: 1,
|
|
134
|
+
offset: 0,
|
|
135
|
+
fields: "+metadata.*,+categories.metadata.*,+external_id",
|
|
136
|
+
variants: {
|
|
137
|
+
$or: [{ ean: sku }, { upc: sku }, { barcode: sku }]
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
const product = productsResponse.products[0];
|
|
141
|
+
if (!product) {
|
|
142
|
+
throw new Error(`Product with SKU ${sku} not found`);
|
|
143
|
+
}
|
|
144
|
+
return product;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* This function should not need to exist.
|
|
148
|
+
* It returns a product-id, given a SKU.
|
|
149
|
+
* @param sku
|
|
150
|
+
* @returns
|
|
151
|
+
*/
|
|
152
|
+
async resolveVariantId(sku) {
|
|
153
|
+
const product = await this.resolveProductForSKU(sku);
|
|
154
|
+
const variant = product.variants?.find((v) => v.sku === sku);
|
|
155
|
+
if (!variant) {
|
|
156
|
+
throw new Error(`Variant with SKU ${sku} not found`);
|
|
157
|
+
}
|
|
158
|
+
return variant.id;
|
|
159
|
+
}
|
|
160
|
+
async getClient() {
|
|
161
|
+
if (!this.client) {
|
|
162
|
+
this.client = this.createAuthenticatedClient(this.context);
|
|
163
|
+
}
|
|
164
|
+
return await this.client;
|
|
165
|
+
}
|
|
166
|
+
getSessionData() {
|
|
167
|
+
return this.context.session[SESSION_KEY] ? this.context.session[SESSION_KEY] : MedusaSessionSchema.parse({});
|
|
168
|
+
}
|
|
169
|
+
setSessionData(sessionData) {
|
|
170
|
+
const existingData = this.context.session[SESSION_KEY];
|
|
171
|
+
this.context.session[SESSION_KEY] = {
|
|
172
|
+
...existingData,
|
|
173
|
+
...sessionData
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
async register(email, password, firstName, lastName, reqCtx) {
|
|
177
|
+
try {
|
|
178
|
+
const client = await this.getClient();
|
|
179
|
+
const tokenResponse = await client.auth.register(
|
|
180
|
+
"customer",
|
|
181
|
+
"emailpass",
|
|
182
|
+
{
|
|
183
|
+
email,
|
|
184
|
+
password
|
|
185
|
+
}
|
|
186
|
+
);
|
|
187
|
+
const customer = await client.store.customer.create({
|
|
188
|
+
email,
|
|
189
|
+
first_name: firstName,
|
|
190
|
+
last_name: lastName
|
|
191
|
+
});
|
|
192
|
+
const identity = await this.login(email, password, reqCtx);
|
|
193
|
+
return identity;
|
|
194
|
+
} catch (error) {
|
|
195
|
+
debug("Registration failed:", error);
|
|
196
|
+
throw new Error(
|
|
197
|
+
`Registration failed: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
async login(email, password, reqCtx) {
|
|
202
|
+
try {
|
|
203
|
+
const client = await this.getClient();
|
|
204
|
+
const authResult = await client.auth.login("customer", "emailpass", {
|
|
205
|
+
email,
|
|
206
|
+
password
|
|
207
|
+
});
|
|
208
|
+
if (typeof authResult === "string") {
|
|
209
|
+
const token = authResult;
|
|
210
|
+
if (token) {
|
|
211
|
+
await client.client.setToken(token);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
const customerResponse = await client.store.customer.retrieve();
|
|
215
|
+
if (customerResponse.customer) {
|
|
216
|
+
const identity = {
|
|
217
|
+
id: {
|
|
218
|
+
userId: customerResponse.customer.id
|
|
219
|
+
},
|
|
220
|
+
type: "Registered"
|
|
221
|
+
};
|
|
222
|
+
return identity;
|
|
223
|
+
}
|
|
224
|
+
return {
|
|
225
|
+
type: "Anonymous"
|
|
226
|
+
};
|
|
227
|
+
} catch (error) {
|
|
228
|
+
debug("Login failed:", error);
|
|
229
|
+
throw new Error(
|
|
230
|
+
`Login failed: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
async logout(reqCtx) {
|
|
235
|
+
const identity = {
|
|
236
|
+
type: "Anonymous"
|
|
237
|
+
};
|
|
238
|
+
const client = await this.getClient();
|
|
239
|
+
try {
|
|
240
|
+
await client.auth.logout();
|
|
241
|
+
await client.client.clearToken();
|
|
242
|
+
return identity;
|
|
243
|
+
} catch (error) {
|
|
244
|
+
debug("Logout failed:", error);
|
|
245
|
+
await client.client.clearToken();
|
|
246
|
+
return identity;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
async createAuthenticatedClient(reqCtx) {
|
|
250
|
+
const tokenStore = new RequestContextTokenStore(reqCtx);
|
|
251
|
+
const authenticatedClient = new Medusa({
|
|
252
|
+
baseUrl: this.config.apiUrl,
|
|
253
|
+
publishableKey: this.config.publishable_key,
|
|
254
|
+
debug: true,
|
|
255
|
+
auth: {
|
|
256
|
+
type: "jwt",
|
|
257
|
+
jwtTokenStorageMethod: "custom",
|
|
258
|
+
storage: tokenStore
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
return authenticatedClient;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
export {
|
|
265
|
+
MedusaAPI,
|
|
266
|
+
MedusaAdminAPI,
|
|
267
|
+
RequestContextTokenStore,
|
|
268
|
+
SESSION_KEY
|
|
269
|
+
};
|