1 | |
2 |
|
3 | |
4 | * Create Customer |
5 | * Create a customer. Needs at least an email, a phone (E.164, e.g. +33612345678) or a name. The optional address becomes the default address. email_marketing records email marketing consent (single opt-in). |
6 | */ |
7 | export async function main( |
8 | auth: RT.Shopify, |
9 | email: string | undefined, |
10 | phone: string | undefined, |
11 | first_name: string | undefined, |
12 | last_name: string | undefined, |
13 | tags: string[] | undefined, |
14 | note: string | undefined, |
15 | address: |
16 | | { |
17 | firstName?: string |
18 | lastName?: string |
19 | company?: string |
20 | address1?: string |
21 | address2?: string |
22 | city?: string |
23 | provinceCode?: string |
24 | zip?: string |
25 | countryCode?: string |
26 | phone?: string |
27 | } |
28 | | undefined, |
29 | email_marketing: "SUBSCRIBED" | "NOT_SUBSCRIBED" | undefined |
30 | ) { |
31 | const endpoint = `https://${auth.store_name}.myshopify.com/admin/api/2026-10/graphql.json` |
32 | const call = async (body: { query: string; variables?: object }) => { |
33 | const response = await fetch(endpoint, { |
34 | method: "POST", |
35 | headers: { |
36 | "X-Shopify-Access-Token": auth.token, |
37 | "Content-Type": "application/json", |
38 | Accept: "application/json", |
39 | }, |
40 | body: JSON.stringify(body), |
41 | }) |
42 | if (!response.ok) { |
43 | throw new Error(`${response.status} ${await response.text()}`) |
44 | } |
45 | const { data, errors } = await response.json() |
46 | if (errors) { |
47 | throw new Error(JSON.stringify(errors)) |
48 | } |
49 | return data |
50 | } |
51 |
|
52 | const data = await call({ |
53 | query: `mutation ($input: CustomerInput!) { customerCreate(input: $input) { customer { id } userErrors { field message } } }`, |
54 | variables: { |
55 | input: { |
56 | email: email || undefined, |
57 | phone: phone || undefined, |
58 | firstName: first_name || undefined, |
59 | lastName: last_name || undefined, |
60 | tags: tags?.length ? tags : undefined, |
61 | note: note || undefined, |
62 | emailMarketingConsent: |
63 | email && email_marketing |
64 | ? { |
65 | marketingState: email_marketing, |
66 | marketingOptInLevel: "SINGLE_OPT_IN", |
67 | } |
68 | : undefined, |
69 | }, |
70 | }, |
71 | }) |
72 | if (data.customerCreate.userErrors.length) { |
73 | throw new Error(JSON.stringify(data.customerCreate.userErrors)) |
74 | } |
75 | const id = data.customerCreate.customer.id |
76 |
|
77 | |
78 | if (address && Object.keys(address).length) { |
79 | const added = await call({ |
80 | query: `mutation ($customerId: ID!, $address: MailingAddressInput!) { customerAddressCreate(customerId: $customerId, address: $address, setAsDefault: true) { address { id } userErrors { field message } } }`, |
81 | variables: { customerId: id, address }, |
82 | }) |
83 | if (added.customerAddressCreate.userErrors.length) { |
84 | throw new Error(JSON.stringify(added.customerAddressCreate.userErrors)) |
85 | } |
86 | } |
87 |
|
88 | return ( |
89 | await call({ |
90 | query: `query ($id: ID!) { customer(id: $id) { id legacyResourceId displayName firstName lastName state tags note locale verifiedEmail taxExempt numberOfOrders amountSpent { amount currencyCode } createdAt updatedAt defaultEmailAddress { emailAddress marketingState marketingOptInLevel } defaultPhoneNumber { phoneNumber } defaultAddress { name firstName lastName company address1 address2 city provinceCode zip countryCodeV2 phone } } }`, |
91 | variables: { id }, |
92 | }) |
93 | ).customer |
94 | } |
95 |
|