@kiva/kv-shop 1.3.2 → 1.4.1

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 (56) hide show
  1. package/dist/basket.cjs +44 -15
  2. package/dist/basket.d.ts +4 -4
  3. package/dist/basket.js +5 -8
  4. package/dist/basketCredits.cjs +197 -0
  5. package/dist/basketCredits.d.ts +18 -0
  6. package/dist/basketCredits.js +12 -0
  7. package/dist/basketItems.cjs +70 -33
  8. package/dist/basketItems.d.ts +11 -1
  9. package/dist/basketItems.js +5 -3
  10. package/dist/basketTotals.cjs +228 -0
  11. package/dist/basketTotals.d.ts +37 -0
  12. package/dist/basketTotals.js +12 -0
  13. package/dist/basketVerification.cjs +41 -0
  14. package/dist/basketVerification.d.ts +10 -0
  15. package/dist/basketVerification.js +8 -0
  16. package/dist/checkoutStatus.cjs +110 -0
  17. package/dist/checkoutStatus.d.ts +20 -0
  18. package/dist/checkoutStatus.js +10 -0
  19. package/dist/{chunk-B7RLQXI6.js → chunk-2NC7LGGO.js} +14 -12
  20. package/dist/{chunk-IYCMZ5WV.js → chunk-4ODZGLWK.js} +21 -0
  21. package/dist/chunk-AI6E33YE.js +33 -0
  22. package/dist/chunk-CBJJUUVR.js +121 -0
  23. package/dist/chunk-DZGZX4F6.js +45 -0
  24. package/dist/chunk-EJ5NGYPO.js +145 -0
  25. package/dist/chunk-FCAOCO7O.js +17 -0
  26. package/dist/chunk-JBQ2KNMP.js +50 -0
  27. package/dist/{chunk-SLMBU6L7.js → chunk-JXQPCEKG.js} +9 -2
  28. package/dist/{chunk-TIASV6B2.js → chunk-KV4SOUVF.js} +1 -1
  29. package/dist/chunk-LZ4UMRCV.js +16 -0
  30. package/dist/chunk-MRCBNXPS.js +35 -0
  31. package/dist/chunk-PC4WUPYU.js +78 -0
  32. package/dist/chunk-TPJPGUO7.js +12 -0
  33. package/dist/components/KvPaymentSelect.vue +8 -1
  34. package/dist/index.cjs +489 -56
  35. package/dist/index.d.ts +12 -5
  36. package/dist/index.js +55 -21
  37. package/dist/oneTimeCheckout.cjs +396 -9
  38. package/dist/oneTimeCheckout.d.ts +11 -10
  39. package/dist/oneTimeCheckout.js +10 -5
  40. package/dist/shopError.cjs +21 -0
  41. package/dist/shopError.d.ts +2 -0
  42. package/dist/shopError.js +1 -1
  43. package/dist/shopQueries.cjs +248 -0
  44. package/dist/shopQueries.d.ts +8 -0
  45. package/dist/shopQueries.js +13 -0
  46. package/dist/subscriptionCheckout.cjs +21 -0
  47. package/dist/subscriptionCheckout.js +2 -2
  48. package/dist/useBraintreeDropIn.cjs +29 -1
  49. package/dist/useBraintreeDropIn.d.ts +9 -9
  50. package/dist/useBraintreeDropIn.js +2 -2
  51. package/dist/validatePreCheckout.cjs +210 -0
  52. package/dist/validatePreCheckout.d.ts +22 -0
  53. package/dist/validatePreCheckout.js +13 -0
  54. package/package.json +3 -3
  55. package/dist/chunk-M4CJOCIQ.js +0 -26
  56. package/dist/chunk-NC7RAUNV.js +0 -66
@@ -0,0 +1,121 @@
1
+ import {
2
+ createBasket,
3
+ getBasketID,
4
+ hasBasketExpired
5
+ } from "./chunk-2NC7LGGO.js";
6
+ import {
7
+ parseShopError
8
+ } from "./chunk-4ODZGLWK.js";
9
+
10
+ // src/shopQueries.ts
11
+ var watchQueries = /* @__PURE__ */ new Set();
12
+ async function callShopMutation(apollo, options, maxretries = 2) {
13
+ try {
14
+ const result = await apollo.mutate({
15
+ ...options,
16
+ variables: {
17
+ ...options.variables,
18
+ basketId: getBasketID()
19
+ },
20
+ refetchQueries: options.awaitRefetchQueries ? Array.from(watchQueries) : []
21
+ });
22
+ if (result?.errors?.length) {
23
+ const basketErrors = result?.errors.filter((err) => hasBasketExpired(err));
24
+ if (basketErrors.length) {
25
+ if (maxretries > 0) {
26
+ await createBasket(apollo);
27
+ return callShopMutation(apollo, options, maxretries - 1);
28
+ }
29
+ throw basketErrors[0];
30
+ }
31
+ if (result?.errors?.length) {
32
+ throw result.errors[0];
33
+ }
34
+ }
35
+ return result?.data;
36
+ } catch (e) {
37
+ throw parseShopError(e);
38
+ }
39
+ }
40
+ async function callShopQuery(apollo, options, maxretries = 2) {
41
+ try {
42
+ const result = await apollo.query({
43
+ ...options,
44
+ variables: {
45
+ ...options.variables,
46
+ basketId: getBasketID()
47
+ }
48
+ });
49
+ if (result?.errors?.length) {
50
+ const basketErrors = result?.errors.filter((err) => hasBasketExpired(err));
51
+ if (basketErrors.length) {
52
+ if (maxretries > 0) {
53
+ await createBasket(apollo);
54
+ return callShopQuery(apollo, options, maxretries - 1);
55
+ }
56
+ throw basketErrors[0];
57
+ }
58
+ if (result?.errors?.length) {
59
+ throw result.errors[0];
60
+ }
61
+ }
62
+ return result?.data;
63
+ } catch (e) {
64
+ throw parseShopError(e);
65
+ }
66
+ }
67
+ function watchShopQuery(apollo, options, maxretries = 2) {
68
+ let retries = 0;
69
+ watchQueries.add(options.query);
70
+ const observable = apollo.watchQuery({
71
+ ...options,
72
+ variables: {
73
+ ...options.variables,
74
+ basketId: getBasketID()
75
+ }
76
+ });
77
+ const oldSubscribe = observable.subscribe.bind(observable);
78
+ observable.subscribe = (...args) => {
79
+ let nextFn;
80
+ let errorFn;
81
+ let completeFn;
82
+ if (typeof args[0] === "function") {
83
+ [nextFn, errorFn, completeFn] = args;
84
+ } else {
85
+ nextFn = args[0]?.next;
86
+ errorFn = args[0]?.error;
87
+ completeFn = args[0]?.complete;
88
+ }
89
+ const newErrorFn = (err) => {
90
+ const basketErrors = err?.graphQLErrors?.filter((e) => hasBasketExpired(e));
91
+ if (basketErrors.length) {
92
+ if (retries < maxretries) {
93
+ createBasket(apollo).then(() => {
94
+ retries += 1;
95
+ observable.refetch({
96
+ ...observable.variables,
97
+ basketId: getBasketID()
98
+ });
99
+ });
100
+ } else {
101
+ errorFn(parseShopError(basketErrors[0]));
102
+ }
103
+ } else {
104
+ if (err?.graphQLErrors?.length) {
105
+ errorFn(parseShopError(err.graphQLErrors[0]));
106
+ }
107
+ if (err?.networkError) {
108
+ errorFn(parseShopError(err.networkError));
109
+ }
110
+ }
111
+ };
112
+ return oldSubscribe(nextFn, newErrorFn, completeFn);
113
+ };
114
+ return observable;
115
+ }
116
+
117
+ export {
118
+ callShopMutation,
119
+ callShopQuery,
120
+ watchShopQuery
121
+ };
@@ -0,0 +1,45 @@
1
+ import {
2
+ watchShopQuery
3
+ } from "./chunk-CBJJUUVR.js";
4
+
5
+ // src/basketTotals.ts
6
+ import { gql } from "@apollo/client/core";
7
+ var basketTotalsQuery = gql`query basketTotals($basketId: String) {
8
+ shop (basketId: $basketId) {
9
+ id
10
+ basket {
11
+ id
12
+ totals {
13
+ bonusAppliedTotal
14
+ bonusAvailableTotal
15
+ creditAmountNeeded
16
+ creditAppliedTotal
17
+ creditAvailableTotal
18
+ donationTotal
19
+ itemTotal
20
+ freeTrialAppliedTotal
21
+ freeTrialAvailableTotal
22
+ loanReservationTotal
23
+ kivaCardTotal
24
+ kivaCreditAppliedTotal
25
+ kivaCreditAvailableTotal
26
+ kivaCreditRemaining
27
+ kivaCreditToReapply
28
+ redemptionCodeAppliedTotal
29
+ redemptionCodeAvailableTotal
30
+ universalCodeAppliedTotal
31
+ universalCodeAvailableTotal
32
+ }
33
+ }
34
+ }
35
+ }`;
36
+ function watchBasketTotals(apollo) {
37
+ return watchShopQuery(apollo, {
38
+ query: basketTotalsQuery
39
+ });
40
+ }
41
+
42
+ export {
43
+ basketTotalsQuery,
44
+ watchBasketTotals
45
+ };
@@ -0,0 +1,145 @@
1
+ import {
2
+ validatePreCheckout
3
+ } from "./chunk-JBQ2KNMP.js";
4
+ import {
5
+ callShopMutation,
6
+ callShopQuery
7
+ } from "./chunk-CBJJUUVR.js";
8
+ import {
9
+ ShopError,
10
+ parseShopError
11
+ } from "./chunk-4ODZGLWK.js";
12
+ import {
13
+ pollForFinishedCheckout
14
+ } from "./chunk-PC4WUPYU.js";
15
+ import {
16
+ getVisitorID
17
+ } from "./chunk-TPJPGUO7.js";
18
+
19
+ // src/oneTimeCheckout.ts
20
+ import { gql } from "@apollo/client/core";
21
+ import numeral from "numeral";
22
+ async function creditAmountNeeded(apollo) {
23
+ const data = await callShopQuery(apollo, {
24
+ query: gql`
25
+ query creditAmountNeeded($basketId: String) {
26
+ shop (basketId: $basketId) {
27
+ id
28
+ basket {
29
+ id
30
+ totals {
31
+ creditAmountNeeded
32
+ }
33
+ }
34
+ }
35
+ }
36
+ `
37
+ }, 0);
38
+ return data?.shop?.basket?.totals?.creditAmountNeeded;
39
+ }
40
+ var creditCheckoutMutation = gql`
41
+ mutation creditCheckout(
42
+ $basketId: String,
43
+ $visitorId: String
44
+ ) {
45
+ shop (basketId: $basketId) {
46
+ id
47
+ transactionId: checkoutAsync (visitorId: $visitorId)
48
+ }
49
+ }
50
+ `;
51
+ var depositCheckoutMutation = gql`
52
+ mutation depositCheckout(
53
+ $basketId: String,
54
+ $amount: Money!,
55
+ $nonce: String!,
56
+ $savePaymentMethod: Boolean,
57
+ $deviceData: String,
58
+ $visitorId: String
59
+ ) {
60
+ shop (basketId: $basketId) {
61
+ id
62
+ transactionId: doNoncePaymentDepositAndCheckoutAsync(
63
+ amount: $amount,
64
+ nonce: $nonce,
65
+ savePaymentMethod: $savePaymentMethod,
66
+ deviceData: $deviceData,
67
+ visitorId: $visitorId
68
+ )
69
+ }
70
+ }
71
+ `;
72
+ function creditCheckout(apollo) {
73
+ return callShopMutation(apollo, {
74
+ mutation: creditCheckoutMutation,
75
+ variables: {
76
+ visitorId: getVisitorID()
77
+ }
78
+ }, 0);
79
+ }
80
+ async function depositCheckout({
81
+ apollo,
82
+ braintree,
83
+ amount
84
+ }) {
85
+ try {
86
+ const paymentMethod = await braintree.requestPaymentMethod();
87
+ if (!paymentMethod) {
88
+ throw new ShopError(
89
+ { code: "shop.dropinNoPaymentMethod" },
90
+ "No payment method returned from braintree dropin"
91
+ );
92
+ }
93
+ const { nonce, deviceData } = paymentMethod;
94
+ return callShopMutation(apollo, {
95
+ mutation: depositCheckoutMutation,
96
+ variables: {
97
+ nonce,
98
+ amount,
99
+ savePaymentMethod: false,
100
+ // save payment methods handled by braintree drop in UI
101
+ deviceData,
102
+ visitorId: getVisitorID()
103
+ }
104
+ }, 0);
105
+ } catch (e) {
106
+ throw parseShopError(e);
107
+ }
108
+ }
109
+ async function executeOneTimeCheckout({
110
+ apollo,
111
+ braintree,
112
+ emailAddress,
113
+ emailOptIn
114
+ }) {
115
+ await validatePreCheckout({
116
+ apollo,
117
+ emailAddress,
118
+ emailOptIn
119
+ });
120
+ const creditNeeded = await creditAmountNeeded(apollo);
121
+ const creditRequired = numeral(creditNeeded).value() > 0;
122
+ if (creditRequired && !braintree) {
123
+ throw new ShopError({ code: "shop.dropinRequired" }, "Braintree dropin required for credit deposit checkout");
124
+ }
125
+ const data = creditRequired ? await depositCheckout({
126
+ apollo,
127
+ braintree,
128
+ amount: creditNeeded
129
+ }) : await creditCheckout(apollo);
130
+ const transactionId = data?.shop?.transactionId;
131
+ const result = await pollForFinishedCheckout({
132
+ apollo,
133
+ transactionSagaId: transactionId,
134
+ timeout: 3e5
135
+ // five minutes
136
+ });
137
+ if (result.errors?.length) {
138
+ throw parseShopError(result.errors[0]);
139
+ }
140
+ window.location.href = `/checkout/post-purchase?kiva_transaction_id=${transactionId}`;
141
+ }
142
+
143
+ export {
144
+ executeOneTimeCheckout
145
+ };
@@ -0,0 +1,17 @@
1
+ // src/basketVerification.ts
2
+ var VerificationState = /* @__PURE__ */ ((VerificationState2) => {
3
+ VerificationState2["VERIFIED"] = "verified";
4
+ VerificationState2["PENDING"] = "pending";
5
+ VerificationState2["REQUIRED"] = "required";
6
+ VerificationState2["MAY_BE_NEEDED"] = "may_be_needed";
7
+ VerificationState2["NOT_NEEDED"] = "not_needed";
8
+ return VerificationState2;
9
+ })(VerificationState || {});
10
+ function isBasketVerified(state) {
11
+ return state === "verified" /* VERIFIED */ || state === "not_needed" /* NOT_NEEDED */;
12
+ }
13
+
14
+ export {
15
+ VerificationState,
16
+ isBasketVerified
17
+ };
@@ -0,0 +1,50 @@
1
+ import {
2
+ callShopMutation
3
+ } from "./chunk-CBJJUUVR.js";
4
+ import {
5
+ ShopError,
6
+ parseShopError
7
+ } from "./chunk-4ODZGLWK.js";
8
+ import {
9
+ getVisitorID
10
+ } from "./chunk-TPJPGUO7.js";
11
+
12
+ // src/validatePreCheckout.ts
13
+ import { gql } from "@apollo/client/core";
14
+ var validatePreCheckoutMutation = gql`
15
+ mutation validatePreCheckout($basketId: String, $email: String, $visitorId: String, $emailOptIn: Boolean) {
16
+ shop (basketId: $basketId) {
17
+ id
18
+ validatePreCheckout (email: $email, visitorId: $visitorId, emailOptIn: $emailOptIn) {
19
+ error
20
+ success
21
+ value
22
+ }
23
+ }
24
+ }`;
25
+ async function validatePreCheckout({
26
+ apollo,
27
+ emailAddress,
28
+ emailOptIn
29
+ }) {
30
+ const data = await callShopMutation(apollo, {
31
+ mutation: validatePreCheckoutMutation,
32
+ variables: {
33
+ visitorId: getVisitorID(),
34
+ email: emailAddress,
35
+ emailOptIn
36
+ }
37
+ }, 0);
38
+ const results = data?.shop?.validatePreCheckout;
39
+ const errors = results.filter(({ success }) => !success).map((result) => parseShopError(result));
40
+ if (errors.length) {
41
+ const aggregate = new ShopError({ code: "shop.failedCheckoutValidation" });
42
+ aggregate.aggregateErrors(errors);
43
+ throw aggregate;
44
+ }
45
+ }
46
+
47
+ export {
48
+ validatePreCheckoutMutation,
49
+ validatePreCheckout
50
+ };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ShopError,
3
3
  parseShopError
4
- } from "./chunk-IYCMZ5WV.js";
4
+ } from "./chunk-4ODZGLWK.js";
5
5
 
6
6
  // src/useBraintreeDropIn.ts
7
7
  import { gql } from "@apollo/client/core";
@@ -22,7 +22,7 @@ async function getClientToken(apollo) {
22
22
  }
23
23
  return data?.shop?.getClientToken;
24
24
  }
25
- function useBraintreeDropIn() {
25
+ function initBraintreeDropin() {
26
26
  let instance;
27
27
  let formattedAmount = "";
28
28
  const paymentMethodRequestable = ref(false);
@@ -152,6 +152,13 @@ function useBraintreeDropIn() {
152
152
  updateAmount
153
153
  };
154
154
  }
155
+ var instances = {};
156
+ function useBraintreeDropIn(key = "default") {
157
+ if (!instances[key]) {
158
+ instances[key] = initBraintreeDropin();
159
+ }
160
+ return instances[key];
161
+ }
155
162
 
156
163
  export {
157
164
  defaultPaymentTypes,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ShopError,
3
3
  parseShopError
4
- } from "./chunk-IYCMZ5WV.js";
4
+ } from "./chunk-4ODZGLWK.js";
5
5
 
6
6
  // src/subscriptionCheckout.ts
7
7
  import { gql } from "@apollo/client/core";
@@ -0,0 +1,16 @@
1
+ // src/util/cookie.ts
2
+ var getCookieValue = (name) => {
3
+ if (typeof document !== void 0) {
4
+ return decodeURIComponent(document.cookie.match(`(^|;)\\s*${name}\\s*=\\s*([^;]+)`)?.pop() || "");
5
+ }
6
+ };
7
+ var setCookieValue = (name, value, options = "") => {
8
+ if (typeof document !== void 0) {
9
+ document.cookie = `${name}=${encodeURIComponent(value)};${options}`;
10
+ }
11
+ };
12
+
13
+ export {
14
+ getCookieValue,
15
+ setCookieValue
16
+ };
@@ -0,0 +1,35 @@
1
+ import {
2
+ callShopMutation
3
+ } from "./chunk-CBJJUUVR.js";
4
+
5
+ // src/basketCredits.ts
6
+ import { gql } from "@apollo/client/core";
7
+ async function applyKivaCredit(apollo) {
8
+ const data = await callShopMutation(apollo, {
9
+ awaitRefetchQueries: true,
10
+ mutation: gql`mutation applyKivaCredit($basketId: String) {
11
+ shop (basketId: $basketId) {
12
+ id
13
+ addCreditByType(creditType: kiva_credit)
14
+ }
15
+ }`
16
+ });
17
+ return !!data?.shop?.addCreditByType;
18
+ }
19
+ async function removeKivaCredit(apollo) {
20
+ const data = await callShopMutation(apollo, {
21
+ awaitRefetchQueries: true,
22
+ mutation: gql`mutation removeKivaCredit($basketId: String) {
23
+ shop (basketId: $basketId) {
24
+ id
25
+ removeCreditByType(creditType: kiva_credit)
26
+ }
27
+ }`
28
+ });
29
+ return !!data?.shop?.removeCreditByType;
30
+ }
31
+
32
+ export {
33
+ applyKivaCredit,
34
+ removeKivaCredit
35
+ };
@@ -0,0 +1,78 @@
1
+ import {
2
+ getVisitorID
3
+ } from "./chunk-TPJPGUO7.js";
4
+
5
+ // src/checkoutStatus.ts
6
+ import { gql } from "@apollo/client/core";
7
+
8
+ // src/util/poll.ts
9
+ function wait(ms) {
10
+ return new Promise((resolve) => setTimeout(resolve, ms));
11
+ }
12
+ async function poll(fn, fnCondition, interval, timeout) {
13
+ const endTime = Date.now() + timeout;
14
+ let result = await fn();
15
+ while (!fnCondition(result)) {
16
+ if (Date.now() > endTime) {
17
+ throw new Error("Polling timed out");
18
+ }
19
+ await wait(interval);
20
+ result = await fn();
21
+ }
22
+ return result;
23
+ }
24
+
25
+ // src/checkoutStatus.ts
26
+ async function getCheckoutStatus({ apollo, transactionSagaId }) {
27
+ return apollo.query({
28
+ query: gql`
29
+ query checkoutStatus($transactionId: String!, $visitorId: String) {
30
+ checkoutStatus(transactionId: $transactionId, visitorId: $visitorId) {
31
+ basketId
32
+ errorCode
33
+ errorMessage
34
+ receipt {
35
+ checkoutId
36
+ }
37
+ requestedAt
38
+ status
39
+ transactionId
40
+ updatedAt
41
+ }
42
+ }
43
+ `,
44
+ variables: {
45
+ transactionId: transactionSagaId,
46
+ visitorId: getVisitorID()
47
+ }
48
+ });
49
+ }
50
+ async function pollForFinishedCheckout({
51
+ apollo,
52
+ transactionSagaId,
53
+ interval = 1e3,
54
+ timeout = 6e4
55
+ }) {
56
+ return poll(
57
+ // function to poll
58
+ () => getCheckoutStatus({
59
+ apollo,
60
+ transactionSagaId
61
+ }),
62
+ // function to check for completed status
63
+ (result) => {
64
+ const { status, errorCode, errorMessage } = result?.data?.checkoutStatus;
65
+ if (status === "COMPLETED" || errorCode || errorMessage) {
66
+ return true;
67
+ }
68
+ return false;
69
+ },
70
+ interval,
71
+ timeout
72
+ );
73
+ }
74
+
75
+ export {
76
+ getCheckoutStatus,
77
+ pollForFinishedCheckout
78
+ };
@@ -0,0 +1,12 @@
1
+ import {
2
+ getCookieValue
3
+ } from "./chunk-LZ4UMRCV.js";
4
+
5
+ // src/util/visitorId.ts
6
+ function getVisitorID() {
7
+ return getCookieValue("uiv");
8
+ }
9
+
10
+ export {
11
+ getVisitorID
12
+ };
@@ -40,6 +40,13 @@ export default defineComponent({
40
40
  type: String,
41
41
  required: true,
42
42
  },
43
+ /**
44
+ * Braintree Drop In instance name.
45
+ */
46
+ dropInName: {
47
+ type: String,
48
+ default: 'default',
49
+ },
43
50
  /**
44
51
  * Paypal flow options.
45
52
  * Must be 'checkout' or 'vault'
@@ -92,7 +99,7 @@ export default defineComponent({
92
99
  paymentMethodRequestable,
93
100
  requestPaymentMethod,
94
101
  updateAmount,
95
- } = useBraintreeDropIn();
102
+ } = useBraintreeDropIn(props.dropInName);
96
103
 
97
104
  const errorToast = ref();
98
105
  const showError = (message: string) => {