@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.
Files changed (72) hide show
  1. package/README.md +11 -0
  2. package/capabilities/cart.capability.js +517 -0
  3. package/capabilities/category.capability.js +216 -0
  4. package/capabilities/checkout.capability.js +533 -0
  5. package/capabilities/identity.capability.js +128 -0
  6. package/capabilities/inventory.capability.js +142 -0
  7. package/capabilities/order-search.capability.js +161 -0
  8. package/capabilities/order.capability.js +179 -0
  9. package/capabilities/price.capability.js +120 -0
  10. package/capabilities/product-associations.capability.js +148 -0
  11. package/capabilities/product-recommendations.capability.js +116 -0
  12. package/capabilities/product-search.capability.js +177 -0
  13. package/capabilities/product.capability.js +252 -0
  14. package/capabilities/profile.capability.js +333 -0
  15. package/core/client.js +269 -0
  16. package/core/initialize.js +290 -0
  17. package/core/initialize.types.js +13 -0
  18. package/factories/cart/cart.factory.js +17 -0
  19. package/factories/category/category.factory.js +17 -0
  20. package/factories/checkout/checkout.factory.js +22 -0
  21. package/factories/identity/identity.factory.js +12 -0
  22. package/factories/index.js +12 -0
  23. package/factories/inventory/inventory.factory.js +12 -0
  24. package/factories/order/order.factory.js +12 -0
  25. package/factories/order-search/order-search.factory.js +12 -0
  26. package/factories/price/price.factory.js +12 -0
  27. package/factories/product/product.factory.js +12 -0
  28. package/factories/product-associations/product-associations.factory.js +12 -0
  29. package/factories/product-search/product-search.factory.js +12 -0
  30. package/factories/profile/profile.factory.js +12 -0
  31. package/index.js +17 -0
  32. package/package.json +17 -0
  33. package/schema/capabilities.schema.js +43 -0
  34. package/schema/configuration.schema.js +11 -0
  35. package/schema/medusa.schema.js +26 -0
  36. package/src/capabilities/cart.capability.d.ts +100 -0
  37. package/src/capabilities/category.capability.d.ts +36 -0
  38. package/src/capabilities/checkout.capability.d.ts +88 -0
  39. package/src/capabilities/identity.capability.d.ts +13 -0
  40. package/src/capabilities/inventory.capability.d.ts +21 -0
  41. package/src/capabilities/order-search.capability.d.ts +53 -0
  42. package/src/capabilities/order.capability.d.ts +49 -0
  43. package/src/capabilities/price.capability.d.ts +16 -0
  44. package/src/capabilities/product-associations.capability.d.ts +19 -0
  45. package/src/capabilities/product-recommendations.capability.d.ts +41 -0
  46. package/src/capabilities/product-search.capability.d.ts +45 -0
  47. package/src/capabilities/product.capability.d.ts +32 -0
  48. package/src/capabilities/profile.capability.d.ts +39 -0
  49. package/src/core/client.d.ts +81 -0
  50. package/src/core/initialize.d.ts +5 -0
  51. package/src/core/initialize.types.d.ts +108 -0
  52. package/src/factories/cart/cart.factory.d.ts +9 -0
  53. package/src/factories/category/category.factory.d.ts +9 -0
  54. package/src/factories/checkout/checkout.factory.d.ts +11 -0
  55. package/src/factories/identity/identity.factory.d.ts +7 -0
  56. package/src/factories/index.d.ts +12 -0
  57. package/src/factories/inventory/inventory.factory.d.ts +7 -0
  58. package/src/factories/order/order.factory.d.ts +7 -0
  59. package/src/factories/order-search/order-search.factory.d.ts +7 -0
  60. package/src/factories/price/price.factory.d.ts +9 -0
  61. package/src/factories/product/product.factory.d.ts +7 -0
  62. package/src/factories/product-associations/product-associations.factory.d.ts +7 -0
  63. package/src/factories/product-search/product-search.factory.d.ts +7 -0
  64. package/src/factories/profile/profile.factory.d.ts +7 -0
  65. package/src/index.d.ts +17 -0
  66. package/src/schema/capabilities.schema.d.ts +116 -0
  67. package/src/schema/configuration.schema.d.ts +9 -0
  68. package/src/schema/medusa.schema.d.ts +33 -0
  69. package/src/test/test-utils.d.ts +2 -0
  70. package/src/utils/medusa-helpers.d.ts +35 -0
  71. package/test/test-utils.js +12 -0
  72. 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
+ };