@reactionary/medusa 0.10.23 → 0.10.24

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.
@@ -0,0 +1,116 @@
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) __defProp(target, key, result);
9
+ return result;
10
+ };
11
+ import { FetchError } from "@medusajs/js-sdk";
12
+ import {
13
+ CompanyRegistrationCapability,
14
+ CompanyRegistrationMutationRegisterSchema,
15
+ CompanyRegistrationQueryCheckRegistrationStatusSchema,
16
+ CompanyRegistrationRequestSchema,
17
+ Reactionary,
18
+ error,
19
+ success
20
+ } from "@reactionary/core";
21
+ import createDebug from "debug";
22
+ import { handleProviderError } from "../utils/medusa-helpers.js";
23
+ const debug = createDebug("reactionary:medusa:company-registration");
24
+ class MedusaCompanyRegistrationCapability extends CompanyRegistrationCapability {
25
+ constructor(config, cache, context, medusaApi, factory) {
26
+ super(cache, context);
27
+ this.medusaApi = medusaApi;
28
+ this.config = config;
29
+ this.factory = factory;
30
+ }
31
+ medusaApi;
32
+ config;
33
+ factory;
34
+ async fetchCompany(companyId) {
35
+ const client = await this.medusaApi.getClient();
36
+ try {
37
+ const response = await client.client.fetch(
38
+ `/store/companies/${companyId}`,
39
+ { method: "GET" }
40
+ );
41
+ return response.company;
42
+ } catch (err) {
43
+ if (err instanceof FetchError && err.status === 404) {
44
+ return null;
45
+ }
46
+ throw err;
47
+ }
48
+ }
49
+ addressPayload(address) {
50
+ return {
51
+ address_name: address.identifier.nickName,
52
+ first_name: address.firstName,
53
+ last_name: address.lastName,
54
+ street_address: address.streetAddress,
55
+ street_number: address.streetNumber,
56
+ city: address.city,
57
+ region: address.region,
58
+ postal_code: address.postalCode,
59
+ country_code: address.countryCode
60
+ };
61
+ }
62
+ async requestRegistration(payload) {
63
+ debug("requestRegistration", payload);
64
+ try {
65
+ const client = await this.medusaApi.getClient();
66
+ const createResponse = await client.client.fetch(
67
+ "/store/company-registrations",
68
+ {
69
+ method: "POST",
70
+ body: {
71
+ name: payload.name,
72
+ email: payload.pointOfContact.email,
73
+ phone: payload.pointOfContact.phone,
74
+ tax_identifier: payload.taxIdentifier,
75
+ duns_identifier: payload.dunsIdentifier,
76
+ tin_identifier: payload.tinIdentifier,
77
+ currency_code: this.context.languageContext.currencyCode.toLowerCase(),
78
+ billing_address: this.addressPayload(payload.billingAddress)
79
+ }
80
+ }
81
+ );
82
+ return success(
83
+ this.factory.parseCompanyRegistrationRequest(this.context, createResponse.company)
84
+ );
85
+ } catch (err) {
86
+ handleProviderError("request company registration", err);
87
+ }
88
+ }
89
+ async checkRequestStatus(payload) {
90
+ debug("checkRequestStatus", payload);
91
+ try {
92
+ const company = await this.fetchCompany(payload.requestIdentifier.key);
93
+ if (!company) {
94
+ return error({ type: "NotFound", identifier: payload.requestIdentifier });
95
+ }
96
+ return success(this.factory.parseCompanyRegistrationRequest(this.context, company));
97
+ } catch (err) {
98
+ handleProviderError("check company registration status", err);
99
+ }
100
+ }
101
+ }
102
+ __decorateClass([
103
+ Reactionary({
104
+ inputSchema: CompanyRegistrationMutationRegisterSchema,
105
+ outputSchema: CompanyRegistrationRequestSchema
106
+ })
107
+ ], MedusaCompanyRegistrationCapability.prototype, "requestRegistration", 1);
108
+ __decorateClass([
109
+ Reactionary({
110
+ inputSchema: CompanyRegistrationQueryCheckRegistrationStatusSchema,
111
+ outputSchema: CompanyRegistrationRequestSchema
112
+ })
113
+ ], MedusaCompanyRegistrationCapability.prototype, "checkRequestStatus", 1);
114
+ export {
115
+ MedusaCompanyRegistrationCapability
116
+ };
@@ -0,0 +1,257 @@
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) __defProp(target, key, result);
9
+ return result;
10
+ };
11
+ import { FetchError } from "@medusajs/js-sdk";
12
+ import {
13
+ CompanyCapability,
14
+ CompanyMutationAddShippingAddressSchema,
15
+ CompanyMutationMakeShippingAddressDefaultSchema,
16
+ CompanyMutationRemoveShippingAddressSchema,
17
+ CompanyMutationUpdateShippingAddressSchema,
18
+ CompanyPaginatedListSchema,
19
+ CompanyQueryByIdSchema,
20
+ CompanyQueryListSchema,
21
+ CompanySchema,
22
+ Reactionary,
23
+ error,
24
+ success
25
+ } from "@reactionary/core";
26
+ import createDebug from "debug";
27
+ import { handleProviderError } from "../utils/medusa-helpers.js";
28
+ const debug = createDebug("reactionary:medusa:company");
29
+ class MedusaCompanyCapability extends CompanyCapability {
30
+ constructor(config, cache, context, medusaApi, factory) {
31
+ super(cache, context);
32
+ this.medusaApi = medusaApi;
33
+ this.config = config;
34
+ this.factory = factory;
35
+ }
36
+ medusaApi;
37
+ config;
38
+ factory;
39
+ async fetchCompany(companyId) {
40
+ const client = await this.medusaApi.getClient();
41
+ try {
42
+ const response = await client.client.fetch(
43
+ `/store/companies/${companyId}`,
44
+ { method: "GET" }
45
+ );
46
+ return response.company;
47
+ } catch (err) {
48
+ if (err instanceof FetchError && err.status === 404) {
49
+ return null;
50
+ }
51
+ throw err;
52
+ }
53
+ }
54
+ async fetchCompanyOrThrow(companyId) {
55
+ const company = await this.fetchCompany(companyId);
56
+ if (!company) {
57
+ throw new Error(`Company ${companyId} disappeared after mutation`);
58
+ }
59
+ return company;
60
+ }
61
+ async fetchCompanyByTaxIdentifier(taxIdentifier) {
62
+ const client = await this.medusaApi.getClient();
63
+ try {
64
+ const response = await client.client.fetch(
65
+ `/store/companies/by-tax-identifier/${encodeURIComponent(taxIdentifier)}`,
66
+ { method: "GET" }
67
+ );
68
+ return response.company;
69
+ } catch (err) {
70
+ if (err instanceof FetchError && err.status === 404) {
71
+ return null;
72
+ }
73
+ throw err;
74
+ }
75
+ }
76
+ findAddress(company, nickName, type) {
77
+ return company.addresses?.find(
78
+ (a) => a.type === type && (a.address_name ?? "") === nickName
79
+ );
80
+ }
81
+ addressPayload(address) {
82
+ return {
83
+ address_name: address.identifier.nickName,
84
+ first_name: address.firstName,
85
+ last_name: address.lastName,
86
+ street_address: address.streetAddress,
87
+ street_number: address.streetNumber,
88
+ city: address.city,
89
+ region: address.region,
90
+ postal_code: address.postalCode,
91
+ country_code: address.countryCode
92
+ };
93
+ }
94
+ async getById(payload) {
95
+ try {
96
+ const company = await this.fetchCompanyByTaxIdentifier(payload.identifier.taxIdentifier);
97
+ if (!company) {
98
+ return error({ type: "NotFound", identifier: payload.identifier });
99
+ }
100
+ return success(this.factory.parseCompany(this.context, company));
101
+ } catch (err) {
102
+ handleProviderError("get company", err);
103
+ }
104
+ }
105
+ async listCompanies(payload) {
106
+ debug("listCompanies", payload);
107
+ try {
108
+ const client = await this.medusaApi.getClient();
109
+ const response = await client.client.fetch("/store/customers/me/employees", { method: "GET" });
110
+ const companyIds = Array.from(new Set(response.employees.map((e) => e.company.id)));
111
+ const { pageNumber, pageSize } = payload.search.paginationOptions;
112
+ const start = (pageNumber - 1) * pageSize;
113
+ const pageIds = companyIds.slice(start, start + pageSize);
114
+ const companies = (await Promise.all(pageIds.map((id) => this.fetchCompany(id)))).filter(
115
+ (company) => company !== null
116
+ );
117
+ return success(
118
+ this.factory.parseCompanyPaginatedList(
119
+ this.context,
120
+ { items: companies, totalCount: companyIds.length },
121
+ payload
122
+ )
123
+ );
124
+ } catch (err) {
125
+ handleProviderError("list companies", err);
126
+ }
127
+ }
128
+ async addShippingAddress(payload) {
129
+ debug("addShippingAddress", payload);
130
+ try {
131
+ const company = await this.fetchCompanyByTaxIdentifier(payload.company.taxIdentifier);
132
+ if (!company) {
133
+ return error({ type: "NotFound", identifier: payload.company });
134
+ }
135
+ const companyId = company.id;
136
+ const existing = this.findAddress(company, payload.address.identifier.nickName, "shipping");
137
+ if (existing) {
138
+ return error({
139
+ type: "InvalidInput",
140
+ error: "A shipping address with the same nickname already exists"
141
+ });
142
+ }
143
+ const client = await this.medusaApi.getClient();
144
+ await client.client.fetch(`/store/companies/${companyId}/addresses`, {
145
+ method: "POST",
146
+ body: { ...this.addressPayload(payload.address), type: "shipping", is_default: false }
147
+ });
148
+ return success(this.factory.parseCompany(this.context, await this.fetchCompanyOrThrow(companyId)));
149
+ } catch (err) {
150
+ handleProviderError("add shipping address", err);
151
+ }
152
+ }
153
+ async updateShippingAddress(payload) {
154
+ debug("updateShippingAddress", payload);
155
+ try {
156
+ const company = await this.fetchCompanyByTaxIdentifier(payload.company.taxIdentifier);
157
+ if (!company) {
158
+ return error({ type: "NotFound", identifier: payload.company });
159
+ }
160
+ const companyId = company.id;
161
+ const existing = this.findAddress(company, payload.address.identifier.nickName, "shipping");
162
+ if (!existing) {
163
+ return error({ type: "NotFound", identifier: payload.address.identifier });
164
+ }
165
+ const client = await this.medusaApi.getClient();
166
+ await client.client.fetch(`/store/companies/${companyId}/addresses/${existing.id}`, {
167
+ method: "POST",
168
+ body: this.addressPayload(payload.address)
169
+ });
170
+ return success(this.factory.parseCompany(this.context, await this.fetchCompanyOrThrow(companyId)));
171
+ } catch (err) {
172
+ handleProviderError("update shipping address", err);
173
+ }
174
+ }
175
+ async removeShippingAddress(payload) {
176
+ debug("removeShippingAddress", payload);
177
+ try {
178
+ const company = await this.fetchCompanyByTaxIdentifier(payload.company.taxIdentifier);
179
+ if (!company) {
180
+ return error({ type: "NotFound", identifier: payload.company });
181
+ }
182
+ const companyId = company.id;
183
+ const existing = this.findAddress(company, payload.addressIdentifier.nickName, "shipping");
184
+ if (!existing) {
185
+ return error({ type: "NotFound", identifier: payload.addressIdentifier });
186
+ }
187
+ const client = await this.medusaApi.getClient();
188
+ await client.client.fetch(`/store/companies/${companyId}/addresses/${existing.id}`, {
189
+ method: "DELETE"
190
+ });
191
+ return success(this.factory.parseCompany(this.context, await this.fetchCompanyOrThrow(companyId)));
192
+ } catch (err) {
193
+ handleProviderError("remove shipping address", err);
194
+ }
195
+ }
196
+ async makeShippingAddressDefault(payload) {
197
+ debug("makeShippingAddressDefault", payload);
198
+ try {
199
+ const company = await this.fetchCompanyByTaxIdentifier(payload.company.taxIdentifier);
200
+ if (!company) {
201
+ return error({ type: "NotFound", identifier: payload.company });
202
+ }
203
+ const companyId = company.id;
204
+ const existing = this.findAddress(company, payload.addressIdentifier.nickName, "shipping");
205
+ if (!existing) {
206
+ return error({ type: "NotFound", identifier: payload.addressIdentifier });
207
+ }
208
+ const client = await this.medusaApi.getClient();
209
+ await client.client.fetch(`/store/companies/${companyId}/addresses/${existing.id}`, {
210
+ method: "POST",
211
+ body: { is_default: true }
212
+ });
213
+ return success(this.factory.parseCompany(this.context, await this.fetchCompanyOrThrow(companyId)));
214
+ } catch (err) {
215
+ handleProviderError("make shipping address default", err);
216
+ }
217
+ }
218
+ }
219
+ __decorateClass([
220
+ Reactionary({
221
+ inputSchema: CompanyQueryByIdSchema,
222
+ outputSchema: CompanySchema
223
+ })
224
+ ], MedusaCompanyCapability.prototype, "getById", 1);
225
+ __decorateClass([
226
+ Reactionary({
227
+ inputSchema: CompanyQueryListSchema,
228
+ outputSchema: CompanyPaginatedListSchema
229
+ })
230
+ ], MedusaCompanyCapability.prototype, "listCompanies", 1);
231
+ __decorateClass([
232
+ Reactionary({
233
+ inputSchema: CompanyMutationAddShippingAddressSchema,
234
+ outputSchema: CompanySchema
235
+ })
236
+ ], MedusaCompanyCapability.prototype, "addShippingAddress", 1);
237
+ __decorateClass([
238
+ Reactionary({
239
+ inputSchema: CompanyMutationUpdateShippingAddressSchema,
240
+ outputSchema: CompanySchema
241
+ })
242
+ ], MedusaCompanyCapability.prototype, "updateShippingAddress", 1);
243
+ __decorateClass([
244
+ Reactionary({
245
+ inputSchema: CompanyMutationRemoveShippingAddressSchema,
246
+ outputSchema: CompanySchema
247
+ })
248
+ ], MedusaCompanyCapability.prototype, "removeShippingAddress", 1);
249
+ __decorateClass([
250
+ Reactionary({
251
+ inputSchema: CompanyMutationMakeShippingAddressDefaultSchema,
252
+ outputSchema: CompanySchema
253
+ })
254
+ ], MedusaCompanyCapability.prototype, "makeShippingAddressDefault", 1);
255
+ export {
256
+ MedusaCompanyCapability
257
+ };
@@ -0,0 +1,221 @@
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) __defProp(target, key, result);
9
+ return result;
10
+ };
11
+ import { FetchError } from "@medusajs/js-sdk";
12
+ import {
13
+ EmployeeInvitationCapability,
14
+ EmployeeInvitationMutationAcceptInvitationSchema,
15
+ EmployeeInvitationMutationInviteEmployeeSchema,
16
+ EmployeeInvitationMutationRevokeInvitationSchema,
17
+ EmployeeInvitationSchema,
18
+ EmployeeInvitationPaginatedListSchema,
19
+ EmployeeInvitationQueryListSchema,
20
+ EmployeeIssuedInvitationSchema,
21
+ Reactionary,
22
+ error,
23
+ success
24
+ } from "@reactionary/core";
25
+ import createDebug from "debug";
26
+ import {
27
+ parseInvitationKey
28
+ } from "../factories/employee-invitation/employee-invitation.factory.js";
29
+ import { handleProviderError } from "../utils/medusa-helpers.js";
30
+ const debug = createDebug("reactionary:medusa:employee-invitation");
31
+ const EMPLOYEE_INVITATION_FIELDS = [
32
+ "id",
33
+ "email",
34
+ "role",
35
+ "status",
36
+ "company_id",
37
+ "company.tax_identifier",
38
+ "accepted_at",
39
+ "validUntil"
40
+ ].join(",");
41
+ class MedusaEmployeeInvitationCapability extends EmployeeInvitationCapability {
42
+ constructor(config, cache, context, medusaApi, factory) {
43
+ super(cache, context);
44
+ this.medusaApi = medusaApi;
45
+ this.config = config;
46
+ this.factory = factory;
47
+ }
48
+ medusaApi;
49
+ config;
50
+ factory;
51
+ // company.taxIdentifier is the real, caller-chosen business tax id - not the Medusa-internal company
52
+ // id the REST API is keyed by - so it has to be resolved to that id before it can be used in a path.
53
+ async resolveCompanyId(taxIdentifier) {
54
+ const client = await this.medusaApi.getClient();
55
+ try {
56
+ const response = await client.client.fetch(
57
+ `/store/companies/by-tax-identifier/${encodeURIComponent(taxIdentifier)}`,
58
+ { method: "GET" }
59
+ );
60
+ return response.company.id;
61
+ } catch (err) {
62
+ if (err instanceof FetchError && err.status === 404) {
63
+ return null;
64
+ }
65
+ throw err;
66
+ }
67
+ }
68
+ // The accept-invitation route returns the raw workflow result rather than a query.graph response, so
69
+ // it never includes the nested `company` relation (only the `company_id` scalar column) - this is
70
+ // used to look the company back up by that id, purely to read its real tax_identifier.
71
+ async fetchCompany(companyId) {
72
+ const client = await this.medusaApi.getClient();
73
+ try {
74
+ const response = await client.client.fetch(
75
+ `/store/companies/${companyId}`,
76
+ { method: "GET", query: { fields: "tax_identifier" } }
77
+ );
78
+ return response.company;
79
+ } catch (err) {
80
+ if (err instanceof FetchError && err.status === 404) {
81
+ return null;
82
+ }
83
+ throw err;
84
+ }
85
+ }
86
+ async inviteEmployee(payload) {
87
+ debug("inviteEmployee", payload);
88
+ try {
89
+ const companyId = await this.resolveCompanyId(payload.company.taxIdentifier);
90
+ if (!companyId) {
91
+ return error({ type: "NotFound", identifier: payload.company });
92
+ }
93
+ const client = await this.medusaApi.getClient();
94
+ const response = await client.client.fetch(`/store/companies/${companyId}/employee-invitations`, {
95
+ method: "POST",
96
+ body: {
97
+ email: payload.email,
98
+ role: this.factory.mapRole(payload.role)
99
+ },
100
+ query: { fields: EMPLOYEE_INVITATION_FIELDS }
101
+ });
102
+ return success(
103
+ this.factory.parseEmployeeIssuedInvitation(
104
+ this.context,
105
+ response.employee_invitation,
106
+ payload
107
+ )
108
+ );
109
+ } catch (err) {
110
+ handleProviderError("invite employee", err);
111
+ }
112
+ }
113
+ async acceptInvitation(payload) {
114
+ debug("acceptInvitation", { invitationIdentifier: payload.invitationIdentifier });
115
+ try {
116
+ const { invitationId } = parseInvitationKey(payload.invitationIdentifier.key);
117
+ const client = await this.medusaApi.getClient();
118
+ const response = await client.client.fetch(`/store/employee-invitations/${invitationId}/accept`, {
119
+ method: "POST",
120
+ body: { securityToken: payload.securityToken }
121
+ });
122
+ const company = await this.fetchCompany(response.employee_invitation.company_id);
123
+ return success(
124
+ this.factory.parseEmployeeInvitation(this.context, {
125
+ ...response.employee_invitation,
126
+ company: company ?? void 0
127
+ })
128
+ );
129
+ } catch (err) {
130
+ handleProviderError("accept invitation", err);
131
+ }
132
+ }
133
+ async revokeInvitation(payload) {
134
+ debug("revokeInvitation", payload);
135
+ try {
136
+ const { companyId, invitationId } = parseInvitationKey(
137
+ payload.invitationIdentifier.key
138
+ );
139
+ const client = await this.medusaApi.getClient();
140
+ await client.client.fetch(
141
+ `/store/companies/${companyId}/employee-invitations/${invitationId}`,
142
+ { method: "DELETE" }
143
+ );
144
+ return success(void 0);
145
+ } catch (err) {
146
+ handleProviderError("revoke invitation", err);
147
+ }
148
+ }
149
+ async listInvitations(payload) {
150
+ debug("listInvitations", payload);
151
+ try {
152
+ const client = await this.medusaApi.getClient();
153
+ const { pageNumber, pageSize } = payload.search.paginationOptions;
154
+ let response;
155
+ if (payload.search.company) {
156
+ const companyId = await this.resolveCompanyId(payload.search.company.taxIdentifier);
157
+ if (!companyId) {
158
+ return error({ type: "NotFound", identifier: payload.search.company });
159
+ }
160
+ response = await client.client.fetch(
161
+ `/store/companies/${companyId}/employee-invitations`,
162
+ {
163
+ method: "GET",
164
+ query: {
165
+ fields: EMPLOYEE_INVITATION_FIELDS,
166
+ email: payload.search.email,
167
+ limit: pageSize,
168
+ offset: (pageNumber - 1) * pageSize
169
+ }
170
+ }
171
+ );
172
+ } else if (payload.search.email) {
173
+ response = await client.client.fetch("/store/employee-invitations", {
174
+ method: "GET",
175
+ query: {
176
+ fields: EMPLOYEE_INVITATION_FIELDS,
177
+ limit: pageSize,
178
+ offset: (pageNumber - 1) * pageSize
179
+ }
180
+ });
181
+ } else {
182
+ response = { employee_invitations: [], count: 0 };
183
+ }
184
+ return success(
185
+ this.factory.parseEmployeeInvitationPaginatedList(
186
+ this.context,
187
+ { items: response.employee_invitations, totalCount: response.count },
188
+ payload
189
+ )
190
+ );
191
+ } catch (err) {
192
+ handleProviderError("list invitations", err);
193
+ }
194
+ }
195
+ }
196
+ __decorateClass([
197
+ Reactionary({
198
+ inputSchema: EmployeeInvitationMutationInviteEmployeeSchema,
199
+ outputSchema: EmployeeIssuedInvitationSchema
200
+ })
201
+ ], MedusaEmployeeInvitationCapability.prototype, "inviteEmployee", 1);
202
+ __decorateClass([
203
+ Reactionary({
204
+ inputSchema: EmployeeInvitationMutationAcceptInvitationSchema,
205
+ outputSchema: EmployeeInvitationSchema
206
+ })
207
+ ], MedusaEmployeeInvitationCapability.prototype, "acceptInvitation", 1);
208
+ __decorateClass([
209
+ Reactionary({
210
+ inputSchema: EmployeeInvitationMutationRevokeInvitationSchema
211
+ })
212
+ ], MedusaEmployeeInvitationCapability.prototype, "revokeInvitation", 1);
213
+ __decorateClass([
214
+ Reactionary({
215
+ inputSchema: EmployeeInvitationQueryListSchema,
216
+ outputSchema: EmployeeInvitationPaginatedListSchema
217
+ })
218
+ ], MedusaEmployeeInvitationCapability.prototype, "listInvitations", 1);
219
+ export {
220
+ MedusaEmployeeInvitationCapability
221
+ };