Skip to content

Commit a3197be

Browse files
committed
✨ Introducing CrystallizeCustomerManager
1 parent 4768860 commit a3197be

File tree

8 files changed

+157
-46
lines changed

8 files changed

+157
-46
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@crystallize/js-api-client",
33
"license": "MIT",
4-
"version": "1.0.3",
4+
"version": "1.1.0",
55
"author": "Crystallize <[email protected]> (https://crystallize.com)",
66
"contributors": [
77
"Sébastien Morel <[email protected]>"

src/core/customer.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { jsonToGraphQLQuery } from 'json-to-graphql-query';
2+
import {
3+
createCustomerInputRequest,
4+
CreateCustomerInputRequest,
5+
updateCustomerInputRequest,
6+
UpdateCustomerInputRequest,
7+
} from '../types/customer';
8+
import { ClientInterface } from './client';
9+
10+
export function createCustomerManager(apiClient: ClientInterface) {
11+
const create = async (intentCustomer: CreateCustomerInputRequest, extraResultQuery?: any): Promise<any> => {
12+
const intent = createCustomerInputRequest.parse(intentCustomer);
13+
const api = apiClient.pimApi;
14+
15+
const mutation = {
16+
mutation: {
17+
customer: {
18+
create: {
19+
__args: {
20+
input: {
21+
...intent,
22+
tenantId: apiClient.config.tenantId || intent.tenantId || '',
23+
},
24+
},
25+
identifier: true,
26+
...(extraResultQuery !== undefined ? extraResultQuery : {}),
27+
},
28+
},
29+
},
30+
};
31+
const confirmation = await api(jsonToGraphQLQuery(mutation));
32+
return confirmation.customer.create;
33+
};
34+
35+
const update = async (
36+
identifier: string,
37+
intentCustomer: UpdateCustomerInputRequest,
38+
extraResultQuery?: any,
39+
): Promise<any> => {
40+
const intent = updateCustomerInputRequest.parse(intentCustomer);
41+
const api = apiClient.pimApi;
42+
43+
const mutation = {
44+
mutation: {
45+
customer: {
46+
update: {
47+
__args: {
48+
identifier,
49+
input: intent,
50+
tenantId: apiClient.config.tenantId || '',
51+
},
52+
identifier: true,
53+
...(extraResultQuery !== undefined ? extraResultQuery : {}),
54+
},
55+
},
56+
},
57+
};
58+
const confirmation = await api(jsonToGraphQLQuery(mutation));
59+
return confirmation.customer.update;
60+
};
61+
return {
62+
create,
63+
update,
64+
};
65+
}

src/core/subscription.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export function createSubscriptionContractManager(apiClient: ClientInterface) {
3838
status: {
3939
...intent.status,
4040
renewAt: intent.status.renewAt.toISOString(),
41-
activeUntil: intent.status.renewAt.toISOString(),
41+
activeUntil: intent.status.activeUntil.toISOString(),
4242
},
4343
},
4444
},
@@ -72,7 +72,7 @@ export function createSubscriptionContractManager(apiClient: ClientInterface) {
7272
},
7373
},
7474
id: true,
75-
createdAt: true,
75+
updatedAt: true,
7676
...(extraResultQuery !== undefined ? extraResultQuery : {}),
7777
},
7878
},

src/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@ export * from './core/catalogue';
55
export * from './core/order';
66
export * from './core/search';
77
export * from './core/subscription';
8+
export * from './core/customer';
89
export * from './types/product';
910
export * from './types/order';
1011
export * from './types/payment';
1112
export * from './types/components';
1213
export * from './types/search';
1314
export * from './types/subscription';
15+
export * from './types/address';
16+
export * from './types/customer';
1417

1518
import { createClient } from './core/client';
1619
import { createNavigationFetcher } from './core/navigation';
@@ -20,6 +23,7 @@ import { createOrderPusher, createOrderPaymentUpdater, createOrderFetcher } from
2023
import { createCatalogueFetcher } from './core/catalogue';
2124
import { createSearcher } from './core/search';
2225
import { createSubscriptionContractManager } from './core/subscription';
26+
import { createCustomerManager } from './core/customer';
2327

2428
export const CrystallizeClient = createClient({
2529
tenantId: globalThis?.process?.env?.CRYSTALLIZE_TENANT_ID ?? '',
@@ -47,3 +51,4 @@ export const CrystallizeOrderFetcherById = orderFetcher.byId;
4751
export const CrystallizeOrderFetcherByCustomerIdentifier = orderFetcher.byCustomerIdentifier;
4852

4953
export const CrystallizeSubscriptionContractManager = createSubscriptionContractManager(CrystallizeClient);
54+
export const CrystallizeCustomerManager = createCustomerManager(CrystallizeClient);

src/types/address.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { z } from 'zod';
2+
import { EnumType } from 'json-to-graphql-query';
3+
4+
export const addressInputRequest = z
5+
.object({
6+
type: z.enum(['delivery', 'billing', 'other']).transform((val) => new EnumType(val)),
7+
firstName: z.string().optional(),
8+
middleName: z.string().optional(),
9+
lastName: z.string().optional(),
10+
street: z.string().optional(),
11+
street2: z.string().optional(),
12+
streetNumber: z.string().optional(),
13+
postalCode: z.string().optional(),
14+
city: z.string().optional(),
15+
state: z.string().optional(),
16+
country: z.string().optional(),
17+
phone: z.string().optional(),
18+
email: z.string().optional(),
19+
})
20+
.strict();
21+
export type AddressInputRequest = z.infer<typeof addressInputRequest>;
22+
23+
export type Address = AddressInputRequest;

src/types/customer.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { z } from 'zod';
2+
import { Address, addressInputRequest } from './address';
3+
4+
export const orderCustomerInputRequest = z
5+
.object({
6+
identifier: z.string().optional(),
7+
firstName: z.string().optional(),
8+
middleName: z.string().optional(),
9+
lastName: z.string().optional(),
10+
birthDate: z.date().optional(),
11+
companyName: z.string().optional(),
12+
taxNumber: z.string().optional(),
13+
addresses: z.array(addressInputRequest).optional(),
14+
})
15+
.strict();
16+
export type OrderCustomerInputRequest = z.infer<typeof orderCustomerInputRequest>;
17+
18+
export type OrderCustomer = Omit<OrderCustomerInputRequest, 'addresses'> & {
19+
addresses: Address[];
20+
};
21+
22+
export const createCustomerInputRequest = orderCustomerInputRequest
23+
.extend({
24+
tenantId: z.string().optional(),
25+
lastName: z.string(),
26+
firstName: z.string(),
27+
phone: z.string().optional(),
28+
meta: z
29+
.array(
30+
z.object({
31+
key: z.string(),
32+
value: z.string().optional(),
33+
}),
34+
)
35+
.optional(),
36+
identifier: z.string().optional(),
37+
externalReferences: z
38+
.array(
39+
z.object({
40+
key: z.string(),
41+
value: z.string().optional(),
42+
}),
43+
)
44+
.optional(),
45+
email: z.string(),
46+
})
47+
.strict();
48+
export type CreateCustomerInputRequest = z.infer<typeof createCustomerInputRequest>;
49+
50+
export const updateCustomerInputRequest = createCustomerInputRequest.omit({ identifier: true, tenantId: true });
51+
export type UpdateCustomerInputRequest = z.infer<typeof updateCustomerInputRequest>;
52+
53+
export type Customer = Omit<CreateCustomerInputRequest, 'addresses'> & {
54+
addresses: Address[];
55+
};

src/types/order.ts

Lines changed: 4 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { EnumType } from 'json-to-graphql-query';
22
import { z } from 'zod';
3+
import { OrderCustomer, orderCustomerInputRequest } from './customer';
34
import {
45
CashPayment,
56
cashPaymentInputRequest,
@@ -81,39 +82,6 @@ export const orderItemInputRequest = z
8182
.strict();
8283
export type OrderItemInputRequest = z.infer<typeof orderItemInputRequest>;
8384

84-
export const addressInputRequest = z
85-
.object({
86-
type: z.enum(['delivery', 'billing', 'other']).transform((val) => new EnumType(val)),
87-
firstName: z.string().optional(),
88-
middleName: z.string().optional(),
89-
lastName: z.string().optional(),
90-
street: z.string().optional(),
91-
street2: z.string().optional(),
92-
streetNumber: z.string().optional(),
93-
postalCode: z.string().optional(),
94-
city: z.string().optional(),
95-
state: z.string().optional(),
96-
country: z.string().optional(),
97-
phone: z.string().optional(),
98-
email: z.string().optional(),
99-
})
100-
.strict();
101-
export type AddressInputRequest = z.infer<typeof addressInputRequest>;
102-
103-
export const customerInputRequest = z
104-
.object({
105-
identifier: z.string().optional(),
106-
firstName: z.string().optional(),
107-
middleName: z.string().optional(),
108-
lastName: z.string().optional(),
109-
birthDate: z.date().optional(),
110-
companyName: z.string().optional(),
111-
taxNumber: z.string().optional(),
112-
addresses: z.array(addressInputRequest).optional(),
113-
})
114-
.strict();
115-
export type CustomerInputRequest = z.infer<typeof customerInputRequest>;
116-
11785
export const paymentInputRequest = z
11886
.object({
11987
provider: paymentProvider,
@@ -128,7 +96,7 @@ export type PaymentInputRequest = z.infer<typeof paymentInputRequest>;
12896

12997
export const updateOrderInputRequest = z
13098
.object({
131-
customer: customerInputRequest.optional(),
99+
customer: orderCustomerInputRequest.optional(),
132100
cart: z.array(orderItemInputRequest).optional(),
133101
payment: z.array(paymentInputRequest).optional(),
134102
total: priceInputRequest.optional(),
@@ -140,7 +108,7 @@ export type UpdateOrderInputRequest = z.infer<typeof updateOrderInputRequest>;
140108

141109
export const createOrderInputRequest = updateOrderInputRequest
142110
.extend({
143-
customer: customerInputRequest,
111+
customer: orderCustomerInputRequest,
144112
cart: z.array(orderItemInputRequest),
145113
createdAt: z.date().optional(),
146114
})
@@ -162,7 +130,7 @@ export interface Order {
162130
createdAt: Date;
163131
updatedAt: Date;
164132
cart: OrderItem[];
165-
customer: Customer;
133+
customer: OrderCustomer;
166134
payment?: Payment[];
167135
total?: Price;
168136
additionnalInformation?: string;
@@ -182,12 +150,6 @@ export interface OrderItem {
182150
subTotal?: Price;
183151
meta?: OrderMetadata[];
184152
}
185-
export type Address = AddressInputRequest;
186-
187-
export type Customer = Omit<CustomerInputRequest, 'addresses'> & {
188-
addresses: Address[];
189-
};
190-
191153
export type Payment = KlarnaPayment | PaypalPayment | StripePayment | CashPayment | CustomPayment;
192154

193155
export interface Price {

src/types/subscription.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { z } from 'zod';
22
import { EnumType } from 'json-to-graphql-query';
3-
import { addressInputRequest, paymentInputRequest } from './order';
3+
import { paymentInputRequest } from './order';
4+
import { addressInputRequest } from './address';
45

56
export const subscriptionContractMetadataInputRequest = z
67
.object({

0 commit comments

Comments
 (0)