diff --git a/.gitignore b/.gitignore index 0a6a5cda8..7723be302 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,7 @@ secrets.json .nvmrc # VSCode settings -.vscode \ No newline at end of file +.vscode + +#Emacs +*~ \ No newline at end of file diff --git a/src/checkout-resource.js b/src/checkout-resource.js index 878dd5ab0..f0d0c37e5 100644 --- a/src/checkout-resource.js +++ b/src/checkout-resource.js @@ -5,6 +5,7 @@ import handleCheckoutMutation from './handle-checkout-mutation'; // GraphQL import checkoutNodeQuery from './graphql/checkoutNodeQuery.graphql'; import checkoutCreateMutation from './graphql/checkoutCreateMutation.graphql'; +import checkoutCustomerAssociateV2 from './graphql/checkoutCustomerAssociateV2.graphql'; import checkoutLineItemsAddMutation from './graphql/checkoutLineItemsAddMutation.graphql'; import checkoutLineItemsRemoveMutation from './graphql/checkoutLineItemsRemoveMutation.graphql'; import checkoutLineItemsReplaceMutation from './graphql/checkoutLineItemsReplaceMutation.graphql'; @@ -16,6 +17,7 @@ import checkoutGiftCardsAppendMutation from './graphql/checkoutGiftCardsAppendMu import checkoutGiftCardRemoveV2Mutation from './graphql/checkoutGiftCardRemoveV2Mutation.graphql'; import checkoutEmailUpdateV2Mutation from './graphql/checkoutEmailUpdateV2Mutation.graphql'; import checkoutShippingAddressUpdateV2Mutation from './graphql/checkoutShippingAddressUpdateV2Mutation.graphql'; +import checkoutShippingLineUpdateMutation from './graphql/checkoutShippingLineUpdateMutation.graphql'; /** * The JS Buy SDK checkout resource @@ -78,6 +80,12 @@ class CheckoutResource extends Resource { .then(handleCheckoutMutation('checkoutCreate', this.graphQLClient)); } + associateCustomer(checkoutId, customerAccessToken) { + return this.graphQLClient + .send(checkoutCustomerAssociateV2, {checkoutId, customerAccessToken}) + .then(handleCheckoutMutation('checkoutCustomerAssociateV2', this.graphQLClient)); + } + /** * Replaces the value of checkout's custom attributes and/or note with values defined in the input * @@ -326,6 +334,20 @@ class CheckoutResource extends Resource { .send(checkoutShippingAddressUpdateV2Mutation, {checkoutId, shippingAddress}) .then(handleCheckoutMutation('checkoutShippingAddressUpdateV2', this.graphQLClient)); } + + /** + * Updates the shipping lines on an existing checkout. + * + * @param {String} checkoutId The ID of the checkout to update shipping address. + * @param {Object} shippingRateHandle A unique identifier to a Checkout’s shipping provide + * @return {Promise|GraphModel} A promise resolving with the updated checkout. + */ + updateShippingLineAddress(checkoutId, shippingRateHandle) { + return this.graphQLClient + .send(checkoutShippingLineUpdateMutation, {checkoutId, shippingRateHandle}) + .then(handleCheckoutMutation('checkoutShippingLineUpdate', this.graphQLClient)); + } + } export default CheckoutResource; diff --git a/src/client.js b/src/client.js index 1bd350913..85d04f850 100644 --- a/src/client.js +++ b/src/client.js @@ -4,6 +4,7 @@ import ProductResource from './product-resource'; import CollectionResource from './collection-resource'; import ShopResource from './shop-resource'; import CheckoutResource from './checkout-resource'; +import CustomerResource from './customer-resource'; import ImageResource from './image-resource'; import {version} from '../package.json'; @@ -80,6 +81,7 @@ class Client { this.collection = new CollectionResource(this.graphQLClient); this.shop = new ShopResource(this.graphQLClient); this.checkout = new CheckoutResource(this.graphQLClient); + this.customer = new CustomerResource(this.graphQLClient); this.image = new ImageResource(this.graphQLClient); } diff --git a/src/customer-resource.js b/src/customer-resource.js new file mode 100644 index 000000000..b5321af54 --- /dev/null +++ b/src/customer-resource.js @@ -0,0 +1,206 @@ +import Resource from './resource'; +import defaultResolver from './default-resolver'; +import handleCustomerMutation from './handle-customer-mutation'; + +// GraphQL +import customerNodeQuery from './graphql/customerNodeQuery.graphql'; + +import customerCreateMutation from './graphql/customerCreateMutation.graphql'; + +import customerAccessTokenCreateMutation from './graphql/customerAccessTokenCreateMutation.graphql'; +import customerAccessTokenCreateWithMultipassMutation from './graphql/customerAccessTokenCreateWithMultipassMutation.graphql'; +import customerAccessTokenDeleteMutation from './graphql/customerAccessTokenDeleteMutation.graphql'; +import customerAccessTokenRenewMutation from './graphql/customerAccessTokenRenewMutation.graphql'; + +import customerActivateByUrlMutation from './graphql/customerActivateByUrlMutation.graphql'; +import customerActivateMutation from './graphql/customerActivateMutation.graphql'; + +import customerAddressCreateMutation from './graphql/customerAddressCreateMutation.graphql'; +import customerAddressDeleteMutation from './graphql/customerAddressDeleteMutation.graphql'; +import customerAddressUpdateMutation from './graphql/customerAddressUpdateMutation.graphql'; + +import customerDefaultAddressUpdateMutation from './graphql/customerDefaultAddressUpdateMutation.graphql'; +import customerRecoverMutation from './graphql/customerRecoverMutation.graphql'; +import customerResetByUrlMutation from './graphql/customerResetByUrlMutation.graphql'; +import customerResetMutation from './graphql/customerResetMutation.graphql'; + +import customerUpdateMutation from './graphql/customerUpdateMutation.graphql'; + +/** + * The JS Buy SDK customer resource + * @class + */ +class CustomerResource extends Resource { + fetch(customerAccessToken) { + return this.graphQLClient + .send(customerNodeQuery, {customerAccessToken}) + .then(defaultResolver('customer')) + } + + /** + * Creates a customer. + * + * @example + * const input = { + * email: "isamu@to-kyo.to", + * password: "HiZqFuDvDdQ7" + * }; + * + * client.customer.create(input).then((customer) => { + * // Do something with the newly created customer + * }); + * + * @param {Object} [input] An input object containing of: + * @param {String} [input.email] The customer’s email + * @param {String} [input.password] The login password used by the customer. + * @return {Promise|GraphModel} A promise resolving with the created customer. + */ + create(input) { + return this.graphQLClient + .send(customerCreateMutation, {input}) + .then(handleCustomerMutation('customerCreate')); + } + + /** + * Update a customer. + * + */ + update(customerAccessToken, customer) { + return this.graphQLClient + .send(customerUpdateMutation, {customerAccessToken, customer}) + .then(handleCustomerMutation('customerUpdate')); + } + + /** + * Create a access token. + * + */ + createAccessToken(input) { + return this.graphQLClient + .send(customerAccessTokenCreateMutation, {input}) + .then(handleCustomerMutation('customerAccessTokenCreate')); + } + + /** + * Delete a access token. + * + */ + deleteAccessToken(customerAccessToken) { + return this.graphQLClient + .send(customerAccessTokenDeleteMutation, {customerAccessToken}) + .then(handleCustomerMutation('customerAccessTokenDelete')); + } + + /** + * Renew a access token. + * + */ + renewAccessToken(customerAccessToken) { + return this.graphQLClient + .send(customerAccessTokenRenewMutation, {customerAccessToken}) + .then(handleCustomerMutation('customerAccessTokenRenew')); + } + + /** + * Create a access token with Multipass. + * + */ + createAccessTokenWithMultipass(multipassToken) { + return this.graphQLClient + .send(customerAccessTokenCreateWithMultipassMutation, {multipassToken}) + .then(handleCustomerMutation('customerAccessTokenCreateWithMultipass')); + } + + /** + * Activate customer account. + * + */ + activate(id, input) { + return this.graphQLClient + .send(customerActivateMutation, {id, input}) + .then(handleCustomerMutation('customerActivate')); + } + + /** + * Activate customer account by URL. + * + */ + activateByUrl(activationUrl, password) { + return this.graphQLClient + .send(customerActivateByUrlMutation, {activationUrl, password}) + .then(handleCustomerMutation('customerActivateByUrl')); + } + + /** + * Create customer's address. + * + */ + createAddress(customerAccessToken, address) { + return this.graphQLClient + .send(customerAddressCreateMutation, {customerAccessToken, address}) + .then(handleCustomerMutation('customerAddressCreate')); + } + + /** + * Delete customer's address. + * + */ + deleteAddress(id, customerAccessToken) { + return this.graphQLClient + .send(customerAddressDeleteMutation, {id, customerAccessToken}) + .then(handleCustomerMutation('customerAddressDelete')); + } + + /** + * Update customer's address. + * + */ + updateAddress(customerAccessToken, id, address) { + return this.graphQLClient + .send(customerAddressUpdateMutation, {customerAccessToken, id, address}) + .then(handleCustomerMutation('customerAddressUpdate')); + } + + /** + * Update customer's default address. + * + */ + updateDefaultAddress(customerAccessToken, addressId) { + return this.graphQLClient + .send(customerDefaultAddressUpdateMutation, {customerAccessToken, addressId}) + .then(handleCustomerMutation('customerDefaultAddressUpdate')); + } + + /** + * Recover customer. + * + */ + recover(email) { + return this.graphQLClient + .send(customerRecoverMutation, {email}) + .then(handleCustomerMutation('customerRecover')); + } + + /** + * Reset customer password. + * + */ + reset(id, input) { + return this.graphQLClient + .send(customerResetMutation, {id, input}) + .then(handleCustomerMutation('customerReset')); + } + + /** + * Reset customer password by Url. + * + */ + resetByUrl(resetUrl, password) { + return this.graphQLClient + .send(customerResetByUrlMutation, {resetUrl, password}) + .then(handleCustomerMutation('customerResetByUrl')); + } + +} + +export default CustomerResource; diff --git a/src/graphql/checkoutCustomerAssociateV2.graphql b/src/graphql/checkoutCustomerAssociateV2.graphql new file mode 100644 index 000000000..eb8a65439 --- /dev/null +++ b/src/graphql/checkoutCustomerAssociateV2.graphql @@ -0,0 +1,18 @@ +mutation checkoutCustomerAssociateV2($checkoutId: ID!, $customerAccessToken: String!) { + checkoutCustomerAssociateV2( + checkoutId: $checkoutId + customerAccessToken: $customerAccessToken + ) { + checkout { + id + } + checkoutUserErrors { + code + field + message + } + customer { + id + } + } +} diff --git a/src/graphql/checkoutShippingLineUpdateMutation.graphql b/src/graphql/checkoutShippingLineUpdateMutation.graphql new file mode 100644 index 000000000..fe6009c95 --- /dev/null +++ b/src/graphql/checkoutShippingLineUpdateMutation.graphql @@ -0,0 +1,15 @@ +mutation checkoutShippingLineUpdate($checkoutId: ID!, $shippingRateHandle: String!) { + checkoutShippingLineUpdate( + checkoutId: $checkoutId + shippingRateHandle: $shippingRateHandle + ) { + checkout { + id + } + checkoutUserErrors { + code + field + message + } + } +} \ No newline at end of file diff --git a/src/graphql/customerAccessTokenCreateMutation.graphql b/src/graphql/customerAccessTokenCreateMutation.graphql new file mode 100644 index 000000000..6ac0a7bc1 --- /dev/null +++ b/src/graphql/customerAccessTokenCreateMutation.graphql @@ -0,0 +1,13 @@ +mutation customerAccessTokenCreate($input: CustomerAccessTokenCreateInput!) { + customerAccessTokenCreate(input: $input) { + customerAccessToken { + accessToken + expiresAt + } + customerUserErrors { + code + field + message + } + } +} \ No newline at end of file diff --git a/src/graphql/customerAccessTokenCreateWithMultipassMutation.graphql b/src/graphql/customerAccessTokenCreateWithMultipassMutation.graphql new file mode 100644 index 000000000..d8b6b3d2c --- /dev/null +++ b/src/graphql/customerAccessTokenCreateWithMultipassMutation.graphql @@ -0,0 +1,13 @@ +mutation customerAccessTokenCreateWithMultipass($multipassToken: String!) { + customerAccessTokenCreateWithMultipass(multipassToken: $multipassToken) { + customerAccessToken { + accessToken + expiresAt + } + customerUserErrors { + code + field + message + } + } +} \ No newline at end of file diff --git a/src/graphql/customerAccessTokenDeleteMutation.graphql b/src/graphql/customerAccessTokenDeleteMutation.graphql new file mode 100644 index 000000000..aa0db5fe8 --- /dev/null +++ b/src/graphql/customerAccessTokenDeleteMutation.graphql @@ -0,0 +1,10 @@ +mutation customerAccessTokenDelete($customerAccessToken: String!) { + customerAccessTokenDelete(customerAccessToken: $customerAccessToken) { + deletedAccessToken + deletedCustomerAccessTokenId + userErrors { + field + message + } + } +} \ No newline at end of file diff --git a/src/graphql/customerAccessTokenRenewMutation.graphql b/src/graphql/customerAccessTokenRenewMutation.graphql new file mode 100644 index 000000000..6115070db --- /dev/null +++ b/src/graphql/customerAccessTokenRenewMutation.graphql @@ -0,0 +1,12 @@ +mutation customerAccessTokenRenew($customerAccessToken: String!) { + customerAccessTokenRenew(customerAccessToken: $customerAccessToken) { + customerAccessToken { + accessToken + expiresAt + } + userErrors { + field + message + } + } +} \ No newline at end of file diff --git a/src/graphql/customerActivateByUrlMutation.graphql b/src/graphql/customerActivateByUrlMutation.graphql new file mode 100644 index 000000000..870c562a8 --- /dev/null +++ b/src/graphql/customerActivateByUrlMutation.graphql @@ -0,0 +1,16 @@ +mutation customerActivateByUrl($activationUrl: URL!, $password: String!) { + customerActivateByUrl(activationUrl: $activationUrl, password: $password) { + customer { + id + } + customerAccessToken { + accessToken + expiresAt + } + customerUserErrors { + code + field + message + } + } +} \ No newline at end of file diff --git a/src/graphql/customerActivateMutation.graphql b/src/graphql/customerActivateMutation.graphql new file mode 100644 index 000000000..5421ba2b9 --- /dev/null +++ b/src/graphql/customerActivateMutation.graphql @@ -0,0 +1,16 @@ +mutation customerActivate($id: ID!, $input: CustomerActivateInput!) { + customerActivate(id: $id, input: $input) { + customer { + id + } + customerAccessToken { + accessToken + expiresAt + } + customerUserErrors { + code + field + message + } + } +} \ No newline at end of file diff --git a/src/graphql/customerAddressCreateMutation.graphql b/src/graphql/customerAddressCreateMutation.graphql new file mode 100644 index 000000000..bd9a48be5 --- /dev/null +++ b/src/graphql/customerAddressCreateMutation.graphql @@ -0,0 +1,15 @@ +mutation customerAddressCreate($customerAccessToken: String!, $address: MailingAddressInput!) { + customerAddressCreate( + customerAccessToken: $customerAccessToken + address: $address + ) { + customerAddress { + id + } + customerUserErrors { + code + field + message + } + } +} diff --git a/src/graphql/customerAddressDeleteMutation.graphql b/src/graphql/customerAddressDeleteMutation.graphql new file mode 100644 index 000000000..915f6ad52 --- /dev/null +++ b/src/graphql/customerAddressDeleteMutation.graphql @@ -0,0 +1,10 @@ +mutation customerAddressDelete($id: ID!, $customerAccessToken: String!) { + customerAddressDelete(id: $id, customerAccessToken: $customerAccessToken) { + customerUserErrors { + code + field + message + } + deletedCustomerAddressId + } +} \ No newline at end of file diff --git a/src/graphql/customerAddressUpdateMutation.graphql b/src/graphql/customerAddressUpdateMutation.graphql new file mode 100644 index 000000000..a80e7a477 --- /dev/null +++ b/src/graphql/customerAddressUpdateMutation.graphql @@ -0,0 +1,16 @@ +mutation customerAddressUpdate($customerAccessToken: String!, $id: ID!, $address: MailingAddressInput!) { + customerAddressUpdate( + customerAccessToken: $customerAccessToken + id: $id + address: $address + ) { + customerAddress { + id + } + customerUserErrors { + code + field + message + } + } +} \ No newline at end of file diff --git a/src/graphql/customerCreateMutation.graphql b/src/graphql/customerCreateMutation.graphql new file mode 100644 index 000000000..c928a4d13 --- /dev/null +++ b/src/graphql/customerCreateMutation.graphql @@ -0,0 +1,12 @@ +mutation customerCreate($input: CustomerCreateInput!) { + customerCreate(input: $input) { + customer { + id + } + customerUserErrors { + code + field + message + } + } +} diff --git a/src/graphql/customerDefaultAddressUpdateMutation.graphql b/src/graphql/customerDefaultAddressUpdateMutation.graphql new file mode 100644 index 000000000..9939c90d0 --- /dev/null +++ b/src/graphql/customerDefaultAddressUpdateMutation.graphql @@ -0,0 +1,15 @@ +mutation customerDefaultAddressUpdate($customerAccessToken: String!, $addressId: ID!) { + customerDefaultAddressUpdate( + customerAccessToken: $customerAccessToken + addressId: $addressId + ) { + customer { + id + } + customerUserErrors { + code + field + message + } + } +} \ No newline at end of file diff --git a/src/graphql/customerNodeQuery.graphql b/src/graphql/customerNodeQuery.graphql new file mode 100644 index 000000000..d4f09d7ce --- /dev/null +++ b/src/graphql/customerNodeQuery.graphql @@ -0,0 +1,8 @@ +query($customerAccessToken: String!) { + customer(customerAccessToken: $customerAccessToken) { + id + firstName + lastName + tags + } +} diff --git a/src/graphql/customerRecoverMutation.graphql b/src/graphql/customerRecoverMutation.graphql new file mode 100644 index 000000000..5e7d6c480 --- /dev/null +++ b/src/graphql/customerRecoverMutation.graphql @@ -0,0 +1,9 @@ +mutation customerRecover($email: String!) { + customerRecover(email: $email) { + customerUserErrors { + code + field + message + } + } +} diff --git a/src/graphql/customerResetByUrlMutation.graphql b/src/graphql/customerResetByUrlMutation.graphql new file mode 100644 index 000000000..0c4d37443 --- /dev/null +++ b/src/graphql/customerResetByUrlMutation.graphql @@ -0,0 +1,16 @@ +mutation customerResetByUrl($resetUrl: URL!, $password: String!) { + customerResetByUrl(resetUrl: $resetUrl, password: $password) { + customer { + id + } + customerAccessToken { + accessToken + expiresAt + } + customerUserErrors { + code + field + message + } + } +} \ No newline at end of file diff --git a/src/graphql/customerResetMutation.graphql b/src/graphql/customerResetMutation.graphql new file mode 100644 index 000000000..3b1d4d248 --- /dev/null +++ b/src/graphql/customerResetMutation.graphql @@ -0,0 +1,16 @@ +mutation customerReset($id: ID!, $input: CustomerResetInput!) { + customerReset(id: $id, input: $input) { + customer { + id + } + customerAccessToken { + accessToken + expiresAt + } + customerUserErrors { + code + field + message + } + } +} \ No newline at end of file diff --git a/src/graphql/customerUpdateMutation.graphql b/src/graphql/customerUpdateMutation.graphql new file mode 100644 index 000000000..af4332f69 --- /dev/null +++ b/src/graphql/customerUpdateMutation.graphql @@ -0,0 +1,16 @@ +mutation customerUpdate($customerAccessToken: String!, $customer: CustomerUpdateInput!) { + customerUpdate(customerAccessToken: $customerAccessToken, customer: $customer) { + customer { + id + } + customerAccessToken { + accessToken + expiresAt + } + customerUserErrors { + code + field + message + } + } +} \ No newline at end of file diff --git a/src/handle-customer-mutation.js b/src/handle-customer-mutation.js new file mode 100644 index 000000000..5cb390ede --- /dev/null +++ b/src/handle-customer-mutation.js @@ -0,0 +1,27 @@ +export default function handleCustomerMutation(mutationRootKey) { + return function({data = {}, errors}) { + try { + const rootData = data[mutationRootKey]; + + if (errors && errors.length) { + return Promise.reject(new Error(JSON.stringify(errors))); + } + + if (rootData && rootData.customerUserErrors && rootData.customerUserErrors.length) { + return Promise.reject(new Error(JSON.stringify(rootData.customerUserErrors))); + } + + if (rootData && rootData.userErrors && rootData.userErrors.length) { + return Promise.reject(new Error(JSON.stringify(rootData.userErrors))); + } + + if (rootData) { + return rootData; + } + + return Promise.reject(new Error(`The ${mutationRootKey} mutation failed due to an unknown error.`)); + } catch (_) { + return Promise.reject(new Error(`The ${mutationRootKey} mutation failed due to an unknown error.`)); + } + }; +}