@duffel/components 3.0.0-canary → 3.0.0

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 (164) hide show
  1. package/.eslintrc.js +14 -1
  2. package/.github/workflows/release.yml +4 -1
  3. package/.storybook/__snapshots__/Storyshots.test.js.snap +185 -0
  4. package/CONTRIBUTING.md +83 -0
  5. package/README.md +34 -109
  6. package/config/esbuild.base.config.js +7 -3
  7. package/config/esbuild.cdn.config.js +4 -3
  8. package/config/esbuild.dev.config.js +4 -3
  9. package/config/esbuild.react.config.js +3 -3
  10. package/package.json +16 -5
  11. package/react-dist/components/{Card.d.ts → DuffelAncillaries/Card.d.ts} +1 -1
  12. package/react-dist/components/{DuffelAncillaries.d.ts → DuffelAncillaries/DuffelAncillaries.d.ts} +1 -1
  13. package/react-dist/components/{DuffelAncillariesCustomElement.d.ts → DuffelAncillaries/DuffelAncillariesCustomElement.d.ts} +1 -1
  14. package/react-dist/components/{bags → DuffelAncillaries/bags}/BaggageSelectionCard.d.ts +2 -2
  15. package/react-dist/components/{bags → DuffelAncillaries/bags}/BaggageSelectionController.d.ts +2 -2
  16. package/react-dist/components/{bags → DuffelAncillaries/bags}/BaggageSelectionModal.d.ts +2 -2
  17. package/react-dist/components/{bags → DuffelAncillaries/bags}/BaggageSelectionModalBody.d.ts +2 -2
  18. package/react-dist/components/{bags → DuffelAncillaries/bags}/BaggageSelectionModalBodyPassenger.d.ts +2 -2
  19. package/react-dist/components/{bags → DuffelAncillaries/bags}/BaggageSelectionModalFooter.d.ts +1 -1
  20. package/react-dist/components/{bags → DuffelAncillaries/bags}/BaggageSelectionModalHeader.d.ts +1 -1
  21. package/react-dist/components/{bags → DuffelAncillaries/bags}/IncludedBaggageBanner.d.ts +1 -1
  22. package/react-dist/components/{cancel_for_any_reason → DuffelAncillaries/cancel_for_any_reason}/CfarSelectionCard.d.ts +2 -2
  23. package/react-dist/components/{cancel_for_any_reason → DuffelAncillaries/cancel_for_any_reason}/CfarSelectionModal.d.ts +2 -2
  24. package/react-dist/components/{cancel_for_any_reason → DuffelAncillaries/cancel_for_any_reason}/CfarSelectionModalBody.d.ts +1 -1
  25. package/react-dist/components/{cancel_for_any_reason → DuffelAncillaries/cancel_for_any_reason}/CfarSelectionModalFooter.d.ts +2 -2
  26. package/react-dist/components/{seats → DuffelAncillaries/seats}/Amenity.d.ts +1 -1
  27. package/react-dist/components/{seats → DuffelAncillaries/seats}/Element.d.ts +2 -2
  28. package/react-dist/components/{seats → DuffelAncillaries/seats}/Legend.d.ts +1 -1
  29. package/react-dist/components/{seats → DuffelAncillaries/seats}/Row.d.ts +2 -2
  30. package/react-dist/components/{seats → DuffelAncillaries/seats}/RowSection.d.ts +2 -2
  31. package/react-dist/components/{seats → DuffelAncillaries/seats}/SeatElement.d.ts +2 -2
  32. package/react-dist/components/{seats → DuffelAncillaries/seats}/SeatInfo.d.ts +1 -1
  33. package/react-dist/components/{seats → DuffelAncillaries/seats}/SeatMap.d.ts +2 -2
  34. package/react-dist/components/{seats → DuffelAncillaries/seats}/SeatSelectionCard.d.ts +3 -3
  35. package/react-dist/components/{seats → DuffelAncillaries/seats}/SeatSelectionModal.d.ts +3 -3
  36. package/react-dist/components/{seats → DuffelAncillaries/seats}/SeatSelectionModalFooter.d.ts +2 -2
  37. package/react-dist/components/{seats → DuffelAncillaries/seats}/SeatSelectionModalHeader.d.ts +1 -1
  38. package/react-dist/components/{seats → DuffelAncillaries/seats}/SeatUnavailable.d.ts +1 -1
  39. package/react-dist/components/DuffelPayments/DuffelPayments.d.ts +11 -0
  40. package/react-dist/components/DuffelPayments/DuffelPaymentsCustomElement.d.ts +14 -0
  41. package/react-dist/components/{Button.d.ts → shared/Button.d.ts} +2 -2
  42. package/react-dist/components/{ErrorBoundary.d.ts → shared/ErrorBoundary.d.ts} +1 -1
  43. package/react-dist/components/{IconButton.d.ts → shared/IconButton.d.ts} +1 -1
  44. package/react-dist/components/{NonIdealState.d.ts → shared/NonIdealState.d.ts} +1 -1
  45. package/react-dist/custom-elements.d.ts +6 -0
  46. package/react-dist/custom-elements.js +37 -0
  47. package/react-dist/custom-elements.js.map +7 -0
  48. package/react-dist/index.d.ts +4 -5
  49. package/react-dist/index.js +21 -20
  50. package/react-dist/index.js.map +4 -4
  51. package/react-dist/lib/captureErrorInSentry.d.ts +1 -1
  52. package/react-dist/lib/fetchFromDuffelAPI.d.ts +7 -0
  53. package/react-dist/lib/logging.d.ts +7 -14
  54. package/react-dist/lib/retrieveSeatMaps.d.ts +1 -1
  55. package/react-dist/types/DuffelAncillariesProps.d.ts +1 -1
  56. package/scripts/generate-fixture.ts +13 -8
  57. package/scripts/upload-to-cdn.sh +4 -9
  58. package/src/components/{Card.tsx → DuffelAncillaries/Card.tsx} +1 -1
  59. package/src/components/{Counter.tsx → DuffelAncillaries/Counter.tsx} +1 -1
  60. package/src/components/{DuffelAncillaries.tsx → DuffelAncillaries/DuffelAncillaries.tsx} +61 -63
  61. package/src/components/{DuffelAncillariesCustomElement.tsx → DuffelAncillaries/DuffelAncillariesCustomElement.tsx} +2 -2
  62. package/src/components/{bags → DuffelAncillaries/bags}/BaggageSelectionCard.tsx +4 -4
  63. package/src/components/{bags → DuffelAncillaries/bags}/BaggageSelectionController.tsx +2 -2
  64. package/src/components/{bags → DuffelAncillaries/bags}/BaggageSelectionModal.tsx +3 -3
  65. package/src/components/{bags → DuffelAncillaries/bags}/BaggageSelectionModalBody.tsx +3 -3
  66. package/src/components/{bags → DuffelAncillaries/bags}/BaggageSelectionModalBodyPassenger.tsx +2 -2
  67. package/src/components/{bags → DuffelAncillaries/bags}/BaggageSelectionModalFooter.tsx +2 -2
  68. package/src/components/{bags → DuffelAncillaries/bags}/BaggageSelectionModalHeader.tsx +1 -1
  69. package/src/components/{bags → DuffelAncillaries/bags}/IncludedBaggageBanner.tsx +1 -1
  70. package/src/components/{cancel_for_any_reason → DuffelAncillaries/cancel_for_any_reason}/CfarSelectionCard.tsx +4 -4
  71. package/src/components/{cancel_for_any_reason → DuffelAncillaries/cancel_for_any_reason}/CfarSelectionModal.tsx +3 -3
  72. package/src/components/{cancel_for_any_reason → DuffelAncillaries/cancel_for_any_reason}/CfarSelectionModalBody.tsx +3 -3
  73. package/src/components/{cancel_for_any_reason → DuffelAncillaries/cancel_for_any_reason}/CfarSelectionModalBodyListItem.tsx +1 -1
  74. package/src/components/{cancel_for_any_reason → DuffelAncillaries/cancel_for_any_reason}/CfarSelectionModalFooter.tsx +4 -4
  75. package/src/components/{seats → DuffelAncillaries/seats}/Amenity.tsx +2 -2
  76. package/src/components/{seats → DuffelAncillaries/seats}/DeckSelect.tsx +1 -1
  77. package/src/components/{seats → DuffelAncillaries/seats}/Element.tsx +2 -2
  78. package/src/components/{seats → DuffelAncillaries/seats}/ExitElement.tsx +1 -1
  79. package/src/components/{seats → DuffelAncillaries/seats}/Legend.tsx +2 -2
  80. package/src/components/{seats → DuffelAncillaries/seats}/Row.tsx +2 -2
  81. package/src/components/{seats → DuffelAncillaries/seats}/RowSection.tsx +5 -2
  82. package/src/components/{seats → DuffelAncillaries/seats}/SeatElement.tsx +3 -3
  83. package/src/components/{seats → DuffelAncillaries/seats}/SeatInfo.tsx +1 -1
  84. package/src/components/{seats → DuffelAncillaries/seats}/SeatMap.tsx +2 -2
  85. package/src/components/{seats → DuffelAncillaries/seats}/SeatMapUnavailable.tsx +1 -1
  86. package/src/components/{seats → DuffelAncillaries/seats}/SeatSelectionCard.tsx +5 -5
  87. package/src/components/{seats → DuffelAncillaries/seats}/SeatSelectionModal.tsx +4 -4
  88. package/src/components/{seats → DuffelAncillaries/seats}/SeatSelectionModalBody.tsx +1 -1
  89. package/src/components/{seats → DuffelAncillaries/seats}/SeatSelectionModalFooter.tsx +3 -3
  90. package/src/components/{seats → DuffelAncillaries/seats}/SeatSelectionModalHeader.tsx +1 -1
  91. package/src/components/{seats → DuffelAncillaries/seats}/SeatUnavailable.tsx +2 -2
  92. package/src/components/DuffelPayments/DuffelPayments.tsx +218 -0
  93. package/src/components/DuffelPayments/DuffelPaymentsCustomElement.tsx +130 -0
  94. package/src/components/{Button.tsx → shared/Button.tsx} +4 -3
  95. package/src/components/{ErrorBoundary.tsx → shared/ErrorBoundary.tsx} +2 -2
  96. package/src/components/{Icon.tsx → shared/Icon.tsx} +2 -1
  97. package/src/components/{IconButton.tsx → shared/IconButton.tsx} +1 -1
  98. package/src/components/{Modal.tsx → shared/Modal.tsx} +5 -1
  99. package/src/components/{NonIdealState.tsx → shared/NonIdealState.tsx} +1 -1
  100. package/src/custom-elements.ts +13 -0
  101. package/src/examples/client-side/README.md +30 -0
  102. package/src/examples/client-side/index.html +1 -1
  103. package/src/examples/full-stack/README.md +34 -0
  104. package/src/examples/full-stack/index.html +1 -1
  105. package/src/examples/full-stack/server.mjs +1 -0
  106. package/src/examples/just-typescript/src/index.html +2 -2
  107. package/src/examples/just-typescript/src/index.ts +2 -1
  108. package/src/examples/payments-custom-element/README.md +17 -0
  109. package/src/examples/payments-custom-element/index.html +43 -0
  110. package/src/examples/payments-just-typescript/README.md +37 -0
  111. package/src/examples/payments-just-typescript/package.json +16 -0
  112. package/src/examples/payments-just-typescript/src/index.html +23 -0
  113. package/src/examples/payments-just-typescript/src/index.ts +18 -0
  114. package/src/examples/payments-just-typescript/yarn.lock +154 -0
  115. package/src/examples/react-app/src/index.tsx +11 -6
  116. package/src/index.ts +4 -5
  117. package/src/lib/captureErrorInSentry.ts +2 -20
  118. package/src/lib/fetchFromDuffelAPI.ts +36 -6
  119. package/src/lib/formatDate.ts +3 -4
  120. package/src/lib/getBaggageServiceDescription.ts +2 -4
  121. package/src/lib/getTotalAmountForServices.ts +1 -1
  122. package/src/lib/logging.ts +52 -32
  123. package/src/lib/retrieveOffer.ts +11 -6
  124. package/src/lib/retrieveSeatMaps.ts +13 -8
  125. package/src/stories/BaggageSelectionModalHeader.stories.tsx +1 -1
  126. package/src/stories/Button.stories.tsx +12 -3
  127. package/src/stories/DuffelAncillaries.stories.tsx +1 -1
  128. package/src/stories/DuffelPayments.stories.tsx +34 -0
  129. package/src/stories/Icon.stories.tsx +3 -2
  130. package/src/stories/IconButton.stories.tsx +1 -1
  131. package/src/styles/components/DuffelPayments.css +42 -0
  132. package/src/styles/components/Modal.css +2 -1
  133. package/src/styles/global.css +1 -0
  134. package/src/tests/components/DuffelAncillaries.test.tsx +1 -1
  135. package/src/tests/lib/createPriceFormatters.test.tsx +1 -1
  136. package/src/tests/lib/formatAvailableServices.test.tsx +1 -1
  137. package/src/tests/lib/formatSeatMaps.test.tsx +2 -2
  138. package/src/tests/lib/getCurrencyForServices.test.tsx +1 -1
  139. package/src/tests/lib/hasServiceOfSameMetadataTypeAlreadyBeenSelected.test.ts +1 -1
  140. package/src/tests/lib/logging.test.tsx +14 -14
  141. package/src/tests/lib/moneyStringFormatter.test.tsx +1 -1
  142. package/src/tests/lib/validateProps.test.tsx +1 -1
  143. package/src/types/DuffelAncillariesProps.ts +1 -1
  144. package/tsconfig.json +1 -1
  145. /package/react-dist/components/{Counter.d.ts → DuffelAncillaries/Counter.d.ts} +0 -0
  146. /package/react-dist/components/{cancel_for_any_reason → DuffelAncillaries/cancel_for_any_reason}/CfarSelectionModalBodyListItem.d.ts +0 -0
  147. /package/react-dist/components/{cancel_for_any_reason → DuffelAncillaries/cancel_for_any_reason}/CfarSelectionModalHeader.d.ts +0 -0
  148. /package/react-dist/components/{seats → DuffelAncillaries/seats}/DeckSelect.d.ts +0 -0
  149. /package/react-dist/components/{seats → DuffelAncillaries/seats}/EmptyElement.d.ts +0 -0
  150. /package/react-dist/components/{seats → DuffelAncillaries/seats}/ExitElement.d.ts +0 -0
  151. /package/react-dist/components/{seats → DuffelAncillaries/seats}/SeatMapUnavailable.d.ts +0 -0
  152. /package/react-dist/components/{seats → DuffelAncillaries/seats}/SeatSelectionModalBody.d.ts +0 -0
  153. /package/react-dist/components/{AnimatedLoaderEllipsis.d.ts → shared/AnimatedLoaderEllipsis.d.ts} +0 -0
  154. /package/react-dist/components/{FetchOfferErrorState.d.ts → shared/FetchOfferErrorState.d.ts} +0 -0
  155. /package/react-dist/components/{Icon.d.ts → shared/Icon.d.ts} +0 -0
  156. /package/react-dist/components/{Modal.d.ts → shared/Modal.d.ts} +0 -0
  157. /package/react-dist/components/{Stamp.d.ts → shared/Stamp.d.ts} +0 -0
  158. /package/react-dist/components/{Tabs.d.ts → shared/Tabs.d.ts} +0 -0
  159. /package/src/components/{cancel_for_any_reason → DuffelAncillaries/cancel_for_any_reason}/CfarSelectionModalHeader.tsx +0 -0
  160. /package/src/components/{seats → DuffelAncillaries/seats}/EmptyElement.tsx +0 -0
  161. /package/src/components/{AnimatedLoaderEllipsis.tsx → shared/AnimatedLoaderEllipsis.tsx} +0 -0
  162. /package/src/components/{FetchOfferErrorState.tsx → shared/FetchOfferErrorState.tsx} +0 -0
  163. /package/src/components/{Stamp.tsx → shared/Stamp.tsx} +0 -0
  164. /package/src/components/{Tabs.tsx → shared/Tabs.tsx} +0 -0
@@ -11,7 +11,7 @@
11
11
  />
12
12
 
13
13
  <!-- 1. This script loads duffel-components -->
14
- <script src="http://localhost:8000/ancillaries/index.js"></script>
14
+ <script src="http://localhost:8000/duffel-ancillaries.js"></script>
15
15
  </head>
16
16
 
17
17
  <body style="font-family: sans-serif">
@@ -154,4 +154,5 @@ http
154
154
  })
155
155
  .listen(6262);
156
156
 
157
+ // eslint-disable-next-line
157
158
  console.log(`\n🐄 Serving example on http://localhost:6262`);
@@ -11,11 +11,11 @@
11
11
  />
12
12
 
13
13
  <script src="../dist/index.js" defer></script>
14
- <title>React app example</title>
14
+ <title>ancillaries component just typescript example</title>
15
15
  </head>
16
16
  <body>
17
17
  <h1 style="margin-bottom: 2rem">
18
- Duffel ancillaries component react-app example
18
+ Duffel ancillaries component just typescript example
19
19
  </h1>
20
20
 
21
21
  <duffel-ancillaries></duffel-ancillaries>
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  onDuffelAncillariesPayloadReady,
3
3
  renderDuffelAncillariesCustomElement,
4
- } from "duffel-components";
4
+ } from "duffel-components/custom-elements";
5
5
 
6
6
  window.onload = () => {
7
7
  renderDuffelAncillariesCustomElement({
@@ -29,6 +29,7 @@ window.onload = () => {
29
29
  ],
30
30
  });
31
31
  onDuffelAncillariesPayloadReady((data, metadata) => {
32
+ /* eslint-disable */
32
33
  console.table(data);
33
34
  console.table(metadata);
34
35
  });
@@ -0,0 +1,17 @@
1
+ # Duffel payments custom element example
2
+
3
+ ## Setup
4
+
5
+ ```sh
6
+ # .env.local
7
+
8
+ # The url for the component CDN.
9
+ # This is used to load both the styles an
10
+ # COMPONENT_CDN=https://assets.duffel.com/components/ancillaries/VERSION # production
11
+ COMPONENT_CDN=http://localhost:8000 # development
12
+ ```
13
+
14
+ ## Run the example
15
+
16
+ 1. Serve the Duffel component bundle and watch for changes to rebuild on port `8000` using `yarn dev`.
17
+ 2. Open `src/examples/payments-custom-element/index.html` on your browser.
@@ -0,0 +1,43 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Payment page example</title>
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <link
7
+ rel="icon"
8
+ type="image/png"
9
+ sizes="96x96"
10
+ href="https://duffel.com/images/favicon/favicon-96x96.png"
11
+ />
12
+
13
+ <!-- 1. This script loads duffel-components -->
14
+ <script src="http://localhost:8000/duffel-payments.js"></script>
15
+ </head>
16
+
17
+ <body style="font-family: sans-serif">
18
+ <h1 style="margin-bottom: 2rem">Payment page example</h1>
19
+
20
+ <!-- 2. Add the custom element to your markup where you want to render the payments card -->
21
+ <duffel-payments></duffel-payments>
22
+ </body>
23
+ <script>
24
+ const duffelpaymentsElement = document.querySelector("duffel-payments");
25
+
26
+ // 3. Render the component with the required data, you can safely call this function as many times as you want.
27
+ duffelpaymentsElement.render({
28
+ paymentIntentClientToken:
29
+ "eyJjbGllbnRfc2VjcmV0IjoicGlfM0psczlVQWcySmhFeTh2WTBSTm1MU0JkX3NlY3JldF9QUW9yZXNuU3laeWJadGRiejZwNzBCbUdPIiwicHVibGlzaGFibGVfa2V5IjoicGtfdGVzdF9EQUJLY0E2Vzh6OTc0cTdPSWY0YmJ2MVQwMEpwRmMyOUpWIn0=",
30
+ debug: true,
31
+ });
32
+
33
+ // 4. Listen to 'onSuccessfulPayment' event on the component:
34
+ duffelpaymentsElement.addEventListener("onSuccessfulPayment", () =>
35
+ console.log("onPayloadReady\n")
36
+ );
37
+
38
+ // 5. If we run into an issue with the payment, you can listen to 'onFailedPayment' event:
39
+ duffelpaymentsElement.addEventListener("onFailedPayment", (event) =>
40
+ console.log("onPayloadReady\n", event.detail)
41
+ );
42
+ </script>
43
+ </html>
@@ -0,0 +1,37 @@
1
+ # payments-just-typescript example
2
+
3
+ ## TL;DR
4
+
5
+ Start on the root of the `duffel-components` repository:
6
+
7
+ ```sh
8
+ # build duffel-components for react env:
9
+ yarn react-build
10
+
11
+ # change directory to example folder
12
+ cd src/examples/payments-just-typescript
13
+
14
+ # cleanup last install and build
15
+ rm -rf node_modules && rm -rf dist
16
+
17
+ # install new version
18
+ yarn
19
+
20
+ # build and watch example
21
+ yarn build
22
+
23
+ # open example
24
+ open src/index.html -a "Safari"
25
+ ```
26
+
27
+ ## Build duffel-components
28
+
29
+ First, navigate to the root folder of the duffel-components repository and run `yarn react-build` to build the package. It should output a react-dist folder on the root. This folder is the one we reference on `src/examples/payments-just-typescript/package.json` dependencies under `duffel-components`
30
+
31
+ ## Install dependencies
32
+
33
+ Once the package is built, you can cd into this directory and run `yarn` to install all dependencies. If there are changes to `react-dist` since your last install, you'll need to `rm -rf node_modules`, otherwise the updates build will not be installed.
34
+
35
+ ## Run example
36
+
37
+ Finally, run `yarn dev` to build `src/examples/payments-just-typescript/src/index.tsx`. This will produce `src/examples/payments-just-typescript/dist` folder that is referenced by `src/examples/payments-just-typescript/src/index.html`. You can then open `src/examples/payments-just-typescript/src/index.html` on your browser to see the example up and running.
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "just-typescript",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "build": "esbuild src/index.ts --bundle --outfile=dist/index.js"
7
+ },
8
+ "dependencies": {
9
+ "@types/node": "20.2.5",
10
+ "typescript": "5.0.4",
11
+ "duffel-components": "../../../../duffel-components/react-dist"
12
+ },
13
+ "devDependencies": {
14
+ "esbuild": "^0.17.19"
15
+ }
16
+ }
@@ -0,0 +1,23 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <link
7
+ rel="icon"
8
+ type="image/png"
9
+ sizes="96x96"
10
+ href="https://duffel.com/images/favicon/favicon-96x96.png"
11
+ />
12
+
13
+ <script src="../dist/index.js" defer></script>
14
+ <title>Duffel payments component just typescript example</title>
15
+ </head>
16
+ <body>
17
+ <h1 style="margin-bottom: 2rem">
18
+ Duffel payments component just typescript example
19
+ </h1>
20
+
21
+ <duffel-payments></duffel-payments>
22
+ </body>
23
+ </html>
@@ -0,0 +1,18 @@
1
+ import {
2
+ onDuffelPaymentsFailedPayment,
3
+ onDuffelPaymentsSuccessfulPayment,
4
+ renderDuffelPaymentsCustomElement,
5
+ } from "duffel-components/custom-elements";
6
+
7
+ window.onload = () => {
8
+ renderDuffelPaymentsCustomElement({
9
+ paymentIntentClientToken:
10
+ "eyJjbGllbnRfc2VjcmV0IjoicGlfM0psczlVQWcySmhFeTh2WTBSTm1MU0JkX3NlY3JldF9QUW9yZXNuU3laeWJadGRiejZwNzBCbUdPIiwicHVibGlzaGFibGVfa2V5IjoicGtfdGVzdF9EQUJLY0E2Vzh6OTc0cTdPSWY0YmJ2MVQwMEpwRmMyOUpWIn0=",
11
+ });
12
+
13
+ // eslint-disable-next-line
14
+ onDuffelPaymentsFailedPayment((error) => console.error(error));
15
+
16
+ // eslint-disable-next-line
17
+ onDuffelPaymentsSuccessfulPayment(() => console.log("Payment successful"));
18
+ };
@@ -0,0 +1,154 @@
1
+ # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2
+ # yarn lockfile v1
3
+
4
+
5
+ "@esbuild/android-arm64@0.17.19":
6
+ version "0.17.19"
7
+ resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz#bafb75234a5d3d1b690e7c2956a599345e84a2fd"
8
+ integrity sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==
9
+
10
+ "@esbuild/android-arm@0.17.19":
11
+ version "0.17.19"
12
+ resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.17.19.tgz#5898f7832c2298bc7d0ab53701c57beb74d78b4d"
13
+ integrity sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==
14
+
15
+ "@esbuild/android-x64@0.17.19":
16
+ version "0.17.19"
17
+ resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.17.19.tgz#658368ef92067866d95fb268719f98f363d13ae1"
18
+ integrity sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==
19
+
20
+ "@esbuild/darwin-arm64@0.17.19":
21
+ version "0.17.19"
22
+ resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz#584c34c5991b95d4d48d333300b1a4e2ff7be276"
23
+ integrity sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==
24
+
25
+ "@esbuild/darwin-x64@0.17.19":
26
+ version "0.17.19"
27
+ resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz#7751d236dfe6ce136cce343dce69f52d76b7f6cb"
28
+ integrity sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==
29
+
30
+ "@esbuild/freebsd-arm64@0.17.19":
31
+ version "0.17.19"
32
+ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz#cacd171665dd1d500f45c167d50c6b7e539d5fd2"
33
+ integrity sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==
34
+
35
+ "@esbuild/freebsd-x64@0.17.19":
36
+ version "0.17.19"
37
+ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz#0769456eee2a08b8d925d7c00b79e861cb3162e4"
38
+ integrity sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==
39
+
40
+ "@esbuild/linux-arm64@0.17.19":
41
+ version "0.17.19"
42
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz#38e162ecb723862c6be1c27d6389f48960b68edb"
43
+ integrity sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==
44
+
45
+ "@esbuild/linux-arm@0.17.19":
46
+ version "0.17.19"
47
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz#1a2cd399c50040184a805174a6d89097d9d1559a"
48
+ integrity sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==
49
+
50
+ "@esbuild/linux-ia32@0.17.19":
51
+ version "0.17.19"
52
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz#e28c25266b036ce1cabca3c30155222841dc035a"
53
+ integrity sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==
54
+
55
+ "@esbuild/linux-loong64@0.17.19":
56
+ version "0.17.19"
57
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz#0f887b8bb3f90658d1a0117283e55dbd4c9dcf72"
58
+ integrity sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==
59
+
60
+ "@esbuild/linux-mips64el@0.17.19":
61
+ version "0.17.19"
62
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz#f5d2a0b8047ea9a5d9f592a178ea054053a70289"
63
+ integrity sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==
64
+
65
+ "@esbuild/linux-ppc64@0.17.19":
66
+ version "0.17.19"
67
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz#876590e3acbd9fa7f57a2c7d86f83717dbbac8c7"
68
+ integrity sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==
69
+
70
+ "@esbuild/linux-riscv64@0.17.19":
71
+ version "0.17.19"
72
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz#7f49373df463cd9f41dc34f9b2262d771688bf09"
73
+ integrity sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==
74
+
75
+ "@esbuild/linux-s390x@0.17.19":
76
+ version "0.17.19"
77
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz#e2afd1afcaf63afe2c7d9ceacd28ec57c77f8829"
78
+ integrity sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==
79
+
80
+ "@esbuild/linux-x64@0.17.19":
81
+ version "0.17.19"
82
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz#8a0e9738b1635f0c53389e515ae83826dec22aa4"
83
+ integrity sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==
84
+
85
+ "@esbuild/netbsd-x64@0.17.19":
86
+ version "0.17.19"
87
+ resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz#c29fb2453c6b7ddef9a35e2c18b37bda1ae5c462"
88
+ integrity sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==
89
+
90
+ "@esbuild/openbsd-x64@0.17.19":
91
+ version "0.17.19"
92
+ resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz#95e75a391403cb10297280d524d66ce04c920691"
93
+ integrity sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==
94
+
95
+ "@esbuild/sunos-x64@0.17.19":
96
+ version "0.17.19"
97
+ resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz#722eaf057b83c2575937d3ffe5aeb16540da7273"
98
+ integrity sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==
99
+
100
+ "@esbuild/win32-arm64@0.17.19":
101
+ version "0.17.19"
102
+ resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz#9aa9dc074399288bdcdd283443e9aeb6b9552b6f"
103
+ integrity sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==
104
+
105
+ "@esbuild/win32-ia32@0.17.19":
106
+ version "0.17.19"
107
+ resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz#95ad43c62ad62485e210f6299c7b2571e48d2b03"
108
+ integrity sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==
109
+
110
+ "@esbuild/win32-x64@0.17.19":
111
+ version "0.17.19"
112
+ resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz#8cfaf2ff603e9aabb910e9c0558c26cf32744061"
113
+ integrity sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==
114
+
115
+ "@types/node@20.2.5":
116
+ version "20.2.5"
117
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.2.5.tgz#26d295f3570323b2837d322180dfbf1ba156fefb"
118
+ integrity sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==
119
+
120
+ duffel-components@../../../../duffel-components/react-dist:
121
+ version "0.0.0"
122
+
123
+ esbuild@^0.17.19:
124
+ version "0.17.19"
125
+ resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.19.tgz#087a727e98299f0462a3d0bcdd9cd7ff100bd955"
126
+ integrity sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==
127
+ optionalDependencies:
128
+ "@esbuild/android-arm" "0.17.19"
129
+ "@esbuild/android-arm64" "0.17.19"
130
+ "@esbuild/android-x64" "0.17.19"
131
+ "@esbuild/darwin-arm64" "0.17.19"
132
+ "@esbuild/darwin-x64" "0.17.19"
133
+ "@esbuild/freebsd-arm64" "0.17.19"
134
+ "@esbuild/freebsd-x64" "0.17.19"
135
+ "@esbuild/linux-arm" "0.17.19"
136
+ "@esbuild/linux-arm64" "0.17.19"
137
+ "@esbuild/linux-ia32" "0.17.19"
138
+ "@esbuild/linux-loong64" "0.17.19"
139
+ "@esbuild/linux-mips64el" "0.17.19"
140
+ "@esbuild/linux-ppc64" "0.17.19"
141
+ "@esbuild/linux-riscv64" "0.17.19"
142
+ "@esbuild/linux-s390x" "0.17.19"
143
+ "@esbuild/linux-x64" "0.17.19"
144
+ "@esbuild/netbsd-x64" "0.17.19"
145
+ "@esbuild/openbsd-x64" "0.17.19"
146
+ "@esbuild/sunos-x64" "0.17.19"
147
+ "@esbuild/win32-arm64" "0.17.19"
148
+ "@esbuild/win32-ia32" "0.17.19"
149
+ "@esbuild/win32-x64" "0.17.19"
150
+
151
+ typescript@5.0.4:
152
+ version "5.0.4"
153
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b"
154
+ integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==
@@ -1,12 +1,10 @@
1
- import { DuffelAncillaries } from "duffel-components";
1
+ import { DuffelAncillaries, DuffelPayments } from "duffel-components";
2
2
  import React from "react";
3
3
  import { createRoot } from "react-dom/client";
4
4
 
5
5
  const App: React.FC = () => (
6
- <>
7
- <h1 style={{ marginBottom: "2rem" }}>
8
- Duffel ancillaries component react-app example
9
- </h1>
6
+ <div style={{ display: "grid", gridTemplateColumns: "1fr", rowGap: "2rem" }}>
7
+ <h1>Duffel ancillaries component react-app example</h1>
10
8
 
11
9
  <DuffelAncillaries
12
10
  offer_id="fixture_off_1"
@@ -31,9 +29,16 @@ const App: React.FC = () => (
31
29
  born_on: "1942-10-17",
32
30
  },
33
31
  ]}
32
+ // eslint-disable-next-line
34
33
  onPayloadReady={console.log}
35
34
  />
36
- </>
35
+
36
+ <DuffelPayments
37
+ paymentIntentClientToken="eyJjbGllbnRfc2VjcmV0IjoicGlfM0psczlVQWcySmhFeTh2WTBSTm1MU0JkX3NlY3JldF9QUW9yZXNuU3laeWJadGRiejZwNzBCbUdPIiwicHVibGlzaGFibGVfa2V5IjoicGtfdGVzdF9EQUJLY0E2Vzh6OTc0cTdPSWY0YmJ2MVQwMEpwRmMyOUpWIn0="
38
+ onSuccessfulPayment={console.log}
39
+ onFailedPayment={console.log}
40
+ />
41
+ </div>
37
42
  );
38
43
 
39
44
  const rootElement = document.getElementById("root");
package/src/index.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  /**
2
- * This file is the entry point for the library.
3
- * If you'd like to expose other components,
4
- * they must be exported here.
2
+ * This file is the main entry point for the library -- `@duffel/components`.
3
+ * If you'd like to expose other react components, please add them here.
5
4
  */
6
- export * from "./components/DuffelAncillaries";
7
- export * from "./components/DuffelAncillariesCustomElement";
5
+ export * from "./components/DuffelAncillaries/DuffelAncillaries";
6
+ export * from "./components/DuffelPayments/DuffelPayments";
8
7
  export * from "./types";
@@ -1,8 +1,5 @@
1
1
  import * as Sentry from "@sentry/browser";
2
2
 
3
- /* eslint-disable-next-line @typescript-eslint/no-var-requires */
4
- const PACKAGE_DOT_JSON = require("../../package.json");
5
-
6
3
  let hasSentryInitiated = false;
7
4
  function initiateSentry() {
8
5
  Sentry.init({
@@ -13,7 +10,7 @@ function initiateSentry() {
13
10
  * this value to allow Sentry to resolve the correct source maps when
14
11
  * processing events.
15
12
  */
16
- release: `${PACKAGE_DOT_JSON.name}@${PACKAGE_DOT_JSON.version}`,
13
+ release: process.env.COMPONENT_VERSION,
17
14
 
18
15
  /**
19
16
  * List of integrations that should be installed after SDK was initialized.
@@ -36,25 +33,10 @@ function initiateSentry() {
36
33
  hasSentryInitiated = true;
37
34
  }
38
35
 
39
- export const captureErrorInSentry = (
40
- error: Error,
41
- context?: Record<string, any>
42
- ) => {
36
+ export const captureErrorInSentry = (error: Error) => {
43
37
  if (!hasSentryInitiated) {
44
38
  initiateSentry();
45
39
  }
46
40
 
47
- Sentry.configureScope((scope) => {
48
- if (error.message) {
49
- scope.setFingerprint([error.message]);
50
- }
51
-
52
- if (context) {
53
- Object.entries(context).forEach(([key, value]) =>
54
- scope.setExtra(key, value)
55
- );
56
- }
57
- });
58
-
59
41
  return Sentry.captureException(error);
60
42
  };
@@ -1,3 +1,12 @@
1
+ import { logGroup } from "./logging";
2
+
3
+ export interface ErrorResponse extends Response {
4
+ data: { meta: any; errors: any[] };
5
+ }
6
+ export const isErrorResponse = (response: any): response is ErrorResponse => {
7
+ return "data" in response && Array.isArray(response.data.errors);
8
+ };
9
+
1
10
  const DUFFEL_API_URL = process.env.DUFFEL_API_URL;
2
11
  const COMPONENT_VERSION = process.env.COMPONENT_VERSION;
3
12
 
@@ -7,9 +16,11 @@ export async function fetchFromDuffelAPI(
7
16
  method = "GET",
8
17
  body?: string
9
18
  ) {
10
- const response = await fetch(
11
- `${DUFFEL_API_URL}/ancillaries-component/${path}`,
12
- {
19
+ logGroup("Making request to the Duffel API", { path, method });
20
+ const fullUrl = `${DUFFEL_API_URL}/ancillaries-component/${path}`;
21
+ let response: Response | null = null;
22
+ try {
23
+ response = await fetch(fullUrl, {
13
24
  method,
14
25
  body,
15
26
  headers: {
@@ -17,8 +28,27 @@ export async function fetchFromDuffelAPI(
17
28
  Authorization: `Bearer ${withClientKey}`,
18
29
  "User-Agent": `Duffel/ancillaries-component@${COMPONENT_VERSION}`,
19
30
  },
20
- }
21
- );
31
+ });
32
+ } catch (error) {
33
+ logGroup("Failed to make request to the Duffel API", { error });
34
+ throw error;
35
+ }
36
+
37
+ const data = await response.json();
38
+ if (Array.isArray(data.errors)) {
39
+ logGroup("Request to the Duffel API failed", {
40
+ operation: `${method} ${fullUrl}`,
41
+ method,
42
+ request_id: data?.meta?.request_id,
43
+ errors: data.errors,
44
+ status: response.status,
45
+ });
46
+ throw { ...response, data };
47
+ } else {
48
+ logGroup("Request to the Duffel succeeded", {
49
+ request_id: data?.meta?.request_id,
50
+ });
51
+ }
22
52
 
23
- return await response.json();
53
+ return data;
24
54
  }
@@ -5,10 +5,9 @@ export const formatDateString = (dateString: string) => {
5
5
  if (!isNaN(date.valueOf())) return formatDate(date);
6
6
  else {
7
7
  captureErrorInSentry(
8
- new Error("formatDateString attempted to parse an invalid date string"),
9
- {
10
- dateString,
11
- }
8
+ new Error(
9
+ `formatDateString attempted to parse an invalid date string: ${dateString}`
10
+ )
12
11
  );
13
12
  }
14
13
  };
@@ -6,8 +6,7 @@ export const getBaggageServiceDescription = (
6
6
  ) => {
7
7
  if (!metadata) {
8
8
  captureErrorInSentry(
9
- new Error("getBaggageServiceDescription was not given any metadata"),
10
- { metadata }
9
+ new Error("getBaggageServiceDescription was not given any metadata")
11
10
  );
12
11
  return null;
13
12
  }
@@ -19,8 +18,7 @@ export const getBaggageServiceDescription = (
19
18
  !metadata.maximum_depth_cm
20
19
  ) {
21
20
  captureErrorInSentry(
22
- new Error("getBaggageServiceDescription metadata doesn't have any data"),
23
- { metadata }
21
+ new Error("getBaggageServiceDescription metadata doesn't have any data")
24
22
  );
25
23
  return null;
26
24
  }
@@ -37,7 +37,7 @@ export const getTotalAmountForServicesWithPriceMap = (
37
37
  } else {
38
38
  captureErrorInSentry(
39
39
  new Error(
40
- `The service id provided could not be found in neither the offer nor the seat maps. Service id: ${id}`
40
+ `The service id (${id}) provided could not be found in neither the offer nor the seat maps.`
41
41
  )
42
42
  );
43
43
  }