From dc5eea1ad0a60df0e63f075576604d9da20ee67f Mon Sep 17 00:00:00 2001 From: jackbeeby Date: Thu, 5 Dec 2024 18:20:27 +1100 Subject: [PATCH] wdc --- .changeset/config.json | 15 + .dependency-cruiser.js | 274 + .env.example | 3 + .env.test | 14 + .eslintignore | 3 + .eslintrc | 150 + .gitattributes | 1 + .graphqlrc.yml | 48 + .husky/pre-commit | 4 + .lintstagedrc.js | 13 + .npmrc | 2 + .prettierignore | 11 + .prettierrc | 5 + .vscode/extensions.json | 8 + .vscode/launch.json | 16 + .vscode/settings.json | 11 + CHANGELOG.md | 40 + CODEOWNERS | 3 + Dockerfile | 50 + SECURITY.md | 5 + fix-coverage-report.cjs | 22 + global.d.ts | 39 + graphql/fragments/.gitkeep | 0 graphql/fragments/Money.graphql | 4 + .../fragments/OrderOrCheckoutLines.graphql | 110 + .../OrderOrCheckoutSourceObject.graphql | 45 + ...entGatewayInitializeSessionAddress.graphql | 5 + ...ymentGatewayInitializeSessionEvent.graphql | 49 + .../fragments/PaymentGatewayRecipient.graphql | 11 + ...ansactionCancelationRequestedEvent.graphql | 20 + .../TransactionChargeRequestedEvent.graphql | 24 + ...ransactionInitializeSessionAddress.graphql | 14 + .../TransactionInitializeSessionEvent.graphql | 26 + .../TransactionProcessSessionEvent.graphql | 54 + .../TransactionRefundRequestedEvent.graphql | 24 + graphql/mutations/.gitkeep | 0 .../mutations/TransactionEventReport.graphql | 28 + graphql/mutations/UpdateAppMetadata.graphql | 10 + .../mutations/UpdatePublicMetadata.graphql | 10 + graphql/queries/.gitkeep | 0 graphql/queries/FetchAppDetails.graphql | 16 + graphql/queries/FetchChannels.graphql | 6 + graphql/schema.graphql | 28869 ++++++++++++++++ graphql/subscriptions/.gitkeep | 0 .../PaymentGatewayInitializeSession.graphql | 5 + .../TransactionCancelationRequested.graphql | 5 + .../TransactionChargeRequested.graphql | 5 + .../TransactionInitializeSession.graphql | 5 + .../TransactionProcessSession.graphql | 5 + .../TransactionRefundRequested.graphql | 5 + next-env.d.ts | 5 + next.config.mjs | 31 + package.json | 152 + pnpm-lock.yaml | 12008 +++++++ public/favicon-32x32.png | Bin 0 -> 453 bytes public/icons/icon-144x144.png | Bin 0 -> 1348 bytes public/icons/icon-192x192.png | Bin 0 -> 1761 bytes public/icons/icon-256x256.png | Bin 0 -> 2238 bytes public/icons/icon-384x384.png | Bin 0 -> 3841 bytes public/icons/icon-48x48.png | Bin 0 -> 583 bytes public/icons/icon-512x512.png | Bin 0 -> 5392 bytes public/icons/icon-72x72.png | Bin 0 -> 733 bytes public/icons/icon-96x96.png | Bin 0 -> 978 bytes public/logo.png | Bin 0 -> 7924 bytes sentry.client.config.js | 18 + sentry.edge.config.js | 16 + sentry.properties | 4 + sentry.server.config.js | 18 + src/__tests__/apiTestsUtils.ts | 20 + src/__tests__/pages/index.test.tsx | 26 + src/__tests__/polly.ts | 269 + src/__tests__/test-env.mjs | 51 + src/__tests__/testAPL.ts | 59 + src/app-bridge-instance.ts | 7 + src/backend-lib/api-route-utils.test.ts | 294 + src/backend-lib/api-route-utils.ts | 128 + src/deploy.ts | 12 + src/errors.ts | 79 + src/lib/api-response.ts | 71 + src/lib/create-graphq-client.ts | 52 + src/lib/env.mjs | 62 + src/lib/gql-ast-to-string.ts | 8 + src/lib/invariant.test.ts | 13 + src/lib/invariant.ts | 20 + src/lib/isEnv.ts | 4 + src/lib/logger.ts | 103 + src/lib/use-fetch.ts | 119 + src/lib/utils.test.ts | 98 + src/lib/utils.ts | 62 + src/load-env.ts | 2 + .../FetchWebhookId.graphql | 10 + .../UpdateWebhook.graphql | 12 + .../1-add-issuing-pricinpal/index.ts | 42 + .../app-configuration.test.ts | 159 + .../app-configuration/app-configuration.ts | 126 + .../app-configuration/metadata-manager.ts | 142 + src/modules/app-configuration/utils.ts | 38 + .../jwt/check-token-expiration.test.ts | 43 + src/modules/jwt/check-token-expiration.ts | 22 + src/modules/jwt/check-token-offline.ts | 23 + src/modules/jwt/consts.ts | 3 + .../__tests__/mocks.ts | 10 + .../payment-app-configuration-factory.ts | 38 + .../payment-app-configuration.test.ts | 225 + .../__tests__/utils.ts | 35 + .../payment-app-configuration/app-config.ts | 48 + .../payment-app-configuration/config-entry.ts | 99 + .../config-manager.test.ts | 167 + .../config-manager.ts | 188 + .../input-schemas.ts | 18 + .../mapping-manager.test.ts | 71 + .../mapping-manager.ts | 90 + .../payment-app-configuration-factory.ts | 21 + .../payment-app-configuration.router.ts | 107 + .../payment-app-configuration.ts | 158 + .../payment-app-configuration/utils.ts | 25 + .../webhook-manager.ts | 154 + .../recording.har | 388 + .../recording.har | 139 + .../recording.har | 361 + .../recording.har | 139 + src/modules/stripe/currencies.test.ts | 68 + src/modules/stripe/currencies.ts | 52 + src/modules/stripe/stripe-api.test.ts | 94 + src/modules/stripe/stripe-api.ts | 230 + .../trpc/protected-client-procedure.ts | 122 + src/modules/trpc/trpc-app-router.ts | 9 + src/modules/trpc/trpc-client.ts | 87 + src/modules/trpc/trpc-context.ts | 17 + src/modules/trpc/trpc-server.ts | 43 + src/modules/trpc/utils.ts | 82 + src/modules/ui/atoms/Chip/Chip.tsx | 38 + .../atoms/FileUploadInput/FileUploadInput.tsx | 56 + .../FileUploadInput/fileUploadInput.css.ts | 25 + .../RoundedActionBox/RoundedActionBox.tsx | 83 + .../RoundedActionBox/roundedActionBox.css.ts | 52 + src/modules/ui/atoms/Skeleton/Skeleton.css.ts | 11 + src/modules/ui/atoms/Skeleton/Skeleton.tsx | 16 + src/modules/ui/atoms/Table/Table.tsx | 22 + src/modules/ui/atoms/Table/table.css.ts | 74 + .../ui/atoms/macaw-ui/FormFileUploadInput.tsx | 24 + src/modules/ui/atoms/macaw-ui/FormInput.tsx | 39 + src/modules/ui/atoms/macaw-ui/FormSelect.tsx | 42 + src/modules/ui/atoms/macaw-ui/RadioGroup.tsx | 42 + src/modules/ui/atoms/modal.css.ts | 35 + .../ConfigurationSummary.tsx | 57 + .../ChannelToConfigurationTable.tsx | 153 + .../channelToConfigurationTable.css.ts | 24 + .../ConfigurationsTable.tsx | 62 + .../configurationsTable.css.ts | 22 + .../ConfirmationButton/ConfirmationButton.tsx | 118 + .../molecules/FullPageError/FullPageError.tsx | 7 + src/modules/ui/no-ssr-wrapper.tsx | 19 + .../AddStripeConfigurationForm.tsx | 65 + .../AddStripeCredentialsForm.tsx | 157 + .../DeleteStripeConfigurationForm.tsx | 82 + .../ChannelToConfigurationList.tsx | 89 + .../ui/organisms/GlobalErrorModal/modal.tsx | 42 + .../ui/organisms/GlobalErrorModal/state.ts | 29 + .../StripeConfigurationList.tsx | 52 + src/modules/ui/templates/AppLayout.tsx | 92 + src/modules/ui/templates/appLayout.css.ts | 66 + src/modules/ui/theme-synchronizer.test.tsx | 50 + src/modules/ui/theme-synchronizer.tsx | 33 + .../recording.har | 470 + .../recording.har | 678 + .../recording.har | 896 + .../recording.har | 678 + .../recording.har | 678 + .../recording.har | 678 + .../recording.har | 678 + .../recording.har | 678 + .../recording.har | 678 + .../recording.har | 683 + .../recording.har | 683 + .../recording.har | 683 + .../recording.har | 683 + .../recording.har | 683 + .../recording.har | 683 + .../recording.har | 906 + .../recording.har | 683 + .../recording.har | 683 + .../recording.har | 465 + .../recording.har | 683 + .../recording.har | 683 + .../recording.har | 683 + .../recording.har | 683 + .../recording.har | 683 + .../recording.har | 683 + .../recording.har | 683 + .../recording.har | 683 + .../recording.har | 237 + .../recording.har | 239 + .../recording.har | 237 + .../recording.har | 239 + .../recording.har | 460 + .../recording.har | 464 + .../recording.har | 460 + .../recording.har | 464 + .../recording.har | 639 + .../recording.har | 858 + .../recording.har | 639 + .../recording.har | 858 + .../recording.har | 639 + .../recording.har | 858 + .../recording.har | 639 + .../recording.har | 858 + .../recording.har | 639 + .../recording.har | 858 + .../recording.har | 639 + .../recording.har | 858 + .../recording.har | 639 + .../recording.har | 858 + .../recording.har | 639 + .../recording.har | 858 + .../recording.har | 639 + .../recording.har | 858 + .../recording.har | 639 + .../recording.har | 858 + .../recording.har | 639 + .../recording.har | 858 + .../recording.har | 639 + .../recording.har | 858 + .../recording.har | 639 + .../recording.har | 858 + .../recording.har | 639 + .../recording.har | 858 + .../recording.har | 639 + .../recording.har | 858 + .../recording.har | 639 + .../recording.har | 858 + .../recording.har | 639 + .../recording.har | 858 + .../recording.har | 639 + .../recording.har | 858 + ...ransaction-initialize-session.test.ts.snap | 37 + .../transaction-process-session.test.ts.snap | 37 + src/modules/webhooks/__tests__/utils.ts | 489 + ...payment-gateway-initialize-session.test.ts | 25 + .../payment-gateway-initialize-session.ts | 37 + src/modules/webhooks/stripe-webhook.errors.ts | 6 + src/modules/webhooks/stripe-webhook.test.ts | 453 + src/modules/webhooks/stripe-webhook.ts | 525 + .../transaction-cancelation-requested.test.ts | 74 + .../transaction-cancelation-requested.ts | 60 + .../transaction-charge-requested.test.ts | 118 + .../webhooks/transaction-charge-requested.ts | 79 + .../transaction-initialize-session.test.ts | 72 + .../transaction-initialize-session.ts | 106 + .../transaction-process-session.test.ts | 84 + .../webhooks/transaction-process-session.ts | 100 + .../transaction-refund-requested.test.ts | 227 + .../webhooks/transaction-refund-requested.ts | 95 + src/pages/_app.tsx | 66 + src/pages/_error.js | 39 + src/pages/api/manifest.ts | 43 + src/pages/api/register.ts | 25 + src/pages/api/trpc/[trpc].ts | 26 + .../payment-gateway-initialize-session.ts | 44 + .../transaction-cancelation-requested.ts | 44 + .../saleor/transaction-charge-requested.ts | 43 + .../saleor/transaction-initialize-session.ts | 49 + .../saleor/transaction-process-session.ts | 49 + .../saleor/transaction-refund-requested.ts | 43 + src/pages/api/webhooks/stripe/index.ts | 58 + src/pages/config.tsx | 138 + src/pages/configurations/add.tsx | 26 + .../configurations/edit/[configurationId].tsx | 33 + src/pages/configurations/list.tsx | 86 + src/pages/index.tsx | 136 + src/run-migrations.ts | 223 + src/saleor-app.ts | 46 + src/schemas/.gitignore | 6 + ...ayInitializeSessionRequestData.schema.json | 17 + ...tewayInitializeSessionResponse.schema.json | 21 + ...onCancelationRequestedResponse.schema.json | 16 + ...sactionChargeRequestedResponse.schema.json | 14 + ...ctionInitializeSessionResponse.schema.json | 24 + ...nsactionProcessSessionResponse.schema.json | 24 + ...sactionRefundRequestedResponse.schema.json | 14 + .../__snapshots__/compiler.test.ts.snap | 6 + src/schemas/definitions.json | 84 + src/setup-tests.ts | 19 + src/styles/global.css.ts | 20 + src/types.ts | 16 + tsconfig.json | 36 + .../vanilla-extract__next-plugin/index.d.ts | 6 + vitest.config.ts | 30 + 288 files changed, 101937 insertions(+) create mode 100644 .changeset/config.json create mode 100644 .dependency-cruiser.js create mode 100644 .env.example create mode 100644 .env.test create mode 100644 .eslintignore create mode 100644 .eslintrc create mode 100644 .gitattributes create mode 100644 .graphqlrc.yml create mode 100755 .husky/pre-commit create mode 100644 .lintstagedrc.js create mode 100644 .npmrc create mode 100644 .prettierignore create mode 100644 .prettierrc create mode 100644 .vscode/extensions.json create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 CHANGELOG.md create mode 100644 CODEOWNERS create mode 100644 Dockerfile create mode 100644 SECURITY.md create mode 100755 fix-coverage-report.cjs create mode 100644 global.d.ts create mode 100644 graphql/fragments/.gitkeep create mode 100644 graphql/fragments/Money.graphql create mode 100644 graphql/fragments/OrderOrCheckoutLines.graphql create mode 100644 graphql/fragments/OrderOrCheckoutSourceObject.graphql create mode 100644 graphql/fragments/PaymentGatewayInitializeSessionAddress.graphql create mode 100644 graphql/fragments/PaymentGatewayInitializeSessionEvent.graphql create mode 100644 graphql/fragments/PaymentGatewayRecipient.graphql create mode 100644 graphql/fragments/TransactionCancelationRequestedEvent.graphql create mode 100644 graphql/fragments/TransactionChargeRequestedEvent.graphql create mode 100644 graphql/fragments/TransactionInitializeSessionAddress.graphql create mode 100644 graphql/fragments/TransactionInitializeSessionEvent.graphql create mode 100644 graphql/fragments/TransactionProcessSessionEvent.graphql create mode 100644 graphql/fragments/TransactionRefundRequestedEvent.graphql create mode 100644 graphql/mutations/.gitkeep create mode 100644 graphql/mutations/TransactionEventReport.graphql create mode 100644 graphql/mutations/UpdateAppMetadata.graphql create mode 100644 graphql/mutations/UpdatePublicMetadata.graphql create mode 100644 graphql/queries/.gitkeep create mode 100644 graphql/queries/FetchAppDetails.graphql create mode 100644 graphql/queries/FetchChannels.graphql create mode 100644 graphql/schema.graphql create mode 100644 graphql/subscriptions/.gitkeep create mode 100644 graphql/subscriptions/PaymentGatewayInitializeSession.graphql create mode 100644 graphql/subscriptions/TransactionCancelationRequested.graphql create mode 100644 graphql/subscriptions/TransactionChargeRequested.graphql create mode 100644 graphql/subscriptions/TransactionInitializeSession.graphql create mode 100644 graphql/subscriptions/TransactionProcessSession.graphql create mode 100644 graphql/subscriptions/TransactionRefundRequested.graphql create mode 100644 next-env.d.ts create mode 100644 next.config.mjs create mode 100644 package.json create mode 100644 pnpm-lock.yaml create mode 100644 public/favicon-32x32.png create mode 100644 public/icons/icon-144x144.png create mode 100644 public/icons/icon-192x192.png create mode 100644 public/icons/icon-256x256.png create mode 100644 public/icons/icon-384x384.png create mode 100644 public/icons/icon-48x48.png create mode 100644 public/icons/icon-512x512.png create mode 100644 public/icons/icon-72x72.png create mode 100644 public/icons/icon-96x96.png create mode 100644 public/logo.png create mode 100644 sentry.client.config.js create mode 100644 sentry.edge.config.js create mode 100644 sentry.properties create mode 100644 sentry.server.config.js create mode 100644 src/__tests__/apiTestsUtils.ts create mode 100644 src/__tests__/pages/index.test.tsx create mode 100644 src/__tests__/polly.ts create mode 100644 src/__tests__/test-env.mjs create mode 100644 src/__tests__/testAPL.ts create mode 100644 src/app-bridge-instance.ts create mode 100644 src/backend-lib/api-route-utils.test.ts create mode 100644 src/backend-lib/api-route-utils.ts create mode 100644 src/deploy.ts create mode 100644 src/errors.ts create mode 100644 src/lib/api-response.ts create mode 100644 src/lib/create-graphq-client.ts create mode 100644 src/lib/env.mjs create mode 100644 src/lib/gql-ast-to-string.ts create mode 100644 src/lib/invariant.test.ts create mode 100644 src/lib/invariant.ts create mode 100644 src/lib/isEnv.ts create mode 100644 src/lib/logger.ts create mode 100644 src/lib/use-fetch.ts create mode 100644 src/lib/utils.test.ts create mode 100644 src/lib/utils.ts create mode 100644 src/load-env.ts create mode 100644 src/migrations/1-add-issuing-pricinpal/FetchWebhookId.graphql create mode 100644 src/migrations/1-add-issuing-pricinpal/UpdateWebhook.graphql create mode 100644 src/migrations/1-add-issuing-pricinpal/index.ts create mode 100644 src/modules/app-configuration/app-configuration.test.ts create mode 100644 src/modules/app-configuration/app-configuration.ts create mode 100644 src/modules/app-configuration/metadata-manager.ts create mode 100644 src/modules/app-configuration/utils.ts create mode 100644 src/modules/jwt/check-token-expiration.test.ts create mode 100644 src/modules/jwt/check-token-expiration.ts create mode 100644 src/modules/jwt/check-token-offline.ts create mode 100644 src/modules/jwt/consts.ts create mode 100644 src/modules/payment-app-configuration/__tests__/mocks.ts create mode 100644 src/modules/payment-app-configuration/__tests__/payment-app-configuration-factory.ts create mode 100644 src/modules/payment-app-configuration/__tests__/payment-app-configuration.test.ts create mode 100644 src/modules/payment-app-configuration/__tests__/utils.ts create mode 100644 src/modules/payment-app-configuration/app-config.ts create mode 100644 src/modules/payment-app-configuration/config-entry.ts create mode 100644 src/modules/payment-app-configuration/config-manager.test.ts create mode 100644 src/modules/payment-app-configuration/config-manager.ts create mode 100644 src/modules/payment-app-configuration/input-schemas.ts create mode 100644 src/modules/payment-app-configuration/mapping-manager.test.ts create mode 100644 src/modules/payment-app-configuration/mapping-manager.ts create mode 100644 src/modules/payment-app-configuration/payment-app-configuration-factory.ts create mode 100644 src/modules/payment-app-configuration/payment-app-configuration.router.ts create mode 100644 src/modules/payment-app-configuration/payment-app-configuration.ts create mode 100644 src/modules/payment-app-configuration/utils.ts create mode 100644 src/modules/payment-app-configuration/webhook-manager.ts create mode 100644 src/modules/stripe/__recordings__/stripe-api_748119249/validateStripeKeys_2838756478/not-throw-error-if-both-keys-are-correct_4216631210/recording.har create mode 100644 src/modules/stripe/__recordings__/stripe-api_748119249/validateStripeKeys_2838756478/should-throw-error-if-both-keys-are-invalid_2549431215/recording.har create mode 100644 src/modules/stripe/__recordings__/stripe-api_748119249/validateStripeKeys_2838756478/should-throw-error-if-publishable-key-is-invalid_3942585802/recording.har create mode 100644 src/modules/stripe/__recordings__/stripe-api_748119249/validateStripeKeys_2838756478/should-throw-error-if-secret-key-is-invalid_476878657/recording.har create mode 100644 src/modules/stripe/currencies.test.ts create mode 100644 src/modules/stripe/currencies.ts create mode 100644 src/modules/stripe/stripe-api.test.ts create mode 100644 src/modules/stripe/stripe-api.ts create mode 100644 src/modules/trpc/protected-client-procedure.ts create mode 100644 src/modules/trpc/trpc-app-router.ts create mode 100644 src/modules/trpc/trpc-client.ts create mode 100644 src/modules/trpc/trpc-context.ts create mode 100644 src/modules/trpc/trpc-server.ts create mode 100644 src/modules/trpc/utils.ts create mode 100644 src/modules/ui/atoms/Chip/Chip.tsx create mode 100644 src/modules/ui/atoms/FileUploadInput/FileUploadInput.tsx create mode 100644 src/modules/ui/atoms/FileUploadInput/fileUploadInput.css.ts create mode 100644 src/modules/ui/atoms/RoundedActionBox/RoundedActionBox.tsx create mode 100644 src/modules/ui/atoms/RoundedActionBox/roundedActionBox.css.ts create mode 100644 src/modules/ui/atoms/Skeleton/Skeleton.css.ts create mode 100644 src/modules/ui/atoms/Skeleton/Skeleton.tsx create mode 100644 src/modules/ui/atoms/Table/Table.tsx create mode 100644 src/modules/ui/atoms/Table/table.css.ts create mode 100644 src/modules/ui/atoms/macaw-ui/FormFileUploadInput.tsx create mode 100644 src/modules/ui/atoms/macaw-ui/FormInput.tsx create mode 100644 src/modules/ui/atoms/macaw-ui/FormSelect.tsx create mode 100644 src/modules/ui/atoms/macaw-ui/RadioGroup.tsx create mode 100644 src/modules/ui/atoms/modal.css.ts create mode 100644 src/modules/ui/molecules/ConfigurationSummary/ConfigurationSummary.tsx create mode 100644 src/modules/ui/molecules/ConfigurationsTable/ChannelToConfigurationTable/ChannelToConfigurationTable.tsx create mode 100644 src/modules/ui/molecules/ConfigurationsTable/ChannelToConfigurationTable/channelToConfigurationTable.css.ts create mode 100644 src/modules/ui/molecules/ConfigurationsTable/ConfigurationsTable.tsx create mode 100644 src/modules/ui/molecules/ConfigurationsTable/configurationsTable.css.ts create mode 100644 src/modules/ui/molecules/ConfirmationButton/ConfirmationButton.tsx create mode 100644 src/modules/ui/molecules/FullPageError/FullPageError.tsx create mode 100644 src/modules/ui/no-ssr-wrapper.tsx create mode 100644 src/modules/ui/organisms/AddStripeConfigurationForm/AddStripeConfigurationForm.tsx create mode 100644 src/modules/ui/organisms/AddStripeConfigurationForm/AddStripeCredentialsForm.tsx create mode 100644 src/modules/ui/organisms/AddStripeConfigurationForm/DeleteStripeConfigurationForm.tsx create mode 100644 src/modules/ui/organisms/ChannelToConfigurationList/ChannelToConfigurationList.tsx create mode 100644 src/modules/ui/organisms/GlobalErrorModal/modal.tsx create mode 100644 src/modules/ui/organisms/GlobalErrorModal/state.ts create mode 100644 src/modules/ui/organisms/StripeConfigurationList/StripeConfigurationList.tsx create mode 100644 src/modules/ui/templates/AppLayout.tsx create mode 100644 src/modules/ui/templates/appLayout.css.ts create mode 100644 src/modules/ui/theme-synchronizer.test.tsx create mode 100644 src/modules/ui/theme-synchronizer.tsx create mode 100644 src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/American-Express-pm_card_amex_1702901941/should-cancel-pre-authorized-card_3641244857/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Diners-Club-pm_card_diners_3136405054/should-cancel-pre-authorized-card_3641244857/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Discover-pm_card_discover_3985489676/should-cancel-pre-authorized-card_3641244857/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-cancel-pre-authorized-card_3641244857/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Mastercard-pm_card_mastercard_3189003338/should-cancel-pre-authorized-card_3641244857/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-cancel-pre-authorized-card_3641244857/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/UnionPay-pm_card_unionpay_3165217716/should-cancel-pre-authorized-card_3641244857/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Visa-debit-pm_card_visa_debit_2311568982/should-cancel-pre-authorized-card_3641244857/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Visa-pm_card_visa_1355345048/should-cancel-pre-authorized-card_3641244857/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/American-Express-pm_card_amex_1702901941/should-charge-pre-authorized-card_3197581963/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/American-Express-pm_card_amex_1702901941/should-partially-charge-pre-authorized-card_330064185/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Diners-Club-pm_card_diners_3136405054/should-charge-pre-authorized-card_3197581963/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Diners-Club-pm_card_diners_3136405054/should-partially-charge-pre-authorized-card_330064185/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Discover-pm_card_discover_3985489676/should-charge-pre-authorized-card_3197581963/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Discover-pm_card_discover_3985489676/should-partially-charge-pre-authorized-card_330064185/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-charge-pre-authorized-card_3197581963/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-partially-charge-pre-authorized-card_330064185/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Mastercard-pm_card_mastercard_3189003338/should-charge-pre-authorized-card_3197581963/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Mastercard-pm_card_mastercard_3189003338/should-partially-charge-pre-authorized-card_330064185/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-charge-pre-authorized-card_3197581963/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-partially-charge-pre-authorized-card_330064185/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/UnionPay-pm_card_unionpay_3165217716/should-charge-pre-authorized-card_3197581963/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/UnionPay-pm_card_unionpay_3165217716/should-partially-charge-pre-authorized-card_330064185/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Visa-debit-pm_card_visa_debit_2311568982/should-charge-pre-authorized-card_3197581963/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Visa-debit-pm_card_visa_debit_2311568982/should-partially-charge-pre-authorized-card_330064185/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Visa-pm_card_visa_1355345048/should-charge-pre-authorized-card_3197581963/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Visa-pm_card_visa_1355345048/should-partially-charge-pre-authorized-card_330064185/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionInitializeSessionWebhookHandler_3934145280/Checkout_2840636407/should-work-authorization_889917716/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionInitializeSessionWebhookHandler_3934145280/Checkout_2840636407/should-work-charge_2556039247/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionInitializeSessionWebhookHandler_3934145280/Order_2373458299/should-work-authorization_889917716/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionInitializeSessionWebhookHandler_3934145280/Order_2373458299/should-work-charge_2556039247/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionProcessSessionWebhookHandler_1802350267/Checkout_2840636407/should-work-authorization_889917716/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionProcessSessionWebhookHandler_1802350267/Checkout_2840636407/should-work-charge_2556039247/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionProcessSessionWebhookHandler_1802350267/Order_2373458299/should-work-authorization_889917716/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionProcessSessionWebhookHandler_1802350267/Order_2373458299/should-work-charge_2556039247/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/American-Express-pm_card_amex_1702901941/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/American-Express-pm_card_amex_1702901941/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/American-Express-pm_card_amex_1702901941/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/American-Express-pm_card_amex_1702901941/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Diners-Club-pm_card_diners_3136405054/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Diners-Club-pm_card_diners_3136405054/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Diners-Club-pm_card_diners_3136405054/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Diners-Club-pm_card_diners_3136405054/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Discover-pm_card_discover_3985489676/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Discover-pm_card_discover_3985489676/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Discover-pm_card_discover_3985489676/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Discover-pm_card_discover_3985489676/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-pm_card_mastercard_3189003338/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-pm_card_mastercard_3189003338/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-pm_card_mastercard_3189003338/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-pm_card_mastercard_3189003338/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/UnionPay-pm_card_unionpay_3165217716/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/UnionPay-pm_card_unionpay_3165217716/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/UnionPay-pm_card_unionpay_3165217716/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/UnionPay-pm_card_unionpay_3165217716/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-debit-pm_card_visa_debit_2311568982/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-debit-pm_card_visa_debit_2311568982/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-debit-pm_card_visa_debit_2311568982/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-debit-pm_card_visa_debit_2311568982/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-pm_card_visa_1355345048/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-pm_card_visa_1355345048/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-pm_card_visa_1355345048/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har create mode 100644 src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-pm_card_visa_1355345048/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har create mode 100644 src/modules/webhooks/__snapshots__/transaction-initialize-session.test.ts.snap create mode 100644 src/modules/webhooks/__snapshots__/transaction-process-session.test.ts.snap create mode 100644 src/modules/webhooks/__tests__/utils.ts create mode 100644 src/modules/webhooks/payment-gateway-initialize-session.test.ts create mode 100644 src/modules/webhooks/payment-gateway-initialize-session.ts create mode 100644 src/modules/webhooks/stripe-webhook.errors.ts create mode 100644 src/modules/webhooks/stripe-webhook.test.ts create mode 100644 src/modules/webhooks/stripe-webhook.ts create mode 100644 src/modules/webhooks/transaction-cancelation-requested.test.ts create mode 100644 src/modules/webhooks/transaction-cancelation-requested.ts create mode 100644 src/modules/webhooks/transaction-charge-requested.test.ts create mode 100644 src/modules/webhooks/transaction-charge-requested.ts create mode 100644 src/modules/webhooks/transaction-initialize-session.test.ts create mode 100644 src/modules/webhooks/transaction-initialize-session.ts create mode 100644 src/modules/webhooks/transaction-process-session.test.ts create mode 100644 src/modules/webhooks/transaction-process-session.ts create mode 100644 src/modules/webhooks/transaction-refund-requested.test.ts create mode 100644 src/modules/webhooks/transaction-refund-requested.ts create mode 100644 src/pages/_app.tsx create mode 100644 src/pages/_error.js create mode 100644 src/pages/api/manifest.ts create mode 100644 src/pages/api/register.ts create mode 100644 src/pages/api/trpc/[trpc].ts create mode 100644 src/pages/api/webhooks/saleor/payment-gateway-initialize-session.ts create mode 100644 src/pages/api/webhooks/saleor/transaction-cancelation-requested.ts create mode 100644 src/pages/api/webhooks/saleor/transaction-charge-requested.ts create mode 100644 src/pages/api/webhooks/saleor/transaction-initialize-session.ts create mode 100644 src/pages/api/webhooks/saleor/transaction-process-session.ts create mode 100644 src/pages/api/webhooks/saleor/transaction-refund-requested.ts create mode 100644 src/pages/api/webhooks/stripe/index.ts create mode 100644 src/pages/config.tsx create mode 100644 src/pages/configurations/add.tsx create mode 100644 src/pages/configurations/edit/[configurationId].tsx create mode 100644 src/pages/configurations/list.tsx create mode 100644 src/pages/index.tsx create mode 100644 src/run-migrations.ts create mode 100644 src/saleor-app.ts create mode 100644 src/schemas/.gitignore create mode 100644 src/schemas/PaymentGatewayInitializeSession/PaymentGatewayInitializeSessionRequestData.schema.json create mode 100644 src/schemas/PaymentGatewayInitializeSession/PaymentGatewayInitializeSessionResponse.schema.json create mode 100644 src/schemas/TransactionCancelationRequested/TransactionCancelationRequestedResponse.schema.json create mode 100644 src/schemas/TransactionChargeRequested/TransactionChargeRequestedResponse.schema.json create mode 100644 src/schemas/TransactionInitializeSession/TransactionInitializeSessionResponse.schema.json create mode 100644 src/schemas/TransactionProcessSession/TransactionProcessSessionResponse.schema.json create mode 100644 src/schemas/TransactionRefundRequesed/TransactionRefundRequestedResponse.schema.json create mode 100644 src/schemas/__snapshots__/compiler.test.ts.snap create mode 100644 src/schemas/definitions.json create mode 100644 src/setup-tests.ts create mode 100644 src/styles/global.css.ts create mode 100644 src/types.ts create mode 100644 tsconfig.json create mode 100644 typings/vanilla-extract__next-plugin/index.d.ts create mode 100644 vitest.config.ts diff --git a/.changeset/config.json b/.changeset/config.json new file mode 100644 index 0000000..341e0bf --- /dev/null +++ b/.changeset/config.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json", + "changelog": "@changesets/cli/changelog", + "commit": false, + "fixed": [], + "linked": [], + "access": "restricted", + "baseBranch": "main", + "updateInternalDependencies": "patch", + "ignore": [], + "privatePackages": { + "version": true, + "tag": true + } +} diff --git a/.dependency-cruiser.js b/.dependency-cruiser.js new file mode 100644 index 0000000..f5ac697 --- /dev/null +++ b/.dependency-cruiser.js @@ -0,0 +1,274 @@ +/** @type {import('dependency-cruiser').IConfiguration} */ +export default { + forbidden: [ + /* rules from the 'recommended' preset: */ + { + name: "no-circular", + severity: "warn", + comment: + "This dependency is part of a circular relationship. You might want to revise " + + "your solution (i.e. use dependency inversion, make sure the modules have a single responsibility) ", + from: {}, + to: { + circular: true, + }, + }, + { + name: "no-orphans", + comment: + "This is an orphan module - it's likely not used (anymore?). Either use it or " + + "remove it. If it's logical this module is an orphan (i.e. it's a config file), " + + "add an exception for it in your dependency-cruiser configuration. By default " + + "this rule does not scrutinize dot-files (e.g. .eslintrc.js), TypeScript declaration " + + "files (.d.ts), tsconfig.json and some of the babel and webpack configs.", + severity: "warn", + from: { + orphan: true, + pathNot: [ + "(^|/)\\.[^/]+\\.(js|jsx|cjs|mjs|ts|tsx|cts|ctsx|mts|mtsx|json)$", // dot files + "\\.d\\.ts$", // TypeScript declaration files + "(^|/)tsconfig\\.json$", // TypeScript config + "(^|/)(babel|webpack)\\.config\\.(js|jsx|cjs|mjs|ts|tsx|cts|ctsx|mts|mtsx|json)$", // other configs + ], + }, + to: {}, + }, + { + name: "no-deprecated-core", + comment: + "A module depends on a node core module that has been deprecated. Find an alternative - these are " + + "bound to exist - node doesn't deprecate lightly.", + severity: "warn", + from: {}, + to: { + dependencyTypes: ["core"], + path: [ + "^(v8/tools/codemap)$", + "^(v8/tools/consarray)$", + "^(v8/tools/csvparser)$", + "^(v8/tools/logreader)$", + "^(v8/tools/profile_view)$", + "^(v8/tools/profile)$", + "^(v8/tools/SourceMap)$", + "^(v8/tools/splaytree)$", + "^(v8/tools/tickprocessor-driver)$", + "^(v8/tools/tickprocessor)$", + "^(node-inspect/lib/_inspect)$", + "^(node-inspect/lib/internal/inspect_client)$", + "^(node-inspect/lib/internal/inspect_repl)$", + "^(async_hooks)$", + "^(punycode)$", + "^(domain)$", + "^(constants)$", + "^(sys)$", + "^(_linklist)$", + "^(_stream_wrap)$", + ], + }, + }, + { + name: "not-to-deprecated", + comment: + "This module uses a (version of an) npm module that has been deprecated. Either upgrade to a later " + + "version of that module, or find an alternative. Deprecated modules are a security risk.", + severity: "warn", + from: {}, + to: { + dependencyTypes: ["deprecated"], + }, + }, + { + name: "no-non-package-json", + severity: "error", + comment: + "This module depends on an npm package that isn't in the 'dependencies' section of your package.json. " + + "That's problematic as the package either (1) won't be available on live (2 - worse) will be " + + "available on live with an non-guaranteed version. Fix it by adding the package to the dependencies " + + "in your package.json.", + from: {}, + to: { + dependencyTypes: ["npm-no-pkg", "npm-unknown"], + }, + }, + { + name: "not-to-unresolvable", + comment: + "This module depends on a module that cannot be found ('resolved to disk'). If it's an npm " + + "module: add it to your package.json. In all other cases you likely already know what to do.", + severity: "error", + from: { + pathNot: "generated/graphql.ts", + }, + to: { + pathNot: "@saleor/app-sdk/types", + couldNotResolve: true, + dependencyTypesNot: ["type-only"], + }, + }, + { + name: "no-duplicate-dep-types", + comment: + "Likely this module depends on an external ('npm') package that occurs more than once " + + "in your package.json i.e. bot as a devDependencies and in dependencies. This will cause " + + "maintenance problems later on.", + severity: "warn", + from: {}, + to: { + moreThanOneDependencyType: true, + // as it's pretty common to have a type import be a type only import + // _and_ (e.g.) a devDependency - don't consider type-only dependency + // types for this rule + dependencyTypesNot: ["type-only"], + }, + }, + + /* rules you might want to tweak for your specific situation: */ + { + name: "not-to-spec", + comment: + "This module depends on a spec (test) file. The sole responsibility of a spec file is to test code. " + + "If there's something in a spec that's of use to other modules, it doesn't have that single " + + "responsibility anymore. Factor it out into (e.g.) a separate utility/ helper or a mock.", + severity: "error", + from: { + pathNot: + "(saleor-app\\.ts$)|(__tests__/\\.*)|(\\.(spec|test)\\.(js|jsx|mjs|cjs|ts|tsx|cts|ctsx|mts|mtsx\\.md)$)", + }, + to: { + path: "(__tests__/\\.*)|(\\.(spec|test)\\.(js|jsx|mjs|cjs|ts|tsx|cts|ctsx|mts|mtsx\\.md)$)", + }, + }, + { + name: "not-to-dev-dep", + severity: "error", + comment: + "This module depends on an npm package from the 'devDependencies' section of your " + + "package.json. It looks like something that ships to production, though. To prevent problems " + + "with npm packages that aren't there on production declare it (only!) in the 'dependencies'" + + "section of your package.json. If this module is development only - add it to the " + + "from.pathNot re of the not-to-dev-dep rule in the dependency-cruiser configuration", + from: { + path: "^(src)", + pathNot: + "(src/schemas/compiler.mts)|(.*/__tests__/.*)|(setup-tests\\.ts$)|(\\.(spec|test)\\.(js|jsx|mjs|cjs|ts|tsx|cts|ctsx|mts|mtsx\\.md))$", + }, + to: { + dependencyTypes: ["npm-dev"], + }, + }, + { + name: "optional-deps-used", + severity: "info", + comment: + "This module depends on an npm package that is declared as an optional dependency " + + "in your package.json. As this makes sense in limited situations only, it's flagged here. " + + "If you're using an optional dependency here by design - add an exception to your" + + "dependency-cruiser configuration.", + from: {}, + to: { + dependencyTypes: ["npm-optional"], + }, + }, + { + name: "peer-deps-used", + comment: + "This module depends on an npm package that is declared as a peer dependency " + + "in your package.json. This makes sense if your package is e.g. a plugin, but in " + + "other cases - maybe not so much. If the use of a peer dependency is intentional " + + "add an exception to your dependency-cruiser configuration.", + severity: "warn", + from: {}, + to: { + dependencyTypes: ["npm-peer"], + }, + }, + ], + options: { + /* conditions specifying which files not to follow further when encountered: + - path: a regular expression to match + - dependencyTypes: see https://github.com/sverweij/dependency-cruiser/blob/master/doc/rules-reference.md#dependencytypes-and-dependencytypesnot + for a complete list + */ + doNotFollow: { + path: "node_modules", + }, + + /* false (the default): ignore dependencies that only exist before typescript-to-javascript compilation + true: also detect dependencies that only exist before typescript-to-javascript compilation + "specify": for each dependency identify whether it only exists before compilation or also after + */ + tsPreCompilationDeps: true, + + /* TypeScript project file ('tsconfig.json') to use for + (1) compilation and + (2) resolution (e.g. with the paths property) + + The (optional) fileName attribute specifies which file to take (relative to + dependency-cruiser's current working directory). When not provided + defaults to './tsconfig.json'. + */ + tsConfig: { + fileName: "tsconfig.json", + }, + + /* options to pass on to enhanced-resolve, the package dependency-cruiser + uses to resolve module references to disk. You can set most of these + options in a webpack.conf.js - this section is here for those + projects that don't have a separate webpack config file. + + Note: settings in webpack.conf.js override the ones specified here. + */ + enhancedResolveOptions: { + /* List of strings to consider as 'exports' fields in package.json. Use + ['exports'] when you use packages that use such a field and your environment + supports it (e.g. node ^12.19 || >=14.7 or recent versions of webpack). + + If you have an `exportsFields` attribute in your webpack config, that one + will have precedence over the one specified here. + */ + exportsFields: ["exports"], + /* List of conditions to check for in the exports field. e.g. use ['imports'] + if you're only interested in exposed es6 modules, ['require'] for commonjs, + or all conditions at once `(['import', 'require', 'node', 'default']`) + if anything goes for you. Only works when the 'exportsFields' array is + non-empty. + + If you have a 'conditionNames' attribute in your webpack config, that one will + have precedence over the one specified here. + */ + conditionNames: ["import", "require", "node", "default"], + /* + If your TypeScript project makes use of types specified in 'types' + fields in package.jsons of external dependencies, specify "types" + in addition to "main" in here, so enhanced-resolve (the resolver + dependency-cruiser uses) knows to also look there. You can also do + this if you're not sure, but still use TypeScript. In a future version + of dependency-cruiser this will likely become the default. + */ + mainFields: ["module", "main", "types"], + }, + reporterOptions: { + dot: { + /* pattern of modules that can be consolidated in the detailed + graphical dependency graph. The default pattern in this configuration + collapses everything in node_modules to one folder deep so you see + the external modules, but not the innards your app depends upon. + */ + collapsePattern: "node_modules/(@[^/]+/[^/]+|[^/]+)", + }, + archi: { + /* pattern of modules that can be consolidated in the high level + graphical dependency graph. If you use the high level graphical + dependency graph reporter (`archi`) you probably want to tweak + this collapsePattern to your situation. + */ + collapsePattern: + "^(packages|src|lib|app|bin|test(s?)|spec(s?))/[^/]+|node_modules/(@[^/]+/[^/]+|[^/]+)", + }, + text: { + highlightFocused: true, + }, + }, + }, +}; +// generated: dependency-cruiser@12.11.0 on 2023-03-25T15:14:42.761Z diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..eb8bbe2 --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +#"fatal" | "error" | "warn" | "info" | "debug" | "trace" +APP_DEBUG=info +SECRET_KEY=aaaaaaaa diff --git a/.env.test b/.env.test new file mode 100644 index 0000000..137dc74 --- /dev/null +++ b/.env.test @@ -0,0 +1,14 @@ +APP_DEBUG=error +SECRET_KEY=aaaaaaaa + +TEST_SALEOR_API_URL="https://saleor.localhost:8080/graphql/" +TEST_SALEOR_JWKS='{\"keys\": [{\"kty\": \"RSA\", \"key_ops\": [\"verify\"], \"n\": \"1dBwlEgrHxAM64KH-pupx-VBeISR4Jkh6NLIDStGarXQkLECSMrmGd8eIzKZ4vSvOF0zxfE7zFVRTm4MzFWBxrr0YWoWQRDIKteEcUTDerfVQ0NbUPZAz6siIg4X-qI1rWWu85nkjWAFOax6ociMh9nG46pekueATkjd6lxdrkcjLUgRMm_CRoIQL8Ad7tYt67Ua8gvIkXcF5pV6Cr7ukjySnOzavP25k6XkAgmNEI_Nl60rL4a0imoBZUXRoWCXmqpPFNH5HtyHj7FxFEEoqPZ_-4NIT-eTMgrbqC-lLixjQuyZIZcZHXiC0CBcw-cdPSxsqqcxagcSiBrzoX9idw\", \"e\": \"AQAB\", \"use\": \"sig\", \"kid\": \"1\"}]}' + +# Remaining TEST_* vars must be configured separately +TEST_SALEOR_APP_TOKEN=op://Shop-ex/saleor-app-payment-stripe_TEST_ENVS/TEST_SALEOR_APP_TOKEN +TEST_SALEOR_APP_ID=op://Shop-ex/saleor-app-payment-stripe_TEST_ENVS/TEST_SALEOR_APP_ID +TEST_PAYMENT_APP_SECRET_KEY=op://Shop-ex/saleor-app-payment-stripe_TEST_ENVS/TEST_PAYMENT_APP_SECRET_KEY +TEST_PAYMENT_APP_PUBLISHABLE_KEY=op://Shop-ex/saleor-app-payment-stripe_TEST_ENVS/TEST_PAYMENT_APP_PUBLISHABLE_KEY +TEST_PAYMENT_APP_WEBHOOK_SECRET=op://Shop-ex/saleor-app-payment-stripe_TEST_ENVS/TEST_PAYMENT_APP_WEBHOOK_SECRET +TEST_PAYMENT_APP_WEBHOOK_ID=op://Shop-ex/saleor-app-payment-stripe_TEST_ENVS/TEST_PAYMENT_APP_WEBHOOK_ID +# When you add more variables remember to add them in .github/workflows/main.yml and src/__tests__/test-env.mjs diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..dfc5bb4 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,3 @@ +generated/ +src/schemas/**/*.mjs +src/schemas/**/*.mts diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..4a3381a --- /dev/null +++ b/.eslintrc @@ -0,0 +1,150 @@ +{ + "$schema": "https://json.schemastore.org/eslintrc.json", + "plugins": ["@typescript-eslint", "require-form-method", "node", "vitest"], + "parserOptions": { + "project": "tsconfig.json" + }, + "extends": [ + "next", + "next/core-web-vitals", + "plugin:@typescript-eslint/recommended", + "plugin:@typescript-eslint/recommended-requiring-type-checking", + "plugin:import/recommended", + "plugin:import/typescript", + "prettier", + "plugin:vitest/recommended", + "plugin:@saleor/saleor-app/recommended" + ], + "rules": { + // use double quotes, allow template strings + "quotes": ["error", "double", { "avoidEscape": true }], + + // sort imports + "import/order": "error", + + // no let exports + "import/no-mutable-exports": "error", + + "import/no-cycle": "error", + "import/no-default-export": "error", + + // prevent default import from Sentry because it doesn't work 😬 + "no-restricted-syntax": [ + "error", + { + "selector": "ImportDeclaration[source.value='@sentry/nextjs'] > ImportDefaultSpecifier", + "message": "Use `import * as Sentry from '@sentry/nextjs';`" + } + ], + + // allow {} even though it's unsafe but comes handy + "@typescript-eslint/ban-types": [ + "error", + { + "types": { + "{}": false + } + } + ], + + "@typescript-eslint/consistent-type-imports": [ + "error", + { + "prefer": "type-imports", + "fixStyle": "inline-type-imports", + "disallowTypeAnnotations": false + } + ], + + "import/no-duplicates": ["error", { "prefer-inline": true }], + + "@typescript-eslint/no-restricted-imports": [ + "error", + { + "patterns": [ + { + "group": ["@/__tests__/test-env.mjs"], + "message": "Test envs cannot be imported into application code" + } + ] + } + ], + + "node/no-process-env": ["error"], + + // false negatives + "import/namespace": ["off"], + + // we allow empty interfaces + "no-empty-pattern": "off", + "@typescript-eslint/no-empty-interface": "off", + + // we allow empty functions + "@typescript-eslint/no-empty-function": "off", + + // we sometimes use async functions that don't await anything + "@typescript-eslint/require-await": "off", + + // make sure to `await` inside try…catch + "@typescript-eslint/return-await": ["error", "in-try-catch"], + + // allow unused vars prefixed with `_` + "@typescript-eslint/no-unused-vars": [ + "error", + { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" } + ], + + // numbers and booleans are fine in template strings + "@typescript-eslint/restrict-template-expressions": [ + "error", + { "allowNumber": true, "allowBoolean": true } + ], + + // for security reasons, always require forms to provide method="post" + "require-form-method/require-form-method": "error", + + // for security reasons, always require buttons to provide type="button" ("submit" on rare occasions) + "react/button-has-type": ["error", { "button": true, "submit": true, "reset": false }] + }, + "overrides": [ + { + "files": ["*.test.tsx", "*.test.ts", "**/__tests__/**/*.ts?(x)"], + "rules": { + // let's make our lives easier in tests + "@typescript-eslint/no-unsafe-assignment": "off", + "@typescript-eslint/no-unsafe-member-access": "off", + "@typescript-eslint/no-unsafe-return": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-non-null-assertion": "off", + + // allow imports from testEnv + "@typescript-eslint/no-restricted-imports": "off" + } + }, + { + // https://github.com/testing-library/eslint-plugin-testing-library#run-the-plugin-only-against-test-files + "files": ["**/__tests__/**/*.[jt]sx", "**/?(*.)+(spec|test).[jt]sx"], + "extends": ["plugin:testing-library/react"] + }, + { + // We allow process.env access in env.mjs and testEnv.mjs + "files": ["**/env.mjs", "**/test-env.mjs", "next.config.mjs"], + "rules": { + "node/no-process-env": "off" + } + }, + { + "files": ["src/pages/**/*.ts?(x)"], + "rules": { + "import/no-default-export": "off" + } + }, + { + "files": ["*.cjs", "*.cts"], + "rules": { + "@typescript-eslint/no-var-requires": "off" + } + } + ], + "ignorePatterns": ["*.js", "*.jsx"] +} diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..e66e70e --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.har linguist-generated=true diff --git a/.graphqlrc.yml b/.graphqlrc.yml new file mode 100644 index 0000000..38ba902 --- /dev/null +++ b/.graphqlrc.yml @@ -0,0 +1,48 @@ +schema: graphql/schema.graphql +documents: [graphql/**/*.graphql, src/migrations/**/*.graphql, src/**/*.ts, src/**/*.tsx] +extensions: + codegen: + overwrite: true + generates: + generated/graphql.ts: + hooks: + afterAllFileWrite: + - prettier --write + config: + immutableTypes: true + strictScalars: true + defaultScalarType: "unknown" + useTypeImports: true + dedupeFragments: true + skipTypename: true + scalars: + _Any: "unknown" + Date: "string" + DateTime: "string" + Decimal: "number" + Minute: "number" + GenericScalar: "JSONValue" + JSON: "JSONValue" + JSONString: "string" + Metadata: "Record" + PositiveDecimal: "number" + Upload: "unknown" + UUID: "string" + WeightScalar: "number" + plugins: + - add: + content: | + /* c8 ignore start */ + import type { JSONValue } from '@/types'; + - typescript + - typescript-operations: + skipTypeNameForRoot: true + exportFragmentSpreadSubTypes: true + - urql-introspection + - typescript-urql: + documentVariablePrefix: "Untyped" + fragmentVariablePrefix: "Untyped" + - typed-document-node + generated/schema.graphql: + plugins: + - schema-ast diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..58b1861 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +pnpm exec lint-staged diff --git a/.lintstagedrc.js b/.lintstagedrc.js new file mode 100644 index 0000000..7a27c6b --- /dev/null +++ b/.lintstagedrc.js @@ -0,0 +1,13 @@ +// https://nextjs.org/docs/basic-features/eslint#lint-staged + +import path from "path"; + +const buildEslintCommand = (filenames) => + `next lint --fix --file ${filenames + .map((f) => path.relative(process.cwd(), f)) + .join(" --file ")}`; + +export default { + "*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}": [buildEslintCommand], + "*.*": "prettier --write --ignore-unknown", +}; diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..1cf98d2 --- /dev/null +++ b/.npmrc @@ -0,0 +1,2 @@ +strict-peer-dependencies=false +save-exact=true diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..a26e18c --- /dev/null +++ b/.prettierignore @@ -0,0 +1,11 @@ +.next +pnpm-lock.yaml +graphql/schema.graphql +*.har +src/schemas/**/*.ts +src/schemas/**/*.mts +src/schemas/**/*.cts +src/schemas/**/*.js +src/schemas/**/*.mjs +src/schemas/**/*.cjs +coverage/** diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..f5724e7 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,5 @@ +{ + "singleQuote": false, + "printWidth": 100, + "trailingComma": "all" +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..f6f4ac4 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,8 @@ +{ + "recommendations": [ + "graphql.vscode-graphql", + "graphql.vscode-graphql-syntax", + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode" + ] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..4bd141a --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Launch Program", + "skipFiles": ["/**"], + "program": "${workspaceFolder}/src/pages/api/test.ts", + "outFiles": ["${workspaceFolder}/**/*.js"] + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..255ed78 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "editor.formatOnSave": true, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "typescript.tsdk": "node_modules/typescript/lib", + "eslint.run": "onSave", + "editor.codeActionsOnSave": { + "source.fixAll": "always" + }, + "graphql-config.load.rootDir": "./", + "graphql-config.load.configName": "graphql" +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..d66ac75 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,40 @@ +# saleor-app-payment-stripe + +## 0.4.0 + +### Minor Changes + +- c69f6b8: Added "ALLOWED_DOMAIN_PATTERN" env that can be used to allow/disallow specific Saleor instances + +## 0.3.0 + +### Minor Changes + +- 6817fbe: Fixed blank configuration screen; Stripe API is now on the latest version + +### Patch Changes + +- e47cd4e: Bumped zod from 3.22.2 to 3.22.3 + +## 0.2.1 + +### Patch Changes + +- be1419f: Update Sentry to 7.77.0 + +## 0.2.0 + +### Minor Changes + +- a1df783: Add webhook ID to the summary view + +### Patch Changes + +- a1df783: Add simple skeletons +- 4d8b58b: Add more logs + +## 0.1.0 + +### Minor Changes + +- baf1c0e: Initial release diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..b771f0c --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,3 @@ +* @saleor/apps-guild +/.github/ @saleor/SRE +* @saleor/Shopex-JS diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..f7b22d8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,50 @@ +# syntax = docker/dockerfile:1 +ARG NODE_VERSION=22.9.0 +FROM node:${NODE_VERSION}-slim AS base +ENV NODE_VERSION="$NODE_VERSION" + + +LABEL fly_launch_runtime="Next.js" + +# Next.js app lives here +WORKDIR /app + +# Install pnpm +ARG PNPM_VERSION=8.12.0 +RUN npm install -g pnpm@$PNPM_VERSION + + +FROM base AS build + +# Set these via `docker run -e APP_DEBUG=debug ...` +# OR set them in your deployed containers environment secrets +# these are needed for pnpm install schema:generate +ENV APL='file' +ENV APP_DEBUG='debug' +# do not replace these here, set these in the deployed environment, or docker run -e ... +# ENV TEST_SALEOR_API_URL='' +# ENV UPSTASH_TOKEN='' +# ENV UPSTASH_URL='' +# ENV SECRET_KEY='test-see-comment-above' + + +ENV NODE_ENV="production" + +WORKDIR /app + +COPY package.json pnpm-lock.yaml ./ +RUN pnpm install --frozen-lockfile --prod=false + +COPY . . +RUN SECRET_KEY='test-see-comment-above' pnpm run build +# Remove development dependencies +RUN pnpm prune --prod +# Final stage for app image +FROM base + +# Copy built application +COPY --from=build /app /app + +# Start the server by default, this can be overwritten at runtime +EXPOSE 3000 +CMD [ "pnpm", "run", "start" ] diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..0e86c47 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,5 @@ +# Reporting a Vulnerability + +If you discover a security vulnerability in saleor-app-payment-stripe please disclose it via [our huntr page](https://huntr.dev/repos/saleor/saleor-app-payment-stripe/). Information about bounties, CVEs, response times and past reports are all there. + +Thank you for improving the security of saleor-app-payment-stripe. diff --git a/fix-coverage-report.cjs b/fix-coverage-report.cjs new file mode 100755 index 0000000..6dee6dc --- /dev/null +++ b/fix-coverage-report.cjs @@ -0,0 +1,22 @@ +#!/usr/bin/env node +/* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment */ + +// https://github.com/ArtiomTr/jest-coverage-report-action/issues/244#issuecomment-1260555231 +const fs = require("fs"); + +const testReportFilename = process.cwd() + "/coverage/report.json"; +const coverageReportFilename = process.cwd() + "/coverage/coverage-final.json"; + +const testReport = require(testReportFilename); +const coverageReport = require(coverageReportFilename); + +testReport.coverageMap = coverageReport; + +fs.writeFile(testReportFilename, JSON.stringify(testReport), (err) => { + if (err) { + console.error(err); + process.exit(1); + } + + console.log("Coverage report appended to " + testReportFilename); +}); diff --git a/global.d.ts b/global.d.ts new file mode 100644 index 0000000..66bc00f --- /dev/null +++ b/global.d.ts @@ -0,0 +1,39 @@ +type NonFalsy = T extends false | 0 | "" | null | undefined | 0n ? never : T; + +interface Array { + includes(searchElement: unknown, fromIndex?: number): searchElement is T; +} + +interface ReadonlyArray { + includes(searchElement: unknown, fromIndex?: number): searchElement is T; +} + +interface Body { + json(): Promise; +} + +interface Array { + filter(predicate: BooleanConstructor, thisArg?: unknown): NonFalsy[]; +} + +interface ReadonlyArray { + filter(predicate: BooleanConstructor, thisArg?: unknown): NonFalsy[]; +} + +interface ArrayConstructor { + isArray(arg: unknown): arg is unknown[]; +} + +interface JSON { + /** + * Converts a JavaScript Object Notation (JSON) string into an object. + * @param text A valid JSON string. + * @param reviver A function that transforms the results. This function is called for each member of the object. + * If a member contains nested objects, the nested objects are transformed before the parent object is. + */ + parse(text: string, reviver?: (this: unknown, key: string, value: unknown) => unknown): unknown; +} + +interface Set { + has(value: unknown): value is T; +} diff --git a/graphql/fragments/.gitkeep b/graphql/fragments/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/graphql/fragments/Money.graphql b/graphql/fragments/Money.graphql new file mode 100644 index 0000000..0ce4dff --- /dev/null +++ b/graphql/fragments/Money.graphql @@ -0,0 +1,4 @@ +fragment Money on Money { + currency + amount +} diff --git a/graphql/fragments/OrderOrCheckoutLines.graphql b/graphql/fragments/OrderOrCheckoutLines.graphql new file mode 100644 index 0000000..ddfef23 --- /dev/null +++ b/graphql/fragments/OrderOrCheckoutLines.graphql @@ -0,0 +1,110 @@ +fragment OrderOrCheckoutLines on OrderOrCheckout { + __typename + ... on Checkout { + channel { + id + slug + } + shippingPrice { + gross { + ...Money + } + net { + ...Money + } + tax { + ...Money + } + } + deliveryMethod { + __typename + ... on ShippingMethod { + id + name + } + } + lines { + __typename + id + quantity + totalPrice { + gross { + ...Money + } + net { + ...Money + } + tax { + ...Money + } + } + checkoutVariant: variant { + name + sku + product { + name + thumbnail { + url + } + category { + name + } + } + } + } + } + ... on Order { + channel { + id + slug + } + shippingPrice { + gross { + ...Money + } + net { + ...Money + } + tax { + ...Money + } + } + deliveryMethod { + __typename + ... on ShippingMethod { + id + name + } + } + lines { + __typename + id + quantity + taxRate + totalPrice { + gross { + ...Money + } + net { + ...Money + } + tax { + ...Money + } + } + orderVariant: variant { + name + sku + product { + name + thumbnail { + url + } + category { + name + } + } + } + } + } +} diff --git a/graphql/fragments/OrderOrCheckoutSourceObject.graphql b/graphql/fragments/OrderOrCheckoutSourceObject.graphql new file mode 100644 index 0000000..5efe046 --- /dev/null +++ b/graphql/fragments/OrderOrCheckoutSourceObject.graphql @@ -0,0 +1,45 @@ +fragment OrderOrCheckoutSourceObject on OrderOrCheckout { + __typename + ... on Checkout { + id + languageCode + channel { + id + slug + } + userEmail: email + billingAddress { + ...TransactionInitializeSessionAddress + } + shippingAddress { + ...TransactionInitializeSessionAddress + } + total: totalPrice { + gross { + ...Money + } + } + ...OrderOrCheckoutLines + } + ... on Order { + id + languageCodeEnum + userEmail + channel { + id + slug + } + billingAddress { + ...TransactionInitializeSessionAddress + } + shippingAddress { + ...TransactionInitializeSessionAddress + } + total { + gross { + ...Money + } + } + ...OrderOrCheckoutLines + } +} diff --git a/graphql/fragments/PaymentGatewayInitializeSessionAddress.graphql b/graphql/fragments/PaymentGatewayInitializeSessionAddress.graphql new file mode 100644 index 0000000..3f0bbc5 --- /dev/null +++ b/graphql/fragments/PaymentGatewayInitializeSessionAddress.graphql @@ -0,0 +1,5 @@ +fragment PaymentGatewayInitializeSessionAddress on Address { + country { + code + } +} diff --git a/graphql/fragments/PaymentGatewayInitializeSessionEvent.graphql b/graphql/fragments/PaymentGatewayInitializeSessionEvent.graphql new file mode 100644 index 0000000..dabeb82 --- /dev/null +++ b/graphql/fragments/PaymentGatewayInitializeSessionEvent.graphql @@ -0,0 +1,49 @@ +fragment PaymentGatewayInitializeSessionEvent on PaymentGatewayInitializeSession { + __typename + recipient { + ...PaymentGatewayRecipient + } + data + amount + issuingPrincipal { + ... on Node { + id + } + } + sourceObject { + __typename + ... on Checkout { + id + channel { + id + slug + } + languageCode + billingAddress { + ...PaymentGatewayInitializeSessionAddress + } + total: totalPrice { + gross { + ...Money + } + } + } + ... on Order { + id + channel { + id + slug + } + languageCodeEnum + userEmail + billingAddress { + ...PaymentGatewayInitializeSessionAddress + } + total { + gross { + ...Money + } + } + } + } +} diff --git a/graphql/fragments/PaymentGatewayRecipient.graphql b/graphql/fragments/PaymentGatewayRecipient.graphql new file mode 100644 index 0000000..548a15c --- /dev/null +++ b/graphql/fragments/PaymentGatewayRecipient.graphql @@ -0,0 +1,11 @@ +fragment PaymentGatewayRecipient on App { + id + privateMetadata { + key + value + } + metadata { + key + value + } +} diff --git a/graphql/fragments/TransactionCancelationRequestedEvent.graphql b/graphql/fragments/TransactionCancelationRequestedEvent.graphql new file mode 100644 index 0000000..494cc5a --- /dev/null +++ b/graphql/fragments/TransactionCancelationRequestedEvent.graphql @@ -0,0 +1,20 @@ +fragment TransactionCancelationRequestedEvent on TransactionCancelationRequested { + __typename + recipient { + ...PaymentGatewayRecipient + } + action { + actionType + amount + } + transaction { + id + pspReference + sourceObject: order { + channel { + id + slug + } + } + } +} diff --git a/graphql/fragments/TransactionChargeRequestedEvent.graphql b/graphql/fragments/TransactionChargeRequestedEvent.graphql new file mode 100644 index 0000000..bf17e4b --- /dev/null +++ b/graphql/fragments/TransactionChargeRequestedEvent.graphql @@ -0,0 +1,24 @@ +fragment TransactionChargeRequestedEvent on TransactionChargeRequested { + __typename + recipient { + ...PaymentGatewayRecipient + } + action { + amount + actionType + } + transaction { + id + pspReference + sourceObject: order { + ... on Order { + total { + gross { + ...Money + } + } + } + ...OrderOrCheckoutLines + } + } +} diff --git a/graphql/fragments/TransactionInitializeSessionAddress.graphql b/graphql/fragments/TransactionInitializeSessionAddress.graphql new file mode 100644 index 0000000..9522831 --- /dev/null +++ b/graphql/fragments/TransactionInitializeSessionAddress.graphql @@ -0,0 +1,14 @@ +fragment TransactionInitializeSessionAddress on Address { + firstName + lastName + phone + city + streetAddress1 + streetAddress2 + postalCode + countryArea + companyName + country { + code + } +} diff --git a/graphql/fragments/TransactionInitializeSessionEvent.graphql b/graphql/fragments/TransactionInitializeSessionEvent.graphql new file mode 100644 index 0000000..5894bda --- /dev/null +++ b/graphql/fragments/TransactionInitializeSessionEvent.graphql @@ -0,0 +1,26 @@ +fragment TransactionInitializeSessionEvent on TransactionInitializeSession { + __typename + recipient { + ...PaymentGatewayRecipient + } + data + merchantReference + action { + amount + currency + actionType + } + issuingPrincipal { + ... on Node { + id + } + } + transaction { + id + pspReference + } + sourceObject { + __typename + ...OrderOrCheckoutSourceObject + } +} diff --git a/graphql/fragments/TransactionProcessSessionEvent.graphql b/graphql/fragments/TransactionProcessSessionEvent.graphql new file mode 100644 index 0000000..2f8444b --- /dev/null +++ b/graphql/fragments/TransactionProcessSessionEvent.graphql @@ -0,0 +1,54 @@ +fragment TransactionProcessSessionEvent on TransactionProcessSession { + __typename + recipient { + ...PaymentGatewayRecipient + } + data + merchantReference + action { + amount + currency + actionType + } + transaction { + id + pspReference + } + sourceObject { + __typename + ... on Checkout { + id + languageCode + userEmail: email + billingAddress { + ...TransactionInitializeSessionAddress + } + shippingAddress { + ...TransactionInitializeSessionAddress + } + total: totalPrice { + gross { + ...Money + } + } + ...OrderOrCheckoutLines + } + ... on Order { + id + languageCodeEnum + userEmail + billingAddress { + ...TransactionInitializeSessionAddress + } + shippingAddress { + ...TransactionInitializeSessionAddress + } + total { + gross { + ...Money + } + } + ...OrderOrCheckoutLines + } + } +} diff --git a/graphql/fragments/TransactionRefundRequestedEvent.graphql b/graphql/fragments/TransactionRefundRequestedEvent.graphql new file mode 100644 index 0000000..f3d33e2 --- /dev/null +++ b/graphql/fragments/TransactionRefundRequestedEvent.graphql @@ -0,0 +1,24 @@ +fragment TransactionRefundRequestedEvent on TransactionRefundRequested { + __typename + recipient { + ...PaymentGatewayRecipient + } + action { + amount + actionType + } + transaction { + id + pspReference + sourceObject: order { + ... on Order { + total { + gross { + ...Money + } + } + } + ...OrderOrCheckoutLines + } + } +} diff --git a/graphql/mutations/.gitkeep b/graphql/mutations/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/graphql/mutations/TransactionEventReport.graphql b/graphql/mutations/TransactionEventReport.graphql new file mode 100644 index 0000000..99c9ad9 --- /dev/null +++ b/graphql/mutations/TransactionEventReport.graphql @@ -0,0 +1,28 @@ +mutation TransactionEventReport( + $transactionId: ID! + $amount: PositiveDecimal! + $availableActions: [TransactionActionEnum!]! + $externalUrl: String! + $message: String + $pspReference: String! + $time: DateTime! + $type: TransactionEventTypeEnum! +) { + transactionEventReport( + id: $transactionId + amount: $amount + availableActions: $availableActions + externalUrl: $externalUrl + message: $message + pspReference: $pspReference + time: $time + type: $type + ) { + alreadyProcessed + errors { + field + message + code + } + } +} diff --git a/graphql/mutations/UpdateAppMetadata.graphql b/graphql/mutations/UpdateAppMetadata.graphql new file mode 100644 index 0000000..718ec63 --- /dev/null +++ b/graphql/mutations/UpdateAppMetadata.graphql @@ -0,0 +1,10 @@ +mutation UpdateAppMetadata($id: ID!, $input: [MetadataInput!]!) { + updatePrivateMetadata(id: $id, input: $input) { + item { + privateMetadata { + key + value + } + } + } +} diff --git a/graphql/mutations/UpdatePublicMetadata.graphql b/graphql/mutations/UpdatePublicMetadata.graphql new file mode 100644 index 0000000..3fc5b65 --- /dev/null +++ b/graphql/mutations/UpdatePublicMetadata.graphql @@ -0,0 +1,10 @@ +mutation UpdatePublicMetadata($id: ID!, $input: [MetadataInput!]!) { + updateMetadata(id: $id, input: $input) { + item { + metadata { + key + value + } + } + } +} diff --git a/graphql/queries/.gitkeep b/graphql/queries/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/graphql/queries/FetchAppDetails.graphql b/graphql/queries/FetchAppDetails.graphql new file mode 100644 index 0000000..c57da4f --- /dev/null +++ b/graphql/queries/FetchAppDetails.graphql @@ -0,0 +1,16 @@ +query FetchAppDetails { + shop { + schemaVersion + } + app { + id + privateMetadata { + key + value + } + metadata { + key + value + } + } +} diff --git a/graphql/queries/FetchChannels.graphql b/graphql/queries/FetchChannels.graphql new file mode 100644 index 0000000..255213e --- /dev/null +++ b/graphql/queries/FetchChannels.graphql @@ -0,0 +1,6 @@ +query FetchChannels { + channels { + id + name + } +} diff --git a/graphql/schema.graphql b/graphql/schema.graphql new file mode 100644 index 0000000..a210f4e --- /dev/null +++ b/graphql/schema.graphql @@ -0,0 +1,28869 @@ +schema { + query: Query + mutation: Mutation + subscription: Subscription +} + +type Query { + """ + Look up a webhook by ID. Requires one of the following permissions: MANAGE_APPS, OWNER. + """ + webhook( + """ID of the webhook.""" + id: ID! + ): Webhook + + """ + List of all available webhook events. + + Requires one of the following permissions: MANAGE_APPS. + """ + webhookEvents: [WebhookEvent!] @deprecated(reason: "This field will be removed in Saleor 4.0. Use `WebhookEventTypeAsyncEnum` and `WebhookEventTypeSyncEnum` to get available event types.") + + """ + Retrieve a sample payload for a given webhook event based on real data. It can be useful for some integrations where sample payload is required. + """ + webhookSamplePayload( + """Name of the requested event type.""" + eventType: WebhookSampleEventTypeEnum! + ): JSONString + + """ + Look up a warehouse by ID. + + Requires one of the following permissions: MANAGE_PRODUCTS, MANAGE_ORDERS, MANAGE_SHIPPING. + """ + warehouse( + """ID of a warehouse.""" + id: ID + + """ + External ID of a warehouse. + + Added in Saleor 3.10. + """ + externalReference: String + ): Warehouse + + """ + List of warehouses. + + Requires one of the following permissions: MANAGE_PRODUCTS, MANAGE_ORDERS, MANAGE_SHIPPING. + """ + warehouses( + filter: WarehouseFilterInput + sortBy: WarehouseSortingInput + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): WarehouseCountableConnection + + """ + Returns a list of all translatable items of a given kind. + + Requires one of the following permissions: MANAGE_TRANSLATIONS. + """ + translations( + """Kind of objects to retrieve.""" + kind: TranslatableKinds! + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): TranslatableItemConnection + + """ + Lookup a translatable item by ID. + + Requires one of the following permissions: MANAGE_TRANSLATIONS. + """ + translation( + """ID of the object to retrieve.""" + id: ID! + + """Kind of the object to retrieve.""" + kind: TranslatableKinds! + ): TranslatableItem + + """ + Look up a tax configuration. + + Added in Saleor 3.9. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: AUTHENTICATED_STAFF_USER, AUTHENTICATED_APP. + """ + taxConfiguration( + """ID of a tax configuration.""" + id: ID! + ): TaxConfiguration + + """ + List of tax configurations. + + Added in Saleor 3.9. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: AUTHENTICATED_STAFF_USER, AUTHENTICATED_APP. + """ + taxConfigurations( + """Filtering options for tax configurations.""" + filter: TaxConfigurationFilterInput + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): TaxConfigurationCountableConnection + + """ + Look up a tax class. + + Added in Saleor 3.9. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: AUTHENTICATED_STAFF_USER, AUTHENTICATED_APP. + """ + taxClass( + """ID of a tax class.""" + id: ID! + ): TaxClass + + """ + List of tax classes. + + Added in Saleor 3.9. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: AUTHENTICATED_STAFF_USER, AUTHENTICATED_APP. + """ + taxClasses( + """Sort tax classes.""" + sortBy: TaxClassSortingInput + + """Filtering options for tax classes.""" + filter: TaxClassFilterInput + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): TaxClassCountableConnection + + """ + Tax class rates grouped by country. + + Requires one of the following permissions: AUTHENTICATED_STAFF_USER, AUTHENTICATED_APP. + """ + taxCountryConfiguration( + """Country for which to return tax class rates.""" + countryCode: CountryCode! + ): TaxCountryConfiguration + + "\\n\\nRequires one of the following permissions: AUTHENTICATED_STAFF_USER, AUTHENTICATED_APP." + taxCountryConfigurations: [TaxCountryConfiguration!] + + """ + Look up a stock by ID + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + stock( + """ID of an warehouse""" + id: ID! + ): Stock + + """ + List of stocks. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + stocks( + filter: StockFilterInput + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): StockCountableConnection + + """Return information about the shop.""" + shop: Shop! + + """ + Order related settings from site settings. Returns `orderSettings` for the first `channel` in alphabetical order. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderSettings: OrderSettings @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `channel` query to fetch the `orderSettings` field instead.") + + """ + Gift card related settings from site settings. + + Requires one of the following permissions: MANAGE_GIFT_CARD. + """ + giftCardSettings: GiftCardSettings! + + """ + Look up a shipping zone by ID. + + Requires one of the following permissions: MANAGE_SHIPPING. + """ + shippingZone( + """ID of the shipping zone.""" + id: ID! + + """Slug of a channel for which the data should be returned.""" + channel: String + ): ShippingZone + + """ + List of the shop's shipping zones. + + Requires one of the following permissions: MANAGE_SHIPPING. + """ + shippingZones( + """Filtering options for shipping zones.""" + filter: ShippingZoneFilterInput + + """Slug of a channel for which the data should be returned.""" + channel: String + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): ShippingZoneCountableConnection + + """ + Look up digital content by ID. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + digitalContent( + """ID of the digital content.""" + id: ID! + ): DigitalContent + + """ + List of digital content. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + digitalContents( + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): DigitalContentCountableConnection + + """List of the shop's categories.""" + categories( + """Filtering options for categories.""" + filter: CategoryFilterInput + + """Sort categories.""" + sortBy: CategorySortingInput + + """Filter categories by the nesting level in the category tree.""" + level: Int + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): CategoryCountableConnection + + """Look up a category by ID or slug.""" + category( + """ID of the category.""" + id: ID + + """Slug of the category""" + slug: String + ): Category + + """ + Look up a collection by ID. Requires one of the following permissions to include the unpublished items: MANAGE_ORDERS, MANAGE_DISCOUNTS, MANAGE_PRODUCTS. + """ + collection( + """ID of the collection.""" + id: ID + + """Slug of the category""" + slug: String + + """Slug of a channel for which the data should be returned.""" + channel: String + ): Collection + + """ + List of the shop's collections. Requires one of the following permissions to include the unpublished items: MANAGE_ORDERS, MANAGE_DISCOUNTS, MANAGE_PRODUCTS. + """ + collections( + """Filtering options for collections.""" + filter: CollectionFilterInput + + """Sort collections.""" + sortBy: CollectionSortingInput + + """Slug of a channel for which the data should be returned.""" + channel: String + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): CollectionCountableConnection + + """ + Look up a product by ID. Requires one of the following permissions to include the unpublished items: MANAGE_ORDERS, MANAGE_DISCOUNTS, MANAGE_PRODUCTS. + """ + product( + """ID of the product.""" + id: ID + + """Slug of the product.""" + slug: String + + """ + External ID of the product. + + Added in Saleor 3.10. + """ + externalReference: String + + """Slug of a channel for which the data should be returned.""" + channel: String + ): Product + + """ + List of the shop's products. Requires one of the following permissions to include the unpublished items: MANAGE_ORDERS, MANAGE_DISCOUNTS, MANAGE_PRODUCTS. + """ + products( + """Filtering options for products.""" + filter: ProductFilterInput + + """Sort products.""" + sortBy: ProductOrder + + """Slug of a channel for which the data should be returned.""" + channel: String + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): ProductCountableConnection + + """Look up a product type by ID.""" + productType( + """ID of the product type.""" + id: ID! + ): ProductType + + """List of the shop's product types.""" + productTypes( + """Filtering options for product types.""" + filter: ProductTypeFilterInput + + """Sort product types.""" + sortBy: ProductTypeSortingInput + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): ProductTypeCountableConnection + + """ + Look up a product variant by ID or SKU. Requires one of the following permissions to include the unpublished items: MANAGE_ORDERS, MANAGE_DISCOUNTS, MANAGE_PRODUCTS. + """ + productVariant( + """ID of the product variant.""" + id: ID + + """Sku of the product variant.""" + sku: String + + """ + External ID of the product. + + Added in Saleor 3.10. + """ + externalReference: String + + """Slug of a channel for which the data should be returned.""" + channel: String + ): ProductVariant + + """ + List of product variants. Requires one of the following permissions to include the unpublished items: MANAGE_ORDERS, MANAGE_DISCOUNTS, MANAGE_PRODUCTS. + """ + productVariants( + """Filter product variants by given IDs.""" + ids: [ID!] + + """Slug of a channel for which the data should be returned.""" + channel: String + + """Filtering options for product variant.""" + filter: ProductVariantFilterInput + + """Sort products variants.""" + sortBy: ProductVariantSortingInput + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): ProductVariantCountableConnection + + """ + List of top selling products. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + reportProductSales( + """Span of time.""" + period: ReportingPeriod! + + """Slug of a channel for which the data should be returned.""" + channel: String! + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): ProductVariantCountableConnection + + """ + Look up a payment by ID. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + payment( + """ID of the payment.""" + id: ID! + ): Payment + + """ + List of payments. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + payments( + """Filtering options for payments.""" + filter: PaymentFilterInput + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): PaymentCountableConnection + + """ + Look up a transaction by ID. + + Added in Saleor 3.6. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: HANDLE_PAYMENTS. + """ + transaction( + """ID of a transaction.""" + id: ID! + ): TransactionItem + + """Look up a page by ID or slug.""" + page( + """ID of the page.""" + id: ID + + """The slug of the page.""" + slug: String + ): Page + + """List of the shop's pages.""" + pages( + """Sort pages.""" + sortBy: PageSortingInput + + """Filtering options for pages.""" + filter: PageFilterInput + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): PageCountableConnection + + """Look up a page type by ID.""" + pageType( + """ID of the page type.""" + id: ID! + ): PageType + + """List of the page types.""" + pageTypes( + """Sort page types.""" + sortBy: PageTypeSortingInput + + """Filtering options for page types.""" + filter: PageTypeFilterInput + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): PageTypeCountableConnection + + """ + List of activity events to display on homepage (at the moment it only contains order-events). + + Requires one of the following permissions: MANAGE_ORDERS. + """ + homepageEvents( + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): OrderEventCountableConnection + + """Look up an order by ID or external reference.""" + order( + """ID of an order.""" + id: ID + + """ + External ID of an order. + + Added in Saleor 3.10. + """ + externalReference: String + ): Order + + """ + List of orders. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orders( + """Sort orders.""" + sortBy: OrderSortingInput + + """Filtering options for orders.""" + filter: OrderFilterInput + + """Slug of a channel for which the data should be returned.""" + channel: String + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): OrderCountableConnection + + """ + List of draft orders. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + draftOrders( + """Sort draft orders.""" + sortBy: OrderSortingInput + + """Filtering options for draft orders.""" + filter: OrderDraftFilterInput + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): OrderCountableConnection + + """ + Return the total sales amount from a specific period. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + ordersTotal( + """A period of time.""" + period: ReportingPeriod + + """Slug of a channel for which the data should be returned.""" + channel: String + ): TaxedMoney + + """Look up an order by token.""" + orderByToken( + """The order's token.""" + token: UUID! + ): Order @deprecated(reason: "This field will be removed in Saleor 4.0.") + + """Look up a navigation menu by ID or name.""" + menu( + """Slug of a channel for which the data should be returned.""" + channel: String + + """ID of the menu.""" + id: ID + + """The menu's name.""" + name: String + + """The menu's slug.""" + slug: String + ): Menu + + """List of the storefront's menus.""" + menus( + """Slug of a channel for which the data should be returned.""" + channel: String + + """Sort menus.""" + sortBy: MenuSortingInput + + """ + Filtering options for menus. + + `slug`: This field will be removed in Saleor 4.0. Use `slugs` instead. + """ + filter: MenuFilterInput + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): MenuCountableConnection + + """Look up a menu item by ID.""" + menuItem( + """ID of the menu item.""" + id: ID! + + """Slug of a channel for which the data should be returned.""" + channel: String + ): MenuItem + + """List of the storefronts's menu items.""" + menuItems( + """Slug of a channel for which the data should be returned.""" + channel: String + + """Sort menus items.""" + sortBy: MenuItemSortingInput + + """Filtering options for menu items.""" + filter: MenuItemFilterInput + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): MenuItemCountableConnection + + """ + Look up a gift card by ID. + + Requires one of the following permissions: MANAGE_GIFT_CARD. + """ + giftCard( + """ID of the gift card.""" + id: ID! + ): GiftCard + + """ + List of gift cards. + + Requires one of the following permissions: MANAGE_GIFT_CARD. + """ + giftCards( + """ + Sort gift cards. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + sortBy: GiftCardSortingInput + + """ + Filtering options for gift cards. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + filter: GiftCardFilterInput + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): GiftCardCountableConnection + + """ + List of gift card currencies. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_GIFT_CARD. + """ + giftCardCurrencies: [String!]! + + """ + List of gift card tags. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_GIFT_CARD. + """ + giftCardTags( + """Filtering options for gift card tags.""" + filter: GiftCardTagFilterInput + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): GiftCardTagCountableConnection + + """ + Look up a plugin by ID. + + Requires one of the following permissions: MANAGE_PLUGINS. + """ + plugin( + """ID of the plugin.""" + id: ID! + ): Plugin + + """ + List of plugins. + + Requires one of the following permissions: MANAGE_PLUGINS. + """ + plugins( + """Filtering options for plugins.""" + filter: PluginFilterInput + + """Sort plugins.""" + sortBy: PluginSortingInput + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): PluginCountableConnection + + """ + Look up a sale by ID. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + sale( + """ID of the sale.""" + id: ID! + + """Slug of a channel for which the data should be returned.""" + channel: String + ): Sale + + """ + List of the shop's sales. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + sales( + """Filtering options for sales.""" + filter: SaleFilterInput + + """Sort sales.""" + sortBy: SaleSortingInput + + """ + Search sales by name, value or type. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `filter.search` input instead. + """ + query: String + + """Slug of a channel for which the data should be returned.""" + channel: String + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): SaleCountableConnection + + """ + Look up a voucher by ID. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + voucher( + """ID of the voucher.""" + id: ID! + + """Slug of a channel for which the data should be returned.""" + channel: String + ): Voucher + + """ + List of the shop's vouchers. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + vouchers( + """Filtering options for vouchers.""" + filter: VoucherFilterInput + + """Sort voucher.""" + sortBy: VoucherSortingInput + + """ + Search vouchers by name or code. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `filter.search` input instead. + """ + query: String + + """Slug of a channel for which the data should be returned.""" + channel: String + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): VoucherCountableConnection + + """ + Look up a export file by ID. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + exportFile( + """ID of the export file job.""" + id: ID! + ): ExportFile + + """ + List of export files. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + exportFiles( + """Filtering options for export files.""" + filter: ExportFileFilterInput + + """Sort export files.""" + sortBy: ExportFileSortingInput + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): ExportFileCountableConnection + + """List of all tax rates available from tax gateway.""" + taxTypes: [TaxType!] + + """Look up a checkout by token and slug of channel.""" + checkout( + """ + The checkout's ID. + + Added in Saleor 3.4. + """ + id: ID + + """ + The checkout's token. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + token: UUID + ): Checkout + + """ + List of checkouts. + + Requires one of the following permissions: MANAGE_CHECKOUTS. + """ + checkouts( + """ + Sort checkouts. + + Added in Saleor 3.1. + """ + sortBy: CheckoutSortingInput + + """ + Filtering options for checkouts. + + Added in Saleor 3.1. + """ + filter: CheckoutFilterInput + + """Slug of a channel for which the data should be returned.""" + channel: String + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): CheckoutCountableConnection + + """ + List of checkout lines. + + Requires one of the following permissions: MANAGE_CHECKOUTS. + """ + checkoutLines( + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): CheckoutLineCountableConnection + + """Look up a channel by ID or slug.""" + channel( + """ID of the channel.""" + id: ID + + """ + Slug of the channel. + + Added in Saleor 3.6. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + slug: String + ): Channel + + """ + List of all channels. + + Requires one of the following permissions: AUTHENTICATED_APP, AUTHENTICATED_STAFF_USER. + """ + channels: [Channel!] + + """List of the shop's attributes.""" + attributes( + """Filtering options for attributes.""" + filter: AttributeFilterInput + + """ + Filtering options for attributes. + + Added in Saleor 3.11. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + where: AttributeWhereInput + + """ + Search attributes. + + Added in Saleor 3.11. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + search: String + + """Sorting options for attributes.""" + sortBy: AttributeSortingInput + + """Slug of a channel for which the data should be returned.""" + channel: String + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): AttributeCountableConnection + + """Look up an attribute by ID, slug or external reference.""" + attribute( + """ID of the attribute.""" + id: ID + + """Slug of the attribute.""" + slug: String + + """ + External ID of the attribute. + + Added in Saleor 3.10. + """ + externalReference: String + ): Attribute + + """ + List of all apps installations + + Requires one of the following permissions: MANAGE_APPS. + """ + appsInstallations: [AppInstallation!]! + + """ + List of the apps. + + Requires one of the following permissions: AUTHENTICATED_STAFF_USER, MANAGE_APPS. + """ + apps( + """Filtering options for apps.""" + filter: AppFilterInput + + """Sort apps.""" + sortBy: AppSortingInput + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): AppCountableConnection + + """ + Look up an app by ID. If ID is not provided, return the currently authenticated app. + + Requires one of the following permissions: AUTHENTICATED_STAFF_USER AUTHENTICATED_APP. The authenticated app has access to its resources. Fetching different apps requires MANAGE_APPS permission. + """ + app( + """ID of the app.""" + id: ID + ): App + + """ + List of all extensions. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: AUTHENTICATED_STAFF_USER, AUTHENTICATED_APP. + """ + appExtensions( + """Filtering options for apps extensions.""" + filter: AppExtensionFilterInput + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): AppExtensionCountableConnection + + """ + Look up an app extension by ID. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: AUTHENTICATED_STAFF_USER, AUTHENTICATED_APP. + """ + appExtension( + """ID of the app extension.""" + id: ID! + ): AppExtension + + """Returns address validation rules.""" + addressValidationRules( + """Two-letter ISO 3166-1 country code.""" + countryCode: CountryCode! + + """Designation of a region, province or state.""" + countryArea: String + + """City or a town name.""" + city: String + + """Sublocality like a district.""" + cityArea: String + ): AddressValidationData + + """Look up an address by ID.""" + address( + """ID of an address.""" + id: ID! + ): Address + + """ + List of the shop's customers. + + Requires one of the following permissions: MANAGE_ORDERS, MANAGE_USERS. + """ + customers( + """Filtering options for customers.""" + filter: CustomerFilterInput + + """Sort customers.""" + sortBy: UserSortingInput + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): UserCountableConnection + + """ + List of permission groups. + + Requires one of the following permissions: MANAGE_STAFF. + """ + permissionGroups( + """Filtering options for permission groups.""" + filter: PermissionGroupFilterInput + + """Sort permission groups.""" + sortBy: PermissionGroupSortingInput + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): GroupCountableConnection + + """ + Look up permission group by ID. + + Requires one of the following permissions: MANAGE_STAFF. + """ + permissionGroup( + """ID of the group.""" + id: ID! + ): Group + + """Return the currently authenticated user.""" + me: User + + """ + List of the shop's staff users. + + Requires one of the following permissions: MANAGE_STAFF. + """ + staffUsers( + """Filtering options for staff users.""" + filter: StaffUserInput + + """Sort staff users.""" + sortBy: UserSortingInput + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): UserCountableConnection + + """ + Look up a user by ID or email address. + + Requires one of the following permissions: MANAGE_STAFF, MANAGE_USERS, MANAGE_ORDERS. + """ + user( + """ID of the user.""" + id: ID + + """Email address of the user.""" + email: String + + """ + External ID of the user. + + Added in Saleor 3.10. + """ + externalReference: String + ): User + _entities(representations: [_Any]): [_Entity] + _service: _Service +} + +"""Webhook.""" +type Webhook implements Node { + id: ID! + name: String! + + """List of webhook events.""" + events: [WebhookEvent!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `asyncEvents` or `syncEvents` instead.") + + """List of synchronous webhook events.""" + syncEvents: [WebhookEventSync!]! + + """List of asynchronous webhook events.""" + asyncEvents: [WebhookEventAsync!]! + app: App! + + """Event deliveries.""" + eventDeliveries( + """Event delivery sorter.""" + sortBy: EventDeliverySortingInput + + """Event delivery filter options.""" + filter: EventDeliveryFilterInput + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): EventDeliveryCountableConnection + + """Target URL for webhook.""" + targetUrl: String! + + """Informs if webhook is activated.""" + isActive: Boolean! + + """Used to create a hash signature for each payload.""" + secretKey: String @deprecated(reason: "This field will be removed in Saleor 4.0. As of Saleor 3.5, webhook payloads default to signing using a verifiable JWS.") + + """Used to define payloads for specific events.""" + subscriptionQuery: String + + """ + Custom headers, which will be added to HTTP request. + + Added in Saleor 3.12. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + customHeaders: JSONString +} + +"""An object with an ID""" +interface Node { + """The ID of the object.""" + id: ID! +} + +"""Webhook event.""" +type WebhookEvent { + """Display name of the event.""" + name: String! + + """Internal name of the event type.""" + eventType: WebhookEventTypeEnum! +} + +"""Enum determining type of webhook.""" +enum WebhookEventTypeEnum { + """All the events.""" + ANY_EVENTS + + """A new address created.""" + ADDRESS_CREATED + + """An address updated.""" + ADDRESS_UPDATED + + """An address deleted.""" + ADDRESS_DELETED + + """A new app installed.""" + APP_INSTALLED + + """An app updated.""" + APP_UPDATED + + """An app deleted.""" + APP_DELETED + + """An app status is changed.""" + APP_STATUS_CHANGED + + """A new attribute is created.""" + ATTRIBUTE_CREATED + + """An attribute is updated.""" + ATTRIBUTE_UPDATED + + """An attribute is deleted.""" + ATTRIBUTE_DELETED + + """A new attribute value is created.""" + ATTRIBUTE_VALUE_CREATED + + """An attribute value is updated.""" + ATTRIBUTE_VALUE_UPDATED + + """An attribute value is deleted.""" + ATTRIBUTE_VALUE_DELETED + + """A new category created.""" + CATEGORY_CREATED + + """A category is updated.""" + CATEGORY_UPDATED + + """A category is deleted.""" + CATEGORY_DELETED + + """A new channel created.""" + CHANNEL_CREATED + + """A channel is updated.""" + CHANNEL_UPDATED + + """A channel is deleted.""" + CHANNEL_DELETED + + """A channel status is changed.""" + CHANNEL_STATUS_CHANGED + + """A new gift card created.""" + GIFT_CARD_CREATED + + """A gift card is updated.""" + GIFT_CARD_UPDATED + + """A gift card is deleted.""" + GIFT_CARD_DELETED + + """A gift card status is changed.""" + GIFT_CARD_STATUS_CHANGED + + """ + A gift card metadata is updated. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + GIFT_CARD_METADATA_UPDATED + + """A new menu created.""" + MENU_CREATED + + """A menu is updated.""" + MENU_UPDATED + + """A menu is deleted.""" + MENU_DELETED + + """A new menu item created.""" + MENU_ITEM_CREATED + + """A menu item is updated.""" + MENU_ITEM_UPDATED + + """A menu item is deleted.""" + MENU_ITEM_DELETED + + """A new order is placed.""" + ORDER_CREATED + + """ + An order is confirmed (status change unconfirmed -> unfulfilled) by a staff user using the OrderConfirm mutation. It also triggers when the user completes the checkout and the shop setting `automatically_confirm_all_new_orders` is enabled. + """ + ORDER_CONFIRMED + + """Payment is made and an order is fully paid.""" + ORDER_FULLY_PAID + + """ + An order is updated; triggered for all changes related to an order; covers all other order webhooks, except for ORDER_CREATED. + """ + ORDER_UPDATED + + """An order is cancelled.""" + ORDER_CANCELLED + + """An order is fulfilled.""" + ORDER_FULFILLED + + """ + An order metadata is updated. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + ORDER_METADATA_UPDATED + + """A draft order is created.""" + DRAFT_ORDER_CREATED + + """A draft order is updated.""" + DRAFT_ORDER_UPDATED + + """A draft order is deleted.""" + DRAFT_ORDER_DELETED + + """A sale is created.""" + SALE_CREATED + + """A sale is updated.""" + SALE_UPDATED + + """A sale is deleted.""" + SALE_DELETED + + """A sale is activated or deactivated.""" + SALE_TOGGLE + + """An invoice for order requested.""" + INVOICE_REQUESTED + + """An invoice is deleted.""" + INVOICE_DELETED + + """Invoice has been sent.""" + INVOICE_SENT + + """A new customer account is created.""" + CUSTOMER_CREATED + + """A customer account is updated.""" + CUSTOMER_UPDATED + + """A customer account is deleted.""" + CUSTOMER_DELETED + + """ + A customer account metadata is updated. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + CUSTOMER_METADATA_UPDATED + + """A new collection is created.""" + COLLECTION_CREATED + + """A collection is updated.""" + COLLECTION_UPDATED + + """A collection is deleted.""" + COLLECTION_DELETED + + """ + A collection metadata is updated. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + COLLECTION_METADATA_UPDATED + + """A new product is created.""" + PRODUCT_CREATED + + """A product is updated.""" + PRODUCT_UPDATED + + """A product is deleted.""" + PRODUCT_DELETED + + """ + A new product media is created. + + Added in Saleor 3.12. + """ + PRODUCT_MEDIA_CREATED + + """ + A product media is updated. + + Added in Saleor 3.12. + """ + PRODUCT_MEDIA_UPDATED + + """ + A product media is deleted. + + Added in Saleor 3.12. + """ + PRODUCT_MEDIA_DELETED + + """ + A product metadata is updated. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + PRODUCT_METADATA_UPDATED + + """A new product variant is created.""" + PRODUCT_VARIANT_CREATED + + """A product variant is updated.""" + PRODUCT_VARIANT_UPDATED + + """A product variant is deleted.""" + PRODUCT_VARIANT_DELETED + + """A product variant is out of stock.""" + PRODUCT_VARIANT_OUT_OF_STOCK + + """A product variant is back in stock.""" + PRODUCT_VARIANT_BACK_IN_STOCK + + """A product variant stock is updated""" + PRODUCT_VARIANT_STOCK_UPDATED + + """ + A product variant metadata is updated. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + PRODUCT_VARIANT_METADATA_UPDATED + + """A new checkout is created.""" + CHECKOUT_CREATED + + """ + A checkout is updated. It also triggers all updates related to the checkout. + """ + CHECKOUT_UPDATED + + """ + A checkout metadata is updated. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + CHECKOUT_METADATA_UPDATED + + """A new fulfillment is created.""" + FULFILLMENT_CREATED + + """A fulfillment is cancelled.""" + FULFILLMENT_CANCELED + + """A fulfillment is approved.""" + FULFILLMENT_APPROVED + + """ + A fulfillment metadata is updated. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + FULFILLMENT_METADATA_UPDATED + + """User notification triggered.""" + NOTIFY_USER + + """A new page is created.""" + PAGE_CREATED + + """A page is updated.""" + PAGE_UPDATED + + """A page is deleted.""" + PAGE_DELETED + + """A new page type is created.""" + PAGE_TYPE_CREATED + + """A page type is updated.""" + PAGE_TYPE_UPDATED + + """A page type is deleted.""" + PAGE_TYPE_DELETED + + """A new permission group is created.""" + PERMISSION_GROUP_CREATED + + """A permission group is updated.""" + PERMISSION_GROUP_UPDATED + + """A permission group is deleted.""" + PERMISSION_GROUP_DELETED + + """A new shipping price is created.""" + SHIPPING_PRICE_CREATED + + """A shipping price is updated.""" + SHIPPING_PRICE_UPDATED + + """A shipping price is deleted.""" + SHIPPING_PRICE_DELETED + + """A new shipping zone is created.""" + SHIPPING_ZONE_CREATED + + """A shipping zone is updated.""" + SHIPPING_ZONE_UPDATED + + """A shipping zone is deleted.""" + SHIPPING_ZONE_DELETED + + """ + A shipping zone metadata is updated. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + SHIPPING_ZONE_METADATA_UPDATED + + """A new staff user is created.""" + STAFF_CREATED + + """A staff user is updated.""" + STAFF_UPDATED + + """A staff user is deleted.""" + STAFF_DELETED + + """ + An action requested for transaction. + + DEPRECATED: this subscription will be removed in Saleor 3.14 (Preview Feature). Use `TRANSACTION_CHARGE_REQUESTED`, `TRANSACTION_REFUND_REQUESTED`, `TRANSACTION_CANCELATION_REQUESTED` instead. + """ + TRANSACTION_ACTION_REQUEST + + """ + Transaction item metadata is updated. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + TRANSACTION_ITEM_METADATA_UPDATED + + """A new translation is created.""" + TRANSLATION_CREATED + + """A translation is updated.""" + TRANSLATION_UPDATED + + """A new warehouse created.""" + WAREHOUSE_CREATED + + """A warehouse is updated.""" + WAREHOUSE_UPDATED + + """A warehouse is deleted.""" + WAREHOUSE_DELETED + + """ + A warehouse metadata is updated. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + WAREHOUSE_METADATA_UPDATED + + """A new voucher created.""" + VOUCHER_CREATED + + """A voucher is updated.""" + VOUCHER_UPDATED + + """A voucher is deleted.""" + VOUCHER_DELETED + + """ + A voucher metadata is updated. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + VOUCHER_METADATA_UPDATED + + """An observability event is created.""" + OBSERVABILITY + + """ + A thumbnail is created. + + Added in Saleor 3.12. + """ + THUMBNAIL_CREATED + + """Authorize payment.""" + PAYMENT_AUTHORIZE + + """Capture payment.""" + PAYMENT_CAPTURE + + """Confirm payment.""" + PAYMENT_CONFIRM + + """Listing available payment gateways.""" + PAYMENT_LIST_GATEWAYS + + """Process payment.""" + PAYMENT_PROCESS + + """Refund payment.""" + PAYMENT_REFUND + + """Void payment.""" + PAYMENT_VOID + + """ + Event called when charge has been requested for transaction. + + Added in Saleor 3.13. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + TRANSACTION_CHARGE_REQUESTED + + """ + Event called when refund has been requested for transaction. + + Added in Saleor 3.13. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + TRANSACTION_REFUND_REQUESTED + + """ + Event called when cancel has been requested for transaction. + + Added in Saleor 3.13. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + TRANSACTION_CANCELATION_REQUESTED + + """ + Event called for checkout tax calculation. + + Added in Saleor 3.6. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + CHECKOUT_CALCULATE_TAXES + + """ + Event called for order tax calculation. + + Added in Saleor 3.6. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + ORDER_CALCULATE_TAXES + + """Fetch external shipping methods for checkout.""" + SHIPPING_LIST_METHODS_FOR_CHECKOUT + + """Filter shipping methods for order.""" + ORDER_FILTER_SHIPPING_METHODS + + """Filter shipping methods for checkout.""" + CHECKOUT_FILTER_SHIPPING_METHODS + PAYMENT_GATEWAY_INITIALIZE_SESSION + TRANSACTION_INITIALIZE_SESSION + TRANSACTION_PROCESS_SESSION +} + +"""Synchronous webhook event.""" +type WebhookEventSync { + """Display name of the event.""" + name: String! + + """Internal name of the event type.""" + eventType: WebhookEventTypeSyncEnum! +} + +"""Enum determining type of webhook.""" +enum WebhookEventTypeSyncEnum { + """Authorize payment.""" + PAYMENT_AUTHORIZE + + """Capture payment.""" + PAYMENT_CAPTURE + + """Confirm payment.""" + PAYMENT_CONFIRM + + """Listing available payment gateways.""" + PAYMENT_LIST_GATEWAYS + + """Process payment.""" + PAYMENT_PROCESS + + """Refund payment.""" + PAYMENT_REFUND + + """Void payment.""" + PAYMENT_VOID + + """ + Event called when charge has been requested for transaction. + + Added in Saleor 3.13. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + TRANSACTION_CHARGE_REQUESTED + + """ + Event called when refund has been requested for transaction. + + Added in Saleor 3.13. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + TRANSACTION_REFUND_REQUESTED + + """ + Event called when cancel has been requested for transaction. + + Added in Saleor 3.13. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + TRANSACTION_CANCELATION_REQUESTED + + """ + Event called for checkout tax calculation. + + Added in Saleor 3.6. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + CHECKOUT_CALCULATE_TAXES + + """ + Event called for order tax calculation. + + Added in Saleor 3.6. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + ORDER_CALCULATE_TAXES + + """Fetch external shipping methods for checkout.""" + SHIPPING_LIST_METHODS_FOR_CHECKOUT + + """Filter shipping methods for order.""" + ORDER_FILTER_SHIPPING_METHODS + + """Filter shipping methods for checkout.""" + CHECKOUT_FILTER_SHIPPING_METHODS + PAYMENT_GATEWAY_INITIALIZE_SESSION + TRANSACTION_INITIALIZE_SESSION + TRANSACTION_PROCESS_SESSION +} + +"""Asynchronous webhook event.""" +type WebhookEventAsync { + """Display name of the event.""" + name: String! + + """Internal name of the event type.""" + eventType: WebhookEventTypeAsyncEnum! +} + +"""Enum determining type of webhook.""" +enum WebhookEventTypeAsyncEnum { + """All the events.""" + ANY_EVENTS + + """A new address created.""" + ADDRESS_CREATED + + """An address updated.""" + ADDRESS_UPDATED + + """An address deleted.""" + ADDRESS_DELETED + + """A new app installed.""" + APP_INSTALLED + + """An app updated.""" + APP_UPDATED + + """An app deleted.""" + APP_DELETED + + """An app status is changed.""" + APP_STATUS_CHANGED + + """A new attribute is created.""" + ATTRIBUTE_CREATED + + """An attribute is updated.""" + ATTRIBUTE_UPDATED + + """An attribute is deleted.""" + ATTRIBUTE_DELETED + + """A new attribute value is created.""" + ATTRIBUTE_VALUE_CREATED + + """An attribute value is updated.""" + ATTRIBUTE_VALUE_UPDATED + + """An attribute value is deleted.""" + ATTRIBUTE_VALUE_DELETED + + """A new category created.""" + CATEGORY_CREATED + + """A category is updated.""" + CATEGORY_UPDATED + + """A category is deleted.""" + CATEGORY_DELETED + + """A new channel created.""" + CHANNEL_CREATED + + """A channel is updated.""" + CHANNEL_UPDATED + + """A channel is deleted.""" + CHANNEL_DELETED + + """A channel status is changed.""" + CHANNEL_STATUS_CHANGED + + """A new gift card created.""" + GIFT_CARD_CREATED + + """A gift card is updated.""" + GIFT_CARD_UPDATED + + """A gift card is deleted.""" + GIFT_CARD_DELETED + + """A gift card status is changed.""" + GIFT_CARD_STATUS_CHANGED + + """ + A gift card metadata is updated. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + GIFT_CARD_METADATA_UPDATED + + """A new menu created.""" + MENU_CREATED + + """A menu is updated.""" + MENU_UPDATED + + """A menu is deleted.""" + MENU_DELETED + + """A new menu item created.""" + MENU_ITEM_CREATED + + """A menu item is updated.""" + MENU_ITEM_UPDATED + + """A menu item is deleted.""" + MENU_ITEM_DELETED + + """A new order is placed.""" + ORDER_CREATED + + """ + An order is confirmed (status change unconfirmed -> unfulfilled) by a staff user using the OrderConfirm mutation. It also triggers when the user completes the checkout and the shop setting `automatically_confirm_all_new_orders` is enabled. + """ + ORDER_CONFIRMED + + """Payment is made and an order is fully paid.""" + ORDER_FULLY_PAID + + """ + An order is updated; triggered for all changes related to an order; covers all other order webhooks, except for ORDER_CREATED. + """ + ORDER_UPDATED + + """An order is cancelled.""" + ORDER_CANCELLED + + """An order is fulfilled.""" + ORDER_FULFILLED + + """ + An order metadata is updated. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + ORDER_METADATA_UPDATED + + """A draft order is created.""" + DRAFT_ORDER_CREATED + + """A draft order is updated.""" + DRAFT_ORDER_UPDATED + + """A draft order is deleted.""" + DRAFT_ORDER_DELETED + + """A sale is created.""" + SALE_CREATED + + """A sale is updated.""" + SALE_UPDATED + + """A sale is deleted.""" + SALE_DELETED + + """A sale is activated or deactivated.""" + SALE_TOGGLE + + """An invoice for order requested.""" + INVOICE_REQUESTED + + """An invoice is deleted.""" + INVOICE_DELETED + + """Invoice has been sent.""" + INVOICE_SENT + + """A new customer account is created.""" + CUSTOMER_CREATED + + """A customer account is updated.""" + CUSTOMER_UPDATED + + """A customer account is deleted.""" + CUSTOMER_DELETED + + """ + A customer account metadata is updated. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + CUSTOMER_METADATA_UPDATED + + """A new collection is created.""" + COLLECTION_CREATED + + """A collection is updated.""" + COLLECTION_UPDATED + + """A collection is deleted.""" + COLLECTION_DELETED + + """ + A collection metadata is updated. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + COLLECTION_METADATA_UPDATED + + """A new product is created.""" + PRODUCT_CREATED + + """A product is updated.""" + PRODUCT_UPDATED + + """A product is deleted.""" + PRODUCT_DELETED + + """ + A new product media is created. + + Added in Saleor 3.12. + """ + PRODUCT_MEDIA_CREATED + + """ + A product media is updated. + + Added in Saleor 3.12. + """ + PRODUCT_MEDIA_UPDATED + + """ + A product media is deleted. + + Added in Saleor 3.12. + """ + PRODUCT_MEDIA_DELETED + + """ + A product metadata is updated. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + PRODUCT_METADATA_UPDATED + + """A new product variant is created.""" + PRODUCT_VARIANT_CREATED + + """A product variant is updated.""" + PRODUCT_VARIANT_UPDATED + + """A product variant is deleted.""" + PRODUCT_VARIANT_DELETED + + """A product variant is out of stock.""" + PRODUCT_VARIANT_OUT_OF_STOCK + + """A product variant is back in stock.""" + PRODUCT_VARIANT_BACK_IN_STOCK + + """A product variant stock is updated""" + PRODUCT_VARIANT_STOCK_UPDATED + + """ + A product variant metadata is updated. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + PRODUCT_VARIANT_METADATA_UPDATED + + """A new checkout is created.""" + CHECKOUT_CREATED + + """ + A checkout is updated. It also triggers all updates related to the checkout. + """ + CHECKOUT_UPDATED + + """ + A checkout metadata is updated. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + CHECKOUT_METADATA_UPDATED + + """A new fulfillment is created.""" + FULFILLMENT_CREATED + + """A fulfillment is cancelled.""" + FULFILLMENT_CANCELED + + """A fulfillment is approved.""" + FULFILLMENT_APPROVED + + """ + A fulfillment metadata is updated. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + FULFILLMENT_METADATA_UPDATED + + """User notification triggered.""" + NOTIFY_USER + + """A new page is created.""" + PAGE_CREATED + + """A page is updated.""" + PAGE_UPDATED + + """A page is deleted.""" + PAGE_DELETED + + """A new page type is created.""" + PAGE_TYPE_CREATED + + """A page type is updated.""" + PAGE_TYPE_UPDATED + + """A page type is deleted.""" + PAGE_TYPE_DELETED + + """A new permission group is created.""" + PERMISSION_GROUP_CREATED + + """A permission group is updated.""" + PERMISSION_GROUP_UPDATED + + """A permission group is deleted.""" + PERMISSION_GROUP_DELETED + + """A new shipping price is created.""" + SHIPPING_PRICE_CREATED + + """A shipping price is updated.""" + SHIPPING_PRICE_UPDATED + + """A shipping price is deleted.""" + SHIPPING_PRICE_DELETED + + """A new shipping zone is created.""" + SHIPPING_ZONE_CREATED + + """A shipping zone is updated.""" + SHIPPING_ZONE_UPDATED + + """A shipping zone is deleted.""" + SHIPPING_ZONE_DELETED + + """ + A shipping zone metadata is updated. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + SHIPPING_ZONE_METADATA_UPDATED + + """A new staff user is created.""" + STAFF_CREATED + + """A staff user is updated.""" + STAFF_UPDATED + + """A staff user is deleted.""" + STAFF_DELETED + + """ + An action requested for transaction. + + DEPRECATED: this subscription will be removed in Saleor 3.14 (Preview Feature). Use `TRANSACTION_CHARGE_REQUESTED`, `TRANSACTION_REFUND_REQUESTED`, `TRANSACTION_CANCELATION_REQUESTED` instead. + """ + TRANSACTION_ACTION_REQUEST + + """ + Transaction item metadata is updated. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + TRANSACTION_ITEM_METADATA_UPDATED + + """A new translation is created.""" + TRANSLATION_CREATED + + """A translation is updated.""" + TRANSLATION_UPDATED + + """A new warehouse created.""" + WAREHOUSE_CREATED + + """A warehouse is updated.""" + WAREHOUSE_UPDATED + + """A warehouse is deleted.""" + WAREHOUSE_DELETED + + """ + A warehouse metadata is updated. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + WAREHOUSE_METADATA_UPDATED + + """A new voucher created.""" + VOUCHER_CREATED + + """A voucher is updated.""" + VOUCHER_UPDATED + + """A voucher is deleted.""" + VOUCHER_DELETED + + """ + A voucher metadata is updated. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + VOUCHER_METADATA_UPDATED + + """An observability event is created.""" + OBSERVABILITY + + """ + A thumbnail is created. + + Added in Saleor 3.12. + """ + THUMBNAIL_CREATED +} + +"""Represents app data.""" +type App implements Node & ObjectWithMetadata { + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + + """List of the app's permissions.""" + permissions: [Permission!] + + """The date and time when the app was created.""" + created: DateTime + + """Determine if app will be set active or not.""" + isActive: Boolean + + """Name of the app.""" + name: String + + """Type of the app.""" + type: AppTypeEnum + + """ + Last 4 characters of the tokens. + + Requires one of the following permissions: MANAGE_APPS, OWNER. + """ + tokens: [AppToken!] + + """ + List of webhooks assigned to this app. + + Requires one of the following permissions: MANAGE_APPS, OWNER. + """ + webhooks: [Webhook!] + + """Description of this app.""" + aboutApp: String + + """Description of the data privacy defined for this app.""" + dataPrivacy: String @deprecated(reason: "This field will be removed in Saleor 4.0. Use `dataPrivacyUrl` instead.") + + """URL to details about the privacy policy on the app owner page.""" + dataPrivacyUrl: String + + """Homepage of the app.""" + homepageUrl: String + + """Support page for the app.""" + supportUrl: String + + """URL to iframe with the configuration for the app.""" + configurationUrl: String @deprecated(reason: "This field will be removed in Saleor 4.0. Use `appUrl` instead.") + + """URL to iframe with the app.""" + appUrl: String + + """ + URL to manifest used during app's installation. + + Added in Saleor 3.5. + """ + manifestUrl: String + + """Version number of the app.""" + version: String + + """JWT token used to authenticate by thridparty app.""" + accessToken: String + + """ + App's dashboard extensions. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + extensions: [AppExtension!]! +} + +interface ObjectWithMetadata { + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + """ + metafields(keys: [String!]): Metadata +} + +type MetadataItem { + """Key of a metadata item.""" + key: String! + + """Value of a metadata item.""" + value: String! +} + +""" +Metadata is a map of key-value pairs, both keys and values are `String`. + +Example: +``` +{ + "key1": "value1", + "key2": "value2" +} +``` +""" +scalar Metadata + +"""Represents a permission object in a friendly form.""" +type Permission { + """Internal code for permission.""" + code: PermissionEnum! + + """Describe action(s) allowed to do by permission.""" + name: String! +} + +"""An enumeration.""" +enum PermissionEnum { + MANAGE_USERS + MANAGE_STAFF + IMPERSONATE_USER + MANAGE_APPS + MANAGE_OBSERVABILITY + MANAGE_CHECKOUTS + HANDLE_CHECKOUTS + HANDLE_TAXES + MANAGE_TAXES + MANAGE_CHANNELS + MANAGE_DISCOUNTS + MANAGE_GIFT_CARD + MANAGE_MENUS + MANAGE_ORDERS + MANAGE_PAGES + MANAGE_PAGE_TYPES_AND_ATTRIBUTES + HANDLE_PAYMENTS + MANAGE_PLUGINS + MANAGE_PRODUCTS + MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES + MANAGE_SHIPPING + MANAGE_SETTINGS + MANAGE_TRANSLATIONS +} + +""" +The `DateTime` scalar type represents a DateTime +value as specified by +[iso8601](https://en.wikipedia.org/wiki/ISO_8601). +""" +scalar DateTime + +"""Enum determining type of your App.""" +enum AppTypeEnum { + """ + Local Saleor App. The app is fully manageable from dashboard. You can change assigned permissions, add webhooks, or authentication token + """ + LOCAL + + """ + Third party external App. Installation is fully automated. Saleor uses a defined App manifest to gather all required information. + """ + THIRDPARTY +} + +"""Represents token data.""" +type AppToken implements Node { + id: ID! + + """Name of the authenticated token.""" + name: String + + """Last 4 characters of the token.""" + authToken: String +} + +"""Represents app data.""" +type AppExtension implements Node { + id: ID! + + """List of the app extension's permissions.""" + permissions: [Permission!]! + + """Label of the extension to show in the dashboard.""" + label: String! + + """URL of a view where extension's iframe is placed.""" + url: String! + + """Place where given extension will be mounted.""" + mount: AppExtensionMountEnum! + + """Type of way how app extension will be opened.""" + target: AppExtensionTargetEnum! + app: App! + + """JWT token used to authenticate by thridparty app extension.""" + accessToken: String +} + +"""All places where app extension can be mounted.""" +enum AppExtensionMountEnum { + CUSTOMER_OVERVIEW_CREATE + CUSTOMER_OVERVIEW_MORE_ACTIONS + CUSTOMER_DETAILS_MORE_ACTIONS + PRODUCT_OVERVIEW_CREATE + PRODUCT_OVERVIEW_MORE_ACTIONS + PRODUCT_DETAILS_MORE_ACTIONS + NAVIGATION_CATALOG + NAVIGATION_ORDERS + NAVIGATION_CUSTOMERS + NAVIGATION_DISCOUNTS + NAVIGATION_TRANSLATIONS + NAVIGATION_PAGES + ORDER_DETAILS_MORE_ACTIONS + ORDER_OVERVIEW_CREATE + ORDER_OVERVIEW_MORE_ACTIONS +} + +""" +All available ways of opening an app extension. + + POPUP - app's extension will be mounted as a popup window + APP_PAGE - redirect to app's page +""" +enum AppExtensionTargetEnum { + POPUP + APP_PAGE +} + +type EventDeliveryCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [EventDeliveryCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +""" +The Relay compliant `PageInfo` type, containing data necessary to paginate this connection. +""" +type PageInfo { + """When paginating forwards, are there more items?""" + hasNextPage: Boolean! + + """When paginating backwards, are there more items?""" + hasPreviousPage: Boolean! + + """When paginating backwards, the cursor to continue.""" + startCursor: String + + """When paginating forwards, the cursor to continue.""" + endCursor: String +} + +type EventDeliveryCountableEdge { + """The item at the end of the edge.""" + node: EventDelivery! + + """A cursor for use in pagination.""" + cursor: String! +} + +"""Event delivery.""" +type EventDelivery implements Node { + id: ID! + createdAt: DateTime! + + """Event delivery status.""" + status: EventDeliveryStatusEnum! + + """Webhook event type.""" + eventType: WebhookEventTypeEnum! + + """Event delivery attempts.""" + attempts( + """Event delivery sorter""" + sortBy: EventDeliveryAttemptSortingInput + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): EventDeliveryAttemptCountableConnection + + """Event payload.""" + payload: String +} + +enum EventDeliveryStatusEnum { + PENDING + SUCCESS + FAILED +} + +type EventDeliveryAttemptCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [EventDeliveryAttemptCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type EventDeliveryAttemptCountableEdge { + """The item at the end of the edge.""" + node: EventDeliveryAttempt! + + """A cursor for use in pagination.""" + cursor: String! +} + +"""Event delivery attempts.""" +type EventDeliveryAttempt implements Node { + id: ID! + + """Event delivery creation date and time.""" + createdAt: DateTime! + + """Task id for delivery attempt.""" + taskId: String + + """Delivery attempt duration.""" + duration: Float + + """Delivery attempt response content.""" + response: String + + """Response headers for delivery attempt.""" + responseHeaders: String + + """Delivery attempt response status code.""" + responseStatusCode: Int + + """Request headers for delivery attempt.""" + requestHeaders: String + + """Event delivery status.""" + status: EventDeliveryStatusEnum! +} + +input EventDeliveryAttemptSortingInput { + """Specifies the direction in which to sort products.""" + direction: OrderDirection! + + """Sort attempts by the selected field.""" + field: EventDeliveryAttemptSortField! +} + +enum OrderDirection { + """Specifies an ascending sort order.""" + ASC + + """Specifies a descending sort order.""" + DESC +} + +enum EventDeliveryAttemptSortField { + """Sort event delivery attempts by created at.""" + CREATED_AT +} + +input EventDeliverySortingInput { + """Specifies the direction in which to sort products.""" + direction: OrderDirection! + + """Sort deliveries by the selected field.""" + field: EventDeliverySortField! +} + +enum EventDeliverySortField { + """Sort event deliveries by created at.""" + CREATED_AT +} + +input EventDeliveryFilterInput { + status: EventDeliveryStatusEnum + eventType: WebhookEventTypeEnum +} + +scalar JSONString + +"""An enumeration.""" +enum WebhookSampleEventTypeEnum { + ADDRESS_CREATED + ADDRESS_UPDATED + ADDRESS_DELETED + APP_INSTALLED + APP_UPDATED + APP_DELETED + APP_STATUS_CHANGED + ATTRIBUTE_CREATED + ATTRIBUTE_UPDATED + ATTRIBUTE_DELETED + ATTRIBUTE_VALUE_CREATED + ATTRIBUTE_VALUE_UPDATED + ATTRIBUTE_VALUE_DELETED + CATEGORY_CREATED + CATEGORY_UPDATED + CATEGORY_DELETED + CHANNEL_CREATED + CHANNEL_UPDATED + CHANNEL_DELETED + CHANNEL_STATUS_CHANGED + GIFT_CARD_CREATED + GIFT_CARD_UPDATED + GIFT_CARD_DELETED + GIFT_CARD_STATUS_CHANGED + GIFT_CARD_METADATA_UPDATED + MENU_CREATED + MENU_UPDATED + MENU_DELETED + MENU_ITEM_CREATED + MENU_ITEM_UPDATED + MENU_ITEM_DELETED + ORDER_CREATED + ORDER_CONFIRMED + ORDER_FULLY_PAID + ORDER_UPDATED + ORDER_CANCELLED + ORDER_FULFILLED + ORDER_METADATA_UPDATED + DRAFT_ORDER_CREATED + DRAFT_ORDER_UPDATED + DRAFT_ORDER_DELETED + SALE_CREATED + SALE_UPDATED + SALE_DELETED + SALE_TOGGLE + INVOICE_REQUESTED + INVOICE_DELETED + INVOICE_SENT + CUSTOMER_CREATED + CUSTOMER_UPDATED + CUSTOMER_DELETED + CUSTOMER_METADATA_UPDATED + COLLECTION_CREATED + COLLECTION_UPDATED + COLLECTION_DELETED + COLLECTION_METADATA_UPDATED + PRODUCT_CREATED + PRODUCT_UPDATED + PRODUCT_DELETED + PRODUCT_MEDIA_CREATED + PRODUCT_MEDIA_UPDATED + PRODUCT_MEDIA_DELETED + PRODUCT_METADATA_UPDATED + PRODUCT_VARIANT_CREATED + PRODUCT_VARIANT_UPDATED + PRODUCT_VARIANT_DELETED + PRODUCT_VARIANT_OUT_OF_STOCK + PRODUCT_VARIANT_BACK_IN_STOCK + PRODUCT_VARIANT_STOCK_UPDATED + PRODUCT_VARIANT_METADATA_UPDATED + CHECKOUT_CREATED + CHECKOUT_UPDATED + CHECKOUT_METADATA_UPDATED + FULFILLMENT_CREATED + FULFILLMENT_CANCELED + FULFILLMENT_APPROVED + FULFILLMENT_METADATA_UPDATED + NOTIFY_USER + PAGE_CREATED + PAGE_UPDATED + PAGE_DELETED + PAGE_TYPE_CREATED + PAGE_TYPE_UPDATED + PAGE_TYPE_DELETED + PERMISSION_GROUP_CREATED + PERMISSION_GROUP_UPDATED + PERMISSION_GROUP_DELETED + SHIPPING_PRICE_CREATED + SHIPPING_PRICE_UPDATED + SHIPPING_PRICE_DELETED + SHIPPING_ZONE_CREATED + SHIPPING_ZONE_UPDATED + SHIPPING_ZONE_DELETED + SHIPPING_ZONE_METADATA_UPDATED + STAFF_CREATED + STAFF_UPDATED + STAFF_DELETED + TRANSACTION_ACTION_REQUEST + TRANSACTION_ITEM_METADATA_UPDATED + TRANSLATION_CREATED + TRANSLATION_UPDATED + WAREHOUSE_CREATED + WAREHOUSE_UPDATED + WAREHOUSE_DELETED + WAREHOUSE_METADATA_UPDATED + VOUCHER_CREATED + VOUCHER_UPDATED + VOUCHER_DELETED + VOUCHER_METADATA_UPDATED + OBSERVABILITY + THUMBNAIL_CREATED +} + +"""Represents warehouse.""" +type Warehouse implements Node & ObjectWithMetadata { + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + name: String! + slug: String! + email: String! + isPrivate: Boolean! + address: Address! + + """Warehouse company name.""" + companyName: String! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `Address.companyName` instead.") + + """ + Click and collect options: local, all or disabled. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + clickAndCollectOption: WarehouseClickAndCollectOptionEnum! + shippingZones( + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): ShippingZoneCountableConnection! + + """ + External ID of this warehouse. + + Added in Saleor 3.10. + """ + externalReference: String +} + +"""Represents user address data.""" +type Address implements Node & ObjectWithMetadata { + id: ID! + + """ + List of private metadata items. Requires staff permissions to access. + + Added in Saleor 3.10. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.10. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.10. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """ + List of public metadata items. Can be accessed without permissions. + + Added in Saleor 3.10. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.10. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.10. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + firstName: String! + lastName: String! + companyName: String! + streetAddress1: String! + streetAddress2: String! + city: String! + cityArea: String! + postalCode: String! + + """Shop's default country.""" + country: CountryDisplay! + countryArea: String! + phone: String + + """Address is user's default shipping address.""" + isDefaultShippingAddress: Boolean + + """Address is user's default billing address.""" + isDefaultBillingAddress: Boolean +} + +type CountryDisplay { + """Country code.""" + code: String! + + """Country name.""" + country: String! + + """Country tax.""" + vat: VAT @deprecated(reason: "This field will be removed in Saleor 4.0. Use `TaxClassCountryRate` type to manage tax rates per country.") +} + +"""Represents a VAT rate for a country.""" +type VAT { + """Country code.""" + countryCode: String! + + """Standard VAT rate in percent.""" + standardRate: Float + + """Country's VAT rate exceptions for specific types of goods.""" + reducedRates: [ReducedRate!]! +} + +"""Represents a reduced VAT rate for a particular type of goods.""" +type ReducedRate { + """Reduced VAT rate in percent.""" + rate: Float! + + """A type of goods.""" + rateType: String! +} + +"""An enumeration.""" +enum WarehouseClickAndCollectOptionEnum { + DISABLED + LOCAL + ALL +} + +type ShippingZoneCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [ShippingZoneCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type ShippingZoneCountableEdge { + """The item at the end of the edge.""" + node: ShippingZone! + + """A cursor for use in pagination.""" + cursor: String! +} + +""" +Represents a shipping zone in the shop. Zones are the concept used only for grouping shipping methods in the dashboard, and are never exposed to the customers directly. +""" +type ShippingZone implements Node & ObjectWithMetadata { + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + name: String! + default: Boolean! + + """Lowest and highest prices for the shipping.""" + priceRange: MoneyRange + + """List of countries available for the method.""" + countries: [CountryDisplay!]! + + """ + List of shipping methods available for orders shipped to countries within this shipping zone. + """ + shippingMethods: [ShippingMethodType!] + + """List of warehouses for shipping zone.""" + warehouses: [Warehouse!]! + + """List of channels for shipping zone.""" + channels: [Channel!]! + + """Description of a shipping zone.""" + description: String +} + +"""Represents a range of amounts of money.""" +type MoneyRange { + """Lower bound of a price range.""" + start: Money + + """Upper bound of a price range.""" + stop: Money +} + +"""Represents amount of money in specific currency.""" +type Money { + """Currency code.""" + currency: String! + + """Amount of money.""" + amount: Float! +} + +""" +Shipping method are the methods you'll use to get customer's orders to them. They are directly exposed to the customers. +""" +type ShippingMethodType implements Node & ObjectWithMetadata { + """Shipping method ID.""" + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + + """Shipping method name.""" + name: String! + + """ + Shipping method description. + + Rich text format. For reference see https://editorjs.io/ + """ + description: JSONString + + """Type of the shipping method.""" + type: ShippingMethodTypeEnum + + """Returns translated shipping method fields for the given language code.""" + translation( + """A language code to return the translation for shipping method.""" + languageCode: LanguageCodeEnum! + ): ShippingMethodTranslation + + """ + List of channels available for the method. + + Requires one of the following permissions: MANAGE_SHIPPING. + """ + channelListings: [ShippingMethodChannelListing!] + + """The price of the cheapest variant (including discounts).""" + maximumOrderPrice: Money + + """The price of the cheapest variant (including discounts).""" + minimumOrderPrice: Money + + """ + Postal code ranges rule of exclusion or inclusion of the shipping method. + """ + postalCodeRules: [ShippingMethodPostalCodeRule!] + + """ + List of excluded products for the shipping method. + + Requires one of the following permissions: MANAGE_SHIPPING. + """ + excludedProducts( + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): ProductCountableConnection + + """Minimum order weight to use this shipping method.""" + minimumOrderWeight: Weight + + """Maximum order weight to use this shipping method.""" + maximumOrderWeight: Weight + + """Maximum number of days for delivery.""" + maximumDeliveryDays: Int + + """Minimal number of days for delivery.""" + minimumDeliveryDays: Int + + """ + Tax class assigned to this shipping method. + + Requires one of the following permissions: MANAGE_TAXES, MANAGE_SHIPPING. + """ + taxClass: TaxClass +} + +"""An enumeration.""" +enum ShippingMethodTypeEnum { + PRICE + WEIGHT +} + +type ShippingMethodTranslation implements Node { + id: ID! + + """Translation language.""" + language: LanguageDisplay! + name: String + + """ + Translated description of the shipping method. + + Rich text format. For reference see https://editorjs.io/ + """ + description: JSONString +} + +type LanguageDisplay { + """ISO 639 representation of the language name.""" + code: LanguageCodeEnum! + + """Full name of the language.""" + language: String! +} + +"""An enumeration.""" +enum LanguageCodeEnum { + AF + AF_NA + AF_ZA + AGQ + AGQ_CM + AK + AK_GH + AM + AM_ET + AR + AR_AE + AR_BH + AR_DJ + AR_DZ + AR_EG + AR_EH + AR_ER + AR_IL + AR_IQ + AR_JO + AR_KM + AR_KW + AR_LB + AR_LY + AR_MA + AR_MR + AR_OM + AR_PS + AR_QA + AR_SA + AR_SD + AR_SO + AR_SS + AR_SY + AR_TD + AR_TN + AR_YE + AS + AS_IN + ASA + ASA_TZ + AST + AST_ES + AZ + AZ_CYRL + AZ_CYRL_AZ + AZ_LATN + AZ_LATN_AZ + BAS + BAS_CM + BE + BE_BY + BEM + BEM_ZM + BEZ + BEZ_TZ + BG + BG_BG + BM + BM_ML + BN + BN_BD + BN_IN + BO + BO_CN + BO_IN + BR + BR_FR + BRX + BRX_IN + BS + BS_CYRL + BS_CYRL_BA + BS_LATN + BS_LATN_BA + CA + CA_AD + CA_ES + CA_ES_VALENCIA + CA_FR + CA_IT + CCP + CCP_BD + CCP_IN + CE + CE_RU + CEB + CEB_PH + CGG + CGG_UG + CHR + CHR_US + CKB + CKB_IQ + CKB_IR + CS + CS_CZ + CU + CU_RU + CY + CY_GB + DA + DA_DK + DA_GL + DAV + DAV_KE + DE + DE_AT + DE_BE + DE_CH + DE_DE + DE_IT + DE_LI + DE_LU + DJE + DJE_NE + DSB + DSB_DE + DUA + DUA_CM + DYO + DYO_SN + DZ + DZ_BT + EBU + EBU_KE + EE + EE_GH + EE_TG + EL + EL_CY + EL_GR + EN + EN_AE + EN_AG + EN_AI + EN_AS + EN_AT + EN_AU + EN_BB + EN_BE + EN_BI + EN_BM + EN_BS + EN_BW + EN_BZ + EN_CA + EN_CC + EN_CH + EN_CK + EN_CM + EN_CX + EN_CY + EN_DE + EN_DG + EN_DK + EN_DM + EN_ER + EN_FI + EN_FJ + EN_FK + EN_FM + EN_GB + EN_GD + EN_GG + EN_GH + EN_GI + EN_GM + EN_GU + EN_GY + EN_HK + EN_IE + EN_IL + EN_IM + EN_IN + EN_IO + EN_JE + EN_JM + EN_KE + EN_KI + EN_KN + EN_KY + EN_LC + EN_LR + EN_LS + EN_MG + EN_MH + EN_MO + EN_MP + EN_MS + EN_MT + EN_MU + EN_MW + EN_MY + EN_NA + EN_NF + EN_NG + EN_NL + EN_NR + EN_NU + EN_NZ + EN_PG + EN_PH + EN_PK + EN_PN + EN_PR + EN_PW + EN_RW + EN_SB + EN_SC + EN_SD + EN_SE + EN_SG + EN_SH + EN_SI + EN_SL + EN_SS + EN_SX + EN_SZ + EN_TC + EN_TK + EN_TO + EN_TT + EN_TV + EN_TZ + EN_UG + EN_UM + EN_US + EN_VC + EN_VG + EN_VI + EN_VU + EN_WS + EN_ZA + EN_ZM + EN_ZW + EO + ES + ES_AR + ES_BO + ES_BR + ES_BZ + ES_CL + ES_CO + ES_CR + ES_CU + ES_DO + ES_EA + ES_EC + ES_ES + ES_GQ + ES_GT + ES_HN + ES_IC + ES_MX + ES_NI + ES_PA + ES_PE + ES_PH + ES_PR + ES_PY + ES_SV + ES_US + ES_UY + ES_VE + ET + ET_EE + EU + EU_ES + EWO + EWO_CM + FA + FA_AF + FA_IR + FF + FF_ADLM + FF_ADLM_BF + FF_ADLM_CM + FF_ADLM_GH + FF_ADLM_GM + FF_ADLM_GN + FF_ADLM_GW + FF_ADLM_LR + FF_ADLM_MR + FF_ADLM_NE + FF_ADLM_NG + FF_ADLM_SL + FF_ADLM_SN + FF_LATN + FF_LATN_BF + FF_LATN_CM + FF_LATN_GH + FF_LATN_GM + FF_LATN_GN + FF_LATN_GW + FF_LATN_LR + FF_LATN_MR + FF_LATN_NE + FF_LATN_NG + FF_LATN_SL + FF_LATN_SN + FI + FI_FI + FIL + FIL_PH + FO + FO_DK + FO_FO + FR + FR_BE + FR_BF + FR_BI + FR_BJ + FR_BL + FR_CA + FR_CD + FR_CF + FR_CG + FR_CH + FR_CI + FR_CM + FR_DJ + FR_DZ + FR_FR + FR_GA + FR_GF + FR_GN + FR_GP + FR_GQ + FR_HT + FR_KM + FR_LU + FR_MA + FR_MC + FR_MF + FR_MG + FR_ML + FR_MQ + FR_MR + FR_MU + FR_NC + FR_NE + FR_PF + FR_PM + FR_RE + FR_RW + FR_SC + FR_SN + FR_SY + FR_TD + FR_TG + FR_TN + FR_VU + FR_WF + FR_YT + FUR + FUR_IT + FY + FY_NL + GA + GA_GB + GA_IE + GD + GD_GB + GL + GL_ES + GSW + GSW_CH + GSW_FR + GSW_LI + GU + GU_IN + GUZ + GUZ_KE + GV + GV_IM + HA + HA_GH + HA_NE + HA_NG + HAW + HAW_US + HE + HE_IL + HI + HI_IN + HR + HR_BA + HR_HR + HSB + HSB_DE + HU + HU_HU + HY + HY_AM + IA + ID + ID_ID + IG + IG_NG + II + II_CN + IS + IS_IS + IT + IT_CH + IT_IT + IT_SM + IT_VA + JA + JA_JP + JGO + JGO_CM + JMC + JMC_TZ + JV + JV_ID + KA + KA_GE + KAB + KAB_DZ + KAM + KAM_KE + KDE + KDE_TZ + KEA + KEA_CV + KHQ + KHQ_ML + KI + KI_KE + KK + KK_KZ + KKJ + KKJ_CM + KL + KL_GL + KLN + KLN_KE + KM + KM_KH + KN + KN_IN + KO + KO_KP + KO_KR + KOK + KOK_IN + KS + KS_ARAB + KS_ARAB_IN + KSB + KSB_TZ + KSF + KSF_CM + KSH + KSH_DE + KU + KU_TR + KW + KW_GB + KY + KY_KG + LAG + LAG_TZ + LB + LB_LU + LG + LG_UG + LKT + LKT_US + LN + LN_AO + LN_CD + LN_CF + LN_CG + LO + LO_LA + LRC + LRC_IQ + LRC_IR + LT + LT_LT + LU + LU_CD + LUO + LUO_KE + LUY + LUY_KE + LV + LV_LV + MAI + MAI_IN + MAS + MAS_KE + MAS_TZ + MER + MER_KE + MFE + MFE_MU + MG + MG_MG + MGH + MGH_MZ + MGO + MGO_CM + MI + MI_NZ + MK + MK_MK + ML + ML_IN + MN + MN_MN + MNI + MNI_BENG + MNI_BENG_IN + MR + MR_IN + MS + MS_BN + MS_ID + MS_MY + MS_SG + MT + MT_MT + MUA + MUA_CM + MY + MY_MM + MZN + MZN_IR + NAQ + NAQ_NA + NB + NB_NO + NB_SJ + ND + ND_ZW + NDS + NDS_DE + NDS_NL + NE + NE_IN + NE_NP + NL + NL_AW + NL_BE + NL_BQ + NL_CW + NL_NL + NL_SR + NL_SX + NMG + NMG_CM + NN + NN_NO + NNH + NNH_CM + NUS + NUS_SS + NYN + NYN_UG + OM + OM_ET + OM_KE + OR + OR_IN + OS + OS_GE + OS_RU + PA + PA_ARAB + PA_ARAB_PK + PA_GURU + PA_GURU_IN + PCM + PCM_NG + PL + PL_PL + PRG + PS + PS_AF + PS_PK + PT + PT_AO + PT_BR + PT_CH + PT_CV + PT_GQ + PT_GW + PT_LU + PT_MO + PT_MZ + PT_PT + PT_ST + PT_TL + QU + QU_BO + QU_EC + QU_PE + RM + RM_CH + RN + RN_BI + RO + RO_MD + RO_RO + ROF + ROF_TZ + RU + RU_BY + RU_KG + RU_KZ + RU_MD + RU_RU + RU_UA + RW + RW_RW + RWK + RWK_TZ + SAH + SAH_RU + SAQ + SAQ_KE + SAT + SAT_OLCK + SAT_OLCK_IN + SBP + SBP_TZ + SD + SD_ARAB + SD_ARAB_PK + SD_DEVA + SD_DEVA_IN + SE + SE_FI + SE_NO + SE_SE + SEH + SEH_MZ + SES + SES_ML + SG + SG_CF + SHI + SHI_LATN + SHI_LATN_MA + SHI_TFNG + SHI_TFNG_MA + SI + SI_LK + SK + SK_SK + SL + SL_SI + SMN + SMN_FI + SN + SN_ZW + SO + SO_DJ + SO_ET + SO_KE + SO_SO + SQ + SQ_AL + SQ_MK + SQ_XK + SR + SR_CYRL + SR_CYRL_BA + SR_CYRL_ME + SR_CYRL_RS + SR_CYRL_XK + SR_LATN + SR_LATN_BA + SR_LATN_ME + SR_LATN_RS + SR_LATN_XK + SU + SU_LATN + SU_LATN_ID + SV + SV_AX + SV_FI + SV_SE + SW + SW_CD + SW_KE + SW_TZ + SW_UG + TA + TA_IN + TA_LK + TA_MY + TA_SG + TE + TE_IN + TEO + TEO_KE + TEO_UG + TG + TG_TJ + TH + TH_TH + TI + TI_ER + TI_ET + TK + TK_TM + TO + TO_TO + TR + TR_CY + TR_TR + TT + TT_RU + TWQ + TWQ_NE + TZM + TZM_MA + UG + UG_CN + UK + UK_UA + UR + UR_IN + UR_PK + UZ + UZ_ARAB + UZ_ARAB_AF + UZ_CYRL + UZ_CYRL_UZ + UZ_LATN + UZ_LATN_UZ + VAI + VAI_LATN + VAI_LATN_LR + VAI_VAII + VAI_VAII_LR + VI + VI_VN + VO + VUN + VUN_TZ + WAE + WAE_CH + WO + WO_SN + XH + XH_ZA + XOG + XOG_UG + YAV + YAV_CM + YI + YO + YO_BJ + YO_NG + YUE + YUE_HANS + YUE_HANS_CN + YUE_HANT + YUE_HANT_HK + ZGH + ZGH_MA + ZH + ZH_HANS + ZH_HANS_CN + ZH_HANS_HK + ZH_HANS_MO + ZH_HANS_SG + ZH_HANT + ZH_HANT_HK + ZH_HANT_MO + ZH_HANT_TW + ZU + ZU_ZA +} + +"""Represents shipping method channel listing.""" +type ShippingMethodChannelListing implements Node { + id: ID! + channel: Channel! + maximumOrderPrice: Money + minimumOrderPrice: Money + price: Money +} + +"""Represents channel.""" +type Channel implements Node { + id: ID! + + """Slug of the channel.""" + slug: String! + + """ + Name of the channel. + + Requires one of the following permissions: AUTHENTICATED_APP, AUTHENTICATED_STAFF_USER. + """ + name: String! + + """ + Whether the channel is active. + + Requires one of the following permissions: AUTHENTICATED_APP, AUTHENTICATED_STAFF_USER. + """ + isActive: Boolean! + + """ + A currency that is assigned to the channel. + + Requires one of the following permissions: AUTHENTICATED_APP, AUTHENTICATED_STAFF_USER. + """ + currencyCode: String! + + """ + Whether a channel has associated orders. + + Requires one of the following permissions: MANAGE_CHANNELS. + """ + hasOrders: Boolean! + + """ + Default country for the channel. Default country can be used in checkout to determine the stock quantities or calculate taxes when the country was not explicitly provided. + + Added in Saleor 3.1. + + Requires one of the following permissions: AUTHENTICATED_APP, AUTHENTICATED_STAFF_USER. + """ + defaultCountry: CountryDisplay! + + """ + List of warehouses assigned to this channel. + + Added in Saleor 3.5. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: AUTHENTICATED_APP, AUTHENTICATED_STAFF_USER. + """ + warehouses: [Warehouse!]! + + """ + List of shippable countries for the channel. + + Added in Saleor 3.6. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + countries: [CountryDisplay!] + + """ + Shipping methods that are available for the channel. + + Added in Saleor 3.6. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + availableShippingMethodsPerCountry(countries: [CountryCode!]): [ShippingMethodsPerCountry!] + + """ + Define the stock setting for this channel. + + Added in Saleor 3.7. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: AUTHENTICATED_APP, AUTHENTICATED_STAFF_USER. + """ + stockSettings: StockSettings! + + """ + Channel-specific order settings. + + Added in Saleor 3.12. + + Requires one of the following permissions: MANAGE_CHANNELS, MANAGE_ORDERS. + """ + orderSettings: OrderSettings! +} + +""" +List of shipping methods available for the country. + +Added in Saleor 3.6. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type ShippingMethodsPerCountry { + """The country code.""" + countryCode: CountryCode! + + """List of available shipping methods.""" + shippingMethods: [ShippingMethod!] +} + +"""An enumeration.""" +enum CountryCode { + AF + AX + AL + DZ + AS + AD + AO + AI + AQ + AG + AR + AM + AW + AU + AT + AZ + BS + BH + BD + BB + BY + BE + BZ + BJ + BM + BT + BO + BQ + BA + BW + BV + BR + IO + BN + BG + BF + BI + CV + KH + CM + CA + KY + CF + TD + CL + CN + CX + CC + CO + KM + CG + CD + CK + CR + CI + HR + CU + CW + CY + CZ + DK + DJ + DM + DO + EC + EG + SV + GQ + ER + EE + SZ + ET + EU + FK + FO + FJ + FI + FR + GF + PF + TF + GA + GM + GE + DE + GH + GI + GR + GL + GD + GP + GU + GT + GG + GN + GW + GY + HT + HM + VA + HN + HK + HU + IS + IN + ID + IR + IQ + IE + IM + IL + IT + JM + JP + JE + JO + KZ + KE + KI + KW + KG + LA + LV + LB + LS + LR + LY + LI + LT + LU + MO + MG + MW + MY + MV + ML + MT + MH + MQ + MR + MU + YT + MX + FM + MD + MC + MN + ME + MS + MA + MZ + MM + NA + NR + NP + NL + NC + NZ + NI + NE + NG + NU + NF + KP + MK + MP + NO + OM + PK + PW + PS + PA + PG + PY + PE + PH + PN + PL + PT + PR + QA + RE + RO + RU + RW + BL + SH + KN + LC + MF + PM + VC + WS + SM + ST + SA + SN + RS + SC + SL + SG + SX + SK + SI + SB + SO + ZA + GS + KR + SS + ES + LK + SD + SR + SJ + SE + CH + SY + TW + TJ + TZ + TH + TL + TG + TK + TO + TT + TN + TR + TM + TC + TV + UG + UA + AE + GB + UM + US + UY + UZ + VU + VE + VN + VG + VI + WF + EH + YE + ZM + ZW +} + +""" +Shipping methods that can be used as means of shipping for orders and checkouts. +""" +type ShippingMethod implements Node & ObjectWithMetadata { + """Unique ID of ShippingMethod available for Order.""" + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + """ + metafields(keys: [String!]): Metadata + + """Type of the shipping method.""" + type: ShippingMethodTypeEnum @deprecated(reason: "This field will be removed in Saleor 4.0.") + + """Shipping method name.""" + name: String! + + """ + Shipping method description. + + Rich text format. For reference see https://editorjs.io/ + """ + description: JSONString + + """Maximum delivery days for this shipping method.""" + maximumDeliveryDays: Int + + """Minimum delivery days for this shipping method.""" + minimumDeliveryDays: Int + + """Maximum order weight for this shipping method.""" + maximumOrderWeight: Weight @deprecated(reason: "This field will be removed in Saleor 4.0.") + + """Minimum order weight for this shipping method.""" + minimumOrderWeight: Weight @deprecated(reason: "This field will be removed in Saleor 4.0.") + + """Returns translated shipping method fields for the given language code.""" + translation( + """A language code to return the translation for shipping method.""" + languageCode: LanguageCodeEnum! + ): ShippingMethodTranslation + + """The price of selected shipping method.""" + price: Money! + + """Maximum order price for this shipping method.""" + maximumOrderPrice: Money + + """Minimal order price for this shipping method.""" + minimumOrderPrice: Money + + """Describes if this shipping method is active and can be selected.""" + active: Boolean! + + """Message connected to this shipping method.""" + message: String +} + +"""Represents weight value in a specific weight unit.""" +type Weight { + """Weight unit.""" + unit: WeightUnitsEnum! + + """Weight value.""" + value: Float! +} + +"""An enumeration.""" +enum WeightUnitsEnum { + G + LB + OZ + KG + TONNE +} + +""" +Represents the channel stock settings. + +Added in Saleor 3.7. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type StockSettings { + """ + Allocation strategy defines the preference of warehouses for allocations and reservations. + """ + allocationStrategy: AllocationStrategyEnum! +} + +""" +Determine the allocation strategy for the channel. + + PRIORITIZE_SORTING_ORDER - allocate stocks according to the warehouses' order + within the channel + + PRIORITIZE_HIGH_STOCK - allocate stock in a warehouse with the most stock +""" +enum AllocationStrategyEnum { + PRIORITIZE_SORTING_ORDER + PRIORITIZE_HIGH_STOCK +} + +"""Represents the channel-specific order settings.""" +type OrderSettings { + """ + When disabled, all new orders from checkout will be marked as unconfirmed. When enabled orders from checkout will become unfulfilled immediately. + """ + automaticallyConfirmAllNewOrders: Boolean! + + """ + When enabled, all non-shippable gift card orders will be fulfilled automatically. + """ + automaticallyFulfillNonShippableGiftCard: Boolean! + + """ + Determine what strategy will be used to mark the order as paid. Based on the choosen option the proper object will be created and attached to the order, when order is manualy marked as paid. + `PAYMENT_FLOW` - [default option] creates the `Payment` object. + `TRANSACTION_FLOW` - creates the `TransactionItem` object. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + markAsPaidStrategy: MarkAsPaidStrategyEnum! + + """ + Determine the transaction flow strategy to be used. Include the selected option in the payload sent to the payment app, as a requested action for the transaction. + + Added in Saleor 3.13. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + defaultTransactionFlowStrategy: TransactionFlowStrategyEnum! +} + +""" +Determine the mark as paid strategy for the channel. + + TRANSACTION_FLOW - new orders marked as paid will receive a + `TransactionItem` object, that will cover the `order.total`. + + PAYMENT_FLOW - new orders marked as paid will receive a + `Payment` object, that will cover the `order.total`. +""" +enum MarkAsPaidStrategyEnum { + TRANSACTION_FLOW + PAYMENT_FLOW +} + +""" +Determine the transaction flow strategy. + + AUTHORIZATION - the processed transaction should be only authorized + CHARGE - the processed transaction should be charged. +""" +enum TransactionFlowStrategyEnum { + AUTHORIZATION + CHARGE +} + +"""Represents shipping method postal code rule.""" +type ShippingMethodPostalCodeRule implements Node { + """The ID of the object.""" + id: ID! + + """Start address range.""" + start: String + + """End address range.""" + end: String + + """Inclusion type of the postal code rule.""" + inclusionType: PostalCodeRuleInclusionTypeEnum +} + +"""An enumeration.""" +enum PostalCodeRuleInclusionTypeEnum { + INCLUDE + EXCLUDE +} + +type ProductCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [ProductCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type ProductCountableEdge { + """The item at the end of the edge.""" + node: Product! + + """A cursor for use in pagination.""" + cursor: String! +} + +"""Represents an individual item for sale in the storefront.""" +type Product implements Node & ObjectWithMetadata { + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + seoTitle: String + seoDescription: String + name: String! + + """ + Description of the product. + + Rich text format. For reference see https://editorjs.io/ + """ + description: JSONString + productType: ProductType! + slug: String! + category: Category + created: DateTime! + updatedAt: DateTime! + chargeTaxes: Boolean! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `Channel.taxConfiguration` field to determine whether tax collection is enabled.") + weight: Weight + defaultVariant: ProductVariant + rating: Float + + """ + Channel given to retrieve this product. Also used by federation gateway to resolve this object in a federated query. + """ + channel: String + + """ + Description of the product. + + Rich text format. For reference see https://editorjs.io/ + """ + descriptionJson: JSONString @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `description` field instead.") + thumbnail( + """ + Desired longest side the image in pixels. Defaults to 4096. Images are never cropped. Pass 0 to retrieve the original size (not recommended). + """ + size: Int + + """ + The format of the image. When not provided, format of the original image will be used. + + Added in Saleor 3.6. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + format: ThumbnailFormatEnum = ORIGINAL + ): Image + + """ + Lists the storefront product's pricing, the current price and discounts, only meant for displaying. + """ + pricing( + """ + Destination address used to find warehouses where stock availability for this product is checked. If address is empty, uses `Shop.companyAddress` or fallbacks to server's `settings.DEFAULT_COUNTRY` configuration. + """ + address: AddressInput + ): ProductPricingInfo + + """Whether the product is in stock and visible or not.""" + isAvailable( + """ + Destination address used to find warehouses where stock availability for this product is checked. If address is empty, uses `Shop.companyAddress` or fallbacks to server's `settings.DEFAULT_COUNTRY` configuration. + """ + address: AddressInput + ): Boolean + + """A type of tax. Assigned by enabled tax gateway""" + taxType: TaxType @deprecated(reason: "This field will be removed in Saleor 4.0. Use `taxClass` field instead.") + + """ + Get a single attribute attached to product by attribute slug. + + Added in Saleor 3.9. + """ + attribute( + """Slug of the attribute""" + slug: String! + ): SelectedAttribute + + """List of attributes assigned to this product.""" + attributes: [SelectedAttribute!]! + + """ + List of availability in channels for the product. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + channelListings: [ProductChannelListing!] + + """Get a single product media by ID.""" + mediaById( + """ID of a product media.""" + id: ID + ): ProductMedia + + """Get a single product image by ID.""" + imageById( + """ID of a product image.""" + id: ID + ): ProductImage @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `mediaById` field instead.") + + """ + Get a single variant by SKU or ID. + + Added in Saleor 3.9. + """ + variant( + """ID of the variant.""" + id: ID + + """SKU of the variant.""" + sku: String + ): ProductVariant @deprecated(reason: "This field will be removed in Saleor 4.0. Use top-level `variant` query.") + + """ + List of variants for the product. Requires the following permissions to include the unpublished items: MANAGE_ORDERS, MANAGE_DISCOUNTS, MANAGE_PRODUCTS. + """ + variants: [ProductVariant!] + + """List of media for the product.""" + media( + """ + Sort media. + + Added in Saleor 3.9. + """ + sortBy: MediaSortingInput + ): [ProductMedia!] + + """List of images for the product.""" + images: [ProductImage!] @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `media` field instead.") + + """ + List of collections for the product. Requires the following permissions to include the unpublished items: MANAGE_ORDERS, MANAGE_DISCOUNTS, MANAGE_PRODUCTS. + """ + collections: [Collection!] + + """Returns translated product fields for the given language code.""" + translation( + """A language code to return the translation for product.""" + languageCode: LanguageCodeEnum! + ): ProductTranslation + + """Date when product is available for purchase.""" + availableForPurchase: Date @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `availableForPurchaseAt` field to fetch the available for purchase date.") + + """Date when product is available for purchase.""" + availableForPurchaseAt: DateTime + + """Whether the product is available for purchase.""" + isAvailableForPurchase: Boolean + + """ + Tax class assigned to this product type. All products of this product type use this tax class, unless it's overridden in the `Product` type. + + Requires one of the following permissions: AUTHENTICATED_STAFF_USER. + """ + taxClass: TaxClass + + """ + External ID of this product. + + Added in Saleor 3.10. + """ + externalReference: String +} + +""" +Represents a type of product. It defines what attributes are available to products of this type. +""" +type ProductType implements Node & ObjectWithMetadata { + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + name: String! + slug: String! + hasVariants: Boolean! + isShippingRequired: Boolean! + isDigital: Boolean! + weight: Weight + + """The product type kind.""" + kind: ProductTypeKindEnum! + + """List of products of this type.""" + products( + """Slug of a channel for which the data should be returned.""" + channel: String + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): ProductCountableConnection @deprecated(reason: "This field will be removed in Saleor 4.0. Use the top-level `products` query with the `productTypes` filter.") + + """A type of tax. Assigned by enabled tax gateway""" + taxType: TaxType @deprecated(reason: "This field will be removed in Saleor 4.0. Use `taxClass` field instead.") + + """ + Tax class assigned to this product type. All products of this product type use this tax class, unless it's overridden in the `Product` type. + + Requires one of the following permissions: AUTHENTICATED_STAFF_USER. + """ + taxClass: TaxClass + + """Variant attributes of that product type.""" + variantAttributes( + """Define scope of returned attributes.""" + variantSelection: VariantAttributeScope + ): [Attribute!] @deprecated(reason: "This field will be removed in Saleor 4.0. Use `assignedVariantAttributes` instead.") + + """ + Variant attributes of that product type with attached variant selection. + + Added in Saleor 3.1. + """ + assignedVariantAttributes( + """Define scope of returned attributes.""" + variantSelection: VariantAttributeScope + ): [AssignedVariantAttribute!] + + """Product attributes of that product type.""" + productAttributes: [Attribute!] + + """ + List of attributes which can be assigned to this product type. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + availableAttributes( + filter: AttributeFilterInput + where: AttributeWhereInput + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): AttributeCountableConnection +} + +"""An enumeration.""" +enum ProductTypeKindEnum { + NORMAL + GIFT_CARD +} + +"""Representation of tax types fetched from tax gateway.""" +type TaxType { + """Description of the tax type.""" + description: String + + """External tax code used to identify given tax group.""" + taxCode: String +} + +""" +Tax class is a named object used to define tax rates per country. Tax class can be assigned to product types, products and shipping methods to define their tax rates. + +Added in Saleor 3.9. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type TaxClass implements Node & ObjectWithMetadata { + """The ID of the object.""" + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + + """Name of the tax class.""" + name: String! + + """Country-specific tax rates for this tax class.""" + countries: [TaxClassCountryRate!]! +} + +""" +Tax rate for a country. When tax class is null, it represents the default tax rate for that country; otherwise it's a country tax rate specific to the given tax class. + +Added in Saleor 3.9. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type TaxClassCountryRate { + """Country in which this tax rate applies.""" + country: CountryDisplay! + + """Tax rate value.""" + rate: Float! + + """Related tax class.""" + taxClass: TaxClass +} + +""" +Custom attribute of a product. Attributes can be assigned to products and variants at the product type level. +""" +type Attribute implements Node & ObjectWithMetadata { + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + + """The input type to use for entering attribute values in the dashboard.""" + inputType: AttributeInputTypeEnum + + """The entity type which can be used as a reference.""" + entityType: AttributeEntityTypeEnum + + """Name of an attribute displayed in the interface.""" + name: String + + """Internal representation of an attribute name.""" + slug: String + + """The attribute type.""" + type: AttributeTypeEnum + + """The unit of attribute values.""" + unit: MeasurementUnitsEnum + + """List of attribute's values.""" + choices( + """Sort attribute choices.""" + sortBy: AttributeChoicesSortingInput + + """Filtering options for attribute choices.""" + filter: AttributeValueFilterInput + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): AttributeValueCountableConnection + + """ + Whether the attribute requires values to be passed or not. Requires one of the following permissions: MANAGE_PAGES, MANAGE_PAGE_TYPES_AND_ATTRIBUTES, MANAGE_PRODUCTS, MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. + """ + valueRequired: Boolean! + + """ + Whether the attribute should be visible or not in storefront. Requires one of the following permissions: MANAGE_PAGES, MANAGE_PAGE_TYPES_AND_ATTRIBUTES, MANAGE_PRODUCTS, MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. + """ + visibleInStorefront: Boolean! + + """ + Whether the attribute can be filtered in storefront. Requires one of the following permissions: MANAGE_PAGES, MANAGE_PAGE_TYPES_AND_ATTRIBUTES, MANAGE_PRODUCTS, MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. + """ + filterableInStorefront: Boolean! @deprecated(reason: "This field will be removed in Saleor 4.0.") + + """ + Whether the attribute can be filtered in dashboard. Requires one of the following permissions: MANAGE_PAGES, MANAGE_PAGE_TYPES_AND_ATTRIBUTES, MANAGE_PRODUCTS, MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. + """ + filterableInDashboard: Boolean! + + """ + Whether the attribute can be displayed in the admin product list. Requires one of the following permissions: MANAGE_PAGES, MANAGE_PAGE_TYPES_AND_ATTRIBUTES, MANAGE_PRODUCTS, MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. + """ + availableInGrid: Boolean! @deprecated(reason: "This field will be removed in Saleor 4.0.") + + """ + The position of the attribute in the storefront navigation (0 by default). Requires one of the following permissions: MANAGE_PAGES, MANAGE_PAGE_TYPES_AND_ATTRIBUTES, MANAGE_PRODUCTS, MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. + """ + storefrontSearchPosition: Int! @deprecated(reason: "This field will be removed in Saleor 4.0.") + + """Returns translated attribute fields for the given language code.""" + translation( + """A language code to return the translation for attribute.""" + languageCode: LanguageCodeEnum! + ): AttributeTranslation + + """Flag indicating that attribute has predefined choices.""" + withChoices: Boolean! + productTypes( + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): ProductTypeCountableConnection! + productVariantTypes( + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): ProductTypeCountableConnection! + + """ + External ID of this attribute. + + Added in Saleor 3.10. + """ + externalReference: String +} + +"""An enumeration.""" +enum AttributeInputTypeEnum { + DROPDOWN + MULTISELECT + FILE + REFERENCE + NUMERIC + RICH_TEXT + PLAIN_TEXT + SWATCH + BOOLEAN + DATE + DATE_TIME +} + +"""An enumeration.""" +enum AttributeEntityTypeEnum { + PAGE + PRODUCT + PRODUCT_VARIANT +} + +"""An enumeration.""" +enum AttributeTypeEnum { + PRODUCT_TYPE + PAGE_TYPE +} + +"""An enumeration.""" +enum MeasurementUnitsEnum { + CM + M + KM + FT + YD + INCH + SQ_CM + SQ_M + SQ_KM + SQ_FT + SQ_YD + SQ_INCH + CUBIC_MILLIMETER + CUBIC_CENTIMETER + CUBIC_DECIMETER + CUBIC_METER + LITER + CUBIC_FOOT + CUBIC_INCH + CUBIC_YARD + QT + PINT + FL_OZ + ACRE_IN + ACRE_FT + G + LB + OZ + KG + TONNE +} + +type AttributeValueCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [AttributeValueCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type AttributeValueCountableEdge { + """The item at the end of the edge.""" + node: AttributeValue! + + """A cursor for use in pagination.""" + cursor: String! +} + +"""Represents a value of an attribute.""" +type AttributeValue implements Node { + id: ID! + + """Name of a value displayed in the interface.""" + name: String + + """Internal representation of a value (unique per attribute).""" + slug: String + + """ + Represent value of the attribute value (e.g. color values for swatch attributes). + """ + value: String + + """Returns translated attribute value fields for the given language code.""" + translation( + """A language code to return the translation for attribute value.""" + languageCode: LanguageCodeEnum! + ): AttributeValueTranslation + + """The input type to use for entering attribute values in the dashboard.""" + inputType: AttributeInputTypeEnum + + """The ID of the attribute reference.""" + reference: ID + + """Represents file URL and content type (if attribute value is a file).""" + file: File + + """ + Represents the text of the attribute value, includes formatting. + + Rich text format. For reference see https://editorjs.io/ + """ + richText: JSONString + + """ + Represents the text of the attribute value, plain text without formating. + """ + plainText: String + + """Represents the boolean value of the attribute value.""" + boolean: Boolean + + """Represents the date value of the attribute value.""" + date: Date + + """Represents the date/time value of the attribute value.""" + dateTime: DateTime + + """ + External ID of this attribute value. + + Added in Saleor 3.10. + """ + externalReference: String +} + +type AttributeValueTranslation implements Node { + id: ID! + + """Translation language.""" + language: LanguageDisplay! + name: String! + + """ + Attribute value. + + Rich text format. For reference see https://editorjs.io/ + """ + richText: JSONString + + """Attribute plain text value.""" + plainText: String +} + +type File { + """The URL of the file.""" + url: String! + + """Content type of the file.""" + contentType: String +} + +""" +The `Date` scalar type represents a Date +value as specified by +[iso8601](https://en.wikipedia.org/wiki/ISO_8601). +""" +scalar Date + +input AttributeChoicesSortingInput { + """Specifies the direction in which to sort products.""" + direction: OrderDirection! + + """Sort attribute choices by the selected field.""" + field: AttributeChoicesSortField! +} + +enum AttributeChoicesSortField { + """Sort attribute choice by name.""" + NAME + + """Sort attribute choice by slug.""" + SLUG +} + +input AttributeValueFilterInput { + search: String + ids: [ID!] +} + +type AttributeTranslation implements Node { + id: ID! + + """Translation language.""" + language: LanguageDisplay! + name: String! +} + +type ProductTypeCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [ProductTypeCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type ProductTypeCountableEdge { + """The item at the end of the edge.""" + node: ProductType! + + """A cursor for use in pagination.""" + cursor: String! +} + +enum VariantAttributeScope { + ALL + VARIANT_SELECTION + NOT_VARIANT_SELECTION +} + +""" +Represents assigned attribute to variant with variant selection attached. + +Added in Saleor 3.1. +""" +type AssignedVariantAttribute { + """Attribute assigned to variant.""" + attribute: Attribute! + + """ + Determines, whether assigned attribute is allowed for variant selection. Supported variant types for variant selection are: ['dropdown', 'boolean', 'swatch', 'numeric'] + """ + variantSelection: Boolean! +} + +type AttributeCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [AttributeCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type AttributeCountableEdge { + """The item at the end of the edge.""" + node: Attribute! + + """A cursor for use in pagination.""" + cursor: String! +} + +input AttributeFilterInput { + valueRequired: Boolean + isVariantOnly: Boolean + visibleInStorefront: Boolean + filterableInStorefront: Boolean + filterableInDashboard: Boolean + availableInGrid: Boolean + metadata: [MetadataFilter!] + search: String + ids: [ID!] + type: AttributeTypeEnum + inCollection: ID + inCategory: ID + slugs: [String!] + + """ + Specifies the channel by which the data should be filtered. + + DEPRECATED: this field will be removed in Saleor 4.0. Use root-level channel argument instead. + """ + channel: String +} + +input MetadataFilter { + """Key of a metadata item.""" + key: String! + + """Value of a metadata item.""" + value: String +} + +""" +Where filtering options. + +Added in Saleor 3.11. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +input AttributeWhereInput { + valueRequired: Boolean + visibleInStorefront: Boolean + filterableInDashboard: Boolean + metadata: [MetadataFilter!] + ids: [ID!] + name: StringFilterInput + slug: StringFilterInput + withChoices: Boolean + inputType: AttributeInputTypeEnumFilterInput + entityType: AttributeEntityTypeEnumFilterInput + type: AttributeTypeEnumFilterInput + unit: MeasurementUnitsEnumFilterInput + inCollection: ID + inCategory: ID + + """List of conditions that must be met.""" + AND: [AttributeWhereInput!] + + """A list of conditions of which at least one must be met.""" + OR: [AttributeWhereInput!] +} + +""" +Define the filtering options for string fields. + +Added in Saleor 3.11. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +input StringFilterInput { + """The value equal to.""" + eq: String + + """The value included in.""" + oneOf: [String!] +} + +input AttributeInputTypeEnumFilterInput { + """The value equal to.""" + eq: AttributeInputTypeEnum + + """The value included in.""" + oneOf: [AttributeInputTypeEnum!] +} + +input AttributeEntityTypeEnumFilterInput { + """The value equal to.""" + eq: AttributeEntityTypeEnum + + """The value included in.""" + oneOf: [AttributeEntityTypeEnum!] +} + +input AttributeTypeEnumFilterInput { + """The value equal to.""" + eq: AttributeTypeEnum + + """The value included in.""" + oneOf: [AttributeTypeEnum!] +} + +input MeasurementUnitsEnumFilterInput { + """The value equal to.""" + eq: MeasurementUnitsEnum + + """The value included in.""" + oneOf: [MeasurementUnitsEnum!] +} + +""" +Represents a single category of products. Categories allow to organize products in a tree-hierarchies which can be used for navigation in the storefront. +""" +type Category implements Node & ObjectWithMetadata { + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + seoTitle: String + seoDescription: String + name: String! + + """ + Description of the category. + + Rich text format. For reference see https://editorjs.io/ + """ + description: JSONString + slug: String! + parent: Category + level: Int! + + """ + Description of the category. + + Rich text format. For reference see https://editorjs.io/ + """ + descriptionJson: JSONString @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `description` field instead.") + + """List of ancestors of the category.""" + ancestors( + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): CategoryCountableConnection + + """ + List of products in the category. Requires the following permissions to include the unpublished items: MANAGE_ORDERS, MANAGE_DISCOUNTS, MANAGE_PRODUCTS. + """ + products( + """ + Filtering options for products. + + Added in Saleor 3.10. + """ + filter: ProductFilterInput + + """ + Sort products. + + Added in Saleor 3.10. + """ + sortBy: ProductOrder + + """Slug of a channel for which the data should be returned.""" + channel: String + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): ProductCountableConnection + + """List of children of the category.""" + children( + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): CategoryCountableConnection + backgroundImage( + """ + Desired longest side the image in pixels. Defaults to 4096. Images are never cropped. Pass 0 to retrieve the original size (not recommended). + """ + size: Int + + """ + The format of the image. When not provided, format of the original image will be used. + + Added in Saleor 3.6. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + format: ThumbnailFormatEnum = ORIGINAL + ): Image + + """Returns translated category fields for the given language code.""" + translation( + """A language code to return the translation for category.""" + languageCode: LanguageCodeEnum! + ): CategoryTranslation +} + +type CategoryCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [CategoryCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type CategoryCountableEdge { + """The item at the end of the edge.""" + node: Category! + + """A cursor for use in pagination.""" + cursor: String! +} + +input ProductFilterInput { + isPublished: Boolean + collections: [ID!] + categories: [ID!] + hasCategory: Boolean + attributes: [AttributeInput!] + + """Filter by variants having specific stock status.""" + stockAvailability: StockAvailability + stocks: ProductStockFilterInput + search: String + metadata: [MetadataFilter!] + + """ + Filter by the publication date. + + Added in Saleor 3.8. + """ + publishedFrom: DateTime + + """ + Filter by availability for purchase. + + Added in Saleor 3.8. + """ + isAvailable: Boolean + + """ + Filter by the date of availability for purchase. + + Added in Saleor 3.8. + """ + availableFrom: DateTime + + """ + Filter by visibility in product listings. + + Added in Saleor 3.8. + """ + isVisibleInListing: Boolean + price: PriceRangeInput + + """Filter by the lowest variant price after discounts.""" + minimalPrice: PriceRangeInput + + """Filter by when was the most recent update.""" + updatedAt: DateTimeRangeInput + productTypes: [ID!] + + """Filter on whether product is a gift card or not.""" + giftCard: Boolean + ids: [ID!] + hasPreorderedVariants: Boolean + slugs: [String!] + + """ + Specifies the channel by which the data should be filtered. + + DEPRECATED: this field will be removed in Saleor 4.0. Use root-level channel argument instead. + """ + channel: String +} + +input AttributeInput { + """Internal representation of an attribute name.""" + slug: String! + + """Internal representation of a value (unique per attribute).""" + values: [String!] + + """The range that the returned values should be in.""" + valuesRange: IntRangeInput + + """The date/time range that the returned values should be in.""" + dateTime: DateTimeRangeInput + + """ + The date range that the returned values should be in. In case of date/time attributes, the UTC midnight of the given date is used. + """ + date: DateRangeInput + + """The boolean value of the attribute.""" + boolean: Boolean +} + +input IntRangeInput { + """Value greater than or equal to.""" + gte: Int + + """Value less than or equal to.""" + lte: Int +} + +input DateTimeRangeInput { + """Start date.""" + gte: DateTime + + """End date.""" + lte: DateTime +} + +input DateRangeInput { + """Start date.""" + gte: Date + + """End date.""" + lte: Date +} + +enum StockAvailability { + IN_STOCK + OUT_OF_STOCK +} + +input ProductStockFilterInput { + warehouseIds: [ID!] + quantity: IntRangeInput +} + +input PriceRangeInput { + """Price greater than or equal to.""" + gte: Float + + """Price less than or equal to.""" + lte: Float +} + +input ProductOrder { + """Specifies the direction in which to sort products.""" + direction: OrderDirection! + + """ + Specifies the channel in which to sort the data. + + DEPRECATED: this field will be removed in Saleor 4.0. Use root-level channel argument instead. + """ + channel: String + + """ + Sort product by the selected attribute's values. + Note: this doesn't take translations into account yet. + """ + attributeId: ID + + """Sort products by the selected field.""" + field: ProductOrderField +} + +enum ProductOrderField { + """Sort products by name.""" + NAME + + """ + Sort products by rank. Note: This option is available only with the `search` filter. + """ + RANK + + """ + Sort products by price. + + This option requires a channel filter to work as the values can vary between channels. + """ + PRICE + + """ + Sort products by a minimal price of a product's variant. + + This option requires a channel filter to work as the values can vary between channels. + """ + MINIMAL_PRICE + + """Sort products by update date.""" + LAST_MODIFIED + + """Sort products by update date.""" + DATE + + """Sort products by type.""" + TYPE + + """ + Sort products by publication status. + + This option requires a channel filter to work as the values can vary between channels. + """ + PUBLISHED + + """ + Sort products by publication date. + + This option requires a channel filter to work as the values can vary between channels. + """ + PUBLICATION_DATE + + """ + Sort products by publication date. + + This option requires a channel filter to work as the values can vary between channels. + """ + PUBLISHED_AT + + """Sort products by update date.""" + LAST_MODIFIED_AT + + """ + Sort products by collection. Note: This option is available only for the `Collection.products` query. + + This option requires a channel filter to work as the values can vary between channels. + """ + COLLECTION + + """Sort products by rating.""" + RATING + + """ + Sort products by creation date. + + Added in Saleor 3.8. + """ + CREATED_AT +} + +"""Represents an image.""" +type Image { + """The URL of the image.""" + url: String! + + """Alt text for an image.""" + alt: String +} + +"""An enumeration.""" +enum ThumbnailFormatEnum { + ORIGINAL + AVIF + WEBP +} + +type CategoryTranslation implements Node { + id: ID! + + """Translation language.""" + language: LanguageDisplay! + seoTitle: String + seoDescription: String + name: String + + """ + Translated description of the category. + + Rich text format. For reference see https://editorjs.io/ + """ + description: JSONString + + """ + Translated description of the category. + + Rich text format. For reference see https://editorjs.io/ + """ + descriptionJson: JSONString @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `description` field instead.") +} + +"""Represents a version of a product such as different size or color.""" +type ProductVariant implements Node & ObjectWithMetadata { + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + name: String! + sku: String + product: Product! + trackInventory: Boolean! + quantityLimitPerCustomer: Int + weight: Weight + + """ + Channel given to retrieve this product variant. Also used by federation gateway to resolve this object in a federated query. + """ + channel: String + + """ + List of price information in channels for the product. + + Requires one of the following permissions: AUTHENTICATED_APP, AUTHENTICATED_STAFF_USER. + """ + channelListings: [ProductVariantChannelListing!] + + """ + Lists the storefront variant's pricing, the current price and discounts, only meant for displaying. + """ + pricing( + """ + Destination address used to find warehouses where stock availability for this product is checked. If address is empty, uses `Shop.companyAddress` or fallbacks to server's `settings.DEFAULT_COUNTRY` configuration. + """ + address: AddressInput + ): VariantPricingInfo + + """List of attributes assigned to this variant.""" + attributes( + """Define scope of returned attributes.""" + variantSelection: VariantAttributeScope + ): [SelectedAttribute!]! + + """Gross margin percentage value.""" + margin: Int + + """ + Total quantity ordered. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + quantityOrdered: Int + + """ + Total revenue generated by a variant in given period of time. Note: this field should be queried using `reportProductSales` query as it uses optimizations suitable for such calculations. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + revenue(period: ReportingPeriod): TaxedMoney + + """List of images for the product variant.""" + images: [ProductImage!] @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `media` field instead.") + + """List of media for the product variant.""" + media: [ProductMedia!] + + """Returns translated product variant fields for the given language code.""" + translation( + """A language code to return the translation for product variant.""" + languageCode: LanguageCodeEnum! + ): ProductVariantTranslation + + """ + Digital content for the product variant. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + digitalContent: DigitalContent + + """ + Stocks for the product variant. + + Requires one of the following permissions: MANAGE_PRODUCTS, MANAGE_ORDERS. + """ + stocks( + """ + Destination address used to find warehouses where stock availability for this product is checked. If address is empty, uses `Shop.companyAddress` or fallbacks to server's `settings.DEFAULT_COUNTRY` configuration. + """ + address: AddressInput + + """ + Two-letter ISO 3166-1 country code. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `address` argument instead. + """ + countryCode: CountryCode + ): [Stock!] + + """ + Quantity of a product available for sale in one checkout. Field value will be `null` when no `limitQuantityPerCheckout` in global settings has been set, and `productVariant` stocks are not tracked. + """ + quantityAvailable( + """ + Destination address used to find warehouses where stock availability for this product is checked. If address is empty, uses `Shop.companyAddress` or fallbacks to server's `settings.DEFAULT_COUNTRY` configuration. + """ + address: AddressInput + + """ + Two-letter ISO 3166-1 country code. When provided, the exact quantity from a warehouse operating in shipping zones that contain this country will be returned. Otherwise, it will return the maximum quantity from all shipping zones. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `address` argument instead. + """ + countryCode: CountryCode + ): Int + + """ + Preorder data for product variant. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + preorder: PreorderData + created: DateTime! + updatedAt: DateTime! + + """ + External ID of this product. + + Added in Saleor 3.10. + """ + externalReference: String +} + +"""Represents product varaint channel listing.""" +type ProductVariantChannelListing implements Node { + id: ID! + channel: Channel! + price: Money + + """Cost price of the variant.""" + costPrice: Money + + """ + Gross margin percentage value. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + margin: Int + + """ + Preorder variant data. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + preorderThreshold: PreorderThreshold +} + +"""Represents preorder variant data for channel.""" +type PreorderThreshold { + """Preorder threshold for product variant in this channel.""" + quantity: Int + + """Number of sold product variant in this channel.""" + soldUnits: Int! +} + +"""Represents availability of a variant in the storefront.""" +type VariantPricingInfo { + """Whether it is in sale or not.""" + onSale: Boolean + + """The discount amount if in sale (null otherwise).""" + discount: TaxedMoney + + """The discount amount in the local currency.""" + discountLocalCurrency: TaxedMoney + + """The price, with any discount subtracted.""" + price: TaxedMoney + + """The price without any discount.""" + priceUndiscounted: TaxedMoney + + """The discounted price in the local currency.""" + priceLocalCurrency: TaxedMoney +} + +""" +Represents a monetary value with taxes. In cases where taxes were not applied, net and gross values will be equal. +""" +type TaxedMoney { + """Currency code.""" + currency: String! + + """Amount of money including taxes.""" + gross: Money! + + """Amount of money without taxes.""" + net: Money! + + """Amount of taxes.""" + tax: Money! +} + +input AddressInput { + """Given name.""" + firstName: String + + """Family name.""" + lastName: String + + """Company or organization.""" + companyName: String + + """Address.""" + streetAddress1: String + + """Address.""" + streetAddress2: String + + """City.""" + city: String + + """District.""" + cityArea: String + + """Postal code.""" + postalCode: String + + """Country.""" + country: CountryCode + + """State or province.""" + countryArea: String + + """Phone number.""" + phone: String +} + +"""Represents a custom attribute.""" +type SelectedAttribute { + """Name of an attribute displayed in the interface.""" + attribute: Attribute! + + """Values of an attribute.""" + values: [AttributeValue!]! +} + +enum ReportingPeriod { + TODAY + THIS_MONTH +} + +"""Represents a product image.""" +type ProductImage { + """The ID of the image.""" + id: ID! + + """The alt text of the image.""" + alt: String + + """ + The new relative sorting position of the item (from -inf to +inf). 1 moves the item one position forward, -1 moves the item one position backward, 0 leaves the item unchanged. + """ + sortOrder: Int + url( + """ + Desired longest side the image in pixels. Defaults to 4096. Images are never cropped. Pass 0 to retrieve the original size (not recommended). + """ + size: Int + + """ + The format of the image. When not provided, format of the original image will be used. + + Added in Saleor 3.6. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + format: ThumbnailFormatEnum = ORIGINAL + ): String! +} + +"""Represents a product media.""" +type ProductMedia implements Node & ObjectWithMetadata { + id: ID! + + """ + List of private metadata items. Requires staff permissions to access. + + Added in Saleor 3.12. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.12. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.12. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """ + List of public metadata items. Can be accessed without permissions. + + Added in Saleor 3.12. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.12. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.12. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + sortOrder: Int + alt: String! + type: ProductMediaType! + oembedData: JSONString! + url( + """ + Desired longest side the image in pixels. Defaults to 4096. Images are never cropped. Pass 0 to retrieve the original size (not recommended). + """ + size: Int + + """ + The format of the image. When not provided, format of the original image will be used. + + Added in Saleor 3.6. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + format: ThumbnailFormatEnum = ORIGINAL + ): String! + + """ + Product id the media refers to. + + Added in Saleor 3.12. + """ + productId: ID +} + +"""An enumeration.""" +enum ProductMediaType { + IMAGE + VIDEO +} + +type ProductVariantTranslation implements Node { + id: ID! + + """Translation language.""" + language: LanguageDisplay! + name: String! +} + +type DigitalContent implements Node & ObjectWithMetadata { + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + useDefaultSettings: Boolean! + automaticFulfillment: Boolean! + contentFile: String! + maxDownloads: Int + urlValidDays: Int + + """List of URLs for the digital variant.""" + urls: [DigitalContentUrl!] + + """Product variant assigned to digital content.""" + productVariant: ProductVariant! +} + +type DigitalContentUrl implements Node { + id: ID! + content: DigitalContent! + created: DateTime! + downloadNum: Int! + + """URL for digital content.""" + url: String + + """UUID of digital content.""" + token: UUID! +} + +scalar UUID + +"""Represents stock.""" +type Stock implements Node { + id: ID! + warehouse: Warehouse! + productVariant: ProductVariant! + + """ + Quantity of a product in the warehouse's possession, including the allocated stock that is waiting for shipment. + + Requires one of the following permissions: MANAGE_PRODUCTS, MANAGE_ORDERS. + """ + quantity: Int! + + """ + Quantity allocated for orders. + + Requires one of the following permissions: MANAGE_PRODUCTS, MANAGE_ORDERS. + """ + quantityAllocated: Int! + + """ + Quantity reserved for checkouts. + + Requires one of the following permissions: MANAGE_PRODUCTS, MANAGE_ORDERS. + """ + quantityReserved: Int! +} + +"""Represents preorder settings for product variant.""" +type PreorderData { + """ + The global preorder threshold for product variant. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + globalThreshold: Int + + """ + Total number of sold product variant during preorder. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + globalSoldUnits: Int! + + """Preorder end date.""" + endDate: DateTime +} + +"""Represents availability of a product in the storefront.""" +type ProductPricingInfo { + """Whether it is in sale or not.""" + onSale: Boolean + + """The discount amount if in sale (null otherwise).""" + discount: TaxedMoney + + """The discount amount in the local currency.""" + discountLocalCurrency: TaxedMoney + + """The discounted price range of the product variants.""" + priceRange: TaxedMoneyRange + + """The undiscounted price range of the product variants.""" + priceRangeUndiscounted: TaxedMoneyRange + + """ + The discounted price range of the product variants in the local currency. + """ + priceRangeLocalCurrency: TaxedMoneyRange + + """ + Determines whether this product's price displayed in a storefront should include taxes. + + Added in Saleor 3.9. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + displayGrossPrices: Boolean! +} + +"""Represents a range of monetary values.""" +type TaxedMoneyRange { + """Lower bound of a price range.""" + start: TaxedMoney + + """Upper bound of a price range.""" + stop: TaxedMoney +} + +"""Represents product channel listing.""" +type ProductChannelListing implements Node { + id: ID! + publicationDate: Date @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `publishedAt` field to fetch the publication date.") + + """ + The product publication date time. + + Added in Saleor 3.3. + """ + publishedAt: DateTime + isPublished: Boolean! + channel: Channel! + visibleInListings: Boolean! + availableForPurchase: Date @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `availableForPurchaseAt` field to fetch the available for purchase date.") + + """ + The product available for purchase date time. + + Added in Saleor 3.3. + """ + availableForPurchaseAt: DateTime + + """The price of the cheapest variant (including discounts).""" + discountedPrice: Money + + """ + Purchase cost of product. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + purchaseCost: MoneyRange + + """ + Range of margin percentage value. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + margin: Margin + + """Whether the product is available for purchase.""" + isAvailableForPurchase: Boolean + + """ + Lists the storefront product's pricing, the current price and discounts, only meant for displaying. + """ + pricing( + """ + Destination address used to find warehouses where stock availability for this product is checked. If address is empty, uses `Shop.companyAddress` or fallbacks to server's `settings.DEFAULT_COUNTRY` configuration. + """ + address: AddressInput + ): ProductPricingInfo +} + +type Margin { + start: Int + stop: Int +} + +input MediaSortingInput { + """Specifies the direction in which to sort products.""" + direction: OrderDirection! + + """Sort media by the selected field.""" + field: MediaChoicesSortField! +} + +enum MediaChoicesSortField { + """Sort media by ID.""" + ID +} + +"""Represents a collection of products.""" +type Collection implements Node & ObjectWithMetadata { + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + seoTitle: String + seoDescription: String + name: String! + + """ + Description of the collection. + + Rich text format. For reference see https://editorjs.io/ + """ + description: JSONString + slug: String! + + """ + Channel given to retrieve this collection. Also used by federation gateway to resolve this object in a federated query. + """ + channel: String + + """ + Description of the collection. + + Rich text format. For reference see https://editorjs.io/ + """ + descriptionJson: JSONString @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `description` field instead.") + + """List of products in this collection.""" + products( + """Filtering options for products.""" + filter: ProductFilterInput + + """Sort products.""" + sortBy: ProductOrder + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): ProductCountableConnection + backgroundImage( + """ + Desired longest side the image in pixels. Defaults to 4096. Images are never cropped. Pass 0 to retrieve the original size (not recommended). + """ + size: Int + + """ + The format of the image. When not provided, format of the original image will be used. + + Added in Saleor 3.6. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + format: ThumbnailFormatEnum = ORIGINAL + ): Image + + """Returns translated collection fields for the given language code.""" + translation( + """A language code to return the translation for collection.""" + languageCode: LanguageCodeEnum! + ): CollectionTranslation + + """ + List of channels in which the collection is available. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + channelListings: [CollectionChannelListing!] +} + +type CollectionTranslation implements Node { + id: ID! + + """Translation language.""" + language: LanguageDisplay! + seoTitle: String + seoDescription: String + name: String + + """ + Translated description of the collection. + + Rich text format. For reference see https://editorjs.io/ + """ + description: JSONString + + """ + Translated description of the collection. + + Rich text format. For reference see https://editorjs.io/ + """ + descriptionJson: JSONString @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `description` field instead.") +} + +"""Represents collection channel listing.""" +type CollectionChannelListing implements Node { + id: ID! + publicationDate: Date @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `publishedAt` field to fetch the publication date.") + + """ + The collection publication date. + + Added in Saleor 3.3. + """ + publishedAt: DateTime + isPublished: Boolean! + channel: Channel! +} + +type ProductTranslation implements Node { + id: ID! + + """Translation language.""" + language: LanguageDisplay! + seoTitle: String + seoDescription: String + name: String + + """ + Translated description of the product. + + Rich text format. For reference see https://editorjs.io/ + """ + description: JSONString + + """ + Translated description of the product. + + Rich text format. For reference see https://editorjs.io/ + """ + descriptionJson: JSONString @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `description` field instead.") +} + +type WarehouseCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [WarehouseCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type WarehouseCountableEdge { + """The item at the end of the edge.""" + node: Warehouse! + + """A cursor for use in pagination.""" + cursor: String! +} + +input WarehouseFilterInput { + clickAndCollectOption: WarehouseClickAndCollectOptionEnum + search: String + ids: [ID!] + isPrivate: Boolean + channels: [ID!] + slugs: [String!] +} + +input WarehouseSortingInput { + """Specifies the direction in which to sort products.""" + direction: OrderDirection! + + """Sort warehouses by the selected field.""" + field: WarehouseSortField! +} + +enum WarehouseSortField { + """Sort warehouses by name.""" + NAME +} + +type TranslatableItemConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [TranslatableItemEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type TranslatableItemEdge { + """The item at the end of the edge.""" + node: TranslatableItem! + + """A cursor for use in pagination.""" + cursor: String! +} + +union TranslatableItem = ProductTranslatableContent | CollectionTranslatableContent | CategoryTranslatableContent | AttributeTranslatableContent | AttributeValueTranslatableContent | ProductVariantTranslatableContent | PageTranslatableContent | ShippingMethodTranslatableContent | SaleTranslatableContent | VoucherTranslatableContent | MenuItemTranslatableContent + +type ProductTranslatableContent implements Node { + id: ID! + seoTitle: String + seoDescription: String + name: String! + + """ + Description of the product. + + Rich text format. For reference see https://editorjs.io/ + """ + description: JSONString + + """ + Description of the product. + + Rich text format. For reference see https://editorjs.io/ + """ + descriptionJson: JSONString @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `description` field instead.") + + """Returns translated product fields for the given language code.""" + translation( + """A language code to return the translation for product.""" + languageCode: LanguageCodeEnum! + ): ProductTranslation + + """Represents an individual item for sale in the storefront.""" + product: Product @deprecated(reason: "This field will be removed in Saleor 4.0. Get model fields from the root level queries.") + + """List of product attribute values that can be translated.""" + attributeValues: [AttributeValueTranslatableContent!]! +} + +type AttributeValueTranslatableContent implements Node { + id: ID! + name: String! + + """ + Attribute value. + + Rich text format. For reference see https://editorjs.io/ + """ + richText: JSONString + + """Attribute plain text value.""" + plainText: String + + """Returns translated attribute value fields for the given language code.""" + translation( + """A language code to return the translation for attribute value.""" + languageCode: LanguageCodeEnum! + ): AttributeValueTranslation + + """Represents a value of an attribute.""" + attributeValue: AttributeValue @deprecated(reason: "This field will be removed in Saleor 4.0. Get model fields from the root level queries.") + + """ + Associated attribute that can be translated. + + Added in Saleor 3.9. + """ + attribute: AttributeTranslatableContent +} + +type AttributeTranslatableContent implements Node { + id: ID! + name: String! + + """Returns translated attribute fields for the given language code.""" + translation( + """A language code to return the translation for attribute.""" + languageCode: LanguageCodeEnum! + ): AttributeTranslation + + """Custom attribute of a product.""" + attribute: Attribute @deprecated(reason: "This field will be removed in Saleor 4.0. Get model fields from the root level queries.") +} + +type CollectionTranslatableContent implements Node { + id: ID! + seoTitle: String + seoDescription: String + name: String! + + """ + Description of the collection. + + Rich text format. For reference see https://editorjs.io/ + """ + description: JSONString + + """ + Description of the collection. + + Rich text format. For reference see https://editorjs.io/ + """ + descriptionJson: JSONString @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `description` field instead.") + + """Returns translated collection fields for the given language code.""" + translation( + """A language code to return the translation for collection.""" + languageCode: LanguageCodeEnum! + ): CollectionTranslation + + """Represents a collection of products.""" + collection: Collection @deprecated(reason: "This field will be removed in Saleor 4.0. Get model fields from the root level queries.") +} + +type CategoryTranslatableContent implements Node { + id: ID! + seoTitle: String + seoDescription: String + name: String! + + """ + Description of the category. + + Rich text format. For reference see https://editorjs.io/ + """ + description: JSONString + + """ + Description of the category. + + Rich text format. For reference see https://editorjs.io/ + """ + descriptionJson: JSONString @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `description` field instead.") + + """Returns translated category fields for the given language code.""" + translation( + """A language code to return the translation for category.""" + languageCode: LanguageCodeEnum! + ): CategoryTranslation + + """Represents a single category of products.""" + category: Category @deprecated(reason: "This field will be removed in Saleor 4.0. Get model fields from the root level queries.") +} + +type ProductVariantTranslatableContent implements Node { + id: ID! + name: String! + + """Returns translated product variant fields for the given language code.""" + translation( + """A language code to return the translation for product variant.""" + languageCode: LanguageCodeEnum! + ): ProductVariantTranslation + + """Represents a version of a product such as different size or color.""" + productVariant: ProductVariant @deprecated(reason: "This field will be removed in Saleor 4.0. Get model fields from the root level queries.") + + """List of product variant attribute values that can be translated.""" + attributeValues: [AttributeValueTranslatableContent!]! +} + +type PageTranslatableContent implements Node { + id: ID! + seoTitle: String + seoDescription: String + title: String! + + """ + Content of the page. + + Rich text format. For reference see https://editorjs.io/ + """ + content: JSONString + + """ + Content of the page. + + Rich text format. For reference see https://editorjs.io/ + """ + contentJson: JSONString @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `content` field instead.") + + """Returns translated page fields for the given language code.""" + translation( + """A language code to return the translation for page.""" + languageCode: LanguageCodeEnum! + ): PageTranslation + + """ + A static page that can be manually added by a shop operator through the dashboard. + """ + page: Page @deprecated(reason: "This field will be removed in Saleor 4.0. Get model fields from the root level queries.") + + """List of page content attribute values that can be translated.""" + attributeValues: [AttributeValueTranslatableContent!]! +} + +type PageTranslation implements Node { + id: ID! + + """Translation language.""" + language: LanguageDisplay! + seoTitle: String + seoDescription: String + title: String + + """ + Translated content of the page. + + Rich text format. For reference see https://editorjs.io/ + """ + content: JSONString + + """ + Translated description of the page. + + Rich text format. For reference see https://editorjs.io/ + """ + contentJson: JSONString @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `content` field instead.") +} + +""" +A static page that can be manually added by a shop operator through the dashboard. +""" +type Page implements Node & ObjectWithMetadata { + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + seoTitle: String + seoDescription: String + title: String! + + """ + Content of the page. + + Rich text format. For reference see https://editorjs.io/ + """ + content: JSONString + publicationDate: Date @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `publishedAt` field to fetch the publication date.") + + """ + The page publication date. + + Added in Saleor 3.3. + """ + publishedAt: DateTime + isPublished: Boolean! + slug: String! + pageType: PageType! + created: DateTime! + + """ + Content of the page. + + Rich text format. For reference see https://editorjs.io/ + """ + contentJson: JSONString! @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `content` field instead.") + + """Returns translated page fields for the given language code.""" + translation( + """A language code to return the translation for page.""" + languageCode: LanguageCodeEnum! + ): PageTranslation + + """List of attributes assigned to this product.""" + attributes: [SelectedAttribute!]! +} + +""" +Represents a type of page. It defines what attributes are available to pages of this type. +""" +type PageType implements Node & ObjectWithMetadata { + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + name: String! + slug: String! + + """Page attributes of that page type.""" + attributes: [Attribute!] + + """ + Attributes that can be assigned to the page type. + + Requires one of the following permissions: MANAGE_PAGES, MANAGE_PAGE_TYPES_AND_ATTRIBUTES. + """ + availableAttributes( + filter: AttributeFilterInput + where: AttributeWhereInput + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): AttributeCountableConnection + + """ + Whether page type has pages assigned. + + Requires one of the following permissions: MANAGE_PAGES, MANAGE_PAGE_TYPES_AND_ATTRIBUTES. + """ + hasPages: Boolean +} + +type ShippingMethodTranslatableContent implements Node { + id: ID! + name: String! + + """ + Description of the shipping method. + + Rich text format. For reference see https://editorjs.io/ + """ + description: JSONString + + """Returns translated shipping method fields for the given language code.""" + translation( + """A language code to return the translation for shipping method.""" + languageCode: LanguageCodeEnum! + ): ShippingMethodTranslation + + """ + Shipping method are the methods you'll use to get customer's orders to them. They are directly exposed to the customers. + + Requires one of the following permissions: MANAGE_SHIPPING. + """ + shippingMethod: ShippingMethodType @deprecated(reason: "This field will be removed in Saleor 4.0. Get model fields from the root level queries.") +} + +type SaleTranslatableContent implements Node { + id: ID! + name: String! + + """Returns translated sale fields for the given language code.""" + translation( + """A language code to return the translation for sale.""" + languageCode: LanguageCodeEnum! + ): SaleTranslation + + """ + Sales allow creating discounts for categories, collections or products and are visible to all the customers. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + sale: Sale @deprecated(reason: "This field will be removed in Saleor 4.0. Get model fields from the root level queries.") +} + +type SaleTranslation implements Node { + id: ID! + + """Translation language.""" + language: LanguageDisplay! + name: String +} + +""" +Sales allow creating discounts for categories, collections or products and are visible to all the customers. +""" +type Sale implements Node & ObjectWithMetadata { + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + name: String! + type: SaleType! + startDate: DateTime! + endDate: DateTime + created: DateTime! + updatedAt: DateTime! + + """List of categories this sale applies to.""" + categories( + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): CategoryCountableConnection + + """ + List of collections this sale applies to. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + collections( + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): CollectionCountableConnection + + """ + List of products this sale applies to. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + products( + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): ProductCountableConnection + + """ + List of product variants this sale applies to. + + Added in Saleor 3.1. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + variants( + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): ProductVariantCountableConnection + + """Returns translated sale fields for the given language code.""" + translation( + """A language code to return the translation for sale.""" + languageCode: LanguageCodeEnum! + ): SaleTranslation + + """ + List of channels available for the sale. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + channelListings: [SaleChannelListing!] + + """Sale value.""" + discountValue: Float + + """Currency code for sale.""" + currency: String +} + +enum SaleType { + FIXED + PERCENTAGE +} + +type CollectionCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [CollectionCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type CollectionCountableEdge { + """The item at the end of the edge.""" + node: Collection! + + """A cursor for use in pagination.""" + cursor: String! +} + +type ProductVariantCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [ProductVariantCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type ProductVariantCountableEdge { + """The item at the end of the edge.""" + node: ProductVariant! + + """A cursor for use in pagination.""" + cursor: String! +} + +"""Represents sale channel listing.""" +type SaleChannelListing implements Node { + id: ID! + channel: Channel! + discountValue: Float! + currency: String! +} + +type VoucherTranslatableContent implements Node { + id: ID! + name: String + + """Returns translated voucher fields for the given language code.""" + translation( + """A language code to return the translation for voucher.""" + languageCode: LanguageCodeEnum! + ): VoucherTranslation + + """ + Vouchers allow giving discounts to particular customers on categories, collections or specific products. They can be used during checkout by providing valid voucher codes. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + voucher: Voucher @deprecated(reason: "This field will be removed in Saleor 4.0. Get model fields from the root level queries.") +} + +type VoucherTranslation implements Node { + id: ID! + + """Translation language.""" + language: LanguageDisplay! + name: String +} + +""" +Vouchers allow giving discounts to particular customers on categories, collections or specific products. They can be used during checkout by providing valid voucher codes. +""" +type Voucher implements Node & ObjectWithMetadata { + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + name: String + code: String! + usageLimit: Int + used: Int! + startDate: DateTime! + endDate: DateTime + applyOncePerOrder: Boolean! + applyOncePerCustomer: Boolean! + onlyForStaff: Boolean! + minCheckoutItemsQuantity: Int + + """List of categories this voucher applies to.""" + categories( + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): CategoryCountableConnection + + """ + List of collections this voucher applies to. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + collections( + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): CollectionCountableConnection + + """ + List of products this voucher applies to. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + products( + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): ProductCountableConnection + + """ + List of product variants this voucher applies to. + + Added in Saleor 3.1. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + variants( + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): ProductVariantCountableConnection + + """List of countries available for the shipping voucher.""" + countries: [CountryDisplay!] + + """Returns translated voucher fields for the given language code.""" + translation( + """A language code to return the translation for voucher.""" + languageCode: LanguageCodeEnum! + ): VoucherTranslation + + """Determines a type of discount for voucher - value or percentage""" + discountValueType: DiscountValueTypeEnum! + + """Voucher value.""" + discountValue: Float + + """Currency code for voucher.""" + currency: String + + """Minimum order value to apply voucher.""" + minSpent: Money + + """Determines a type of voucher.""" + type: VoucherTypeEnum! + + """ + List of availability in channels for the voucher. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + channelListings: [VoucherChannelListing!] +} + +enum DiscountValueTypeEnum { + FIXED + PERCENTAGE +} + +enum VoucherTypeEnum { + SHIPPING + ENTIRE_ORDER + SPECIFIC_PRODUCT +} + +"""Represents voucher channel listing.""" +type VoucherChannelListing implements Node { + id: ID! + channel: Channel! + discountValue: Float! + currency: String! + minSpent: Money +} + +type MenuItemTranslatableContent implements Node { + id: ID! + name: String! + + """Returns translated menu item fields for the given language code.""" + translation( + """A language code to return the translation for menu item.""" + languageCode: LanguageCodeEnum! + ): MenuItemTranslation + + """ + Represents a single item of the related menu. Can store categories, collection or pages. + """ + menuItem: MenuItem @deprecated(reason: "This field will be removed in Saleor 4.0. Get model fields from the root level queries.") +} + +type MenuItemTranslation implements Node { + id: ID! + + """Translation language.""" + language: LanguageDisplay! + name: String! +} + +""" +Represents a single item of the related menu. Can store categories, collection or pages. +""" +type MenuItem implements Node & ObjectWithMetadata { + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + name: String! + menu: Menu! + parent: MenuItem + category: Category + + """ + A collection associated with this menu item. Requires one of the following permissions to include the unpublished items: MANAGE_ORDERS, MANAGE_DISCOUNTS, MANAGE_PRODUCTS. + """ + collection: Collection + + """ + A page associated with this menu item. Requires one of the following permissions to include unpublished items: MANAGE_PAGES. + """ + page: Page + level: Int! + children: [MenuItem!] + + """URL to the menu item.""" + url: String + + """Returns translated menu item fields for the given language code.""" + translation( + """A language code to return the translation for menu item.""" + languageCode: LanguageCodeEnum! + ): MenuItemTranslation +} + +""" +Represents a single menu - an object that is used to help navigate through the store. +""" +type Menu implements Node & ObjectWithMetadata { + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + name: String! + slug: String! + items: [MenuItem!] +} + +enum TranslatableKinds { + ATTRIBUTE + ATTRIBUTE_VALUE + CATEGORY + COLLECTION + MENU_ITEM + PAGE + PRODUCT + SALE + SHIPPING_METHOD + VARIANT + VOUCHER +} + +""" +Channel-specific tax configuration. + +Added in Saleor 3.9. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type TaxConfiguration implements Node & ObjectWithMetadata { + """The ID of the object.""" + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + + """A channel to which the tax configuration applies to.""" + channel: Channel! + + """Determines whether taxes are charged in the given channel.""" + chargeTaxes: Boolean! + + """ + The default strategy to use for tax calculation in the given channel. Taxes can be calculated either using user-defined flat rates or with a tax app. Empty value means that no method is selected and taxes are not calculated. + """ + taxCalculationStrategy: TaxCalculationStrategy + + """ + Determines whether prices displayed in a storefront should include taxes. + """ + displayGrossPrices: Boolean! + + """Determines whether prices are entered with the tax included.""" + pricesEnteredWithTax: Boolean! + + """List of country-specific exceptions in tax configuration.""" + countries: [TaxConfigurationPerCountry!]! +} + +enum TaxCalculationStrategy { + FLAT_RATES + TAX_APP +} + +""" +Country-specific exceptions of a channel's tax configuration. + +Added in Saleor 3.9. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type TaxConfigurationPerCountry { + """Country in which this configuration applies.""" + country: CountryDisplay! + + """Determines whether taxes are charged in this country.""" + chargeTaxes: Boolean! + + """ + A country-specific strategy to use for tax calculation. Taxes can be calculated either using user-defined flat rates or with a tax app. If not provided, use the value from the channel's tax configuration. + """ + taxCalculationStrategy: TaxCalculationStrategy + + """ + Determines whether prices displayed in a storefront should include taxes for this country. + """ + displayGrossPrices: Boolean! +} + +type TaxConfigurationCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [TaxConfigurationCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type TaxConfigurationCountableEdge { + """The item at the end of the edge.""" + node: TaxConfiguration! + + """A cursor for use in pagination.""" + cursor: String! +} + +input TaxConfigurationFilterInput { + metadata: [MetadataFilter!] + ids: [ID!] +} + +type TaxClassCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [TaxClassCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type TaxClassCountableEdge { + """The item at the end of the edge.""" + node: TaxClass! + + """A cursor for use in pagination.""" + cursor: String! +} + +input TaxClassSortingInput { + """Specifies the direction in which to sort products.""" + direction: OrderDirection! + + """Sort tax classes by the selected field.""" + field: TaxClassSortField! +} + +enum TaxClassSortField { + """Sort tax classes by name.""" + NAME +} + +input TaxClassFilterInput { + metadata: [MetadataFilter!] + ids: [ID!] + countries: [CountryCode!] +} + +""" +Tax class rates grouped by country. + +Added in Saleor 3.9. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type TaxCountryConfiguration { + """A country for which tax class rates are grouped.""" + country: CountryDisplay! + + """List of tax class rates.""" + taxClassCountryRates: [TaxClassCountryRate!]! +} + +type StockCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [StockCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type StockCountableEdge { + """The item at the end of the edge.""" + node: Stock! + + """A cursor for use in pagination.""" + cursor: String! +} + +input StockFilterInput { + quantity: Float + search: String +} + +""" +Represents a shop resource containing general shop data and configuration. +""" +type Shop { + """List of available payment gateways.""" + availablePaymentGateways( + """ + A currency for which gateways will be returned. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `channel` argument instead. + """ + currency: String + + """Slug of a channel for which the data should be returned.""" + channel: String + ): [PaymentGateway!]! + + """List of available external authentications.""" + availableExternalAuthentications: [ExternalAuthentication!]! + + """Shipping methods that are available for the shop.""" + availableShippingMethods( + """Slug of a channel for which the data should be returned.""" + channel: String! + + """Address for which available shipping methods should be returned.""" + address: AddressInput + ): [ShippingMethod!] + + """ + List of all currencies supported by shop's channels. + + Added in Saleor 3.1. + + Requires one of the following permissions: AUTHENTICATED_STAFF_USER, AUTHENTICATED_APP. + """ + channelCurrencies: [String!]! + + """List of countries available in the shop.""" + countries( + """ + A language code to return the translation for. + + DEPRECATED: this field will be removed in Saleor 4.0. + """ + languageCode: LanguageCodeEnum + + """Filtering options for countries""" + filter: CountryFilterInput + ): [CountryDisplay!]! + + """Shop's default country.""" + defaultCountry: CountryDisplay + + """ + Default shop's email sender's name. + + Requires one of the following permissions: MANAGE_SETTINGS. + """ + defaultMailSenderName: String + + """ + Default shop's email sender's address. + + Requires one of the following permissions: MANAGE_SETTINGS. + """ + defaultMailSenderAddress: String + + """Shop's description.""" + description: String + + """Shop's domain data.""" + domain: Domain! + + """List of the shops's supported languages.""" + languages: [LanguageDisplay!]! + + """Shop's name.""" + name: String! + + """List of available permissions.""" + permissions: [Permission!]! + + """List of possible phone prefixes.""" + phonePrefixes: [String!]! + + """Header text.""" + headerText: String + + """ + Automatically approve all new fulfillments. + + Added in Saleor 3.1. + """ + fulfillmentAutoApprove: Boolean! + + """ + Allow to approve fulfillments which are unpaid. + + Added in Saleor 3.1. + """ + fulfillmentAllowUnpaid: Boolean! + + """Enable inventory tracking.""" + trackInventoryByDefault: Boolean + + """Default weight unit.""" + defaultWeightUnit: WeightUnitsEnum + + """Returns translated shop fields for the given language code.""" + translation( + """A language code to return the translation for shop.""" + languageCode: LanguageCodeEnum! + ): ShopTranslation + + """ + Enable automatic fulfillment for all digital products. + + Requires one of the following permissions: MANAGE_SETTINGS. + """ + automaticFulfillmentDigitalProducts: Boolean + + """ + Default number of minutes stock will be reserved for anonymous checkout or null when stock reservation is disabled. + + Added in Saleor 3.1. + + Requires one of the following permissions: MANAGE_SETTINGS. + """ + reserveStockDurationAnonymousUser: Int + + """ + Default number of minutes stock will be reserved for authenticated checkout or null when stock reservation is disabled. + + Added in Saleor 3.1. + + Requires one of the following permissions: MANAGE_SETTINGS. + """ + reserveStockDurationAuthenticatedUser: Int + + """ + Default number of maximum line quantity in single checkout (per single checkout line). + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_SETTINGS. + """ + limitQuantityPerCheckout: Int + + """ + Default number of max downloads per digital content URL. + + Requires one of the following permissions: MANAGE_SETTINGS. + """ + defaultDigitalMaxDownloads: Int + + """ + Default number of days which digital content URL will be valid. + + Requires one of the following permissions: MANAGE_SETTINGS. + """ + defaultDigitalUrlValidDays: Int + + """Company address.""" + companyAddress: Address + + """URL of a view where customers can set their password.""" + customerSetPasswordUrl: String + + """ + List of staff notification recipients. + + Requires one of the following permissions: MANAGE_SETTINGS. + """ + staffNotificationRecipients: [StaffNotificationRecipient!] + + """ + Resource limitations and current usage if any set for a shop + + Requires one of the following permissions: AUTHENTICATED_STAFF_USER. + """ + limits: LimitInfo! + + """ + Saleor API version. + + Requires one of the following permissions: AUTHENTICATED_STAFF_USER, AUTHENTICATED_APP. + """ + version: String! + + """ + Minor Saleor API version. + + Added in Saleor 3.5. + """ + schemaVersion: String! + + """Include taxes in prices.""" + includeTaxesInPrices: Boolean! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `Channel.taxConfiguration.pricesEnteredWithTax` to determine whether prices are entered with tax.") + + """Display prices with tax in store.""" + displayGrossPrices: Boolean! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `Channel.taxConfiguration` to determine whether to display gross or net prices.") + + """Charge taxes on shipping.""" + chargeTaxesOnShipping: Boolean! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `ShippingMethodType.taxClass` to determine whether taxes are calculated for shipping methods; if a tax class is set, the taxes will be calculated, otherwise no tax rate will be applied.") +} + +""" +Available payment gateway backend with configuration necessary to setup client. +""" +type PaymentGateway { + """Payment gateway name.""" + name: String! + + """Payment gateway ID.""" + id: ID! + + """Payment gateway client configuration.""" + config: [GatewayConfigLine!]! + + """Payment gateway supported currencies.""" + currencies: [String!]! +} + +"""Payment gateway client configuration key and value pair.""" +type GatewayConfigLine { + """Gateway config key.""" + field: String! + + """Gateway config value for key.""" + value: String +} + +type ExternalAuthentication { + """ID of external authentication plugin.""" + id: String! + + """Name of external authentication plugin.""" + name: String +} + +input CountryFilterInput { + """ + Boolean for filtering countries by having shipping zone assigned.If 'true', return countries with shipping zone assigned.If 'false', return countries without any shipping zone assigned.If the argument is not provided (null), return all countries. + """ + attachedToShippingZones: Boolean +} + +"""Represents shop's domain.""" +type Domain { + """The host name of the domain.""" + host: String! + + """Inform if SSL is enabled.""" + sslEnabled: Boolean! + + """Shop's absolute URL.""" + url: String! +} + +type ShopTranslation implements Node { + id: ID! + + """Translation language.""" + language: LanguageDisplay! + headerText: String! + description: String! +} + +""" +Represents a recipient of email notifications send by Saleor, such as notifications about new orders. Notifications can be assigned to staff users or arbitrary email addresses. +""" +type StaffNotificationRecipient implements Node { + id: ID! + + """Returns a user subscribed to email notifications.""" + user: User + + """Returns email address of a user subscribed to email notifications.""" + email: String + + """Determines if a notification active.""" + active: Boolean +} + +"""Represents user data.""" +type User implements Node & ObjectWithMetadata { + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + email: String! + firstName: String! + lastName: String! + isStaff: Boolean! + isActive: Boolean! + + """List of all user's addresses.""" + addresses: [Address!]! + + """Returns the last open checkout of this user.""" + checkout: Checkout @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `checkoutTokens` field to fetch the user checkouts.") + + """Returns the checkout UUID's assigned to this user.""" + checkoutTokens( + """Slug of a channel for which the data should be returned.""" + channel: String + ): [UUID!] @deprecated(reason: "This field will be removed in Saleor 4.0. Use `checkoutIds` instead.") + + """Returns the checkout ID's assigned to this user.""" + checkoutIds( + """Slug of a channel for which the data should be returned.""" + channel: String + ): [ID!] + + """ + Returns checkouts assigned to this user. + + Added in Saleor 3.8. + """ + checkouts( + """Slug of a channel for which the data should be returned.""" + channel: String + + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): CheckoutCountableConnection + + """List of the user gift cards.""" + giftCards( + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): GiftCardCountableConnection + + """ + A note about the customer. + + Requires one of the following permissions: MANAGE_USERS, MANAGE_STAFF. + """ + note: String + + """ + List of user's orders. Requires one of the following permissions: MANAGE_STAFF, OWNER. + """ + orders( + """Return the elements in the list that come before the specified cursor.""" + before: String + + """Return the elements in the list that come after the specified cursor.""" + after: String + + """Return the first n elements from the list.""" + first: Int + + """Return the last n elements from the list.""" + last: Int + ): OrderCountableConnection + + """List of user's permissions.""" + userPermissions: [UserPermission!] + + """List of user's permission groups.""" + permissionGroups: [Group!] + + """List of user's permission groups which user can manage.""" + editableGroups: [Group!] + avatar( + """ + Desired longest side the image in pixels. Defaults to 4096. Images are never cropped. Pass 0 to retrieve the original size (not recommended). + """ + size: Int + + """ + The format of the image. When not provided, format of the original image will be used. + + Added in Saleor 3.6. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + format: ThumbnailFormatEnum = ORIGINAL + ): Image + + """ + List of events associated with the user. + + Requires one of the following permissions: MANAGE_USERS, MANAGE_STAFF. + """ + events: [CustomerEvent!] + + """List of stored payment sources.""" + storedPaymentSources( + """Slug of a channel for which the data should be returned.""" + channel: String + ): [PaymentSource!] + + """User language code.""" + languageCode: LanguageCodeEnum! + defaultShippingAddress: Address + defaultBillingAddress: Address + + """ + External ID of this user. + + Added in Saleor 3.10. + """ + externalReference: String + lastLogin: DateTime + dateJoined: DateTime! + updatedAt: DateTime! +} + +"""Checkout object.""" +type Checkout implements Node & ObjectWithMetadata { + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + created: DateTime! + + """Time of last modification of the given checkout.""" + updatedAt: DateTime! + lastChange: DateTime! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `updatedAt` instead.") + user: User + channel: Channel! + billingAddress: Address + shippingAddress: Address + note: String! + discount: Money + discountName: String + translatedDiscountName: String + voucherCode: String + + """Shipping methods that can be used with this checkout.""" + availableShippingMethods: [ShippingMethod!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `shippingMethods` instead.") + + """Shipping methods that can be used with this checkout.""" + shippingMethods: [ShippingMethod!]! + + """ + Collection points that can be used for this order. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + availableCollectionPoints: [Warehouse!]! + + """List of available payment gateways.""" + availablePaymentGateways: [PaymentGateway!]! + + """Email of a customer.""" + email: String + + """List of gift cards associated with this checkout.""" + giftCards: [GiftCard!]! + + """Returns True, if checkout requires shipping.""" + isShippingRequired: Boolean! + + """The number of items purchased.""" + quantity: Int! + + """ + Date when oldest stock reservation for this checkout expires or null if no stock is reserved. + + Added in Saleor 3.1. + """ + stockReservationExpires: DateTime + + """ + A list of checkout lines, each containing information about an item in the checkout. + """ + lines: [CheckoutLine!]! + + """The price of the shipping, with all the taxes included.""" + shippingPrice: TaxedMoney! + + """The shipping method related with checkout.""" + shippingMethod: ShippingMethod @deprecated(reason: "This field will be removed in Saleor 4.0. Use `deliveryMethod` instead.") + + """ + The delivery method selected for this checkout. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + deliveryMethod: DeliveryMethod + + """The price of the checkout before shipping, with taxes included.""" + subtotalPrice: TaxedMoney! + + """ + Returns True if checkout has to be exempt from taxes. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + taxExemption: Boolean! + + """The checkout's token.""" + token: UUID! + + """ + The sum of the the checkout line prices, with all the taxes,shipping costs, and discounts included. + """ + totalPrice: TaxedMoney! + + """ + The difference between the paid and the checkout total amount. + + Added in Saleor 3.13. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + totalBalance: Money! + + """Checkout language code.""" + languageCode: LanguageCodeEnum! + + """ + List of transactions for the checkout. Requires one of the following permissions: MANAGE_CHECKOUTS, HANDLE_PAYMENTS. + + Added in Saleor 3.4. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + transactions: [TransactionItem!] + + """ + Determines whether checkout prices should include taxes when displayed in a storefront. + + Added in Saleor 3.9. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + displayGrossPrices: Boolean! + + """ + The authorize status of the checkout. + + Added in Saleor 3.13. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + authorizeStatus: CheckoutAuthorizeStatusEnum! + + """ + The charge status of the checkout. + + Added in Saleor 3.13. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + chargeStatus: CheckoutChargeStatusEnum! +} + +""" +A gift card is a prepaid electronic payment card accepted in stores. They can be used during checkout by providing a valid gift card codes. +""" +type GiftCard implements Node & ObjectWithMetadata { + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + + """Code in format which allows displaying in a user interface.""" + displayCode: String! + + """Last 4 characters of gift card code.""" + last4CodeChars: String! + + """ + Gift card code. Can be fetched by a staff member with MANAGE_GIFT_CARD when gift card wasn't yet used and by the gift card owner. + """ + code: String! + created: DateTime! + + """ + The user who bought or issued a gift card. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + createdBy: User + + """ + The customer who used a gift card. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + usedBy: User + + """ + Email address of the user who bought or issued gift card. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_USERS, OWNER. + """ + createdByEmail: String + + """ + Email address of the customer who used a gift card. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + usedByEmail: String + lastUsedOn: DateTime + expiryDate: Date + + """ + App which created the gift card. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_APPS, OWNER. + """ + app: App + + """ + Related gift card product. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + product: Product + + """ + List of events associated with the gift card. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_GIFT_CARD. + """ + events( + """Filtering options for gift card events.""" + filter: GiftCardEventFilterInput + ): [GiftCardEvent!]! + + """ + The gift card tag. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_GIFT_CARD. + """ + tags: [GiftCardTag!]! + + """ + Slug of the channel where the gift card was bought. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + boughtInChannel: String + isActive: Boolean! + initialBalance: Money! + currentBalance: Money! + + """The customer who bought a gift card.""" + user: User @deprecated(reason: "This field will be removed in Saleor 4.0. Use `createdBy` field instead.") + + """End date of gift card.""" + endDate: DateTime @deprecated(reason: "This field will be removed in Saleor 4.0. Use `expiryDate` field instead.") + + """Start date of gift card.""" + startDate: DateTime @deprecated(reason: "This field will be removed in Saleor 4.0.") +} + +""" +History log of the gift card. + +Added in Saleor 3.1. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type GiftCardEvent implements Node { + id: ID! + + """Date when event happened at in ISO 8601 format.""" + date: DateTime + + """Gift card event type.""" + type: GiftCardEventsEnum + + """ + User who performed the action. Requires one of the following permissions: MANAGE_USERS, MANAGE_STAFF, OWNER. + """ + user: User + + """ + App that performed the action. Requires one of the following permissions: MANAGE_APPS, OWNER. + """ + app: App + + """Content of the event.""" + message: String + + """Email of the customer.""" + email: String + + """The order ID where gift card was used or bought.""" + orderId: ID + + """User-friendly number of an order where gift card was used or bought.""" + orderNumber: String + + """The list of gift card tags.""" + tags: [String!] + + """The list of old gift card tags.""" + oldTags: [String!] + + """The gift card balance.""" + balance: GiftCardEventBalance + + """The gift card expiry date.""" + expiryDate: Date + + """Previous gift card expiry date.""" + oldExpiryDate: Date +} + +"""An enumeration.""" +enum GiftCardEventsEnum { + ISSUED + BOUGHT + UPDATED + ACTIVATED + DEACTIVATED + BALANCE_RESET + EXPIRY_DATE_UPDATED + TAGS_UPDATED + SENT_TO_CUSTOMER + RESENT + NOTE_ADDED + USED_IN_ORDER +} + +type GiftCardEventBalance { + """Initial balance of the gift card.""" + initialBalance: Money + + """Current balance of the gift card.""" + currentBalance: Money! + + """Previous initial balance of the gift card.""" + oldInitialBalance: Money + + """Previous current balance of the gift card.""" + oldCurrentBalance: Money +} + +input GiftCardEventFilterInput { + type: GiftCardEventsEnum + orders: [ID!] +} + +""" +The gift card tag. + +Added in Saleor 3.1. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type GiftCardTag implements Node { + id: ID! + name: String! +} + +"""Represents an item in the checkout.""" +type CheckoutLine implements Node & ObjectWithMetadata { + id: ID! + + """ + List of private metadata items. Requires staff permissions to access. + + Added in Saleor 3.5. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.5. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.5. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """ + List of public metadata items. Can be accessed without permissions. + + Added in Saleor 3.5. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.5. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.5. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + variant: ProductVariant! + quantity: Int! + + """The unit price of the checkout line, with taxes and discounts.""" + unitPrice: TaxedMoney! + + """The unit price of the checkout line, without discounts.""" + undiscountedUnitPrice: Money! + + """The sum of the checkout line price, taxes and discounts.""" + totalPrice: TaxedMoney! + + """The sum of the checkout line price, without discounts.""" + undiscountedTotalPrice: Money! + + """Indicates whether the item need to be delivered.""" + requiresShipping: Boolean! +} + +""" +Represents a delivery method chosen for the checkout. `Warehouse` type is used when checkout is marked as "click and collect" and `ShippingMethod` otherwise. + +Added in Saleor 3.1. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +union DeliveryMethod = Warehouse | ShippingMethod + +""" +Represents a payment transaction. + +Added in Saleor 3.4. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type TransactionItem implements Node & ObjectWithMetadata { + """The ID of the object.""" + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + createdAt: DateTime! + modifiedAt: DateTime! + + """ + List of actions that can be performed in the current state of a payment. + """ + actions: [TransactionActionEnum!]! + + """Total amount authorized for this payment.""" + authorizedAmount: Money! + + """ + Total amount of ongoing authorization requests for the transaction. + + Added in Saleor 3.13. + """ + authorizePendingAmount: Money! + + """Total amount refunded for this payment.""" + refundedAmount: Money! + + """ + Total amount of ongoing refund requests for the transaction. + + Added in Saleor 3.13. + """ + refundPendingAmount: Money! + + """Total amount voided for this payment.""" + voidedAmount: Money! @deprecated(reason: "This field will be removed in Saleor 3.14 (Preview Feature).Use `canceledAmount` instead.") + + """ + Total amount canceled for this payment. + + Added in Saleor 3.13. + """ + canceledAmount: Money! + + """ + Total amount of ongoing cancel requests for the transaction. + + Added in Saleor 3.13. + """ + cancelPendingAmount: Money! + + """Total amount charged for this payment.""" + chargedAmount: Money! + + """ + Total amount of ongoing charge requests for the transaction. + + Added in Saleor 3.13. + """ + chargePendingAmount: Money! + + """Status of transaction.""" + status: String! @deprecated(reason: "This field will be removed in Saleor 3.14 (Preview Feature). The `status` is not needed. The amounts can be used to define the current status of transactions.") + + """Type of transaction.""" + type: String! @deprecated(reason: "This field will be removed in Saleor 3.14 (Preview Feature). Use `name` or `message` instead.") + + """ + Name of the transaction. + + Added in Saleor 3.13. + """ + name: String! + + """ + Message related to the transaction. + + Added in Saleor 3.13. + """ + message: String! + + """Reference of transaction.""" + reference: String! @deprecated(reason: "This field will be removed in Saleor 3.14 (Preview Feature).Use `pspReference` instead.") + + """ + PSP reference of transaction. + + Added in Saleor 3.13. + """ + pspReference: String! + + """ + The related order. + + Added in Saleor 3.6. + """ + order: Order + + """List of all transaction's events.""" + events: [TransactionEvent!]! + + """ + User or App that created the transaction. + + Added in Saleor 3.13. + """ + createdBy: UserOrApp + + """ + The url that will allow to redirect user to payment provider page with transaction details. + + Added in Saleor 3.13. + """ + externalUrl: String! +} + +""" +Represents possible actions on payment transaction. + + The following actions are possible: + CHARGE - Represents the charge action. + REFUND - Represents a refund action. + VOID - Represents a void action. This field will be removed + in Saleor 3.14 (Preview Feature). Use `CANCEL` instead. + CANCEL - Represents a cancel action. Added in Saleor 3.12. +""" +enum TransactionActionEnum { + CHARGE + REFUND + VOID + CANCEL +} + +"""Represents an order in the shop.""" +type Order implements Node & ObjectWithMetadata { + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + created: DateTime! + updatedAt: DateTime! + status: OrderStatus! + + """ + User who placed the order. This field is set only for orders placed by authenticated users. Can be fetched for orders created in Saleor 3.2 and later, for other orders requires one of the following permissions: MANAGE_USERS, MANAGE_ORDERS, OWNER. + """ + user: User + trackingClientId: String! + + """ + Billing address. The full data can be access for orders created in Saleor 3.2 and later, for other orders requires one of the following permissions: MANAGE_ORDERS, OWNER. + """ + billingAddress: Address + + """ + Shipping address. The full data can be access for orders created in Saleor 3.2 and later, for other orders requires one of the following permissions: MANAGE_ORDERS, OWNER. + """ + shippingAddress: Address + shippingMethodName: String + collectionPointName: String + channel: Channel! + + """List of shipments for the order.""" + fulfillments: [Fulfillment!]! + + """List of order lines.""" + lines: [OrderLine!]! + + """ + List of actions that can be performed in the current state of an order. + """ + actions: [OrderAction!]! + + """Shipping methods that can be used with this order.""" + availableShippingMethods: [ShippingMethod!] @deprecated(reason: "Use `shippingMethods`, this field will be removed in 4.0") + + """Shipping methods related to this order.""" + shippingMethods: [ShippingMethod!]! + + """ + Collection points that can be used for this order. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + availableCollectionPoints: [Warehouse!]! + + """ + List of order invoices. Can be fetched for orders created in Saleor 3.2 and later, for other orders requires one of the following permissions: MANAGE_ORDERS, OWNER. + """ + invoices: [Invoice!]! + + """User-friendly number of an order.""" + number: String! + + """The ID of the order that was the base for this order.""" + original: ID + + """The order origin.""" + origin: OrderOriginEnum! + + """Informs if an order is fully paid.""" + isPaid: Boolean! + + """Internal payment status.""" + paymentStatus: PaymentChargeStatusEnum! + + """User-friendly payment status.""" + paymentStatusDisplay: String! + + """ + The authorize status of the order. + + Added in Saleor 3.4. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + authorizeStatus: OrderAuthorizeStatusEnum! + + """ + The charge status of the order. + + Added in Saleor 3.4. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + chargeStatus: OrderChargeStatusEnum! + + """ + Returns True if order has to be exempt from taxes. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + taxExemption: Boolean! + + """ + List of transactions for the order. Requires one of the following permissions: MANAGE_ORDERS, HANDLE_PAYMENTS. + + Added in Saleor 3.4. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + transactions: [TransactionItem!]! + + """List of payments for the order.""" + payments: [Payment!]! + + """Total amount of the order.""" + total: TaxedMoney! + + """Undiscounted total amount of the order.""" + undiscountedTotal: TaxedMoney! + + """Shipping method for this order.""" + shippingMethod: ShippingMethod @deprecated(reason: "This field will be removed in Saleor 4.0. Use `deliveryMethod` instead.") + + """Total price of shipping.""" + shippingPrice: TaxedMoney! + + """The shipping tax rate value.""" + shippingTaxRate: Float! + + """ + Denormalized tax class assigned to the shipping method. + + Added in Saleor 3.9. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: AUTHENTICATED_STAFF_USER. + """ + shippingTaxClass: TaxClass + + """ + Denormalized name of the tax class assigned to the shipping method. + + Added in Saleor 3.9. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + shippingTaxClassName: String + + """ + Denormalized public metadata of the shipping method's tax class. + + Added in Saleor 3.9. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + shippingTaxClassMetadata: [MetadataItem!]! + + """ + Denormalized private metadata of the shipping method's tax class. Requires staff permissions to access. + + Added in Saleor 3.9. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + shippingTaxClassPrivateMetadata: [MetadataItem!]! + token: String! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `id` instead.") + voucher: Voucher + + """List of user gift cards.""" + giftCards: [GiftCard!]! + customerNote: String! + weight: Weight! + redirectUrl: String + + """The sum of line prices not including shipping.""" + subtotal: TaxedMoney! + + """User-friendly order status.""" + statusDisplay: String! + + """ + Informs whether a draft order can be finalized(turned into a regular order). + """ + canFinalize: Boolean! + + """Amount authorized for the order.""" + totalAuthorized: Money! + + """Amount captured for the order.""" + totalCaptured: Money! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `totalCharged` instead.") + + """ + Amount charged for the order. + + Added in Saleor 3.13. + """ + totalCharged: Money! + + """ + Amount canceled for the order. + + Added in Saleor 3.13. + """ + totalCanceled: Money! + + """ + List of events associated with the order. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + events: [OrderEvent!]! + + """The difference between the paid and the order total amount.""" + totalBalance: Money! + + """ + Email address of the customer. The full data can be access for orders created in Saleor 3.2 and later, for other orders requires one of the following permissions: MANAGE_ORDERS, OWNER. + """ + userEmail: String + + """Returns True, if order requires shipping.""" + isShippingRequired: Boolean! + + """ + The delivery method selected for this order. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + deliveryMethod: DeliveryMethod + languageCode: String! @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `languageCodeEnum` field to fetch the language code. ") + + """Order language code.""" + languageCodeEnum: LanguageCodeEnum! + + """Returns applied discount.""" + discount: Money @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `discounts` field instead.") + + """Discount name.""" + discountName: String @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `discounts` field instead.") + + """Translated discount name.""" + translatedDiscountName: String @deprecated(reason: "This field will be removed in Saleor 4.0. Use the `discounts` field instead. ") + + """List of all discounts assigned to the order.""" + discounts: [OrderDiscount!]! + + """List of errors that occurred during order validation.""" + errors: [OrderError!]! + + """ + Determines whether checkout prices should include taxes when displayed in a storefront. + + Added in Saleor 3.9. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + displayGrossPrices: Boolean! + + """ + External ID of this order. + + Added in Saleor 3.10. + """ + externalReference: String + + """ + ID of the checkout that the order was created from. + + Added in Saleor 3.11. + """ + checkoutId: ID + + """ + List of granted refunds. + + Added in Saleor 3.13. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + grantedRefunds: [OrderGrantedRefund!]! + + """ + Total amount of granted refund. + + Added in Saleor 3.13. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + totalGrantedRefund: Money! + + """ + Total refund amount for the order. + + Added in Saleor 3.13. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + totalRefunded: Money! + + """ + Total amount of ongoing refund requests for the order's transactions. + + Added in Saleor 3.13. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + totalRefundPending: Money! + + """ + Total amount of ongoing authorize requests for the order's transactions. + + Added in Saleor 3.13. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + totalAuthorizePending: Money! + + """ + Total amount of ongoing charge requests for the order's transactions. + + Added in Saleor 3.13. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + totalChargePending: Money! + + """ + Total amount of ongoing cancel requests for the order's transactions. + + Added in Saleor 3.13. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + totalCancelPending: Money! + + """ + The difference amount between granted refund and the amounts that are pending and refunded. + + Added in Saleor 3.13. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + totalRemainingGrant: Money! +} + +"""An enumeration.""" +enum OrderStatus { + DRAFT + UNCONFIRMED + UNFULFILLED + PARTIALLY_FULFILLED + PARTIALLY_RETURNED + RETURNED + FULFILLED + CANCELED +} + +"""Represents order fulfillment.""" +type Fulfillment implements Node & ObjectWithMetadata { + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + fulfillmentOrder: Int! + status: FulfillmentStatus! + trackingNumber: String! + created: DateTime! + + """List of lines for the fulfillment.""" + lines: [FulfillmentLine!] + + """User-friendly fulfillment status.""" + statusDisplay: String + + """Warehouse from fulfillment was fulfilled.""" + warehouse: Warehouse +} + +"""An enumeration.""" +enum FulfillmentStatus { + FULFILLED + REFUNDED + RETURNED + REPLACED + REFUNDED_AND_RETURNED + CANCELED + WAITING_FOR_APPROVAL +} + +"""Represents line of the fulfillment.""" +type FulfillmentLine implements Node { + id: ID! + quantity: Int! + orderLine: OrderLine +} + +"""Represents order line of particular order.""" +type OrderLine implements Node & ObjectWithMetadata { + id: ID! + + """ + List of private metadata items. Requires staff permissions to access. + + Added in Saleor 3.5. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.5. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.5. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """ + List of public metadata items. Can be accessed without permissions. + + Added in Saleor 3.5. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.5. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.5. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + productName: String! + variantName: String! + productSku: String + productVariantId: String + isShippingRequired: Boolean! + quantity: Int! + quantityFulfilled: Int! + unitDiscountReason: String + taxRate: Float! + digitalContentUrl: DigitalContentUrl + thumbnail( + """ + Desired longest side the image in pixels. Defaults to 4096. Images are never cropped. Pass 0 to retrieve the original size (not recommended). + """ + size: Int + + """ + The format of the image. When not provided, format of the original image will be used. + + Added in Saleor 3.6. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + format: ThumbnailFormatEnum = ORIGINAL + ): Image + + """Price of the single item in the order line.""" + unitPrice: TaxedMoney! + + """ + Price of the single item in the order line without applied an order line discount. + """ + undiscountedUnitPrice: TaxedMoney! + + """The discount applied to the single order line.""" + unitDiscount: Money! + + """Value of the discount. Can store fixed value or percent value""" + unitDiscountValue: PositiveDecimal! + + """Price of the order line.""" + totalPrice: TaxedMoney! + + """ + A purchased product variant. Note: this field may be null if the variant has been removed from stock at all. Requires one of the following permissions to include the unpublished items: MANAGE_ORDERS, MANAGE_DISCOUNTS, MANAGE_PRODUCTS. + """ + variant: ProductVariant + + """Product name in the customer's language""" + translatedProductName: String! + + """Variant name in the customer's language""" + translatedVariantName: String! + + """ + List of allocations across warehouses. + + Requires one of the following permissions: MANAGE_PRODUCTS, MANAGE_ORDERS. + """ + allocations: [Allocation!] + + """ + A quantity of items remaining to be fulfilled. + + Added in Saleor 3.1. + """ + quantityToFulfill: Int! + + """Type of the discount: fixed or percent""" + unitDiscountType: DiscountValueTypeEnum + + """ + Denormalized tax class of the product in this order line. + + Added in Saleor 3.9. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: AUTHENTICATED_STAFF_USER. + """ + taxClass: TaxClass + + """ + Denormalized name of the tax class. + + Added in Saleor 3.9. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + taxClassName: String + + """ + Denormalized public metadata of the tax class. + + Added in Saleor 3.9. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + taxClassMetadata: [MetadataItem!]! + + """ + Denormalized private metadata of the tax class. Requires staff permissions to access. + + Added in Saleor 3.9. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + taxClassPrivateMetadata: [MetadataItem!]! +} + +""" +Nonnegative Decimal scalar implementation. + +Should be used in places where value must be nonnegative (0 or greater). +""" +scalar PositiveDecimal + +"""Represents allocation.""" +type Allocation implements Node { + id: ID! + + """ + Quantity allocated for orders. + + Requires one of the following permissions: MANAGE_PRODUCTS, MANAGE_ORDERS. + """ + quantity: Int! + + """ + The warehouse were items were allocated. + + Requires one of the following permissions: MANAGE_PRODUCTS, MANAGE_ORDERS. + """ + warehouse: Warehouse! +} + +enum OrderAction { + """Represents the capture action.""" + CAPTURE + + """Represents a mark-as-paid action.""" + MARK_AS_PAID + + """Represents a refund action.""" + REFUND + + """Represents a void action.""" + VOID +} + +"""Represents an Invoice.""" +type Invoice implements ObjectWithMetadata & Job & Node { + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + + """Job status.""" + status: JobStatusEnum! + createdAt: DateTime! + updatedAt: DateTime! + message: String + + """The ID of the object.""" + id: ID! + number: String + externalUrl: String + + """URL to download an invoice.""" + url: String + + """ + Order related to the invoice. + + Added in Saleor 3.10. + """ + order: Order +} + +interface Job { + """Job status.""" + status: JobStatusEnum! + + """Created date time of job in ISO 8601 format.""" + createdAt: DateTime! + + """Date time of job last update in ISO 8601 format.""" + updatedAt: DateTime! + + """Job message.""" + message: String +} + +"""An enumeration.""" +enum JobStatusEnum { + PENDING + SUCCESS + FAILED + DELETED +} + +"""An enumeration.""" +enum OrderOriginEnum { + CHECKOUT + DRAFT + REISSUE +} + +"""An enumeration.""" +enum PaymentChargeStatusEnum { + NOT_CHARGED + PENDING + PARTIALLY_CHARGED + FULLY_CHARGED + PARTIALLY_REFUNDED + FULLY_REFUNDED + REFUSED + CANCELLED +} + +""" +Determine a current authorize status for order. + + We treat the order as fully authorized when the sum of authorized and charged funds + cover the order.total. + We treat the order as partially authorized when the sum of authorized and charged + funds covers only part of the order.total + We treat the order as not authorized when the sum of authorized and charged funds is + 0. + + NONE - the funds are not authorized + PARTIAL - the funds that are authorized or charged don't cover fully the order's + total + FULL - the funds that are authorized or charged fully cover the order's total +""" +enum OrderAuthorizeStatusEnum { + NONE + PARTIAL + FULL +} + +""" +Determine the current charge status for the order. + + We treat the order as overcharged when the charged amount is bigger that order.total + We treat the order as fully charged when the charged amount is equal to order.total. + We treat the order as partially charged when the charged amount covers only part of + the order.total + + NONE - the funds are not charged. + PARTIAL - the funds that are charged don't cover the order's total + FULL - the funds that are charged fully cover the order's total + OVERCHARGED - the charged funds are bigger than order's total +""" +enum OrderChargeStatusEnum { + NONE + PARTIAL + FULL + OVERCHARGED +} + +"""Represents a payment of a given type.""" +type Payment implements Node & ObjectWithMetadata { + id: ID! + + """List of private metadata items. Requires staff permissions to access.""" + privateMetadata: [MetadataItem!]! + + """ + A single key from private metadata. Requires staff permissions to access. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafield(key: String!): String + + """ + Private metadata. Requires staff permissions to access. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + privateMetafields(keys: [String!]): Metadata + + """List of public metadata items. Can be accessed without permissions.""" + metadata: [MetadataItem!]! + + """ + A single key from public metadata. + + Tip: Use GraphQL aliases to fetch multiple keys. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafield(key: String!): String + + """ + Public metadata. Use `keys` to control which fields you want to include. The default is to include everything. + + Added in Saleor 3.3. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + metafields(keys: [String!]): Metadata + gateway: String! + isActive: Boolean! + created: DateTime! + modified: DateTime! + token: String! + checkout: Checkout + order: Order + paymentMethodType: String! + + """ + IP address of the user who created the payment. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + customerIpAddress: String + + """Internal payment status.""" + chargeStatus: PaymentChargeStatusEnum! + + """ + List of actions that can be performed in the current state of a payment. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + actions: [OrderAction!]! + + """Total amount of the payment.""" + total: Money + + """Total amount captured for this payment.""" + capturedAmount: Money + + """ + List of all transactions within this payment. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + transactions: [Transaction!] + + """ + Maximum amount of money that can be captured. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + availableCaptureAmount: Money + + """ + Maximum amount of money that can be refunded. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + availableRefundAmount: Money + + """The details of the card used for this payment.""" + creditCard: CreditCard +} + +"""An object representing a single payment.""" +type Transaction implements Node { + id: ID! + created: DateTime! + payment: Payment! + token: String! + kind: TransactionKind! + isSuccess: Boolean! + error: String + gatewayResponse: JSONString! + + """Total amount of the transaction.""" + amount: Money +} + +"""An enumeration.""" +enum TransactionKind { + EXTERNAL + AUTH + PENDING + ACTION_TO_CONFIRM + REFUND + REFUND_ONGOING + CAPTURE + VOID + CONFIRM + CANCEL +} + +type CreditCard { + """Card brand.""" + brand: String! + + """First 4 digits of the card number.""" + firstDigits: String + + """Last 4 digits of the card number.""" + lastDigits: String! + + """Two-digit number representing the card’s expiration month.""" + expMonth: Int + + """Four-digit number representing the card’s expiration year.""" + expYear: Int +} + +"""History log of the order.""" +type OrderEvent implements Node { + id: ID! + + """Date when event happened at in ISO 8601 format.""" + date: DateTime + + """Order event type.""" + type: OrderEventsEnum + + """User who performed the action.""" + user: User + + """ + App that performed the action. Requires of of the following permissions: MANAGE_APPS, MANAGE_ORDERS, OWNER. + """ + app: App + + """Content of the event.""" + message: String + + """Email of the customer.""" + email: String + + """Type of an email sent to the customer.""" + emailType: OrderEventsEmailsEnum + + """Amount of money.""" + amount: Float + + """The payment reference from the payment provider.""" + paymentId: String + + """The payment gateway of the payment.""" + paymentGateway: String + + """Number of items.""" + quantity: Int + + """Composed ID of the Fulfillment.""" + composedId: String + + """User-friendly number of an order.""" + orderNumber: String + + """Number of an invoice related to the order.""" + invoiceNumber: String + + """List of oversold lines names.""" + oversoldItems: [String!] + + """The concerned lines.""" + lines: [OrderEventOrderLineObject!] + + """The lines fulfilled.""" + fulfilledItems: [FulfillmentLine!] + + """The warehouse were items were restocked.""" + warehouse: Warehouse + + """The transaction reference of captured payment.""" + transactionReference: String + + """Define if shipping costs were included to the refund.""" + shippingCostsIncluded: Boolean + + """The order which is related to this order.""" + relatedOrder: Order + + """The discount applied to the order.""" + discount: OrderEventDiscountObject + + """The status of payment's transaction.""" + status: TransactionStatus @deprecated(reason: "This field will be removed in Saleor 3.14 (Preview Feature).Use `TransactionEvent` to track the status of `TransactionItem`.") + + """The reference of payment's transaction.""" + reference: String +} + +"""The different order event types.""" +enum OrderEventsEnum { + DRAFT_CREATED + DRAFT_CREATED_FROM_REPLACE + ADDED_PRODUCTS + REMOVED_PRODUCTS + PLACED + PLACED_FROM_DRAFT + OVERSOLD_ITEMS + CANCELED + ORDER_MARKED_AS_PAID + ORDER_FULLY_PAID + ORDER_REPLACEMENT_CREATED + ORDER_DISCOUNT_ADDED + ORDER_DISCOUNT_AUTOMATICALLY_UPDATED + ORDER_DISCOUNT_UPDATED + ORDER_DISCOUNT_DELETED + ORDER_LINE_DISCOUNT_UPDATED + ORDER_LINE_DISCOUNT_REMOVED + ORDER_LINE_PRODUCT_DELETED + ORDER_LINE_VARIANT_DELETED + UPDATED_ADDRESS + EMAIL_SENT + CONFIRMED + PAYMENT_AUTHORIZED + PAYMENT_CAPTURED + EXTERNAL_SERVICE_NOTIFICATION + PAYMENT_REFUNDED + PAYMENT_VOIDED + PAYMENT_FAILED + TRANSACTION_EVENT + TRANSACTION_CHARGE_REQUESTED + + """ + This field will be removed in Saleor 3.14 (Preview Feature). Use `TRANSACTION_CHARGE_REQUESTED` instead. + """ + TRANSACTION_CAPTURE_REQUESTED + TRANSACTION_REFUND_REQUESTED + + """ + This field will be removed in Saleor 3.14 (Preview Feature). Use `TRANSACTION_CANCEL_REQUESTED` instead. + """ + TRANSACTION_VOID_REQUESTED + TRANSACTION_CANCEL_REQUESTED + TRANSACTION_MARK_AS_PAID_FAILED + INVOICE_REQUESTED + INVOICE_GENERATED + INVOICE_UPDATED + INVOICE_SENT + FULFILLMENT_CANCELED + FULFILLMENT_RESTOCKED_ITEMS + FULFILLMENT_FULFILLED_ITEMS + FULFILLMENT_REFUNDED + FULFILLMENT_RETURNED + FULFILLMENT_REPLACED + FULFILLMENT_AWAITS_APPROVAL + TRACKING_UPDATED + NOTE_ADDED + OTHER +} + +"""An enumeration.""" +enum OrderEventsEmailsEnum { + PAYMENT_CONFIRMATION + CONFIRMED + SHIPPING_CONFIRMATION + TRACKING_UPDATED + ORDER_CONFIRMATION + ORDER_CANCEL + ORDER_REFUND + FULFILLMENT_CONFIRMATION + DIGITAL_LINKS +} + +type OrderEventOrderLineObject { + """The variant quantity.""" + quantity: Int + + """The order line.""" + orderLine: OrderLine + + """The variant name.""" + itemName: String + + """The discount applied to the order line.""" + discount: OrderEventDiscountObject +} + +type OrderEventDiscountObject { + """Type of the discount: fixed or percent.""" + valueType: DiscountValueTypeEnum! + + """Value of the discount. Can store fixed value or percent value.""" + value: PositiveDecimal! + + """Explanation for the applied discount.""" + reason: String + + """Returns amount of discount.""" + amount: Money + + """Type of the discount: fixed or percent.""" + oldValueType: DiscountValueTypeEnum + + """Value of the discount. Can store fixed value or percent value.""" + oldValue: PositiveDecimal + + """Returns amount of discount.""" + oldAmount: Money +} + +""" +Represents a status of payment transaction. + + The following statuses are possible: + SUCCESS - Represents a sucess action. + FAILURE - Represents a failure action. + PENDING - Represents a pending action. +""" +enum TransactionStatus { + PENDING + SUCCESS + FAILURE +} + +"""Contains all details related to the applied discount to the order.""" +type OrderDiscount implements Node { + id: ID! + type: OrderDiscountType! + name: String + translatedName: String + + """Type of the discount: fixed or percent""" + valueType: DiscountValueTypeEnum! + + """Value of the discount. Can store fixed value or percent value""" + value: PositiveDecimal! + + """ + Explanation for the applied discount. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + reason: String + + """Returns amount of discount.""" + amount: Money! +} + +"""An enumeration.""" +enum OrderDiscountType { + VOUCHER + MANUAL +} + +type OrderError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: OrderErrorCode! + + """Warehouse ID which causes the error.""" + warehouse: ID + + """List of order line IDs that cause the error.""" + orderLines: [ID!] + + """List of product variants that are associated with the error""" + variants: [ID!] + + """A type of address that causes the error.""" + addressType: AddressTypeEnum +} + +"""An enumeration.""" +enum OrderErrorCode { + BILLING_ADDRESS_NOT_SET + CANNOT_CANCEL_FULFILLMENT + CANNOT_CANCEL_ORDER + CANNOT_DELETE + CANNOT_DISCOUNT + CANNOT_REFUND + CANNOT_FULFILL_UNPAID_ORDER + CAPTURE_INACTIVE_PAYMENT + GIFT_CARD_LINE + NOT_EDITABLE + FULFILL_ORDER_LINE + GRAPHQL_ERROR + INVALID + PRODUCT_NOT_PUBLISHED + PRODUCT_UNAVAILABLE_FOR_PURCHASE + NOT_FOUND + ORDER_NO_SHIPPING_ADDRESS + PAYMENT_ERROR + PAYMENT_MISSING + TRANSACTION_ERROR + REQUIRED + SHIPPING_METHOD_NOT_APPLICABLE + SHIPPING_METHOD_REQUIRED + TAX_ERROR + UNIQUE + VOID_INACTIVE_PAYMENT + ZERO_QUANTITY + INVALID_QUANTITY + INSUFFICIENT_STOCK + DUPLICATED_INPUT_ITEM + NOT_AVAILABLE_IN_CHANNEL + CHANNEL_INACTIVE +} + +"""An enumeration.""" +enum AddressTypeEnum { + BILLING + SHIPPING +} + +""" +The details of granted refund. + +Added in Saleor 3.13. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type OrderGrantedRefund { + id: ID! + + """Time of creation.""" + createdAt: DateTime! + + """Time of last update.""" + updatedAt: DateTime! + + """Refund amount.""" + amount: Money! + + """Reason of the refund.""" + reason: String + + """ + User who performed the action. Requires of of the following permissions: MANAGE_USERS, MANAGE_STAFF, OWNER. + """ + user: User + + """App that performed the action.""" + app: App +} + +"""Represents transaction's event.""" +type TransactionEvent implements Node { + """The ID of the object.""" + id: ID! + createdAt: DateTime! + + """Status of transaction's event.""" + status: TransactionStatus @deprecated(reason: "This field will be removed in Saleor 3.14 (Preview Feature). Use `type` instead.") + + """Reference of transaction's event.""" + reference: String! @deprecated(reason: "This field will be removed in Saleor 3.14 (Preview Feature).Use `pspReference` instead.") + + """ + PSP reference of transaction. + + Added in Saleor 3.13. + """ + pspReference: String! + + """Name of the transaction's event.""" + name: String @deprecated(reason: "This field will be removed in Saleor 3.14 (Preview Feature). Use `message` instead.") + + """ + Message related to the transaction's event. + + Added in Saleor 3.13. + """ + message: String! + + """ + The url that will allow to redirect user to payment provider page with transaction details. + + Added in Saleor 3.13. + """ + externalUrl: String! + + """ + The amount related to this event. + + Added in Saleor 3.13. + """ + amount: Money! + + """ + The type of action related to this event. + + Added in Saleor 3.13. + """ + type: TransactionEventTypeEnum + + """ + User or App that created the transaction event. + + Added in Saleor 3.13. + """ + createdBy: UserOrApp +} + +""" +Represents possible event types. + + Added in Saleor 3.12. + + The following types are possible: + AUTHORIZATION_SUCCESS - represents success authorization. + AUTHORIZATION_FAILURE - represents failure authorization. + AUTHORIZATION_ADJUSTMENT - represents authorization adjustment. + AUTHORIZATION_REQUEST - represents authorization request. + AUTHORIZATION_ACTION_REQUIRED - represents authorization that needs + additional actions from the customer. + CHARGE_ACTION_REQUIRED - represents charge that needs + additional actions from the customer. + CHARGE_SUCCESS - represents success charge. + CHARGE_FAILURE - represents failure charge. + CHARGE_BACK - represents chargeback. + CHARGE_REQUEST - represents charge request. + REFUND_SUCCESS - represents success refund. + REFUND_FAILURE - represents failure refund. + REFUND_REVERSE - represents reverse refund. + REFUND_REQUEST - represents refund request. + CANCEL_SUCCESS - represents success cancel. + CANCEL_FAILURE - represents failure cancel. + CANCEL_REQUEST - represents cancel request. + INFO - represents info event. +""" +enum TransactionEventTypeEnum { + AUTHORIZATION_SUCCESS + AUTHORIZATION_FAILURE + AUTHORIZATION_ADJUSTMENT + AUTHORIZATION_REQUEST + AUTHORIZATION_ACTION_REQUIRED + CHARGE_ACTION_REQUIRED + CHARGE_SUCCESS + CHARGE_FAILURE + CHARGE_BACK + CHARGE_REQUEST + REFUND_SUCCESS + REFUND_FAILURE + REFUND_REVERSE + REFUND_REQUEST + CANCEL_SUCCESS + CANCEL_FAILURE + CANCEL_REQUEST + INFO +} + +union UserOrApp = User | App + +""" +Determine a current authorize status for checkout. + + We treat the checkout as fully authorized when the sum of authorized and charged + funds cover the checkout.total. + We treat the checkout as partially authorized when the sum of authorized and charged + funds covers only part of the checkout.total + We treat the checkout as not authorized when the sum of authorized and charged funds + is 0. + + NONE - the funds are not authorized + PARTIAL - the cover funds don't cover fully the checkout's total + FULL - the cover funds covers the checkout's total +""" +enum CheckoutAuthorizeStatusEnum { + NONE + PARTIAL + FULL +} + +""" +Determine the current charge status for the checkout. + + The checkout is considered overcharged when the sum of the transactionItem's charge + amounts exceeds the value of `checkout.total`. + If the sum of the transactionItem's charge amounts equals + `checkout.total`, we consider the checkout to be fully charged. + If the sum of the transactionItem's charge amounts covers a part of the + `checkout.total`, we treat the checkout as partially charged. + + + NONE - the funds are not charged. + PARTIAL - the funds that are charged don't cover the checkout's total + FULL - the funds that are charged fully cover the checkout's total + OVERCHARGED - the charged funds are bigger than checkout's total +""" +enum CheckoutChargeStatusEnum { + NONE + PARTIAL + FULL + OVERCHARGED +} + +type CheckoutCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [CheckoutCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type CheckoutCountableEdge { + """The item at the end of the edge.""" + node: Checkout! + + """A cursor for use in pagination.""" + cursor: String! +} + +type GiftCardCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [GiftCardCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type GiftCardCountableEdge { + """The item at the end of the edge.""" + node: GiftCard! + + """A cursor for use in pagination.""" + cursor: String! +} + +type OrderCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [OrderCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type OrderCountableEdge { + """The item at the end of the edge.""" + node: Order! + + """A cursor for use in pagination.""" + cursor: String! +} + +type UserPermission { + """Internal code for permission.""" + code: PermissionEnum! + + """Describe action(s) allowed to do by permission.""" + name: String! + + """List of user permission groups which contains this permission.""" + sourcePermissionGroups( + """ID of user whose groups should be returned.""" + userId: ID! + ): [Group!] +} + +"""Represents permission group data.""" +type Group implements Node { + id: ID! + name: String! + + """ + List of group users + + Requires one of the following permissions: MANAGE_STAFF. + """ + users: [User!] + + """List of group permissions""" + permissions: [Permission!] + + """ + True, if the currently authenticated user has rights to manage a group. + """ + userCanManage: Boolean! +} + +"""History log of the customer.""" +type CustomerEvent implements Node { + id: ID! + + """Date when event happened at in ISO 8601 format.""" + date: DateTime + + """Customer event type.""" + type: CustomerEventsEnum + + """User who performed the action.""" + user: User + + """App that performed the action.""" + app: App + + """Content of the event.""" + message: String + + """Number of objects concerned by the event.""" + count: Int + + """The concerned order.""" + order: Order + + """The concerned order line.""" + orderLine: OrderLine +} + +"""An enumeration.""" +enum CustomerEventsEnum { + ACCOUNT_CREATED + ACCOUNT_ACTIVATED + ACCOUNT_DEACTIVATED + PASSWORD_RESET_LINK_SENT + PASSWORD_RESET + EMAIL_CHANGED_REQUEST + PASSWORD_CHANGED + EMAIL_CHANGED + PLACED_ORDER + NOTE_ADDED_TO_ORDER + DIGITAL_LINK_DOWNLOADED + CUSTOMER_DELETED + NAME_ASSIGNED + EMAIL_ASSIGNED + NOTE_ADDED +} + +""" +Represents a payment source stored for user in payment gateway, such as credit card. +""" +type PaymentSource { + """Payment gateway name.""" + gateway: String! + + """ID of stored payment method.""" + paymentMethodId: String + + """Stored credit card details if available.""" + creditCardInfo: CreditCard + + """ + List of public metadata items. + + Added in Saleor 3.1. + + Can be accessed without permissions. + """ + metadata: [MetadataItem!]! +} + +type LimitInfo { + """Defines the current resource usage.""" + currentUsage: Limits! + + """Defines the allowed maximum resource usage, null means unlimited.""" + allowedUsage: Limits! +} + +type Limits { + channels: Int + orders: Int + productVariants: Int + staffUsers: Int + warehouses: Int +} + +"""Gift card related settings from site settings.""" +type GiftCardSettings { + """The gift card expiry type settings.""" + expiryType: GiftCardSettingsExpiryTypeEnum! + + """The gift card expiry period settings.""" + expiryPeriod: TimePeriod +} + +"""An enumeration.""" +enum GiftCardSettingsExpiryTypeEnum { + NEVER_EXPIRE + EXPIRY_PERIOD +} + +type TimePeriod { + """The length of the period.""" + amount: Int! + + """The type of the period.""" + type: TimePeriodTypeEnum! +} + +"""An enumeration.""" +enum TimePeriodTypeEnum { + DAY + WEEK + MONTH + YEAR +} + +input ShippingZoneFilterInput { + search: String + channels: [ID!] +} + +type DigitalContentCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [DigitalContentCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type DigitalContentCountableEdge { + """The item at the end of the edge.""" + node: DigitalContent! + + """A cursor for use in pagination.""" + cursor: String! +} + +input CategoryFilterInput { + search: String + metadata: [MetadataFilter!] + ids: [ID!] + slugs: [String!] +} + +input CategorySortingInput { + """Specifies the direction in which to sort products.""" + direction: OrderDirection! + + """ + Specifies the channel in which to sort the data. + + DEPRECATED: this field will be removed in Saleor 4.0. Use root-level channel argument instead. + """ + channel: String + + """Sort categories by the selected field.""" + field: CategorySortField! +} + +enum CategorySortField { + """Sort categories by name.""" + NAME + + """Sort categories by product count.""" + PRODUCT_COUNT + + """Sort categories by subcategory count.""" + SUBCATEGORY_COUNT +} + +input CollectionFilterInput { + published: CollectionPublished + search: String + metadata: [MetadataFilter!] + ids: [ID!] + slugs: [String!] + + """ + Specifies the channel by which the data should be filtered. + + DEPRECATED: this field will be removed in Saleor 4.0. Use root-level channel argument instead. + """ + channel: String +} + +enum CollectionPublished { + PUBLISHED + HIDDEN +} + +input CollectionSortingInput { + """Specifies the direction in which to sort products.""" + direction: OrderDirection! + + """ + Specifies the channel in which to sort the data. + + DEPRECATED: this field will be removed in Saleor 4.0. Use root-level channel argument instead. + """ + channel: String + + """Sort collections by the selected field.""" + field: CollectionSortField! +} + +enum CollectionSortField { + """Sort collections by name.""" + NAME + + """ + Sort collections by availability. + + This option requires a channel filter to work as the values can vary between channels. + """ + AVAILABILITY + + """Sort collections by product count.""" + PRODUCT_COUNT + + """ + Sort collections by publication date. + + This option requires a channel filter to work as the values can vary between channels. + """ + PUBLICATION_DATE + + """ + Sort collections by publication date. + + This option requires a channel filter to work as the values can vary between channels. + """ + PUBLISHED_AT +} + +input ProductTypeFilterInput { + search: String + configurable: ProductTypeConfigurable + productType: ProductTypeEnum + metadata: [MetadataFilter!] + kind: ProductTypeKindEnum + ids: [ID!] + slugs: [String!] +} + +enum ProductTypeConfigurable { + CONFIGURABLE + SIMPLE +} + +enum ProductTypeEnum { + DIGITAL + SHIPPABLE +} + +input ProductTypeSortingInput { + """Specifies the direction in which to sort products.""" + direction: OrderDirection! + + """Sort product types by the selected field.""" + field: ProductTypeSortField! +} + +enum ProductTypeSortField { + """Sort products by name.""" + NAME + + """Sort products by type.""" + DIGITAL + + """Sort products by shipping.""" + SHIPPING_REQUIRED +} + +input ProductVariantFilterInput { + search: String + sku: [String!] + metadata: [MetadataFilter!] + isPreorder: Boolean + updatedAt: DateTimeRangeInput +} + +input ProductVariantSortingInput { + """Specifies the direction in which to sort products.""" + direction: OrderDirection! + + """Sort productVariants by the selected field.""" + field: ProductVariantSortField! +} + +enum ProductVariantSortField { + """Sort products variants by last modified at.""" + LAST_MODIFIED_AT +} + +type PaymentCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [PaymentCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type PaymentCountableEdge { + """The item at the end of the edge.""" + node: Payment! + + """A cursor for use in pagination.""" + cursor: String! +} + +input PaymentFilterInput { + """ + Filter by ids. + + Added in Saleor 3.8. + """ + ids: [ID!] + checkouts: [ID!] +} + +type PageCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [PageCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type PageCountableEdge { + """The item at the end of the edge.""" + node: Page! + + """A cursor for use in pagination.""" + cursor: String! +} + +input PageSortingInput { + """Specifies the direction in which to sort products.""" + direction: OrderDirection! + + """Sort pages by the selected field.""" + field: PageSortField! +} + +enum PageSortField { + """Sort pages by title.""" + TITLE + + """Sort pages by slug.""" + SLUG + + """Sort pages by visibility.""" + VISIBILITY + + """ + Sort pages by creation date. + + DEPRECATED: this field will be removed in Saleor 4.0. + """ + CREATION_DATE + + """ + Sort pages by publication date. + + DEPRECATED: this field will be removed in Saleor 4.0. + """ + PUBLICATION_DATE + + """ + Sort pages by publication date. + + DEPRECATED: this field will be removed in Saleor 4.0. + """ + PUBLISHED_AT + + """ + Sort pages by creation date. + + DEPRECATED: this field will be removed in Saleor 4.0. + """ + CREATED_AT +} + +input PageFilterInput { + search: String + metadata: [MetadataFilter!] + pageTypes: [ID!] + ids: [ID!] + slugs: [String!] +} + +type PageTypeCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [PageTypeCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type PageTypeCountableEdge { + """The item at the end of the edge.""" + node: PageType! + + """A cursor for use in pagination.""" + cursor: String! +} + +input PageTypeSortingInput { + """Specifies the direction in which to sort products.""" + direction: OrderDirection! + + """Sort page types by the selected field.""" + field: PageTypeSortField! +} + +enum PageTypeSortField { + """Sort page types by name.""" + NAME + + """Sort page types by slug.""" + SLUG +} + +input PageTypeFilterInput { + search: String + slugs: [String!] +} + +type OrderEventCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [OrderEventCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type OrderEventCountableEdge { + """The item at the end of the edge.""" + node: OrderEvent! + + """A cursor for use in pagination.""" + cursor: String! +} + +input OrderSortingInput { + """Specifies the direction in which to sort products.""" + direction: OrderDirection! + + """Sort orders by the selected field.""" + field: OrderSortField! +} + +enum OrderSortField { + """Sort orders by number.""" + NUMBER + + """ + Sort orders by rank. Note: This option is available only with the `search` filter. + """ + RANK + + """ + Sort orders by creation date. + + DEPRECATED: this field will be removed in Saleor 4.0. + """ + CREATION_DATE + + """ + Sort orders by creation date. + + DEPRECATED: this field will be removed in Saleor 4.0. + """ + CREATED_AT + + """Sort orders by last modified at.""" + LAST_MODIFIED_AT + + """Sort orders by customer.""" + CUSTOMER + + """Sort orders by payment.""" + PAYMENT + + """Sort orders by fulfillment status.""" + FULFILLMENT_STATUS +} + +input OrderFilterInput { + paymentStatus: [PaymentChargeStatusEnum!] + status: [OrderStatusFilter!] + customer: String + created: DateRangeInput + search: String + metadata: [MetadataFilter!] + channels: [ID!] + authorizeStatus: [OrderAuthorizeStatusEnum!] + chargeStatus: [OrderChargeStatusEnum!] + updatedAt: DateTimeRangeInput + isClickAndCollect: Boolean + isPreorder: Boolean + ids: [ID!] + giftCardUsed: Boolean + giftCardBought: Boolean + numbers: [String!] + checkoutIds: [ID!] +} + +enum OrderStatusFilter { + READY_TO_FULFILL + READY_TO_CAPTURE + UNFULFILLED + UNCONFIRMED + PARTIALLY_FULFILLED + FULFILLED + CANCELED +} + +input OrderDraftFilterInput { + customer: String + created: DateRangeInput + search: String + metadata: [MetadataFilter!] + channels: [ID!] +} + +type MenuCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [MenuCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type MenuCountableEdge { + """The item at the end of the edge.""" + node: Menu! + + """A cursor for use in pagination.""" + cursor: String! +} + +input MenuSortingInput { + """Specifies the direction in which to sort products.""" + direction: OrderDirection! + + """Sort menus by the selected field.""" + field: MenuSortField! +} + +enum MenuSortField { + """Sort menus by name.""" + NAME + + """Sort menus by items count.""" + ITEMS_COUNT +} + +input MenuFilterInput { + search: String + slug: [String!] + metadata: [MetadataFilter!] + slugs: [String!] +} + +type MenuItemCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [MenuItemCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type MenuItemCountableEdge { + """The item at the end of the edge.""" + node: MenuItem! + + """A cursor for use in pagination.""" + cursor: String! +} + +input MenuItemSortingInput { + """Specifies the direction in which to sort products.""" + direction: OrderDirection! + + """Sort menu items by the selected field.""" + field: MenuItemsSortField! +} + +enum MenuItemsSortField { + """Sort menu items by name.""" + NAME +} + +input MenuItemFilterInput { + search: String + metadata: [MetadataFilter!] +} + +input GiftCardSortingInput { + """Specifies the direction in which to sort products.""" + direction: OrderDirection! + + """Sort gift cards by the selected field.""" + field: GiftCardSortField! +} + +enum GiftCardSortField { + """Sort gift cards by product.""" + PRODUCT + + """Sort gift cards by used by.""" + USED_BY + + """Sort gift cards by current balance.""" + CURRENT_BALANCE + + """ + Sort gift cards by created at. + + Added in Saleor 3.8. + """ + CREATED_AT +} + +input GiftCardFilterInput { + isActive: Boolean + metadata: [MetadataFilter!] + tags: [String!] + products: [ID!] + usedBy: [ID!] + used: Boolean + currency: String + currentBalance: PriceRangeInput + initialBalance: PriceRangeInput + code: String +} + +type GiftCardTagCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [GiftCardTagCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type GiftCardTagCountableEdge { + """The item at the end of the edge.""" + node: GiftCardTag! + + """A cursor for use in pagination.""" + cursor: String! +} + +input GiftCardTagFilterInput { + search: String +} + +"""Plugin.""" +type Plugin { + """Identifier of the plugin.""" + id: ID! + + """Name of the plugin.""" + name: String! + + """Description of the plugin.""" + description: String! + + """Global configuration of the plugin (not channel-specific).""" + globalConfiguration: PluginConfiguration + + """Channel-specific plugin configuration.""" + channelConfigurations: [PluginConfiguration!]! +} + +"""Stores information about a configuration of plugin.""" +type PluginConfiguration { + """Determines if plugin is active or not.""" + active: Boolean! + + """The channel to which the plugin configuration is assigned to.""" + channel: Channel + + """Configuration of the plugin.""" + configuration: [ConfigurationItem!] +} + +"""Stores information about a single configuration field.""" +type ConfigurationItem { + """Name of the field.""" + name: String! + + """Current value of the field.""" + value: String + + """Type of the field.""" + type: ConfigurationTypeFieldEnum + + """Help text for the field.""" + helpText: String + + """Label for the field.""" + label: String +} + +"""An enumeration.""" +enum ConfigurationTypeFieldEnum { + STRING + MULTILINE + BOOLEAN + SECRET + PASSWORD + SECRETMULTILINE + OUTPUT +} + +type PluginCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [PluginCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type PluginCountableEdge { + """The item at the end of the edge.""" + node: Plugin! + + """A cursor for use in pagination.""" + cursor: String! +} + +input PluginFilterInput { + statusInChannels: PluginStatusInChannelsInput + search: String + type: PluginConfigurationType +} + +input PluginStatusInChannelsInput { + active: Boolean! + channels: [ID!]! +} + +enum PluginConfigurationType { + PER_CHANNEL + GLOBAL +} + +input PluginSortingInput { + """Specifies the direction in which to sort products.""" + direction: OrderDirection! + + """Sort plugins by the selected field.""" + field: PluginSortField! +} + +enum PluginSortField { + NAME + IS_ACTIVE +} + +type SaleCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [SaleCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type SaleCountableEdge { + """The item at the end of the edge.""" + node: Sale! + + """A cursor for use in pagination.""" + cursor: String! +} + +input SaleFilterInput { + status: [DiscountStatusEnum!] + saleType: DiscountValueTypeEnum + started: DateTimeRangeInput + search: String + metadata: [MetadataFilter!] + updatedAt: DateTimeRangeInput +} + +enum DiscountStatusEnum { + ACTIVE + EXPIRED + SCHEDULED +} + +input SaleSortingInput { + """Specifies the direction in which to sort products.""" + direction: OrderDirection! + + """ + Specifies the channel in which to sort the data. + + DEPRECATED: this field will be removed in Saleor 4.0. Use root-level channel argument instead. + """ + channel: String + + """Sort sales by the selected field.""" + field: SaleSortField! +} + +enum SaleSortField { + """Sort sales by name.""" + NAME + + """Sort sales by start date.""" + START_DATE + + """Sort sales by end date.""" + END_DATE + + """ + Sort sales by value. + + This option requires a channel filter to work as the values can vary between channels. + """ + VALUE + + """Sort sales by type.""" + TYPE + + """Sort sales by created at.""" + CREATED_AT + + """Sort sales by last modified at.""" + LAST_MODIFIED_AT +} + +type VoucherCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [VoucherCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type VoucherCountableEdge { + """The item at the end of the edge.""" + node: Voucher! + + """A cursor for use in pagination.""" + cursor: String! +} + +input VoucherFilterInput { + status: [DiscountStatusEnum!] + timesUsed: IntRangeInput + discountType: [VoucherDiscountType!] + started: DateTimeRangeInput + search: String + metadata: [MetadataFilter!] + ids: [ID!] +} + +enum VoucherDiscountType { + FIXED + PERCENTAGE + SHIPPING +} + +input VoucherSortingInput { + """Specifies the direction in which to sort products.""" + direction: OrderDirection! + + """ + Specifies the channel in which to sort the data. + + DEPRECATED: this field will be removed in Saleor 4.0. Use root-level channel argument instead. + """ + channel: String + + """Sort vouchers by the selected field.""" + field: VoucherSortField! +} + +enum VoucherSortField { + """Sort vouchers by code.""" + CODE + + """Sort vouchers by start date.""" + START_DATE + + """Sort vouchers by end date.""" + END_DATE + + """ + Sort vouchers by value. + + This option requires a channel filter to work as the values can vary between channels. + """ + VALUE + + """Sort vouchers by type.""" + TYPE + + """Sort vouchers by usage limit.""" + USAGE_LIMIT + + """ + Sort vouchers by minimum spent amount. + + This option requires a channel filter to work as the values can vary between channels. + """ + MINIMUM_SPENT_AMOUNT +} + +"""Represents a job data of exported file.""" +type ExportFile implements Node & Job { + id: ID! + + """Job status.""" + status: JobStatusEnum! + + """Created date time of job in ISO 8601 format.""" + createdAt: DateTime! + + """Date time of job last update in ISO 8601 format.""" + updatedAt: DateTime! + + """Job message.""" + message: String + + """The URL of field to download.""" + url: String + + """List of events associated with the export.""" + events: [ExportEvent!] + user: User + app: App +} + +"""History log of export file.""" +type ExportEvent implements Node { + """The ID of the object.""" + id: ID! + + """Date when event happened at in ISO 8601 format.""" + date: DateTime! + + """Export event type.""" + type: ExportEventsEnum! + + """ + User who performed the action. Requires one of the following permissions: OWNER, MANAGE_STAFF. + """ + user: User + + """ + App which performed the action. Requires one of the following permissions: OWNER, MANAGE_APPS. + """ + app: App + + """Content of the event.""" + message: String! +} + +"""An enumeration.""" +enum ExportEventsEnum { + EXPORT_PENDING + EXPORT_SUCCESS + EXPORT_FAILED + EXPORT_DELETED + EXPORTED_FILE_SENT + EXPORT_FAILED_INFO_SENT +} + +type ExportFileCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [ExportFileCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type ExportFileCountableEdge { + """The item at the end of the edge.""" + node: ExportFile! + + """A cursor for use in pagination.""" + cursor: String! +} + +input ExportFileFilterInput { + createdAt: DateTimeRangeInput + updatedAt: DateTimeRangeInput + status: JobStatusEnum + user: String + app: String +} + +input ExportFileSortingInput { + """Specifies the direction in which to sort products.""" + direction: OrderDirection! + + """Sort export file by the selected field.""" + field: ExportFileSortField! +} + +enum ExportFileSortField { + STATUS + CREATED_AT + UPDATED_AT + LAST_MODIFIED_AT +} + +input CheckoutSortingInput { + """Specifies the direction in which to sort products.""" + direction: OrderDirection! + + """Sort checkouts by the selected field.""" + field: CheckoutSortField! +} + +enum CheckoutSortField { + """Sort checkouts by creation date.""" + CREATION_DATE + + """Sort checkouts by customer.""" + CUSTOMER + + """Sort checkouts by payment.""" + PAYMENT +} + +input CheckoutFilterInput { + customer: String + created: DateRangeInput + search: String + metadata: [MetadataFilter!] + channels: [ID!] + updatedAt: DateRangeInput + authorizeStatus: [CheckoutAuthorizeStatusEnum!] + chargeStatus: [CheckoutChargeStatusEnum!] +} + +type CheckoutLineCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [CheckoutLineCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type CheckoutLineCountableEdge { + """The item at the end of the edge.""" + node: CheckoutLine! + + """A cursor for use in pagination.""" + cursor: String! +} + +input AttributeSortingInput { + """Specifies the direction in which to sort products.""" + direction: OrderDirection! + + """Sort attributes by the selected field.""" + field: AttributeSortField! +} + +enum AttributeSortField { + """Sort attributes by name""" + NAME + + """Sort attributes by slug""" + SLUG + + """Sort attributes by the value required flag""" + VALUE_REQUIRED + + """Sort attributes by the variant only flag""" + IS_VARIANT_ONLY + + """Sort attributes by visibility in the storefront""" + VISIBLE_IN_STOREFRONT + + """Sort attributes by the filterable in storefront flag""" + FILTERABLE_IN_STOREFRONT + + """Sort attributes by the filterable in dashboard flag""" + FILTERABLE_IN_DASHBOARD + + """Sort attributes by their position in storefront""" + STOREFRONT_SEARCH_POSITION + + """ + Sort attributes based on whether they can be displayed or not in a product grid. + """ + AVAILABLE_IN_GRID +} + +"""Represents ongoing installation of app.""" +type AppInstallation implements Node & Job { + id: ID! + + """Job status.""" + status: JobStatusEnum! + + """Created date time of job in ISO 8601 format.""" + createdAt: DateTime! + + """Date time of job last update in ISO 8601 format.""" + updatedAt: DateTime! + + """Job message.""" + message: String + appName: String! + manifestUrl: String! +} + +type AppCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [AppCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type AppCountableEdge { + """The item at the end of the edge.""" + node: App! + + """A cursor for use in pagination.""" + cursor: String! +} + +input AppFilterInput { + search: String + isActive: Boolean + type: AppTypeEnum +} + +input AppSortingInput { + """Specifies the direction in which to sort products.""" + direction: OrderDirection! + + """Sort apps by the selected field.""" + field: AppSortField! +} + +enum AppSortField { + """Sort apps by name.""" + NAME + + """Sort apps by creation date.""" + CREATION_DATE +} + +type AppExtensionCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [AppExtensionCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type AppExtensionCountableEdge { + """The item at the end of the edge.""" + node: AppExtension! + + """A cursor for use in pagination.""" + cursor: String! +} + +input AppExtensionFilterInput { + mount: [AppExtensionMountEnum!] + target: AppExtensionTargetEnum +} + +type AddressValidationData { + countryCode: String! + countryName: String! + addressFormat: String! + addressLatinFormat: String! + allowedFields: [String!]! + requiredFields: [String!]! + upperFields: [String!]! + countryAreaType: String! + countryAreaChoices: [ChoiceValue!]! + cityType: String! + cityChoices: [ChoiceValue!]! + cityAreaType: String! + cityAreaChoices: [ChoiceValue!]! + postalCodeType: String! + postalCodeMatchers: [String!]! + postalCodeExamples: [String!]! + postalCodePrefix: String! +} + +type ChoiceValue { + raw: String + verbose: String +} + +type UserCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [UserCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type UserCountableEdge { + """The item at the end of the edge.""" + node: User! + + """A cursor for use in pagination.""" + cursor: String! +} + +input CustomerFilterInput { + dateJoined: DateRangeInput + numberOfOrders: IntRangeInput + placedOrders: DateRangeInput + search: String + metadata: [MetadataFilter!] + + """ + Filter by ids. + + Added in Saleor 3.8. + """ + ids: [ID!] + updatedAt: DateTimeRangeInput +} + +input UserSortingInput { + """Specifies the direction in which to sort products.""" + direction: OrderDirection! + + """Sort users by the selected field.""" + field: UserSortField! +} + +enum UserSortField { + """Sort users by first name.""" + FIRST_NAME + + """Sort users by last name.""" + LAST_NAME + + """Sort users by email.""" + EMAIL + + """Sort users by order count.""" + ORDER_COUNT + + """Sort users by created at.""" + CREATED_AT + + """Sort users by last modified at.""" + LAST_MODIFIED_AT +} + +type GroupCountableConnection { + """Pagination data for this connection.""" + pageInfo: PageInfo! + edges: [GroupCountableEdge!]! + + """A total count of items in the collection.""" + totalCount: Int +} + +type GroupCountableEdge { + """The item at the end of the edge.""" + node: Group! + + """A cursor for use in pagination.""" + cursor: String! +} + +input PermissionGroupFilterInput { + search: String + ids: [ID!] +} + +input PermissionGroupSortingInput { + """Specifies the direction in which to sort products.""" + direction: OrderDirection! + + """Sort permission group by the selected field.""" + field: PermissionGroupSortField! +} + +enum PermissionGroupSortField { + """Sort permission group accounts by name.""" + NAME +} + +input StaffUserInput { + status: StaffMemberStatus + search: String + ids: [ID!] +} + +enum StaffMemberStatus { + """User account has been activated.""" + ACTIVE + + """User account has not been activated yet.""" + DEACTIVATED +} + +type Mutation { + """ + Creates a new webhook subscription. + + Requires one of the following permissions: MANAGE_APPS, AUTHENTICATED_APP. + """ + webhookCreate( + """Fields required to create a webhook.""" + input: WebhookCreateInput! + ): WebhookCreate + + """ + Delete a webhook. Before the deletion, the webhook is deactivated to pause any deliveries that are already scheduled. The deletion might fail if delivery is in progress. In such a case, the webhook is not deleted but remains deactivated. + + Requires one of the following permissions: MANAGE_APPS, AUTHENTICATED_APP. + """ + webhookDelete( + """ID of a webhook to delete.""" + id: ID! + ): WebhookDelete + + """ + Updates a webhook subscription. + + Requires one of the following permissions: MANAGE_APPS. + """ + webhookUpdate( + """ID of a webhook to update.""" + id: ID! + + """Fields required to update a webhook.""" + input: WebhookUpdateInput! + ): WebhookUpdate + + """ + Retries event delivery. + + Requires one of the following permissions: MANAGE_APPS. + """ + eventDeliveryRetry( + """ID of the event delivery to retry.""" + id: ID! + ): EventDeliveryRetry + + """ + Performs a dry run of a webhook event. Supports a single event (the first, if multiple provided in the `query`). Requires permission relevant to processed event. + + Added in Saleor 3.11. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: AUTHENTICATED_STAFF_USER. + """ + webhookDryRun( + """The ID of an object to serialize.""" + objectId: ID! + + """The subscription query that defines the webhook event and its payload.""" + query: String! + ): WebhookDryRun + + """ + Trigger a webhook event. Supports a single event (the first, if multiple provided in the `webhook.subscription_query`). Requires permission relevant to processed event. Successfully delivered webhook returns `delivery` with status='PENDING' and empty payload. + + Added in Saleor 3.11. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: AUTHENTICATED_STAFF_USER. + """ + webhookTrigger( + """The ID of an object to serialize.""" + objectId: ID! + + """The ID of the webhook.""" + webhookId: ID! + ): WebhookTrigger + + """ + Creates new warehouse. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + createWarehouse( + """Fields required to create warehouse.""" + input: WarehouseCreateInput! + ): WarehouseCreate + + """ + Updates given warehouse. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + updateWarehouse( + """ID of a warehouse to update.""" + id: ID! + + """Fields required to update warehouse.""" + input: WarehouseUpdateInput! + ): WarehouseUpdate + + """ + Deletes selected warehouse. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + deleteWarehouse( + """ID of a warehouse to delete.""" + id: ID! + ): WarehouseDelete + + """ + Add shipping zone to given warehouse. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + assignWarehouseShippingZone( + """ID of a warehouse to update.""" + id: ID! + + """List of shipping zone IDs.""" + shippingZoneIds: [ID!]! + ): WarehouseShippingZoneAssign + + """ + Remove shipping zone from given warehouse. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + unassignWarehouseShippingZone( + """ID of a warehouse to update.""" + id: ID! + + """List of shipping zone IDs.""" + shippingZoneIds: [ID!]! + ): WarehouseShippingZoneUnassign + + """ + Create a tax class. + + Added in Saleor 3.9. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_TAXES. + """ + taxClassCreate( + """Fields required to create a tax class.""" + input: TaxClassCreateInput! + ): TaxClassCreate + + """ + Delete a tax class. After deleting the tax class any products, product types or shipping methods using it are updated to use the default tax class. + + Added in Saleor 3.9. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_TAXES. + """ + taxClassDelete( + """ID of a tax class to delete.""" + id: ID! + ): TaxClassDelete + + """ + Update a tax class. + + Added in Saleor 3.9. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_TAXES. + """ + taxClassUpdate( + """ID of the tax class.""" + id: ID! + + """Fields required to update a tax class.""" + input: TaxClassUpdateInput! + ): TaxClassUpdate + + """ + Update tax configuration for a channel. + + Added in Saleor 3.9. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_TAXES. + """ + taxConfigurationUpdate( + """ID of the tax configuration.""" + id: ID! + + """Fields required to update the tax configuration.""" + input: TaxConfigurationUpdateInput! + ): TaxConfigurationUpdate + + """ + Update tax class rates for a specific country. + + Added in Saleor 3.9. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_TAXES. + """ + taxCountryConfigurationUpdate( + """Country in which to update the tax class rates.""" + countryCode: CountryCode! + + """ + List of tax rates per tax class to update. When `{taxClass: id, rate: null`} is passed, it deletes the rate object for given taxClass ID. When `{rate: Int}` is passed without a tax class, it updates the default tax class for this country. + """ + updateTaxClassRates: [TaxClassRateInput!]! + ): TaxCountryConfigurationUpdate + + """ + Remove all tax class rates for a specific country. + + Added in Saleor 3.9. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_TAXES. + """ + taxCountryConfigurationDelete( + """Country in which to update the tax class rates.""" + countryCode: CountryCode! + ): TaxCountryConfigurationDelete + + """ + Exempt checkout or order from charging the taxes. When tax exemption is enabled, taxes won't be charged for the checkout or order. Taxes may still be calculated in cases when product prices are entered with the tax included and the net price needs to be known. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_TAXES. + """ + taxExemptionManage( + """ID of the Checkout or Order object.""" + id: ID! + + """Determines if a taxes should be exempt.""" + taxExemption: Boolean! + ): TaxExemptionManage + + """ + Updates stocks for a given variant and warehouse. + + Added in Saleor 3.13. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + stockBulkUpdate( + """Policies of error handling. DEFAULT: REJECT_EVERYTHING""" + errorPolicy: ErrorPolicyEnum = reject_everything + + """Input list of stocks to update.""" + stocks: [StockBulkUpdateInput!]! + ): StockBulkUpdate + + """ + Creates a new staff notification recipient. + + Requires one of the following permissions: MANAGE_SETTINGS. + """ + staffNotificationRecipientCreate( + """Fields required to create a staff notification recipient.""" + input: StaffNotificationRecipientInput! + ): StaffNotificationRecipientCreate + + """ + Updates a staff notification recipient. + + Requires one of the following permissions: MANAGE_SETTINGS. + """ + staffNotificationRecipientUpdate( + """ID of a staff notification recipient to update.""" + id: ID! + + """Fields required to update a staff notification recipient.""" + input: StaffNotificationRecipientInput! + ): StaffNotificationRecipientUpdate + + """ + Delete staff notification recipient. + + Requires one of the following permissions: MANAGE_SETTINGS. + """ + staffNotificationRecipientDelete( + """ID of a staff notification recipient to delete.""" + id: ID! + ): StaffNotificationRecipientDelete + + """ + Updates site domain of the shop. + + Requires one of the following permissions: MANAGE_SETTINGS. + """ + shopDomainUpdate( + """Fields required to update site.""" + input: SiteDomainInput + ): ShopDomainUpdate + + """ + Updates shop settings. + + Requires one of the following permissions: MANAGE_SETTINGS. + """ + shopSettingsUpdate( + """Fields required to update shop settings.""" + input: ShopSettingsInput! + ): ShopSettingsUpdate + + """ + Fetch tax rates. + + Requires one of the following permissions: MANAGE_SETTINGS. + """ + shopFetchTaxRates: ShopFetchTaxRates @deprecated(reason: "\\n\\nDEPRECATED: this mutation will be removed in Saleor 4.0.") + + """ + Creates/updates translations for shop settings. + + Requires one of the following permissions: MANAGE_TRANSLATIONS. + """ + shopSettingsTranslate( + """Fields required to update shop settings translations.""" + input: ShopSettingsTranslationInput! + + """Translation language code.""" + languageCode: LanguageCodeEnum! + ): ShopSettingsTranslate + + """ + Update the shop's address. If the `null` value is passed, the currently selected address will be deleted. + + Requires one of the following permissions: MANAGE_SETTINGS. + """ + shopAddressUpdate( + """Fields required to update shop address.""" + input: AddressInput + ): ShopAddressUpdate + + """ + Update shop order settings across all channels. Returns `orderSettings` for the first `channel` in alphabetical order. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderSettingsUpdate( + """Fields required to update shop order settings.""" + input: OrderSettingsUpdateInput! + ): OrderSettingsUpdate @deprecated(reason: "\\n\\nDEPRECATED: this mutation will be removed in Saleor 4.0. Use `channelUpdate` mutation instead.") + + """ + Update gift card settings. + + Requires one of the following permissions: MANAGE_GIFT_CARD. + """ + giftCardSettingsUpdate( + """Fields required to update gift card settings.""" + input: GiftCardSettingsUpdateInput! + ): GiftCardSettingsUpdate + + """ + Manage shipping method's availability in channels. + + Requires one of the following permissions: MANAGE_SHIPPING. + """ + shippingMethodChannelListingUpdate( + """ID of a shipping method to update.""" + id: ID! + + """Fields required to update shipping method channel listings.""" + input: ShippingMethodChannelListingInput! + ): ShippingMethodChannelListingUpdate + + """ + Creates a new shipping price. + + Requires one of the following permissions: MANAGE_SHIPPING. + """ + shippingPriceCreate( + """Fields required to create a shipping price.""" + input: ShippingPriceInput! + ): ShippingPriceCreate + + """ + Deletes a shipping price. + + Requires one of the following permissions: MANAGE_SHIPPING. + """ + shippingPriceDelete( + """ID of a shipping price to delete.""" + id: ID! + ): ShippingPriceDelete + + """ + Deletes shipping prices. + + Requires one of the following permissions: MANAGE_SHIPPING. + """ + shippingPriceBulkDelete( + """List of shipping price IDs to delete.""" + ids: [ID!]! + ): ShippingPriceBulkDelete + + """ + Updates a new shipping price. + + Requires one of the following permissions: MANAGE_SHIPPING. + """ + shippingPriceUpdate( + """ID of a shipping price to update.""" + id: ID! + + """Fields required to update a shipping price.""" + input: ShippingPriceInput! + ): ShippingPriceUpdate + + """ + Creates/updates translations for a shipping method. + + Requires one of the following permissions: MANAGE_TRANSLATIONS. + """ + shippingPriceTranslate( + """ShippingMethodType ID or ShippingMethodTranslatableContent ID.""" + id: ID! + input: ShippingPriceTranslationInput! + + """Translation language code.""" + languageCode: LanguageCodeEnum! + ): ShippingPriceTranslate + + """ + Exclude products from shipping price. + + Requires one of the following permissions: MANAGE_SHIPPING. + """ + shippingPriceExcludeProducts( + """ID of a shipping price.""" + id: ID! + + """Exclude products input.""" + input: ShippingPriceExcludeProductsInput! + ): ShippingPriceExcludeProducts + + """ + Remove product from excluded list for shipping price. + + Requires one of the following permissions: MANAGE_SHIPPING. + """ + shippingPriceRemoveProductFromExclude( + """ID of a shipping price.""" + id: ID! + + """List of products which will be removed from excluded list.""" + products: [ID!]! + ): ShippingPriceRemoveProductFromExclude + + """ + Creates a new shipping zone. + + Requires one of the following permissions: MANAGE_SHIPPING. + """ + shippingZoneCreate( + """Fields required to create a shipping zone.""" + input: ShippingZoneCreateInput! + ): ShippingZoneCreate + + """ + Deletes a shipping zone. + + Requires one of the following permissions: MANAGE_SHIPPING. + """ + shippingZoneDelete( + """ID of a shipping zone to delete.""" + id: ID! + ): ShippingZoneDelete + + """ + Deletes shipping zones. + + Requires one of the following permissions: MANAGE_SHIPPING. + """ + shippingZoneBulkDelete( + """List of shipping zone IDs to delete.""" + ids: [ID!]! + ): ShippingZoneBulkDelete + + """ + Updates a new shipping zone. + + Requires one of the following permissions: MANAGE_SHIPPING. + """ + shippingZoneUpdate( + """ID of a shipping zone to update.""" + id: ID! + + """Fields required to update a shipping zone.""" + input: ShippingZoneUpdateInput! + ): ShippingZoneUpdate + + """ + Assign attributes to a given product type. + + Requires one of the following permissions: MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. + """ + productAttributeAssign( + """The operations to perform.""" + operations: [ProductAttributeAssignInput!]! + + """ID of the product type to assign the attributes into.""" + productTypeId: ID! + ): ProductAttributeAssign + + """ + Update attributes assigned to product variant for given product type. + + Added in Saleor 3.1. + + Requires one of the following permissions: MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. + """ + productAttributeAssignmentUpdate( + """The operations to perform.""" + operations: [ProductAttributeAssignmentUpdateInput!]! + + """ID of the product type to assign the attributes into.""" + productTypeId: ID! + ): ProductAttributeAssignmentUpdate + + """ + Un-assign attributes from a given product type. + + Requires one of the following permissions: MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. + """ + productAttributeUnassign( + """The IDs of the attributes to unassign.""" + attributeIds: [ID!]! + + """ID of the product type from which the attributes should be unassigned.""" + productTypeId: ID! + ): ProductAttributeUnassign + + """ + Creates a new category. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + categoryCreate( + """Fields required to create a category.""" + input: CategoryInput! + + """ + ID of the parent category. If empty, category will be top level category. + """ + parent: ID + ): CategoryCreate + + """ + Deletes a category. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + categoryDelete( + """ID of a category to delete.""" + id: ID! + ): CategoryDelete + + """ + Deletes categories. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + categoryBulkDelete( + """List of category IDs to delete.""" + ids: [ID!]! + ): CategoryBulkDelete + + """ + Updates a category. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + categoryUpdate( + """ID of a category to update.""" + id: ID! + + """Fields required to update a category.""" + input: CategoryInput! + ): CategoryUpdate + + """ + Creates/updates translations for a category. + + Requires one of the following permissions: MANAGE_TRANSLATIONS. + """ + categoryTranslate( + """Category ID or CategoryTranslatableContent ID.""" + id: ID! + input: TranslationInput! + + """Translation language code.""" + languageCode: LanguageCodeEnum! + ): CategoryTranslate + + """ + Adds products to a collection. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + collectionAddProducts( + """ID of a collection.""" + collectionId: ID! + + """List of product IDs.""" + products: [ID!]! + ): CollectionAddProducts + + """ + Creates a new collection. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + collectionCreate( + """Fields required to create a collection.""" + input: CollectionCreateInput! + ): CollectionCreate + + """ + Deletes a collection. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + collectionDelete( + """ID of a collection to delete.""" + id: ID! + ): CollectionDelete + + """ + Reorder the products of a collection. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + collectionReorderProducts( + """ID of a collection.""" + collectionId: ID! + + """The collection products position operations.""" + moves: [MoveProductInput!]! + ): CollectionReorderProducts + + """ + Deletes collections. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + collectionBulkDelete( + """List of collection IDs to delete.""" + ids: [ID!]! + ): CollectionBulkDelete + + """ + Remove products from a collection. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + collectionRemoveProducts( + """ID of a collection.""" + collectionId: ID! + + """List of product IDs.""" + products: [ID!]! + ): CollectionRemoveProducts + + """ + Updates a collection. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + collectionUpdate( + """ID of a collection to update.""" + id: ID! + + """Fields required to update a collection.""" + input: CollectionInput! + ): CollectionUpdate + + """ + Creates/updates translations for a collection. + + Requires one of the following permissions: MANAGE_TRANSLATIONS. + """ + collectionTranslate( + """Collection ID or CollectionTranslatableContent ID.""" + id: ID! + input: TranslationInput! + + """Translation language code.""" + languageCode: LanguageCodeEnum! + ): CollectionTranslate + + """ + Manage collection's availability in channels. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + collectionChannelListingUpdate( + """ID of a collection to update.""" + id: ID! + + """Fields required to create or update collection channel listings.""" + input: CollectionChannelListingUpdateInput! + ): CollectionChannelListingUpdate + + """ + Creates a new product. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + productCreate( + """Fields required to create a product.""" + input: ProductCreateInput! + ): ProductCreate + + """ + Deletes a product. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + productDelete( + """ + External ID of a product to delete. + + Added in Saleor 3.10. + """ + externalReference: String + + """ID of a product to delete.""" + id: ID + ): ProductDelete + + """ + Deletes products. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + productBulkDelete( + """List of product IDs to delete.""" + ids: [ID!]! + ): ProductBulkDelete + + """ + Updates an existing product. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + productUpdate( + """ + External ID of a product to update. + + Added in Saleor 3.10. + """ + externalReference: String + + """ID of a product to update.""" + id: ID + + """Fields required to update a product.""" + input: ProductInput! + ): ProductUpdate + + """ + Creates/updates translations for a product. + + Requires one of the following permissions: MANAGE_TRANSLATIONS. + """ + productTranslate( + """Product ID or ProductTranslatableContent ID.""" + id: ID! + input: TranslationInput! + + """Translation language code.""" + languageCode: LanguageCodeEnum! + ): ProductTranslate + + """ + Manage product's availability in channels. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + productChannelListingUpdate( + """ID of a product to update.""" + id: ID! + + """Fields required to create or update product channel listings.""" + input: ProductChannelListingUpdateInput! + ): ProductChannelListingUpdate + + """ + Create a media object (image or video URL) associated with product. For image, this mutation must be sent as a `multipart` request. More detailed specs of the upload format can be found here: https://github.com/jaydenseric/graphql-multipart-request-spec + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + productMediaCreate( + """Fields required to create a product media.""" + input: ProductMediaCreateInput! + ): ProductMediaCreate + + """ + Reorder the variants of a product. Mutation updates updated_at on product and triggers PRODUCT_UPDATED webhook. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + productVariantReorder( + """The list of variant reordering operations.""" + moves: [ReorderInput!]! + + """Id of product that variants order will be altered.""" + productId: ID! + ): ProductVariantReorder + + """ + Deletes a product media. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + productMediaDelete( + """ID of a product media to delete.""" + id: ID! + ): ProductMediaDelete + + """ + Deletes product media. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + productMediaBulkDelete( + """List of product media IDs to delete.""" + ids: [ID!]! + ): ProductMediaBulkDelete + + """ + Changes ordering of the product media. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + productMediaReorder( + """IDs of a product media in the desired order.""" + mediaIds: [ID!]! + + """ID of product that media order will be altered.""" + productId: ID! + ): ProductMediaReorder + + """ + Updates a product media. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + productMediaUpdate( + """ID of a product media to update.""" + id: ID! + + """Fields required to update a product media.""" + input: ProductMediaUpdateInput! + ): ProductMediaUpdate + + """ + Creates a new product type. + + Requires one of the following permissions: MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. + """ + productTypeCreate( + """Fields required to create a product type.""" + input: ProductTypeInput! + ): ProductTypeCreate + + """ + Deletes a product type. + + Requires one of the following permissions: MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. + """ + productTypeDelete( + """ID of a product type to delete.""" + id: ID! + ): ProductTypeDelete + + """ + Deletes product types. + + Requires one of the following permissions: MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. + """ + productTypeBulkDelete( + """List of product type IDs to delete.""" + ids: [ID!]! + ): ProductTypeBulkDelete + + """ + Updates an existing product type. + + Requires one of the following permissions: MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. + """ + productTypeUpdate( + """ID of a product type to update.""" + id: ID! + + """Fields required to update a product type.""" + input: ProductTypeInput! + ): ProductTypeUpdate + + """ + Reorder the attributes of a product type. + + Requires one of the following permissions: MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. + """ + productTypeReorderAttributes( + """The list of attribute reordering operations.""" + moves: [ReorderInput!]! + + """ID of a product type.""" + productTypeId: ID! + + """The attribute type to reorder.""" + type: ProductAttributeType! + ): ProductTypeReorderAttributes + + """ + Reorder product attribute values. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + productReorderAttributeValues( + """ID of an attribute.""" + attributeId: ID! + + """The list of reordering operations for given attribute values.""" + moves: [ReorderInput!]! + + """ID of a product.""" + productId: ID! + ): ProductReorderAttributeValues + + """ + Create new digital content. This mutation must be sent as a `multipart` request. More detailed specs of the upload format can be found here: https://github.com/jaydenseric/graphql-multipart-request-spec + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + digitalContentCreate( + """Fields required to create a digital content.""" + input: DigitalContentUploadInput! + + """ID of a product variant to upload digital content.""" + variantId: ID! + ): DigitalContentCreate + + """ + Remove digital content assigned to given variant. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + digitalContentDelete( + """ID of a product variant with digital content to remove.""" + variantId: ID! + ): DigitalContentDelete + + """ + Update digital content. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + digitalContentUpdate( + """Fields required to update a digital content.""" + input: DigitalContentInput! + + """ID of a product variant with digital content to update.""" + variantId: ID! + ): DigitalContentUpdate + + """ + Generate new URL to digital content. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + digitalContentUrlCreate( + """Fields required to create a new url.""" + input: DigitalContentUrlCreateInput! + ): DigitalContentUrlCreate + + """ + Creates a new variant for a product. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + productVariantCreate( + """Fields required to create a product variant.""" + input: ProductVariantCreateInput! + ): ProductVariantCreate + + """ + Deletes a product variant. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + productVariantDelete( + """ + External ID of a product variant to update. + + Added in Saleor 3.10. + """ + externalReference: String + + """ID of a product variant to delete.""" + id: ID + + """ + SKU of a product variant to delete. + + Added in Saleor 3.8. + """ + sku: String + ): ProductVariantDelete + + """ + Creates product variants for a given product. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + productVariantBulkCreate( + """ + Policies of error handling. DEFAULT: REJECT_EVERYTHING + + Added in Saleor 3.11. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + errorPolicy: ErrorPolicyEnum = reject_everything + + """ID of the product to create the variants for.""" + product: ID! + + """Input list of product variants to create.""" + variants: [ProductVariantBulkCreateInput!]! + ): ProductVariantBulkCreate + + """ + Update multiple product variants. + + Added in Saleor 3.11. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + productVariantBulkUpdate( + """Policies of error handling. DEFAULT: REJECT_EVERYTHING""" + errorPolicy: ErrorPolicyEnum = reject_everything + + """ID of the product to update the variants for.""" + product: ID! + + """Input list of product variants to update.""" + variants: [ProductVariantBulkUpdateInput!]! + ): ProductVariantBulkUpdate + + """ + Deletes product variants. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + productVariantBulkDelete( + """List of product variant IDs to delete.""" + ids: [ID!] + + """ + List of product variant SKUs to delete. + + Added in Saleor 3.8. + """ + skus: [String!] + ): ProductVariantBulkDelete + + """ + Creates stocks for product variant. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + productVariantStocksCreate( + """Input list of stocks to create.""" + stocks: [StockInput!]! + + """ID of a product variant for which stocks will be created.""" + variantId: ID! + ): ProductVariantStocksCreate + + """ + Delete stocks from product variant. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + productVariantStocksDelete( + """SKU of product variant for which stocks will be deleted.""" + sku: String + + """ID of product variant for which stocks will be deleted.""" + variantId: ID + + """Input list of warehouse IDs.""" + warehouseIds: [ID!] + ): ProductVariantStocksDelete + + """ + Update stocks for product variant. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + productVariantStocksUpdate( + """SKU of product variant for which stocks will be updated.""" + sku: String + + """Input list of stocks to create or update.""" + stocks: [StockInput!]! + + """ID of a product variant for which stocks will be updated.""" + variantId: ID + ): ProductVariantStocksUpdate + + """ + Updates an existing variant for product. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + productVariantUpdate( + """ + External ID of a product variant to update. + + Added in Saleor 3.10. + """ + externalReference: String + + """ID of a product to update.""" + id: ID + + """Fields required to update a product variant.""" + input: ProductVariantInput! + + """ + SKU of a product variant to update. + + Added in Saleor 3.8. + """ + sku: String + ): ProductVariantUpdate + + """ + Set default variant for a product. Mutation triggers PRODUCT_UPDATED webhook. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + productVariantSetDefault( + """Id of a product that will have the default variant set.""" + productId: ID! + + """Id of a variant that will be set as default.""" + variantId: ID! + ): ProductVariantSetDefault + + """ + Creates/updates translations for a product variant. + + Requires one of the following permissions: MANAGE_TRANSLATIONS. + """ + productVariantTranslate( + """ProductVariant ID or ProductVariantTranslatableContent ID.""" + id: ID! + input: NameTranslationInput! + + """Translation language code.""" + languageCode: LanguageCodeEnum! + ): ProductVariantTranslate + + """ + Manage product variant prices in channels. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + productVariantChannelListingUpdate( + """ID of a product variant to update.""" + id: ID + + """ + List of fields required to create or upgrade product variant channel listings. + """ + input: [ProductVariantChannelListingAddInput!]! + + """ + SKU of a product variant to update. + + Added in Saleor 3.8. + """ + sku: String + ): ProductVariantChannelListingUpdate + + """ + Reorder product variant attribute values. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + productVariantReorderAttributeValues( + """ID of an attribute.""" + attributeId: ID! + + """The list of reordering operations for given attribute values.""" + moves: [ReorderInput!]! + + """ID of a product variant.""" + variantId: ID! + ): ProductVariantReorderAttributeValues + + """ + Deactivates product variant preorder. It changes all preorder allocation into regular allocation. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + productVariantPreorderDeactivate( + """ID of a variant which preorder should be deactivated.""" + id: ID! + ): ProductVariantPreorderDeactivate + + """ + Assign an media to a product variant. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + variantMediaAssign( + """ID of a product media to assign to a variant.""" + mediaId: ID! + + """ID of a product variant.""" + variantId: ID! + ): VariantMediaAssign + + """ + Unassign an media from a product variant. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + variantMediaUnassign( + """ID of a product media to unassign from a variant.""" + mediaId: ID! + + """ID of a product variant.""" + variantId: ID! + ): VariantMediaUnassign + + """ + Captures the authorized payment amount. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + paymentCapture( + """Transaction amount.""" + amount: PositiveDecimal + + """Payment ID.""" + paymentId: ID! + ): PaymentCapture + + """ + Refunds the captured payment amount. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + paymentRefund( + """Transaction amount.""" + amount: PositiveDecimal + + """Payment ID.""" + paymentId: ID! + ): PaymentRefund + + """ + Voids the authorized payment. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + paymentVoid( + """Payment ID.""" + paymentId: ID! + ): PaymentVoid + + """Initializes payment process when it is required by gateway.""" + paymentInitialize( + """Slug of a channel for which the data should be returned.""" + channel: String + + """A gateway name used to initialize the payment.""" + gateway: String! + + """Client-side generated data required to initialize the payment.""" + paymentData: JSONString + ): PaymentInitialize + + """Check payment balance.""" + paymentCheckBalance( + """Fields required to check payment balance.""" + input: PaymentCheckBalanceInput! + ): PaymentCheckBalance + + """ + Create transaction for checkout or order. + + Added in Saleor 3.4. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: HANDLE_PAYMENTS. + """ + transactionCreate( + """The ID of the checkout or order.""" + id: ID! + + """Input data required to create a new transaction object.""" + transaction: TransactionCreateInput! + + """Data that defines a transaction event.""" + transactionEvent: TransactionEventInput + ): TransactionCreate + + """ + Create transaction for checkout or order. + + Added in Saleor 3.4. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires the following permissions: OWNER and HANDLE_PAYMENTS. + """ + transactionUpdate( + """The ID of the transaction.""" + id: ID! + + """Input data required to create a new transaction object.""" + transaction: TransactionUpdateInput + + """Data that defines a transaction transaction.""" + transactionEvent: TransactionEventInput + ): TransactionUpdate + + """ + Request an action for payment transaction. + + Added in Saleor 3.4. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: HANDLE_PAYMENTS. + """ + transactionRequestAction( + """Determines the action type.""" + actionType: TransactionActionEnum! + + """ + Transaction request amount. If empty for refund or capture, maximal possible amount will be used. + """ + amount: PositiveDecimal + + """The ID of the transaction.""" + id: ID! + ): TransactionRequestAction + + """ + Report the event for the transaction. + + Added in Saleor 3.13. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires the following permissions: OWNER and HANDLE_PAYMENTS. + """ + transactionEventReport( + """The amount of the event to report.""" + amount: PositiveDecimal! + + """List of all possible actions for the transaction""" + availableActions: [TransactionActionEnum!] + + """ + The url that will allow to redirect user to payment provider page with event details. + """ + externalUrl: String + + """The ID of the transaction.""" + id: ID! + + """The message related to the event.""" + message: String + + """PSP Reference of the event to report.""" + pspReference: String! + + """ + The time of the event to report. If not provide, the current time will be used. + """ + time: DateTime + + """Current status of the event to report.""" + type: TransactionEventTypeEnum! + ): TransactionEventReport + + """ + Initializes a payment gateway session. It triggers the webhook `PAYMENT_GATEWAY_INITIALIZE_SESSION`, to the requested `paymentGateways`. If `paymentGateways` is not provided, the webhook will be send to all subscribed payment gateways. + + Added in Saleor 3.13. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + paymentGatewayInitialize( + """ + The amount requested for initializing the payment gateway. If not provided, the difference between checkout.total - transactions that are already processed will be send. + """ + amount: PositiveDecimal + + """The ID of the checkout or order.""" + id: ID! + + """List of payment gateways to initialize.""" + paymentGateways: [PaymentGatewayToInitialize!] + ): PaymentGatewayInitialize + + """ + Initializes a transaction session. It triggers the webhook `TRANSACTION_INITIALIZE_SESSION`, to the requested `paymentGateways`. + + Added in Saleor 3.13. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + transactionInitialize( + """ + The expected action called for the transaction. By default, the `channel.defaultTransactionFlowStrategy` will be used. The field can be used only by app that has `HANDLE_PAYMENTS` permission. + """ + action: TransactionFlowStrategyEnum + + """ + The amount requested for initializing the payment gateway. If not provided, the difference between checkout.total - transactions that are already processed will be send. + """ + amount: PositiveDecimal + + """The ID of the checkout or order.""" + id: ID! + + """Payment gateway used to initialize the transaction.""" + paymentGateway: PaymentGatewayToInitialize! + ): TransactionInitialize + + """ + Processes a transaction session. It triggers the webhook `TRANSACTION_PROCESS_SESSION`, to the assigned `paymentGateways`. + + Added in Saleor 3.13. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + transactionProcess( + """The data that will be passed to the payment gateway.""" + data: JSON + + """The ID of the transaction to process.""" + id: ID! + ): TransactionProcess + + """ + Creates a new page. + + Requires one of the following permissions: MANAGE_PAGES. + """ + pageCreate( + """Fields required to create a page.""" + input: PageCreateInput! + ): PageCreate + + """ + Deletes a page. + + Requires one of the following permissions: MANAGE_PAGES. + """ + pageDelete( + """ID of a page to delete.""" + id: ID! + ): PageDelete + + """ + Deletes pages. + + Requires one of the following permissions: MANAGE_PAGES. + """ + pageBulkDelete( + """List of page IDs to delete.""" + ids: [ID!]! + ): PageBulkDelete + + """ + Publish pages. + + Requires one of the following permissions: MANAGE_PAGES. + """ + pageBulkPublish( + """List of page IDs to (un)publish.""" + ids: [ID!]! + + """Determine if pages will be published or not.""" + isPublished: Boolean! + ): PageBulkPublish + + """ + Updates an existing page. + + Requires one of the following permissions: MANAGE_PAGES. + """ + pageUpdate( + """ID of a page to update.""" + id: ID! + + """Fields required to update a page.""" + input: PageInput! + ): PageUpdate + + """ + Creates/updates translations for a page. + + Requires one of the following permissions: MANAGE_TRANSLATIONS. + """ + pageTranslate( + """Page ID or PageTranslatableContent ID.""" + id: ID! + input: PageTranslationInput! + + """Translation language code.""" + languageCode: LanguageCodeEnum! + ): PageTranslate + + """ + Create a new page type. + + Requires one of the following permissions: MANAGE_PAGE_TYPES_AND_ATTRIBUTES. + """ + pageTypeCreate( + """Fields required to create page type.""" + input: PageTypeCreateInput! + ): PageTypeCreate + + """ + Update page type. + + Requires one of the following permissions: MANAGE_PAGE_TYPES_AND_ATTRIBUTES. + """ + pageTypeUpdate( + """ID of the page type to update.""" + id: ID + + """Fields required to update page type.""" + input: PageTypeUpdateInput! + ): PageTypeUpdate + + """ + Delete a page type. + + Requires one of the following permissions: MANAGE_PAGE_TYPES_AND_ATTRIBUTES. + """ + pageTypeDelete( + """ID of the page type to delete.""" + id: ID! + ): PageTypeDelete + + """ + Delete page types. + + Requires one of the following permissions: MANAGE_PAGE_TYPES_AND_ATTRIBUTES. + """ + pageTypeBulkDelete( + """List of page type IDs to delete""" + ids: [ID!]! + ): PageTypeBulkDelete + + """ + Assign attributes to a given page type. + + Requires one of the following permissions: MANAGE_PAGE_TYPES_AND_ATTRIBUTES. + """ + pageAttributeAssign( + """The IDs of the attributes to assign.""" + attributeIds: [ID!]! + + """ID of the page type to assign the attributes into.""" + pageTypeId: ID! + ): PageAttributeAssign + + """ + Unassign attributes from a given page type. + + Requires one of the following permissions: MANAGE_PAGE_TYPES_AND_ATTRIBUTES. + """ + pageAttributeUnassign( + """The IDs of the attributes to unassign.""" + attributeIds: [ID!]! + + """ID of the page type from which the attributes should be unassign.""" + pageTypeId: ID! + ): PageAttributeUnassign + + """ + Reorder the attributes of a page type. + + Requires one of the following permissions: MANAGE_PAGE_TYPES_AND_ATTRIBUTES. + """ + pageTypeReorderAttributes( + """The list of attribute reordering operations.""" + moves: [ReorderInput!]! + + """ID of a page type.""" + pageTypeId: ID! + ): PageTypeReorderAttributes + + """ + Reorder page attribute values. + + Requires one of the following permissions: MANAGE_PAGES. + """ + pageReorderAttributeValues( + """ID of an attribute.""" + attributeId: ID! + + """The list of reordering operations for given attribute values.""" + moves: [ReorderInput!]! + + """ID of a page.""" + pageId: ID! + ): PageReorderAttributeValues + + """ + Completes creating an order. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + draftOrderComplete( + """ID of the order that will be completed.""" + id: ID! + ): DraftOrderComplete + + """ + Creates a new draft order. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + draftOrderCreate( + """Fields required to create an order.""" + input: DraftOrderCreateInput! + ): DraftOrderCreate + + """ + Deletes a draft order. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + draftOrderDelete( + """ + External ID of a product to delete. + + Added in Saleor 3.10. + """ + externalReference: String + + """ID of a product to delete.""" + id: ID + ): DraftOrderDelete + + """ + Deletes draft orders. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + draftOrderBulkDelete( + """List of draft order IDs to delete.""" + ids: [ID!]! + ): DraftOrderBulkDelete + + """ + Deletes order lines. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + draftOrderLinesBulkDelete( + """List of order lines IDs to delete.""" + ids: [ID!]! + ): DraftOrderLinesBulkDelete @deprecated(reason: "This field will be removed in Saleor 4.0.") + + """ + Updates a draft order. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + draftOrderUpdate( + """ + External ID of a draft order to update. + + Added in Saleor 3.10. + """ + externalReference: String + + """ID of a draft order to update.""" + id: ID + + """Fields required to update an order.""" + input: DraftOrderInput! + ): DraftOrderUpdate + + """ + Adds note to the order. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderAddNote( + """ID of the order to add a note for.""" + order: ID! + + """Fields required to create a note for the order.""" + input: OrderAddNoteInput! + ): OrderAddNote + + """ + Cancel an order. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderCancel( + """ID of the order to cancel.""" + id: ID! + ): OrderCancel + + """ + Capture an order. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderCapture( + """Amount of money to capture.""" + amount: PositiveDecimal! + + """ID of the order to capture.""" + id: ID! + ): OrderCapture + + """ + Confirms an unconfirmed order by changing status to unfulfilled. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderConfirm( + """ID of an order to confirm.""" + id: ID! + ): OrderConfirm + + """ + Creates new fulfillments for an order. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderFulfill( + """Fields required to create a fulfillment.""" + input: OrderFulfillInput! + + """ID of the order to be fulfilled.""" + order: ID + ): OrderFulfill + + """ + Cancels existing fulfillment and optionally restocks items. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderFulfillmentCancel( + """ID of a fulfillment to cancel.""" + id: ID! + + """Fields required to cancel a fulfillment.""" + input: FulfillmentCancelInput + ): FulfillmentCancel + + """ + Approve existing fulfillment. + + Added in Saleor 3.1. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderFulfillmentApprove( + """True if stock could be exceeded.""" + allowStockToBeExceeded: Boolean = false + + """ID of a fulfillment to approve.""" + id: ID! + + """True if confirmation email should be send.""" + notifyCustomer: Boolean! + ): FulfillmentApprove + + """ + Updates a fulfillment for an order. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderFulfillmentUpdateTracking( + """ID of a fulfillment to update.""" + id: ID! + + """Fields required to update a fulfillment.""" + input: FulfillmentUpdateTrackingInput! + ): FulfillmentUpdateTracking + + """ + Refund products. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderFulfillmentRefundProducts( + """Fields required to create an refund fulfillment.""" + input: OrderRefundProductsInput! + + """ID of the order to be refunded.""" + order: ID! + ): FulfillmentRefundProducts + + """ + Return products. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderFulfillmentReturnProducts( + """Fields required to return products.""" + input: OrderReturnProductsInput! + + """ID of the order to be returned.""" + order: ID! + ): FulfillmentReturnProducts + + """ + Adds granted refund to the order. + + Added in Saleor 3.13. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderGrantRefundCreate( + """ID of the order.""" + id: ID! + + """Fields required to create a granted refund for the order.""" + input: OrderGrantRefundCreateInput! + ): OrderGrantRefundCreate + + """ + Updates granted refund. + + Added in Saleor 3.13. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderGrantRefundUpdate( + """ID of the granted refund.""" + id: ID! + + """Fields required to update a granted refund.""" + input: OrderGrantRefundUpdateInput! + ): OrderGrantRefundUpdate + + """ + Create order lines for an order. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderLinesCreate( + """ID of the order to add the lines to.""" + id: ID! + + """Fields required to add order lines.""" + input: [OrderLineCreateInput!]! + ): OrderLinesCreate + + """ + Deletes an order line from an order. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderLineDelete( + """ID of the order line to delete.""" + id: ID! + ): OrderLineDelete + + """ + Updates an order line of an order. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderLineUpdate( + """ID of the order line to update.""" + id: ID! + + """Fields required to update an order line.""" + input: OrderLineInput! + ): OrderLineUpdate + + """ + Adds discount to the order. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderDiscountAdd( + """Fields required to create a discount for the order.""" + input: OrderDiscountCommonInput! + + """ID of an order to discount.""" + orderId: ID! + ): OrderDiscountAdd + + """ + Update discount for the order. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderDiscountUpdate( + """ID of a discount to update.""" + discountId: ID! + + """Fields required to update a discount for the order.""" + input: OrderDiscountCommonInput! + ): OrderDiscountUpdate + + """ + Remove discount from the order. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderDiscountDelete( + """ID of a discount to remove.""" + discountId: ID! + ): OrderDiscountDelete + + """ + Update discount for the order line. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderLineDiscountUpdate( + """Fields required to update price for the order line.""" + input: OrderDiscountCommonInput! + + """ID of a order line to update price""" + orderLineId: ID! + ): OrderLineDiscountUpdate + + """ + Remove discount applied to the order line. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderLineDiscountRemove( + """ID of a order line to remove its discount""" + orderLineId: ID! + ): OrderLineDiscountRemove + + """ + Mark order as manually paid. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderMarkAsPaid( + """ID of the order to mark paid.""" + id: ID! + + """The external transaction reference.""" + transactionReference: String + ): OrderMarkAsPaid + + """ + Refund an order. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderRefund( + """Amount of money to refund.""" + amount: PositiveDecimal! + + """ID of the order to refund.""" + id: ID! + ): OrderRefund + + """ + Updates an order. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderUpdate( + """ + External ID of an order to update. + + Added in Saleor 3.10. + """ + externalReference: String + + """ID of an order to update.""" + id: ID + + """Fields required to update an order.""" + input: OrderUpdateInput! + ): OrderUpdate + + """ + Updates a shipping method of the order. Requires shipping method ID to update, when null is passed then currently assigned shipping method is removed. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderUpdateShipping( + """ID of the order to update a shipping method.""" + order: ID! + + """Fields required to change shipping method of the order.""" + input: OrderUpdateShippingInput! + ): OrderUpdateShipping + + """ + Void an order. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderVoid( + """ID of the order to void.""" + id: ID! + ): OrderVoid + + """ + Cancels orders. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + orderBulkCancel( + """List of orders IDs to cancel.""" + ids: [ID!]! + ): OrderBulkCancel + + """ + Delete metadata of an object. To use it, you need to have access to the modified object. + """ + deleteMetadata( + """ID or token (for Order and Checkout) of an object to update.""" + id: ID! + + """Metadata keys to delete.""" + keys: [String!]! + ): DeleteMetadata + + """ + Delete object's private metadata. To use it, you need to be an authenticated staff user or an app and have access to the modified object. + """ + deletePrivateMetadata( + """ID or token (for Order and Checkout) of an object to update.""" + id: ID! + + """Metadata keys to delete.""" + keys: [String!]! + ): DeletePrivateMetadata + + """ + Updates metadata of an object. To use it, you need to have access to the modified object. + """ + updateMetadata( + """ID or token (for Order and Checkout) of an object to update.""" + id: ID! + + """Fields required to update the object's metadata.""" + input: [MetadataInput!]! + ): UpdateMetadata + + """ + Updates private metadata of an object. To use it, you need to be an authenticated staff user or an app and have access to the modified object. + """ + updatePrivateMetadata( + """ID or token (for Order and Checkout) of an object to update.""" + id: ID! + + """Fields required to update the object's metadata.""" + input: [MetadataInput!]! + ): UpdatePrivateMetadata + + """ + Assigns storefront's navigation menus. + + Requires one of the following permissions: MANAGE_MENUS, MANAGE_SETTINGS. + """ + assignNavigation( + """ID of the menu.""" + menu: ID + + """Type of the navigation bar to assign the menu to.""" + navigationType: NavigationType! + ): AssignNavigation + + """ + Creates a new Menu. + + Requires one of the following permissions: MANAGE_MENUS. + """ + menuCreate( + """Fields required to create a menu.""" + input: MenuCreateInput! + ): MenuCreate + + """ + Deletes a menu. + + Requires one of the following permissions: MANAGE_MENUS. + """ + menuDelete( + """ID of a menu to delete.""" + id: ID! + ): MenuDelete + + """ + Deletes menus. + + Requires one of the following permissions: MANAGE_MENUS. + """ + menuBulkDelete( + """List of menu IDs to delete.""" + ids: [ID!]! + ): MenuBulkDelete + + """ + Updates a menu. + + Requires one of the following permissions: MANAGE_MENUS. + """ + menuUpdate( + """ID of a menu to update.""" + id: ID! + + """Fields required to update a menu.""" + input: MenuInput! + ): MenuUpdate + + """ + Creates a new menu item. + + Requires one of the following permissions: MANAGE_MENUS. + """ + menuItemCreate( + """ + Fields required to update a menu item. Only one of `url`, `category`, `page`, `collection` is allowed per item. + """ + input: MenuItemCreateInput! + ): MenuItemCreate + + """ + Deletes a menu item. + + Requires one of the following permissions: MANAGE_MENUS. + """ + menuItemDelete( + """ID of a menu item to delete.""" + id: ID! + ): MenuItemDelete + + """ + Deletes menu items. + + Requires one of the following permissions: MANAGE_MENUS. + """ + menuItemBulkDelete( + """List of menu item IDs to delete.""" + ids: [ID!]! + ): MenuItemBulkDelete + + """ + Updates a menu item. + + Requires one of the following permissions: MANAGE_MENUS. + """ + menuItemUpdate( + """ID of a menu item to update.""" + id: ID! + + """ + Fields required to update a menu item. Only one of `url`, `category`, `page`, `collection` is allowed per item. + """ + input: MenuItemInput! + ): MenuItemUpdate + + """ + Creates/updates translations for a menu item. + + Requires one of the following permissions: MANAGE_TRANSLATIONS. + """ + menuItemTranslate( + """MenuItem ID or MenuItemTranslatableContent ID.""" + id: ID! + input: NameTranslationInput! + + """Translation language code.""" + languageCode: LanguageCodeEnum! + ): MenuItemTranslate + + """ + Moves items of menus. + + Requires one of the following permissions: MANAGE_MENUS. + """ + menuItemMove( + """ID of the menu.""" + menu: ID! + + """The menu position data.""" + moves: [MenuItemMoveInput!]! + ): MenuItemMove + + """ + Request an invoice for the order using plugin. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + invoiceRequest( + """Invoice number, if not provided it will be generated.""" + number: String + + """ID of the order related to invoice.""" + orderId: ID! + ): InvoiceRequest + + """ + Requests deletion of an invoice. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + invoiceRequestDelete( + """ID of an invoice to request the deletion.""" + id: ID! + ): InvoiceRequestDelete + + """ + Creates a ready to send invoice. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + invoiceCreate( + """Fields required when creating an invoice.""" + input: InvoiceCreateInput! + + """ID of the order related to invoice.""" + orderId: ID! + ): InvoiceCreate + + """ + Deletes an invoice. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + invoiceDelete( + """ID of an invoice to delete.""" + id: ID! + ): InvoiceDelete + + """ + Updates an invoice. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + invoiceUpdate( + """ID of an invoice to update.""" + id: ID! + + """Fields to use when updating an invoice.""" + input: UpdateInvoiceInput! + ): InvoiceUpdate + + """ + Send an invoice notification to the customer. + + Requires one of the following permissions: MANAGE_ORDERS. + """ + invoiceSendNotification( + """ID of an invoice to be sent.""" + id: ID! + ): InvoiceSendNotification + + """ + Activate a gift card. + + Requires one of the following permissions: MANAGE_GIFT_CARD. + """ + giftCardActivate( + """ID of a gift card to activate.""" + id: ID! + ): GiftCardActivate + + """ + Creates a new gift card. + + Requires one of the following permissions: MANAGE_GIFT_CARD. + """ + giftCardCreate( + """Fields required to create a gift card.""" + input: GiftCardCreateInput! + ): GiftCardCreate + + """ + Delete gift card. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_GIFT_CARD. + """ + giftCardDelete( + """ID of the gift card to delete.""" + id: ID! + ): GiftCardDelete + + """ + Deactivate a gift card. + + Requires one of the following permissions: MANAGE_GIFT_CARD. + """ + giftCardDeactivate( + """ID of a gift card to deactivate.""" + id: ID! + ): GiftCardDeactivate + + """ + Update a gift card. + + Requires one of the following permissions: MANAGE_GIFT_CARD. + """ + giftCardUpdate( + """ID of a gift card to update.""" + id: ID! + + """Fields required to update a gift card.""" + input: GiftCardUpdateInput! + ): GiftCardUpdate + + """ + Resend a gift card. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_GIFT_CARD. + """ + giftCardResend( + """Fields required to resend a gift card.""" + input: GiftCardResendInput! + ): GiftCardResend + + """ + Adds note to the gift card. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_GIFT_CARD. + """ + giftCardAddNote( + """ID of the gift card to add a note for.""" + id: ID! + + """Fields required to create a note for the gift card.""" + input: GiftCardAddNoteInput! + ): GiftCardAddNote + + """ + Create gift cards. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_GIFT_CARD. + """ + giftCardBulkCreate( + """Fields required to create gift cards.""" + input: GiftCardBulkCreateInput! + ): GiftCardBulkCreate + + """ + Delete gift cards. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_GIFT_CARD. + """ + giftCardBulkDelete( + """List of gift card IDs to delete.""" + ids: [ID!]! + ): GiftCardBulkDelete + + """ + Activate gift cards. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_GIFT_CARD. + """ + giftCardBulkActivate( + """List of gift card IDs to activate.""" + ids: [ID!]! + ): GiftCardBulkActivate + + """ + Deactivate gift cards. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_GIFT_CARD. + """ + giftCardBulkDeactivate( + """List of gift card IDs to deactivate.""" + ids: [ID!]! + ): GiftCardBulkDeactivate + + """ + Update plugin configuration. + + Requires one of the following permissions: MANAGE_PLUGINS. + """ + pluginUpdate( + """ID of a channel for which the data should be modified.""" + channelId: ID + + """ID of plugin to update.""" + id: ID! + + """Fields required to update a plugin configuration.""" + input: PluginUpdateInput! + ): PluginUpdate + + """ + Trigger sending a notification with the notify plugin method. Serializes nodes provided as ids parameter and includes this data in the notification payload. + + Added in Saleor 3.1. + """ + externalNotificationTrigger( + """ + Channel slug. Saleor will send a notification within a provided channel. Please, make sure that necessary plugins are active. + """ + channel: String! + + """Input for External Notification Trigger.""" + input: ExternalNotificationTriggerInput! + + """The ID of notification plugin.""" + pluginId: String + ): ExternalNotificationTrigger + + """ + Creates a new sale. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + saleCreate( + """Fields required to create a sale.""" + input: SaleInput! + ): SaleCreate + + """ + Deletes a sale. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + saleDelete( + """ID of a sale to delete.""" + id: ID! + ): SaleDelete + + """ + Deletes sales. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + saleBulkDelete( + """List of sale IDs to delete.""" + ids: [ID!]! + ): SaleBulkDelete + + """ + Updates a sale. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + saleUpdate( + """ID of a sale to update.""" + id: ID! + + """Fields required to update a sale.""" + input: SaleInput! + ): SaleUpdate + + """ + Adds products, categories, collections to a voucher. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + saleCataloguesAdd( + """ID of a sale.""" + id: ID! + + """Fields required to modify catalogue IDs of sale.""" + input: CatalogueInput! + ): SaleAddCatalogues + + """ + Removes products, categories, collections from a sale. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + saleCataloguesRemove( + """ID of a sale.""" + id: ID! + + """Fields required to modify catalogue IDs of sale.""" + input: CatalogueInput! + ): SaleRemoveCatalogues + + """ + Creates/updates translations for a sale. + + Requires one of the following permissions: MANAGE_TRANSLATIONS. + """ + saleTranslate( + """Sale ID or SaleTranslatableContent ID.""" + id: ID! + input: NameTranslationInput! + + """Translation language code.""" + languageCode: LanguageCodeEnum! + ): SaleTranslate + + """ + Manage sale's availability in channels. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + saleChannelListingUpdate( + """ID of a sale to update.""" + id: ID! + + """Fields required to update sale channel listings.""" + input: SaleChannelListingInput! + ): SaleChannelListingUpdate + + """ + Creates a new voucher. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + voucherCreate( + """Fields required to create a voucher.""" + input: VoucherInput! + ): VoucherCreate + + """ + Deletes a voucher. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + voucherDelete( + """ID of a voucher to delete.""" + id: ID! + ): VoucherDelete + + """ + Deletes vouchers. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + voucherBulkDelete( + """List of voucher IDs to delete.""" + ids: [ID!]! + ): VoucherBulkDelete + + """ + Updates a voucher. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + voucherUpdate( + """ID of a voucher to update.""" + id: ID! + + """Fields required to update a voucher.""" + input: VoucherInput! + ): VoucherUpdate + + """ + Adds products, categories, collections to a voucher. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + voucherCataloguesAdd( + """ID of a voucher.""" + id: ID! + + """Fields required to modify catalogue IDs of voucher.""" + input: CatalogueInput! + ): VoucherAddCatalogues + + """ + Removes products, categories, collections from a voucher. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + voucherCataloguesRemove( + """ID of a voucher.""" + id: ID! + + """Fields required to modify catalogue IDs of voucher.""" + input: CatalogueInput! + ): VoucherRemoveCatalogues + + """ + Creates/updates translations for a voucher. + + Requires one of the following permissions: MANAGE_TRANSLATIONS. + """ + voucherTranslate( + """Voucher ID or VoucherTranslatableContent ID.""" + id: ID! + input: NameTranslationInput! + + """Translation language code.""" + languageCode: LanguageCodeEnum! + ): VoucherTranslate + + """ + Manage voucher's availability in channels. + + Requires one of the following permissions: MANAGE_DISCOUNTS. + """ + voucherChannelListingUpdate( + """ID of a voucher to update.""" + id: ID! + + """Fields required to update voucher channel listings.""" + input: VoucherChannelListingInput! + ): VoucherChannelListingUpdate + + """ + Export products to csv file. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + exportProducts( + """Fields required to export product data.""" + input: ExportProductsInput! + ): ExportProducts + + """ + Export gift cards to csv file. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_GIFT_CARD. + """ + exportGiftCards( + """Fields required to export gift cards data.""" + input: ExportGiftCardsInput! + ): ExportGiftCards + + """ + Upload a file. This mutation must be sent as a `multipart` request. More detailed specs of the upload format can be found here: https://github.com/jaydenseric/graphql-multipart-request-spec + + Requires one of the following permissions: AUTHENTICATED_APP, AUTHENTICATED_STAFF_USER. + """ + fileUpload( + """Represents a file in a multipart request.""" + file: Upload! + ): FileUpload + + """Adds a gift card or a voucher to a checkout.""" + checkoutAddPromoCode( + """ + The ID of the checkout. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + checkoutId: ID + + """ + The checkout's ID. + + Added in Saleor 3.4. + """ + id: ID + + """Gift card code or voucher code.""" + promoCode: String! + + """ + Checkout token. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + token: UUID + ): CheckoutAddPromoCode + + """Update billing address in the existing checkout.""" + checkoutBillingAddressUpdate( + """The billing address of the checkout.""" + billingAddress: AddressInput! + + """ + The ID of the checkout. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + checkoutId: ID + + """ + The checkout's ID. + + Added in Saleor 3.4. + """ + id: ID + + """ + Checkout token. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + token: UUID + + """ + The rules for changing validation for received billing address data. + + Added in Saleor 3.5. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + validationRules: CheckoutAddressValidationRules + ): CheckoutBillingAddressUpdate + + """ + Completes the checkout. As a result a new order is created and a payment charge is made. This action requires a successful payment before it can be performed. In case additional confirmation step as 3D secure is required confirmationNeeded flag will be set to True and no order created until payment is confirmed with second call of this mutation. + """ + checkoutComplete( + """ + The ID of the checkout. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + checkoutId: ID + + """ + The checkout's ID. + + Added in Saleor 3.4. + """ + id: ID + + """ + Fields required to update the checkout metadata. + + Added in Saleor 3.8. + """ + metadata: [MetadataInput!] + + """Client-side generated data required to finalize the payment.""" + paymentData: JSONString + + """ + URL of a view where users should be redirected to see the order details. URL in RFC 1808 format. + """ + redirectUrl: String + + """ + Determines whether to store the payment source for future usage. + + DEPRECATED: this field will be removed in Saleor 4.0. Use checkoutPaymentCreate for this action. + """ + storeSource: Boolean = false + + """ + Checkout token. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + token: UUID + ): CheckoutComplete + + """Create a new checkout.""" + checkoutCreate( + """Fields required to create checkout.""" + input: CheckoutCreateInput! + ): CheckoutCreate + + """ + Sets the customer as the owner of the checkout. + + Requires one of the following permissions: AUTHENTICATED_APP, AUTHENTICATED_USER. + """ + checkoutCustomerAttach( + """ + The ID of the checkout. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + checkoutId: ID + + """ + ID of customer to attach to checkout. Requires IMPERSONATE_USER permission when customerId is different than the logged-in user. + """ + customerId: ID + + """ + The checkout's ID. + + Added in Saleor 3.4. + """ + id: ID + + """ + Checkout token. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + token: UUID + ): CheckoutCustomerAttach + + """ + Removes the user assigned as the owner of the checkout. + + Requires one of the following permissions: AUTHENTICATED_APP, AUTHENTICATED_USER. + """ + checkoutCustomerDetach( + """ + The ID of the checkout. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + checkoutId: ID + + """ + The checkout's ID. + + Added in Saleor 3.4. + """ + id: ID + + """ + Checkout token. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + token: UUID + ): CheckoutCustomerDetach + + """Updates email address in the existing checkout object.""" + checkoutEmailUpdate( + """ + The ID of the checkout. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + checkoutId: ID + + """email.""" + email: String! + + """ + The checkout's ID. + + Added in Saleor 3.4. + """ + id: ID + + """ + Checkout token. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + token: UUID + ): CheckoutEmailUpdate + + """Deletes a CheckoutLine.""" + checkoutLineDelete( + """ + The ID of the checkout. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + checkoutId: ID + + """ + The checkout's ID. + + Added in Saleor 3.4. + """ + id: ID + + """ID of the checkout line to delete.""" + lineId: ID + + """ + Checkout token. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + token: UUID + ): CheckoutLineDelete @deprecated(reason: "This field will be removed in Saleor 4.0. Use `checkoutLinesDelete` instead.") + + """Deletes checkout lines.""" + checkoutLinesDelete( + """ + The checkout's ID. + + Added in Saleor 3.4. + """ + id: ID + + """A list of checkout lines.""" + linesIds: [ID!]! + + """ + Checkout token. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + token: UUID + ): CheckoutLinesDelete + + """ + Adds a checkout line to the existing checkout.If line was already in checkout, its quantity will be increased. + """ + checkoutLinesAdd( + """ + The ID of the checkout. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + checkoutId: ID + + """ + The checkout's ID. + + Added in Saleor 3.4. + """ + id: ID + + """ + A list of checkout lines, each containing information about an item in the checkout. + """ + lines: [CheckoutLineInput!]! + + """ + Checkout token. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + token: UUID + ): CheckoutLinesAdd + + """Updates checkout line in the existing checkout.""" + checkoutLinesUpdate( + """ + The ID of the checkout. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + checkoutId: ID + + """ + The checkout's ID. + + Added in Saleor 3.4. + """ + id: ID + + """ + A list of checkout lines, each containing information about an item in the checkout. + """ + lines: [CheckoutLineUpdateInput!]! + + """ + Checkout token. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + token: UUID + ): CheckoutLinesUpdate + + """Remove a gift card or a voucher from a checkout.""" + checkoutRemovePromoCode( + """ + The ID of the checkout. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + checkoutId: ID + + """ + The checkout's ID. + + Added in Saleor 3.4. + """ + id: ID + + """Gift card code or voucher code.""" + promoCode: String + + """Gift card or voucher ID.""" + promoCodeId: ID + + """ + Checkout token. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + token: UUID + ): CheckoutRemovePromoCode + + """Create a new payment for given checkout.""" + checkoutPaymentCreate( + """ + The ID of the checkout. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + checkoutId: ID + + """ + The checkout's ID. + + Added in Saleor 3.4. + """ + id: ID + + """Data required to create a new payment.""" + input: PaymentInput! + + """ + Checkout token. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + token: UUID + ): CheckoutPaymentCreate + + """Update shipping address in the existing checkout.""" + checkoutShippingAddressUpdate( + """ + The ID of the checkout. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + checkoutId: ID + + """ + The checkout's ID. + + Added in Saleor 3.4. + """ + id: ID + + """The mailing address to where the checkout will be shipped.""" + shippingAddress: AddressInput! + + """ + Checkout token. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + token: UUID + + """ + The rules for changing validation for received shipping address data. + + Added in Saleor 3.5. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + validationRules: CheckoutAddressValidationRules + ): CheckoutShippingAddressUpdate + + """Updates the shipping method of the checkout.""" + checkoutShippingMethodUpdate( + """ + The ID of the checkout. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + checkoutId: ID + + """ + The checkout's ID. + + Added in Saleor 3.4. + """ + id: ID + + """Shipping method.""" + shippingMethodId: ID! + + """ + Checkout token. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + token: UUID + ): CheckoutShippingMethodUpdate @deprecated(reason: "This field will be removed in Saleor 4.0. Use `checkoutDeliveryMethodUpdate` instead.") + + """ + Updates the delivery method (shipping method or pick up point) of the checkout. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + checkoutDeliveryMethodUpdate( + """Delivery Method ID (`Warehouse` ID or `ShippingMethod` ID).""" + deliveryMethodId: ID + + """ + The checkout's ID. + + Added in Saleor 3.4. + """ + id: ID + + """ + Checkout token. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + token: UUID + ): CheckoutDeliveryMethodUpdate + + """Update language code in the existing checkout.""" + checkoutLanguageCodeUpdate( + """ + The ID of the checkout. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + checkoutId: ID + + """ + The checkout's ID. + + Added in Saleor 3.4. + """ + id: ID + + """New language code.""" + languageCode: LanguageCodeEnum! + + """ + Checkout token. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `id` instead. + """ + token: UUID + ): CheckoutLanguageCodeUpdate + + """ + Create new order from existing checkout. Requires the following permissions: AUTHENTICATED_APP and HANDLE_CHECKOUTS. + + Added in Saleor 3.2. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + orderCreateFromCheckout( + """ID of a checkout that will be converted to an order.""" + id: ID! + + """ + Fields required to update the checkout metadata. + + Added in Saleor 3.8. + """ + metadata: [MetadataInput!] + + """ + Fields required to update the checkout private metadata. + + Added in Saleor 3.8. + """ + privateMetadata: [MetadataInput!] + + """ + Determines if checkout should be removed after creating an order. Default true. + """ + removeCheckout: Boolean = true + ): OrderCreateFromCheckout + + """ + Creates new channel. + + Requires one of the following permissions: MANAGE_CHANNELS. + """ + channelCreate( + """Fields required to create channel.""" + input: ChannelCreateInput! + ): ChannelCreate + + """ + Update a channel. + + Requires one of the following permissions: MANAGE_CHANNELS. + Requires one of the following permissions when updating only orderSettings field: MANAGE_CHANNELS, MANAGE_ORDERS. + """ + channelUpdate( + """ID of a channel to update.""" + id: ID! + + """Fields required to update a channel.""" + input: ChannelUpdateInput! + ): ChannelUpdate + + """ + Delete a channel. Orders associated with the deleted channel will be moved to the target channel. Checkouts, product availability, and pricing will be removed. + + Requires one of the following permissions: MANAGE_CHANNELS. + """ + channelDelete( + """ID of a channel to delete.""" + id: ID! + + """Fields required to delete a channel.""" + input: ChannelDeleteInput + ): ChannelDelete + + """ + Activate a channel. + + Requires one of the following permissions: MANAGE_CHANNELS. + """ + channelActivate( + """ID of the channel to activate.""" + id: ID! + ): ChannelActivate + + """ + Deactivate a channel. + + Requires one of the following permissions: MANAGE_CHANNELS. + """ + channelDeactivate( + """ID of the channel to deactivate.""" + id: ID! + ): ChannelDeactivate + + """ + Reorder the warehouses of a channel. + + Added in Saleor 3.7. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + + Requires one of the following permissions: MANAGE_CHANNELS. + """ + channelReorderWarehouses( + """ID of a channel.""" + channelId: ID! + + """The list of reordering operations for the given channel warehouses.""" + moves: [ReorderInput!]! + ): ChannelReorderWarehouses + + """Creates an attribute.""" + attributeCreate( + """Fields required to create an attribute.""" + input: AttributeCreateInput! + ): AttributeCreate + + """ + Deletes an attribute. + + Requires one of the following permissions: MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. + """ + attributeDelete( + """ + External ID of an attribute to delete. + + Added in Saleor 3.10. + """ + externalReference: String + + """ID of an attribute to delete.""" + id: ID + ): AttributeDelete + + """ + Updates attribute. + + Requires one of the following permissions: MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. + """ + attributeUpdate( + """ + External ID of an attribute to update. + + Added in Saleor 3.10. + """ + externalReference: String + + """ID of an attribute to update.""" + id: ID + + """Fields required to update an attribute.""" + input: AttributeUpdateInput! + ): AttributeUpdate + + """ + Creates/updates translations for an attribute. + + Requires one of the following permissions: MANAGE_TRANSLATIONS. + """ + attributeTranslate( + """Attribute ID or AttributeTranslatableContent ID.""" + id: ID! + input: NameTranslationInput! + + """Translation language code.""" + languageCode: LanguageCodeEnum! + ): AttributeTranslate + + """ + Deletes attributes. + + Requires one of the following permissions: MANAGE_PAGE_TYPES_AND_ATTRIBUTES. + """ + attributeBulkDelete( + """List of attribute IDs to delete.""" + ids: [ID!]! + ): AttributeBulkDelete + + """ + Deletes values of attributes. + + Requires one of the following permissions: MANAGE_PAGE_TYPES_AND_ATTRIBUTES. + """ + attributeValueBulkDelete( + """List of attribute value IDs to delete.""" + ids: [ID!]! + ): AttributeValueBulkDelete + + """ + Creates a value for an attribute. + + Requires one of the following permissions: MANAGE_PRODUCTS. + """ + attributeValueCreate( + """Attribute to which value will be assigned.""" + attribute: ID! + + """Fields required to create an AttributeValue.""" + input: AttributeValueCreateInput! + ): AttributeValueCreate + + """ + Deletes a value of an attribute. + + Requires one of the following permissions: MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. + """ + attributeValueDelete( + """ + External ID of a value to delete. + + Added in Saleor 3.10. + """ + externalReference: String + + """ID of a value to delete.""" + id: ID + ): AttributeValueDelete + + """ + Updates value of an attribute. + + Requires one of the following permissions: MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. + """ + attributeValueUpdate( + """ + External ID of an AttributeValue to update. + + Added in Saleor 3.10. + """ + externalReference: String + + """ID of an AttributeValue to update.""" + id: ID + + """Fields required to update an AttributeValue.""" + input: AttributeValueUpdateInput! + ): AttributeValueUpdate + + """ + Creates/updates translations for an attribute value. + + Requires one of the following permissions: MANAGE_TRANSLATIONS. + """ + attributeValueTranslate( + """AttributeValue ID or AttributeValueTranslatableContent ID.""" + id: ID! + input: AttributeValueTranslationInput! + + """Translation language code.""" + languageCode: LanguageCodeEnum! + ): AttributeValueTranslate + + """ + Reorder the values of an attribute. + + Requires one of the following permissions: MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. + """ + attributeReorderValues( + """ID of an attribute.""" + attributeId: ID! + + """The list of reordering operations for given attribute values.""" + moves: [ReorderInput!]! + ): AttributeReorderValues + + """ + Creates a new app. Requires the following permissions: AUTHENTICATED_STAFF_USER and MANAGE_APPS. + """ + appCreate( + """Fields required to create a new app.""" + input: AppInput! + ): AppCreate + + """ + Updates an existing app. + + Requires one of the following permissions: MANAGE_APPS. + """ + appUpdate( + """ID of an app to update.""" + id: ID! + + """Fields required to update an existing app.""" + input: AppInput! + ): AppUpdate + + """ + Deletes an app. + + Requires one of the following permissions: MANAGE_APPS. + """ + appDelete( + """ID of an app to delete.""" + id: ID! + ): AppDelete + + """ + Creates a new token. + + Requires one of the following permissions: MANAGE_APPS. + """ + appTokenCreate( + """Fields required to create a new auth token.""" + input: AppTokenInput! + ): AppTokenCreate + + """ + Deletes an authentication token assigned to app. + + Requires one of the following permissions: MANAGE_APPS. + """ + appTokenDelete( + """ID of an auth token to delete.""" + id: ID! + ): AppTokenDelete + + """Verify provided app token.""" + appTokenVerify( + """App token to verify.""" + token: String! + ): AppTokenVerify + + """ + Install new app by using app manifest. Requires the following permissions: AUTHENTICATED_STAFF_USER and MANAGE_APPS. + """ + appInstall( + """Fields required to install a new app.""" + input: AppInstallInput! + ): AppInstall + + """ + Retry failed installation of new app. + + Requires one of the following permissions: MANAGE_APPS. + """ + appRetryInstall( + """Determine if app will be set active or not.""" + activateAfterInstallation: Boolean = true + + """ID of failed installation.""" + id: ID! + ): AppRetryInstall + + """ + Delete failed installation. + + Requires one of the following permissions: MANAGE_APPS. + """ + appDeleteFailedInstallation( + """ID of failed installation to delete.""" + id: ID! + ): AppDeleteFailedInstallation + + """ + Fetch and validate manifest. + + Requires one of the following permissions: MANAGE_APPS. + """ + appFetchManifest(manifestUrl: String!): AppFetchManifest + + """ + Activate the app. + + Requires one of the following permissions: MANAGE_APPS. + """ + appActivate( + """ID of app to activate.""" + id: ID! + ): AppActivate + + """ + Deactivate the app. + + Requires one of the following permissions: MANAGE_APPS. + """ + appDeactivate( + """ID of app to deactivate.""" + id: ID! + ): AppDeactivate + + """Create JWT token.""" + tokenCreate( + """ + The audience that will be included to JWT tokens with prefix `custom:`. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + audience: String + + """Email of a user.""" + email: String! + + """Password of a user.""" + password: String! + ): CreateToken + + """ + Refresh JWT token. Mutation tries to take refreshToken from the input.If it fails it will try to take refreshToken from the http-only cookie -refreshToken. csrfToken is required when refreshToken is provided as a cookie. + """ + tokenRefresh( + """ + CSRF token required to refresh token. This argument is required when refreshToken is provided as a cookie. + """ + csrfToken: String + + """Refresh token.""" + refreshToken: String + ): RefreshToken + + """Verify JWT token.""" + tokenVerify( + """JWT token to validate.""" + token: String! + ): VerifyToken + + """ + Deactivate all JWT tokens of the currently authenticated user. + + Requires one of the following permissions: AUTHENTICATED_USER. + """ + tokensDeactivateAll: DeactivateAllUserTokens + + """Prepare external authentication url for user by custom plugin.""" + externalAuthenticationUrl( + """The data required by plugin to create external authentication url.""" + input: JSONString! + + """The ID of the authentication plugin.""" + pluginId: String! + ): ExternalAuthenticationUrl + + """Obtain external access tokens for user by custom plugin.""" + externalObtainAccessTokens( + """The data required by plugin to create authentication data.""" + input: JSONString! + + """The ID of the authentication plugin.""" + pluginId: String! + ): ExternalObtainAccessTokens + + """Refresh user's access by custom plugin.""" + externalRefresh( + """The data required by plugin to proceed the refresh process.""" + input: JSONString! + + """The ID of the authentication plugin.""" + pluginId: String! + ): ExternalRefresh + + """Logout user by custom plugin.""" + externalLogout( + """The data required by plugin to proceed the logout process.""" + input: JSONString! + + """The ID of the authentication plugin.""" + pluginId: String! + ): ExternalLogout + + """Verify external authentication data by plugin.""" + externalVerify( + """The data required by plugin to proceed the verification.""" + input: JSONString! + + """The ID of the authentication plugin.""" + pluginId: String! + ): ExternalVerify + + """Sends an email with the account password modification link.""" + requestPasswordReset( + """ + Slug of a channel which will be used for notify user. Optional when only one channel exists. + """ + channel: String + + """Email of the user that will be used for password recovery.""" + email: String! + + """ + URL of a view where users should be redirected to reset the password. URL in RFC 1808 format. + """ + redirectUrl: String! + ): RequestPasswordReset + + """Confirm user account with token sent by email during registration.""" + confirmAccount( + """E-mail of the user performing account confirmation.""" + email: String! + + """A one-time token required to confirm the account.""" + token: String! + ): ConfirmAccount + + """ + Sets the user's password from the token sent by email using the RequestPasswordReset mutation. + """ + setPassword( + """Email of a user.""" + email: String! + + """Password of a user.""" + password: String! + + """A one-time token required to set the password.""" + token: String! + ): SetPassword + + """ + Change the password of the logged in user. + + Requires one of the following permissions: AUTHENTICATED_USER. + """ + passwordChange( + """New user password.""" + newPassword: String! + + """Current user password.""" + oldPassword: String + ): PasswordChange + + """ + Request email change of the logged in user. + + Requires one of the following permissions: AUTHENTICATED_USER. + """ + requestEmailChange( + """ + Slug of a channel which will be used to notify users. Optional when only one channel exists. + """ + channel: String + + """New user email.""" + newEmail: String! + + """User password.""" + password: String! + + """ + URL of a view where users should be redirected to update the email address. URL in RFC 1808 format. + """ + redirectUrl: String! + ): RequestEmailChange + + """ + Confirm the email change of the logged-in user. + + Requires one of the following permissions: AUTHENTICATED_USER. + """ + confirmEmailChange( + """ + Slug of a channel which will be used to notify users. Optional when only one channel exists. + """ + channel: String + + """A one-time token required to change the email.""" + token: String! + ): ConfirmEmailChange + + """ + Create a new address for the customer. + + Requires one of the following permissions: AUTHENTICATED_USER. + """ + accountAddressCreate( + """Fields required to create address.""" + input: AddressInput! + + """ + A type of address. If provided, the new address will be automatically assigned as the customer's default address of that type. + """ + type: AddressTypeEnum + ): AccountAddressCreate + + """ + Updates an address of the logged-in user. Requires one of the following permissions: MANAGE_USERS, IS_OWNER. + """ + accountAddressUpdate( + """ID of the address to update.""" + id: ID! + + """Fields required to update the address.""" + input: AddressInput! + ): AccountAddressUpdate + + """ + Delete an address of the logged-in user. Requires one of the following permissions: MANAGE_USERS, IS_OWNER. + """ + accountAddressDelete( + """ID of the address to delete.""" + id: ID! + ): AccountAddressDelete + + """ + Sets a default address for the authenticated user. + + Requires one of the following permissions: AUTHENTICATED_USER. + """ + accountSetDefaultAddress( + """ID of the address to set as default.""" + id: ID! + + """The type of address.""" + type: AddressTypeEnum! + ): AccountSetDefaultAddress + + """Register a new user.""" + accountRegister( + """Fields required to create a user.""" + input: AccountRegisterInput! + ): AccountRegister + + """ + Updates the account of the logged-in user. + + Requires one of the following permissions: AUTHENTICATED_USER. + """ + accountUpdate( + """Fields required to update the account of the logged-in user.""" + input: AccountInput! + ): AccountUpdate + + """ + Sends an email with the account removal link for the logged-in user. + + Requires one of the following permissions: AUTHENTICATED_USER. + """ + accountRequestDeletion( + """ + Slug of a channel which will be used to notify users. Optional when only one channel exists. + """ + channel: String + + """ + URL of a view where users should be redirected to delete their account. URL in RFC 1808 format. + """ + redirectUrl: String! + ): AccountRequestDeletion + + """ + Remove user account. + + Requires one of the following permissions: AUTHENTICATED_USER. + """ + accountDelete( + """ + A one-time token required to remove account. Sent by email using AccountRequestDeletion mutation. + """ + token: String! + ): AccountDelete + + """ + Creates user address. + + Requires one of the following permissions: MANAGE_USERS. + """ + addressCreate( + """Fields required to create address.""" + input: AddressInput! + + """ID of a user to create address for.""" + userId: ID! + ): AddressCreate + + """ + Updates an address. + + Requires one of the following permissions: MANAGE_USERS. + """ + addressUpdate( + """ID of the address to update.""" + id: ID! + + """Fields required to update the address.""" + input: AddressInput! + ): AddressUpdate + + """ + Deletes an address. + + Requires one of the following permissions: MANAGE_USERS. + """ + addressDelete( + """ID of the address to delete.""" + id: ID! + ): AddressDelete + + """ + Sets a default address for the given user. + + Requires one of the following permissions: MANAGE_USERS. + """ + addressSetDefault( + """ID of the address.""" + addressId: ID! + + """The type of address.""" + type: AddressTypeEnum! + + """ID of the user to change the address for.""" + userId: ID! + ): AddressSetDefault + + """ + Creates a new customer. + + Requires one of the following permissions: MANAGE_USERS. + """ + customerCreate( + """Fields required to create a customer.""" + input: UserCreateInput! + ): CustomerCreate + + """ + Updates an existing customer. + + Requires one of the following permissions: MANAGE_USERS. + """ + customerUpdate( + """ + External ID of a customer to update. + + Added in Saleor 3.10. + """ + externalReference: String + + """ID of a customer to update.""" + id: ID + + """Fields required to update a customer.""" + input: CustomerInput! + ): CustomerUpdate + + """ + Deletes a customer. + + Requires one of the following permissions: MANAGE_USERS. + """ + customerDelete( + """ + External ID of a customer to update. + + Added in Saleor 3.10. + """ + externalReference: String + + """ID of a customer to delete.""" + id: ID + ): CustomerDelete + + """ + Deletes customers. + + Requires one of the following permissions: MANAGE_USERS. + """ + customerBulkDelete( + """List of user IDs to delete.""" + ids: [ID!]! + ): CustomerBulkDelete + + """ + Creates a new staff user. Apps are not allowed to perform this mutation. + + Requires one of the following permissions: MANAGE_STAFF. + """ + staffCreate( + """Fields required to create a staff user.""" + input: StaffCreateInput! + ): StaffCreate + + """ + Updates an existing staff user. Apps are not allowed to perform this mutation. + + Requires one of the following permissions: MANAGE_STAFF. + """ + staffUpdate( + """ID of a staff user to update.""" + id: ID! + + """Fields required to update a staff user.""" + input: StaffUpdateInput! + ): StaffUpdate + + """ + Deletes a staff user. Apps are not allowed to perform this mutation. + + Requires one of the following permissions: MANAGE_STAFF. + """ + staffDelete( + """ID of a staff user to delete.""" + id: ID! + ): StaffDelete + + """ + Deletes staff users. Apps are not allowed to perform this mutation. + + Requires one of the following permissions: MANAGE_STAFF. + """ + staffBulkDelete( + """List of user IDs to delete.""" + ids: [ID!]! + ): StaffBulkDelete + + """ + Create a user avatar. Only for staff members. This mutation must be sent as a `multipart` request. More detailed specs of the upload format can be found here: https://github.com/jaydenseric/graphql-multipart-request-spec + + Requires one of the following permissions: AUTHENTICATED_STAFF_USER. + """ + userAvatarUpdate( + """Represents an image file in a multipart request.""" + image: Upload! + ): UserAvatarUpdate + + """ + Deletes a user avatar. Only for staff members. + + Requires one of the following permissions: AUTHENTICATED_STAFF_USER. + """ + userAvatarDelete: UserAvatarDelete + + """ + Activate or deactivate users. + + Requires one of the following permissions: MANAGE_USERS. + """ + userBulkSetActive( + """List of user IDs to (de)activate).""" + ids: [ID!]! + + """Determine if users will be set active or not.""" + isActive: Boolean! + ): UserBulkSetActive + + """ + Create new permission group. Apps are not allowed to perform this mutation. + + Requires one of the following permissions: MANAGE_STAFF. + """ + permissionGroupCreate( + """Input fields to create permission group.""" + input: PermissionGroupCreateInput! + ): PermissionGroupCreate + + """ + Update permission group. Apps are not allowed to perform this mutation. + + Requires one of the following permissions: MANAGE_STAFF. + """ + permissionGroupUpdate( + """ID of the group to update.""" + id: ID! + + """Input fields to create permission group.""" + input: PermissionGroupUpdateInput! + ): PermissionGroupUpdate + + """ + Delete permission group. Apps are not allowed to perform this mutation. + + Requires one of the following permissions: MANAGE_STAFF. + """ + permissionGroupDelete( + """ID of the group to delete.""" + id: ID! + ): PermissionGroupDelete +} + +""" +Creates a new webhook subscription. + +Requires one of the following permissions: MANAGE_APPS, AUTHENTICATED_APP. +""" +type WebhookCreate { + webhookErrors: [WebhookError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [WebhookError!]! + webhook: Webhook +} + +type WebhookError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: WebhookErrorCode! +} + +"""An enumeration.""" +enum WebhookErrorCode { + GRAPHQL_ERROR + INVALID + NOT_FOUND + REQUIRED + UNIQUE + DELETE_FAILED + SYNTAX + MISSING_SUBSCRIPTION + UNABLE_TO_PARSE + MISSING_EVENT + INVALID_CUSTOM_HEADERS +} + +input WebhookCreateInput { + """The name of the webhook.""" + name: String + + """The url to receive the payload.""" + targetUrl: String + + """ + The events that webhook wants to subscribe. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `asyncEvents` or `syncEvents` instead. + """ + events: [WebhookEventTypeEnum!] + + """The asynchronous events that webhook wants to subscribe.""" + asyncEvents: [WebhookEventTypeAsyncEnum!] + + """The synchronous events that webhook wants to subscribe.""" + syncEvents: [WebhookEventTypeSyncEnum!] + + """ID of the app to which webhook belongs.""" + app: ID + + """Determine if webhook will be set active or not.""" + isActive: Boolean + + """ + The secret key used to create a hash signature with each payload. + + DEPRECATED: this field will be removed in Saleor 4.0. As of Saleor 3.5, webhook payloads default to signing using a verifiable JWS. + """ + secretKey: String + + """ + Subscription query used to define a webhook payload. + + Added in Saleor 3.2. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + query: String + + """ + Custom headers, which will be added to HTTP request. There is a limitation of 5 headers per webhook and 998 characters per header.Only "X-*" and "Authorization*" keys are allowed. + + Added in Saleor 3.12. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + customHeaders: JSONString +} + +""" +Delete a webhook. Before the deletion, the webhook is deactivated to pause any deliveries that are already scheduled. The deletion might fail if delivery is in progress. In such a case, the webhook is not deleted but remains deactivated. + +Requires one of the following permissions: MANAGE_APPS, AUTHENTICATED_APP. +""" +type WebhookDelete { + webhookErrors: [WebhookError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [WebhookError!]! + webhook: Webhook +} + +""" +Updates a webhook subscription. + +Requires one of the following permissions: MANAGE_APPS. +""" +type WebhookUpdate { + webhookErrors: [WebhookError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [WebhookError!]! + webhook: Webhook +} + +input WebhookUpdateInput { + """The new name of the webhook.""" + name: String + + """The url to receive the payload.""" + targetUrl: String + + """ + The events that webhook wants to subscribe. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `asyncEvents` or `syncEvents` instead. + """ + events: [WebhookEventTypeEnum!] + + """The asynchronous events that webhook wants to subscribe.""" + asyncEvents: [WebhookEventTypeAsyncEnum!] + + """The synchronous events that webhook wants to subscribe.""" + syncEvents: [WebhookEventTypeSyncEnum!] + + """ID of the app to which webhook belongs.""" + app: ID + + """Determine if webhook will be set active or not.""" + isActive: Boolean + + """ + Use to create a hash signature with each payload. + + DEPRECATED: this field will be removed in Saleor 4.0. As of Saleor 3.5, webhook payloads default to signing using a verifiable JWS. + """ + secretKey: String + + """ + Subscription query used to define a webhook payload. + + Added in Saleor 3.2. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + query: String + + """ + Custom headers, which will be added to HTTP request. There is a limitation of 5 headers per webhook and 998 characters per header.Only "X-*" and "Authorization*" keys are allowed. + + Added in Saleor 3.12. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + customHeaders: JSONString +} + +""" +Retries event delivery. + +Requires one of the following permissions: MANAGE_APPS. +""" +type EventDeliveryRetry { + """Event delivery.""" + delivery: EventDelivery + errors: [WebhookError!]! +} + +""" +Performs a dry run of a webhook event. Supports a single event (the first, if multiple provided in the `query`). Requires permission relevant to processed event. + +Added in Saleor 3.11. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires one of the following permissions: AUTHENTICATED_STAFF_USER. +""" +type WebhookDryRun { + """JSON payload, that would be sent out to webhook's target URL.""" + payload: JSONString + errors: [WebhookDryRunError!]! +} + +type WebhookDryRunError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: WebhookDryRunErrorCode! +} + +"""An enumeration.""" +enum WebhookDryRunErrorCode { + GRAPHQL_ERROR + NOT_FOUND + INVALID_ID + MISSING_PERMISSION + TYPE_NOT_SUPPORTED + SYNTAX + MISSING_SUBSCRIPTION + UNABLE_TO_PARSE + MISSING_EVENT +} + +""" +Trigger a webhook event. Supports a single event (the first, if multiple provided in the `webhook.subscription_query`). Requires permission relevant to processed event. Successfully delivered webhook returns `delivery` with status='PENDING' and empty payload. + +Added in Saleor 3.11. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires one of the following permissions: AUTHENTICATED_STAFF_USER. +""" +type WebhookTrigger { + delivery: EventDelivery + errors: [WebhookTriggerError!]! +} + +type WebhookTriggerError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: WebhookTriggerErrorCode! +} + +"""An enumeration.""" +enum WebhookTriggerErrorCode { + GRAPHQL_ERROR + NOT_FOUND + INVALID_ID + MISSING_PERMISSION + TYPE_NOT_SUPPORTED + SYNTAX + MISSING_SUBSCRIPTION + UNABLE_TO_PARSE + MISSING_QUERY + MISSING_EVENT +} + +""" +Creates new warehouse. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type WarehouseCreate { + warehouseErrors: [WarehouseError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [WarehouseError!]! + warehouse: Warehouse +} + +type WarehouseError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: WarehouseErrorCode! + + """List of shipping zones IDs which causes the error.""" + shippingZones: [ID!] +} + +"""An enumeration.""" +enum WarehouseErrorCode { + ALREADY_EXISTS + GRAPHQL_ERROR + INVALID + NOT_FOUND + REQUIRED + UNIQUE +} + +input WarehouseCreateInput { + """Warehouse slug.""" + slug: String + + """The email address of the warehouse.""" + email: String + + """ + External ID of the warehouse. + + Added in Saleor 3.10. + """ + externalReference: String + + """Warehouse name.""" + name: String! + + """Address of the warehouse.""" + address: AddressInput! + + """ + Shipping zones supported by the warehouse. + + DEPRECATED: this field will be removed in Saleor 4.0. Providing the zone ids will raise a ValidationError. + """ + shippingZones: [ID!] +} + +""" +Updates given warehouse. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type WarehouseUpdate { + warehouseErrors: [WarehouseError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [WarehouseError!]! + warehouse: Warehouse +} + +input WarehouseUpdateInput { + """Warehouse slug.""" + slug: String + + """The email address of the warehouse.""" + email: String + + """ + External ID of the warehouse. + + Added in Saleor 3.10. + """ + externalReference: String + + """Warehouse name.""" + name: String + + """Address of the warehouse.""" + address: AddressInput + + """ + Click and collect options: local, all or disabled. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + clickAndCollectOption: WarehouseClickAndCollectOptionEnum + + """ + Visibility of warehouse stocks. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + isPrivate: Boolean +} + +""" +Deletes selected warehouse. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type WarehouseDelete { + warehouseErrors: [WarehouseError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [WarehouseError!]! + warehouse: Warehouse +} + +""" +Add shipping zone to given warehouse. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type WarehouseShippingZoneAssign { + warehouseErrors: [WarehouseError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [WarehouseError!]! + warehouse: Warehouse +} + +""" +Remove shipping zone from given warehouse. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type WarehouseShippingZoneUnassign { + warehouseErrors: [WarehouseError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [WarehouseError!]! + warehouse: Warehouse +} + +""" +Create a tax class. + +Added in Saleor 3.9. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires one of the following permissions: MANAGE_TAXES. +""" +type TaxClassCreate { + errors: [TaxClassCreateError!]! + taxClass: TaxClass +} + +type TaxClassCreateError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: TaxClassCreateErrorCode! + + """List of country codes for which the configuration is invalid.""" + countryCodes: [String!]! +} + +"""An enumeration.""" +enum TaxClassCreateErrorCode { + GRAPHQL_ERROR + INVALID + NOT_FOUND +} + +input TaxClassCreateInput { + """Name of the tax class.""" + name: String! + + """List of country-specific tax rates to create for this tax class.""" + createCountryRates: [CountryRateInput!] +} + +input CountryRateInput { + """Country in which this rate applies.""" + countryCode: CountryCode! + + """ + Tax rate value provided as percentage. Example: provide `23` to represent `23%` tax rate. + """ + rate: Float! +} + +""" +Delete a tax class. After deleting the tax class any products, product types or shipping methods using it are updated to use the default tax class. + +Added in Saleor 3.9. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires one of the following permissions: MANAGE_TAXES. +""" +type TaxClassDelete { + errors: [TaxClassDeleteError!]! + taxClass: TaxClass +} + +type TaxClassDeleteError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: TaxClassDeleteErrorCode! +} + +"""An enumeration.""" +enum TaxClassDeleteErrorCode { + GRAPHQL_ERROR + INVALID + NOT_FOUND +} + +""" +Update a tax class. + +Added in Saleor 3.9. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires one of the following permissions: MANAGE_TAXES. +""" +type TaxClassUpdate { + errors: [TaxClassUpdateError!]! + taxClass: TaxClass +} + +type TaxClassUpdateError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: TaxClassUpdateErrorCode! + + """List of country codes for which the configuration is invalid.""" + countryCodes: [String!]! +} + +"""An enumeration.""" +enum TaxClassUpdateErrorCode { + DUPLICATED_INPUT_ITEM + GRAPHQL_ERROR + INVALID + NOT_FOUND +} + +input TaxClassUpdateInput { + """Name of the tax class.""" + name: String + + """ + List of country-specific tax rates to create or update for this tax class. + """ + updateCountryRates: [CountryRateUpdateInput!] + + """ + List of country codes for which to remove the tax class rates. Note: It removes all rates for given country code. + """ + removeCountryRates: [CountryCode!] +} + +input CountryRateUpdateInput { + """Country in which this rate applies.""" + countryCode: CountryCode! + + """ + Tax rate value provided as percentage. Example: provide `23` to represent `23%` tax rate. Provide `null` to remove the particular rate. + """ + rate: Float +} + +""" +Update tax configuration for a channel. + +Added in Saleor 3.9. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires one of the following permissions: MANAGE_TAXES. +""" +type TaxConfigurationUpdate { + errors: [TaxConfigurationUpdateError!]! + taxConfiguration: TaxConfiguration +} + +type TaxConfigurationUpdateError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: TaxConfigurationUpdateErrorCode! + + """List of country codes for which the configuration is invalid.""" + countryCodes: [String!]! +} + +"""An enumeration.""" +enum TaxConfigurationUpdateErrorCode { + DUPLICATED_INPUT_ITEM + GRAPHQL_ERROR + INVALID + NOT_FOUND +} + +input TaxConfigurationUpdateInput { + """Determines whether taxes are charged in the given channel.""" + chargeTaxes: Boolean + + """ + The default strategy to use for tax calculation in the given channel. Taxes can be calculated either using user-defined flat rates or with a tax app. Empty value means that no method is selected and taxes are not calculated. + """ + taxCalculationStrategy: TaxCalculationStrategy + + """ + Determines whether prices displayed in a storefront should include taxes. + """ + displayGrossPrices: Boolean + + """Determines whether prices are entered with the tax included.""" + pricesEnteredWithTax: Boolean + + """ + List of tax country configurations to create or update (identified by a country code). + """ + updateCountriesConfiguration: [TaxConfigurationPerCountryInput!] + + """List of country codes for which to remove the tax configuration.""" + removeCountriesConfiguration: [CountryCode!] +} + +input TaxConfigurationPerCountryInput { + """Country in which this configuration applies.""" + countryCode: CountryCode! + + """Determines whether taxes are charged in this country.""" + chargeTaxes: Boolean! + + """ + A country-specific strategy to use for tax calculation. Taxes can be calculated either using user-defined flat rates or with a tax app. If not provided, use the value from the channel's tax configuration. + """ + taxCalculationStrategy: TaxCalculationStrategy + + """ + Determines whether prices displayed in a storefront should include taxes for this country. + """ + displayGrossPrices: Boolean! +} + +""" +Update tax class rates for a specific country. + +Added in Saleor 3.9. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires one of the following permissions: MANAGE_TAXES. +""" +type TaxCountryConfigurationUpdate { + """Updated tax class rates grouped by a country.""" + taxCountryConfiguration: TaxCountryConfiguration + errors: [TaxCountryConfigurationUpdateError!]! +} + +type TaxCountryConfigurationUpdateError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: TaxCountryConfigurationUpdateErrorCode! + + """List of tax class IDs for which the update failed.""" + taxClassIds: [String!]! +} + +"""An enumeration.""" +enum TaxCountryConfigurationUpdateErrorCode { + GRAPHQL_ERROR + INVALID + NOT_FOUND + ONLY_ONE_DEFAULT_COUNTRY_RATE_ALLOWED + CANNOT_CREATE_NEGATIVE_RATE +} + +input TaxClassRateInput { + """ID of a tax class for which to update the tax rate""" + taxClassId: ID + + """Tax rate value.""" + rate: Float +} + +""" +Remove all tax class rates for a specific country. + +Added in Saleor 3.9. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires one of the following permissions: MANAGE_TAXES. +""" +type TaxCountryConfigurationDelete { + """Updated tax class rates grouped by a country.""" + taxCountryConfiguration: TaxCountryConfiguration + errors: [TaxCountryConfigurationDeleteError!]! +} + +type TaxCountryConfigurationDeleteError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: TaxCountryConfigurationDeleteErrorCode! +} + +"""An enumeration.""" +enum TaxCountryConfigurationDeleteErrorCode { + GRAPHQL_ERROR + INVALID + NOT_FOUND +} + +""" +Exempt checkout or order from charging the taxes. When tax exemption is enabled, taxes won't be charged for the checkout or order. Taxes may still be calculated in cases when product prices are entered with the tax included and the net price needs to be known. + +Added in Saleor 3.8. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires one of the following permissions: MANAGE_TAXES. +""" +type TaxExemptionManage { + taxableObject: TaxSourceObject + errors: [TaxExemptionManageError!]! +} + +union TaxSourceObject = Checkout | Order + +type TaxExemptionManageError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: TaxExemptionManageErrorCode! +} + +"""An enumeration.""" +enum TaxExemptionManageErrorCode { + GRAPHQL_ERROR + INVALID + NOT_FOUND + NOT_EDITABLE_ORDER +} + +""" +Updates stocks for a given variant and warehouse. + +Added in Saleor 3.13. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type StockBulkUpdate { + """Returns how many objects were updated.""" + count: Int! + + """List of the updated stocks.""" + results: [StockBulkResult!]! + errors: [StockBulkUpdateError!]! +} + +type StockBulkResult { + """Stock data.""" + stock: Stock + + """List of errors occurred on create or update attempt.""" + errors: [StockBulkUpdateError!] +} + +type StockBulkUpdateError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: StockBulkUpdateErrorCode! +} + +"""An enumeration.""" +enum StockBulkUpdateErrorCode { + GRAPHQL_ERROR + INVALID + NOT_FOUND + REQUIRED +} + +enum ErrorPolicyEnum { + """ + Save what is possible within a single row. If there are errors in an input data row, try to save it partially and skip the invalid part. + """ + IGNORE_FAILED + + """Reject all rows if there is at least one error in any of them.""" + REJECT_EVERYTHING + + """Reject rows with errors.""" + REJECT_FAILED_ROWS +} + +input StockBulkUpdateInput { + """Variant ID.""" + variantId: ID + + """Variant external reference.""" + variantExternalReference: String + + """Warehouse ID.""" + warehouseId: ID + + """Warehouse external reference.""" + warehouseExternalReference: String + + """Quantity of items available for sell.""" + quantity: Int! +} + +""" +Creates a new staff notification recipient. + +Requires one of the following permissions: MANAGE_SETTINGS. +""" +type StaffNotificationRecipientCreate { + shopErrors: [ShopError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ShopError!]! + staffNotificationRecipient: StaffNotificationRecipient +} + +type ShopError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: ShopErrorCode! +} + +"""An enumeration.""" +enum ShopErrorCode { + ALREADY_EXISTS + CANNOT_FETCH_TAX_RATES + GRAPHQL_ERROR + INVALID + NOT_FOUND + REQUIRED + UNIQUE +} + +input StaffNotificationRecipientInput { + """The ID of the user subscribed to email notifications..""" + user: ID + + """Email address of a user subscribed to email notifications.""" + email: String + + """Determines if a notification active.""" + active: Boolean +} + +""" +Updates a staff notification recipient. + +Requires one of the following permissions: MANAGE_SETTINGS. +""" +type StaffNotificationRecipientUpdate { + shopErrors: [ShopError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ShopError!]! + staffNotificationRecipient: StaffNotificationRecipient +} + +""" +Delete staff notification recipient. + +Requires one of the following permissions: MANAGE_SETTINGS. +""" +type StaffNotificationRecipientDelete { + shopErrors: [ShopError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ShopError!]! + staffNotificationRecipient: StaffNotificationRecipient +} + +""" +Updates site domain of the shop. + +Requires one of the following permissions: MANAGE_SETTINGS. +""" +type ShopDomainUpdate { + """Updated shop.""" + shop: Shop + shopErrors: [ShopError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ShopError!]! +} + +input SiteDomainInput { + """Domain name for shop.""" + domain: String + + """Shop site name.""" + name: String +} + +""" +Updates shop settings. + +Requires one of the following permissions: MANAGE_SETTINGS. +""" +type ShopSettingsUpdate { + """Updated shop.""" + shop: Shop + shopErrors: [ShopError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ShopError!]! +} + +input ShopSettingsInput { + """Header text.""" + headerText: String + + """SEO description.""" + description: String + + """Enable inventory tracking.""" + trackInventoryByDefault: Boolean + + """Default weight unit.""" + defaultWeightUnit: WeightUnitsEnum + + """Enable automatic fulfillment for all digital products.""" + automaticFulfillmentDigitalProducts: Boolean + + """ + Enable automatic approval of all new fulfillments. + + Added in Saleor 3.1. + """ + fulfillmentAutoApprove: Boolean + + """ + Enable ability to approve fulfillments which are unpaid. + + Added in Saleor 3.1. + """ + fulfillmentAllowUnpaid: Boolean + + """Default number of max downloads per digital content URL.""" + defaultDigitalMaxDownloads: Int + + """Default number of days which digital content URL will be valid.""" + defaultDigitalUrlValidDays: Int + + """Default email sender's name.""" + defaultMailSenderName: String + + """Default email sender's address.""" + defaultMailSenderAddress: String + + """URL of a view where customers can set their password.""" + customerSetPasswordUrl: String + + """ + Default number of minutes stock will be reserved for anonymous checkout. Enter 0 or null to disable. + + Added in Saleor 3.1. + """ + reserveStockDurationAnonymousUser: Int + + """ + Default number of minutes stock will be reserved for authenticated checkout. Enter 0 or null to disable. + + Added in Saleor 3.1. + """ + reserveStockDurationAuthenticatedUser: Int + + """ + Default number of maximum line quantity in single checkout. Minimum possible value is 1, default value is 50. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + limitQuantityPerCheckout: Int + + """ + Include taxes in prices. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `taxConfigurationUpdate` mutation to configure this setting per channel or country. + """ + includeTaxesInPrices: Boolean + + """ + Display prices with tax in store. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `taxConfigurationUpdate` mutation to configure this setting per channel or country. + """ + displayGrossPrices: Boolean + + """ + Charge taxes on shipping. + + DEPRECATED: this field will be removed in Saleor 4.0. To enable taxes for a shipping method, assign a tax class to the shipping method with `shippingPriceCreate` or `shippingPriceUpdate` mutations. + """ + chargeTaxesOnShipping: Boolean +} + +""" +Fetch tax rates. + +Requires one of the following permissions: MANAGE_SETTINGS. +""" +type ShopFetchTaxRates { + """Updated shop.""" + shop: Shop + shopErrors: [ShopError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ShopError!]! +} + +""" +Creates/updates translations for shop settings. + +Requires one of the following permissions: MANAGE_TRANSLATIONS. +""" +type ShopSettingsTranslate { + """Updated shop settings.""" + shop: Shop + translationErrors: [TranslationError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [TranslationError!]! +} + +type TranslationError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: TranslationErrorCode! +} + +"""An enumeration.""" +enum TranslationErrorCode { + GRAPHQL_ERROR + INVALID + NOT_FOUND + REQUIRED +} + +input ShopSettingsTranslationInput { + headerText: String + description: String +} + +""" +Update the shop's address. If the `null` value is passed, the currently selected address will be deleted. + +Requires one of the following permissions: MANAGE_SETTINGS. +""" +type ShopAddressUpdate { + """Updated shop.""" + shop: Shop + shopErrors: [ShopError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ShopError!]! +} + +""" +Update shop order settings across all channels. Returns `orderSettings` for the first `channel` in alphabetical order. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type OrderSettingsUpdate { + """Order settings.""" + orderSettings: OrderSettings + orderSettingsErrors: [OrderSettingsError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderSettingsError!]! +} + +type OrderSettingsError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: OrderSettingsErrorCode! +} + +"""An enumeration.""" +enum OrderSettingsErrorCode { + INVALID +} + +input OrderSettingsUpdateInput { + """ + When disabled, all new orders from checkout will be marked as unconfirmed. When enabled orders from checkout will become unfulfilled immediately. By default set to True + """ + automaticallyConfirmAllNewOrders: Boolean + + """ + When enabled, all non-shippable gift card orders will be fulfilled automatically. By defualt set to True. + """ + automaticallyFulfillNonShippableGiftCard: Boolean +} + +""" +Update gift card settings. + +Requires one of the following permissions: MANAGE_GIFT_CARD. +""" +type GiftCardSettingsUpdate { + """Gift card settings.""" + giftCardSettings: GiftCardSettings + errors: [GiftCardSettingsError!]! +} + +type GiftCardSettingsError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: GiftCardSettingsErrorCode! +} + +"""An enumeration.""" +enum GiftCardSettingsErrorCode { + INVALID + REQUIRED + GRAPHQL_ERROR +} + +input GiftCardSettingsUpdateInput { + """Defines gift card default expiry settings.""" + expiryType: GiftCardSettingsExpiryTypeEnum + + """Defines gift card expiry period.""" + expiryPeriod: TimePeriodInputType +} + +input TimePeriodInputType { + """The length of the period.""" + amount: Int! + + """The type of the period.""" + type: TimePeriodTypeEnum! +} + +""" +Manage shipping method's availability in channels. + +Requires one of the following permissions: MANAGE_SHIPPING. +""" +type ShippingMethodChannelListingUpdate { + """An updated shipping method instance.""" + shippingMethod: ShippingMethodType + shippingErrors: [ShippingError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ShippingError!]! +} + +type ShippingError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: ShippingErrorCode! + + """List of warehouse IDs which causes the error.""" + warehouses: [ID!] + + """List of channels IDs which causes the error.""" + channels: [ID!] +} + +"""An enumeration.""" +enum ShippingErrorCode { + ALREADY_EXISTS + GRAPHQL_ERROR + INVALID + MAX_LESS_THAN_MIN + NOT_FOUND + REQUIRED + UNIQUE + DUPLICATED_INPUT_ITEM +} + +input ShippingMethodChannelListingInput { + """List of channels to which the shipping method should be assigned.""" + addChannels: [ShippingMethodChannelListingAddInput!] + + """List of channels from which the shipping method should be unassigned.""" + removeChannels: [ID!] +} + +input ShippingMethodChannelListingAddInput { + """ID of a channel.""" + channelId: ID! + + """Shipping price of the shipping method in this channel.""" + price: PositiveDecimal + + """Minimum order price to use this shipping method.""" + minimumOrderPrice: PositiveDecimal + + """Maximum order price to use this shipping method.""" + maximumOrderPrice: PositiveDecimal +} + +""" +Creates a new shipping price. + +Requires one of the following permissions: MANAGE_SHIPPING. +""" +type ShippingPriceCreate { + """A shipping zone to which the shipping method belongs.""" + shippingZone: ShippingZone + shippingMethod: ShippingMethodType + shippingErrors: [ShippingError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ShippingError!]! +} + +input ShippingPriceInput { + """Name of the shipping method.""" + name: String + + """Shipping method description.""" + description: JSONString + + """Minimum order weight to use this shipping method.""" + minimumOrderWeight: WeightScalar + + """Maximum order weight to use this shipping method.""" + maximumOrderWeight: WeightScalar + + """Maximum number of days for delivery.""" + maximumDeliveryDays: Int + + """Minimal number of days for delivery.""" + minimumDeliveryDays: Int + + """Shipping type: price or weight based.""" + type: ShippingMethodTypeEnum + + """Shipping zone this method belongs to.""" + shippingZone: ID + + """Postal code rules to add.""" + addPostalCodeRules: [ShippingPostalCodeRulesCreateInputRange!] + + """Postal code rules to delete.""" + deletePostalCodeRules: [ID!] + + """Inclusion type for currently assigned postal code rules.""" + inclusionType: PostalCodeRuleInclusionTypeEnum + + """ + ID of a tax class to assign to this shipping method. If not provided, the default tax class will be used. + """ + taxClass: ID +} + +scalar WeightScalar + +input ShippingPostalCodeRulesCreateInputRange { + """Start range of the postal code.""" + start: String! + + """End range of the postal code.""" + end: String +} + +""" +Deletes a shipping price. + +Requires one of the following permissions: MANAGE_SHIPPING. +""" +type ShippingPriceDelete { + """A shipping method to delete.""" + shippingMethod: ShippingMethodType + + """A shipping zone to which the shipping method belongs.""" + shippingZone: ShippingZone + shippingErrors: [ShippingError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ShippingError!]! +} + +""" +Deletes shipping prices. + +Requires one of the following permissions: MANAGE_SHIPPING. +""" +type ShippingPriceBulkDelete { + """Returns how many objects were affected.""" + count: Int! + shippingErrors: [ShippingError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ShippingError!]! +} + +""" +Updates a new shipping price. + +Requires one of the following permissions: MANAGE_SHIPPING. +""" +type ShippingPriceUpdate { + """A shipping zone to which the shipping method belongs.""" + shippingZone: ShippingZone + shippingMethod: ShippingMethodType + shippingErrors: [ShippingError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ShippingError!]! +} + +""" +Creates/updates translations for a shipping method. + +Requires one of the following permissions: MANAGE_TRANSLATIONS. +""" +type ShippingPriceTranslate { + translationErrors: [TranslationError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [TranslationError!]! + shippingMethod: ShippingMethodType +} + +input ShippingPriceTranslationInput { + name: String + + """ + Translated shipping method description. + + Rich text format. For reference see https://editorjs.io/ + """ + description: JSONString +} + +""" +Exclude products from shipping price. + +Requires one of the following permissions: MANAGE_SHIPPING. +""" +type ShippingPriceExcludeProducts { + """A shipping method with new list of excluded products.""" + shippingMethod: ShippingMethodType + shippingErrors: [ShippingError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ShippingError!]! +} + +input ShippingPriceExcludeProductsInput { + """List of products which will be excluded.""" + products: [ID!]! +} + +""" +Remove product from excluded list for shipping price. + +Requires one of the following permissions: MANAGE_SHIPPING. +""" +type ShippingPriceRemoveProductFromExclude { + """A shipping method with new list of excluded products.""" + shippingMethod: ShippingMethodType + shippingErrors: [ShippingError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ShippingError!]! +} + +""" +Creates a new shipping zone. + +Requires one of the following permissions: MANAGE_SHIPPING. +""" +type ShippingZoneCreate { + shippingErrors: [ShippingError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ShippingError!]! + shippingZone: ShippingZone +} + +input ShippingZoneCreateInput { + """Shipping zone's name. Visible only to the staff.""" + name: String + + """Description of the shipping zone.""" + description: String + + """List of countries in this shipping zone.""" + countries: [String!] + + """ + Default shipping zone will be used for countries not covered by other zones. + """ + default: Boolean + + """List of warehouses to assign to a shipping zone""" + addWarehouses: [ID!] + + """List of channels to assign to the shipping zone.""" + addChannels: [ID!] +} + +""" +Deletes a shipping zone. + +Requires one of the following permissions: MANAGE_SHIPPING. +""" +type ShippingZoneDelete { + shippingErrors: [ShippingError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ShippingError!]! + shippingZone: ShippingZone +} + +""" +Deletes shipping zones. + +Requires one of the following permissions: MANAGE_SHIPPING. +""" +type ShippingZoneBulkDelete { + """Returns how many objects were affected.""" + count: Int! + shippingErrors: [ShippingError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ShippingError!]! +} + +""" +Updates a new shipping zone. + +Requires one of the following permissions: MANAGE_SHIPPING. +""" +type ShippingZoneUpdate { + shippingErrors: [ShippingError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ShippingError!]! + shippingZone: ShippingZone +} + +input ShippingZoneUpdateInput { + """Shipping zone's name. Visible only to the staff.""" + name: String + + """Description of the shipping zone.""" + description: String + + """List of countries in this shipping zone.""" + countries: [String!] + + """ + Default shipping zone will be used for countries not covered by other zones. + """ + default: Boolean + + """List of warehouses to assign to a shipping zone""" + addWarehouses: [ID!] + + """List of channels to assign to the shipping zone.""" + addChannels: [ID!] + + """List of warehouses to unassign from a shipping zone""" + removeWarehouses: [ID!] + + """List of channels to unassign from the shipping zone.""" + removeChannels: [ID!] +} + +""" +Assign attributes to a given product type. + +Requires one of the following permissions: MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. +""" +type ProductAttributeAssign { + """The updated product type.""" + productType: ProductType + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! +} + +type ProductError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: ProductErrorCode! + + """List of attributes IDs which causes the error.""" + attributes: [ID!] + + """List of attribute values IDs which causes the error.""" + values: [ID!] +} + +"""An enumeration.""" +enum ProductErrorCode { + ALREADY_EXISTS + ATTRIBUTE_ALREADY_ASSIGNED + ATTRIBUTE_CANNOT_BE_ASSIGNED + ATTRIBUTE_VARIANTS_DISABLED + MEDIA_ALREADY_ASSIGNED + DUPLICATED_INPUT_ITEM + GRAPHQL_ERROR + INVALID + INVALID_PRICE + PRODUCT_WITHOUT_CATEGORY + NOT_PRODUCTS_IMAGE + NOT_PRODUCTS_VARIANT + NOT_FOUND + REQUIRED + UNIQUE + VARIANT_NO_DIGITAL_CONTENT + CANNOT_MANAGE_PRODUCT_WITHOUT_VARIANT + PRODUCT_NOT_ASSIGNED_TO_CHANNEL + UNSUPPORTED_MEDIA_PROVIDER + PREORDER_VARIANT_CANNOT_BE_DEACTIVATED +} + +input ProductAttributeAssignInput { + """The ID of the attribute to assign.""" + id: ID! + + """The attribute type to be assigned as.""" + type: ProductAttributeType! + + """ + Whether attribute is allowed in variant selection. Allowed types are: ['dropdown', 'boolean', 'swatch', 'numeric']. + + Added in Saleor 3.1. + """ + variantSelection: Boolean +} + +enum ProductAttributeType { + PRODUCT + VARIANT +} + +""" +Update attributes assigned to product variant for given product type. + +Added in Saleor 3.1. + +Requires one of the following permissions: MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. +""" +type ProductAttributeAssignmentUpdate { + """The updated product type.""" + productType: ProductType + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! +} + +input ProductAttributeAssignmentUpdateInput { + """The ID of the attribute to assign.""" + id: ID! + + """ + Whether attribute is allowed in variant selection. Allowed types are: ['dropdown', 'boolean', 'swatch', 'numeric']. + + Added in Saleor 3.1. + """ + variantSelection: Boolean! +} + +""" +Un-assign attributes from a given product type. + +Requires one of the following permissions: MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. +""" +type ProductAttributeUnassign { + """The updated product type.""" + productType: ProductType + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! +} + +""" +Creates a new category. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type CategoryCreate { + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! + category: Category +} + +input CategoryInput { + """ + Category description. + + Rich text format. For reference see https://editorjs.io/ + """ + description: JSONString + + """Category name.""" + name: String + + """Category slug.""" + slug: String + + """Search engine optimization fields.""" + seo: SeoInput + + """Background image file.""" + backgroundImage: Upload + + """Alt text for a product media.""" + backgroundImageAlt: String + + """ + Fields required to update the category metadata. + + Added in Saleor 3.8. + """ + metadata: [MetadataInput!] + + """ + Fields required to update the category private metadata. + + Added in Saleor 3.8. + """ + privateMetadata: [MetadataInput!] +} + +input SeoInput { + """SEO title.""" + title: String + + """SEO description.""" + description: String +} + +""" +Variables of this type must be set to null in mutations. They will be replaced with a filename from a following multipart part containing a binary file. See: https://github.com/jaydenseric/graphql-multipart-request-spec. +""" +scalar Upload + +input MetadataInput { + """Key of a metadata item.""" + key: String! + + """Value of a metadata item.""" + value: String! +} + +""" +Deletes a category. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type CategoryDelete { + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! + category: Category +} + +""" +Deletes categories. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type CategoryBulkDelete { + """Returns how many objects were affected.""" + count: Int! + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! +} + +""" +Updates a category. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type CategoryUpdate { + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! + category: Category +} + +""" +Creates/updates translations for a category. + +Requires one of the following permissions: MANAGE_TRANSLATIONS. +""" +type CategoryTranslate { + translationErrors: [TranslationError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [TranslationError!]! + category: Category +} + +input TranslationInput { + seoTitle: String + seoDescription: String + name: String + + """ + Translated description. + + Rich text format. For reference see https://editorjs.io/ + """ + description: JSONString +} + +""" +Adds products to a collection. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type CollectionAddProducts { + """Collection to which products will be added.""" + collection: Collection + collectionErrors: [CollectionError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [CollectionError!]! +} + +type CollectionError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """List of products IDs which causes the error.""" + products: [ID!] + + """The error code.""" + code: CollectionErrorCode! +} + +"""An enumeration.""" +enum CollectionErrorCode { + DUPLICATED_INPUT_ITEM + GRAPHQL_ERROR + INVALID + NOT_FOUND + REQUIRED + UNIQUE + CANNOT_MANAGE_PRODUCT_WITHOUT_VARIANT +} + +""" +Creates a new collection. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type CollectionCreate { + collectionErrors: [CollectionError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [CollectionError!]! + collection: Collection +} + +input CollectionCreateInput { + """Informs whether a collection is published.""" + isPublished: Boolean + + """Name of the collection.""" + name: String + + """Slug of the collection.""" + slug: String + + """ + Description of the collection. + + Rich text format. For reference see https://editorjs.io/ + """ + description: JSONString + + """Background image file.""" + backgroundImage: Upload + + """Alt text for an image.""" + backgroundImageAlt: String + + """Search engine optimization fields.""" + seo: SeoInput + + """ + Publication date. ISO 8601 standard. + + DEPRECATED: this field will be removed in Saleor 4.0. + """ + publicationDate: Date + + """ + Fields required to update the collection metadata. + + Added in Saleor 3.8. + """ + metadata: [MetadataInput!] + + """ + Fields required to update the collection private metadata. + + Added in Saleor 3.8. + """ + privateMetadata: [MetadataInput!] + + """List of products to be added to the collection.""" + products: [ID!] +} + +""" +Deletes a collection. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type CollectionDelete { + collectionErrors: [CollectionError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [CollectionError!]! + collection: Collection +} + +""" +Reorder the products of a collection. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type CollectionReorderProducts { + """Collection from which products are reordered.""" + collection: Collection + collectionErrors: [CollectionError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [CollectionError!]! +} + +input MoveProductInput { + """The ID of the product to move.""" + productId: ID! + + """ + The relative sorting position of the product (from -inf to +inf) starting from the first given product's actual position.1 moves the item one position forward, -1 moves the item one position backward, 0 leaves the item unchanged. + """ + sortOrder: Int +} + +""" +Deletes collections. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type CollectionBulkDelete { + """Returns how many objects were affected.""" + count: Int! + collectionErrors: [CollectionError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [CollectionError!]! +} + +""" +Remove products from a collection. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type CollectionRemoveProducts { + """Collection from which products will be removed.""" + collection: Collection + collectionErrors: [CollectionError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [CollectionError!]! +} + +""" +Updates a collection. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type CollectionUpdate { + collectionErrors: [CollectionError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [CollectionError!]! + collection: Collection +} + +input CollectionInput { + """Informs whether a collection is published.""" + isPublished: Boolean + + """Name of the collection.""" + name: String + + """Slug of the collection.""" + slug: String + + """ + Description of the collection. + + Rich text format. For reference see https://editorjs.io/ + """ + description: JSONString + + """Background image file.""" + backgroundImage: Upload + + """Alt text for an image.""" + backgroundImageAlt: String + + """Search engine optimization fields.""" + seo: SeoInput + + """ + Publication date. ISO 8601 standard. + + DEPRECATED: this field will be removed in Saleor 4.0. + """ + publicationDate: Date + + """ + Fields required to update the collection metadata. + + Added in Saleor 3.8. + """ + metadata: [MetadataInput!] + + """ + Fields required to update the collection private metadata. + + Added in Saleor 3.8. + """ + privateMetadata: [MetadataInput!] +} + +""" +Creates/updates translations for a collection. + +Requires one of the following permissions: MANAGE_TRANSLATIONS. +""" +type CollectionTranslate { + translationErrors: [TranslationError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [TranslationError!]! + collection: Collection +} + +""" +Manage collection's availability in channels. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type CollectionChannelListingUpdate { + """An updated collection instance.""" + collection: Collection + collectionChannelListingErrors: [CollectionChannelListingError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [CollectionChannelListingError!]! +} + +type CollectionChannelListingError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: ProductErrorCode! + + """List of attributes IDs which causes the error.""" + attributes: [ID!] + + """List of attribute values IDs which causes the error.""" + values: [ID!] + + """List of channels IDs which causes the error.""" + channels: [ID!] +} + +input CollectionChannelListingUpdateInput { + """List of channels to which the collection should be assigned.""" + addChannels: [PublishableChannelListingInput!] + + """List of channels from which the collection should be unassigned.""" + removeChannels: [ID!] +} + +input PublishableChannelListingInput { + """ID of a channel.""" + channelId: ID! + + """Determines if object is visible to customers.""" + isPublished: Boolean + + """ + Publication date. ISO 8601 standard. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `publishedAt` field instead. + """ + publicationDate: Date + + """ + Publication date time. ISO 8601 standard. + + Added in Saleor 3.3. + """ + publishedAt: DateTime +} + +""" +Creates a new product. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type ProductCreate { + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! + product: Product +} + +input ProductCreateInput { + """List of attributes.""" + attributes: [AttributeValueInput!] + + """ID of the product's category.""" + category: ID + + """ + Determine if taxes are being charged for the product. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `Channel.taxConfiguration` to configure whether tax collection is enabled. + """ + chargeTaxes: Boolean + + """List of IDs of collections that the product belongs to.""" + collections: [ID!] + + """ + Product description. + + Rich text format. For reference see https://editorjs.io/ + """ + description: JSONString + + """Product name.""" + name: String + + """Product slug.""" + slug: String + + """ + ID of a tax class to assign to this product. If not provided, product will use the tax class which is assigned to the product type. + """ + taxClass: ID + + """ + Tax rate for enabled tax gateway. + + DEPRECATED: this field will be removed in Saleor 4.0. Use tax classes to control the tax calculation for a product. + """ + taxCode: String + + """Search engine optimization fields.""" + seo: SeoInput + + """Weight of the Product.""" + weight: WeightScalar + + """Defines the product rating value.""" + rating: Float + + """ + Fields required to update the product metadata. + + Added in Saleor 3.8. + """ + metadata: [MetadataInput!] + + """ + Fields required to update the product private metadata. + + Added in Saleor 3.8. + """ + privateMetadata: [MetadataInput!] + + """ + External ID of this product. + + Added in Saleor 3.10. + """ + externalReference: String + + """ID of the type that product belongs to.""" + productType: ID! +} + +input AttributeValueInput { + """ID of the selected attribute.""" + id: ID + + """ + The value or slug of an attribute to resolve. If the passed value is non-existent, it will be created. This field will be removed in Saleor 4.0. + """ + values: [String!] + + """ + Attribute value ID. + + Added in Saleor 3.9. + """ + dropdown: AttributeValueSelectableTypeInput + + """ + Attribute value ID. + + Added in Saleor 3.9. + """ + swatch: AttributeValueSelectableTypeInput + + """ + List of attribute value IDs. + + Added in Saleor 3.9. + """ + multiselect: [AttributeValueSelectableTypeInput!] + + """ + Numeric value of an attribute. + + Added in Saleor 3.9. + """ + numeric: String + + """URL of the file attribute. Every time, a new value is created.""" + file: String + + """File content type.""" + contentType: String + + """List of entity IDs that will be used as references.""" + references: [ID!] + + """Text content in JSON format.""" + richText: JSONString + + """Plain text content.""" + plainText: String + + """Represents the boolean value of the attribute value.""" + boolean: Boolean + + """Represents the date value of the attribute value.""" + date: Date + + """Represents the date/time value of the attribute value.""" + dateTime: DateTime +} + +""" +Represents attribute value. If no ID provided, value will be resolved. + +Added in Saleor 3.9. +""" +input AttributeValueSelectableTypeInput { + """ID of an attribute value.""" + id: ID + + """ + The value or slug of an attribute to resolve. If the passed value is non-existent, it will be created. + """ + value: String +} + +""" +Deletes a product. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type ProductDelete { + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! + product: Product +} + +""" +Deletes products. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type ProductBulkDelete { + """Returns how many objects were affected.""" + count: Int! + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! +} + +""" +Updates an existing product. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type ProductUpdate { + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! + product: Product +} + +input ProductInput { + """List of attributes.""" + attributes: [AttributeValueInput!] + + """ID of the product's category.""" + category: ID + + """ + Determine if taxes are being charged for the product. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `Channel.taxConfiguration` to configure whether tax collection is enabled. + """ + chargeTaxes: Boolean + + """List of IDs of collections that the product belongs to.""" + collections: [ID!] + + """ + Product description. + + Rich text format. For reference see https://editorjs.io/ + """ + description: JSONString + + """Product name.""" + name: String + + """Product slug.""" + slug: String + + """ + ID of a tax class to assign to this product. If not provided, product will use the tax class which is assigned to the product type. + """ + taxClass: ID + + """ + Tax rate for enabled tax gateway. + + DEPRECATED: this field will be removed in Saleor 4.0. Use tax classes to control the tax calculation for a product. + """ + taxCode: String + + """Search engine optimization fields.""" + seo: SeoInput + + """Weight of the Product.""" + weight: WeightScalar + + """Defines the product rating value.""" + rating: Float + + """ + Fields required to update the product metadata. + + Added in Saleor 3.8. + """ + metadata: [MetadataInput!] + + """ + Fields required to update the product private metadata. + + Added in Saleor 3.8. + """ + privateMetadata: [MetadataInput!] + + """ + External ID of this product. + + Added in Saleor 3.10. + """ + externalReference: String +} + +""" +Creates/updates translations for a product. + +Requires one of the following permissions: MANAGE_TRANSLATIONS. +""" +type ProductTranslate { + translationErrors: [TranslationError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [TranslationError!]! + product: Product +} + +""" +Manage product's availability in channels. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type ProductChannelListingUpdate { + """An updated product instance.""" + product: Product + productChannelListingErrors: [ProductChannelListingError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductChannelListingError!]! +} + +type ProductChannelListingError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: ProductErrorCode! + + """List of attributes IDs which causes the error.""" + attributes: [ID!] + + """List of attribute values IDs which causes the error.""" + values: [ID!] + + """List of channels IDs which causes the error.""" + channels: [ID!] + + """List of variants IDs which causes the error.""" + variants: [ID!] +} + +input ProductChannelListingUpdateInput { + """List of channels to which the product should be assigned or updated.""" + updateChannels: [ProductChannelListingAddInput!] + + """List of channels from which the product should be unassigned.""" + removeChannels: [ID!] +} + +input ProductChannelListingAddInput { + """ID of a channel.""" + channelId: ID! + + """Determines if object is visible to customers.""" + isPublished: Boolean + + """ + Publication date. ISO 8601 standard. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `publishedAt` field instead. + """ + publicationDate: Date + + """ + Publication date time. ISO 8601 standard. + + Added in Saleor 3.3. + """ + publishedAt: DateTime + + """ + Determines if product is visible in product listings (doesn't apply to product collections). + """ + visibleInListings: Boolean + + """Determine if product should be available for purchase.""" + isAvailableForPurchase: Boolean + + """ + A start date from which a product will be available for purchase. When not set and isAvailable is set to True, the current day is assumed. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `availableForPurchaseAt` field instead. + """ + availableForPurchaseDate: Date + + """ + A start date time from which a product will be available for purchase. When not set and `isAvailable` is set to True, the current day is assumed. + + Added in Saleor 3.3. + """ + availableForPurchaseAt: DateTime + + """List of variants to which the channel should be assigned.""" + addVariants: [ID!] + + """List of variants from which the channel should be unassigned.""" + removeVariants: [ID!] +} + +""" +Create a media object (image or video URL) associated with product. For image, this mutation must be sent as a `multipart` request. More detailed specs of the upload format can be found here: https://github.com/jaydenseric/graphql-multipart-request-spec + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type ProductMediaCreate { + product: Product + media: ProductMedia + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! +} + +input ProductMediaCreateInput { + """Alt text for a product media.""" + alt: String + + """Represents an image file in a multipart request.""" + image: Upload + + """ID of an product.""" + product: ID! + + """Represents an URL to an external media.""" + mediaUrl: String +} + +""" +Reorder the variants of a product. Mutation updates updated_at on product and triggers PRODUCT_UPDATED webhook. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type ProductVariantReorder { + product: Product + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! +} + +input ReorderInput { + """The ID of the item to move.""" + id: ID! + + """ + The new relative sorting position of the item (from -inf to +inf). 1 moves the item one position forward, -1 moves the item one position backward, 0 leaves the item unchanged. + """ + sortOrder: Int +} + +""" +Deletes a product media. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type ProductMediaDelete { + product: Product + media: ProductMedia + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! +} + +""" +Deletes product media. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type ProductMediaBulkDelete { + """Returns how many objects were affected.""" + count: Int! + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! +} + +""" +Changes ordering of the product media. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type ProductMediaReorder { + product: Product + media: [ProductMedia!] + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! +} + +""" +Updates a product media. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type ProductMediaUpdate { + product: Product + media: ProductMedia + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! +} + +input ProductMediaUpdateInput { + """Alt text for a product media.""" + alt: String +} + +""" +Creates a new product type. + +Requires one of the following permissions: MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. +""" +type ProductTypeCreate { + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! + productType: ProductType +} + +input ProductTypeInput { + """Name of the product type.""" + name: String + + """Product type slug.""" + slug: String + + """The product type kind.""" + kind: ProductTypeKindEnum + + """ + Determines if product of this type has multiple variants. This option mainly simplifies product management in the dashboard. There is always at least one variant created under the hood. + """ + hasVariants: Boolean + + """List of attributes shared among all product variants.""" + productAttributes: [ID!] + + """ + List of attributes used to distinguish between different variants of a product. + """ + variantAttributes: [ID!] + + """Determines if shipping is required for products of this variant.""" + isShippingRequired: Boolean + + """Determines if products are digital.""" + isDigital: Boolean + + """Weight of the ProductType items.""" + weight: WeightScalar + + """ + Tax rate for enabled tax gateway. + + DEPRECATED: this field will be removed in Saleor 4.0.. Use tax classes to control the tax calculation for a product type. + """ + taxCode: String + + """ + ID of a tax class to assign to this product type. All products of this product type would use this tax class, unless it's overridden in the `Product` type. + """ + taxClass: ID +} + +""" +Deletes a product type. + +Requires one of the following permissions: MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. +""" +type ProductTypeDelete { + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! + productType: ProductType +} + +""" +Deletes product types. + +Requires one of the following permissions: MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. +""" +type ProductTypeBulkDelete { + """Returns how many objects were affected.""" + count: Int! + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! +} + +""" +Updates an existing product type. + +Requires one of the following permissions: MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. +""" +type ProductTypeUpdate { + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! + productType: ProductType +} + +""" +Reorder the attributes of a product type. + +Requires one of the following permissions: MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. +""" +type ProductTypeReorderAttributes { + """Product type from which attributes are reordered.""" + productType: ProductType + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! +} + +""" +Reorder product attribute values. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type ProductReorderAttributeValues { + """Product from which attribute values are reordered.""" + product: Product + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! +} + +""" +Create new digital content. This mutation must be sent as a `multipart` request. More detailed specs of the upload format can be found here: https://github.com/jaydenseric/graphql-multipart-request-spec + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type DigitalContentCreate { + variant: ProductVariant + content: DigitalContent + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! +} + +input DigitalContentUploadInput { + """Use default digital content settings for this product.""" + useDefaultSettings: Boolean! + + """ + Determines how many times a download link can be accessed by a customer. + """ + maxDownloads: Int + + """ + Determines for how many days a download link is active since it was generated. + """ + urlValidDays: Int + + """Overwrite default automatic_fulfillment setting for variant.""" + automaticFulfillment: Boolean + + """ + Fields required to update the digital content metadata. + + Added in Saleor 3.8. + """ + metadata: [MetadataInput!] + + """ + Fields required to update the digital content private metadata. + + Added in Saleor 3.8. + """ + privateMetadata: [MetadataInput!] + + """Represents an file in a multipart request.""" + contentFile: Upload! +} + +""" +Remove digital content assigned to given variant. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type DigitalContentDelete { + variant: ProductVariant + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! +} + +""" +Update digital content. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type DigitalContentUpdate { + variant: ProductVariant + content: DigitalContent + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! +} + +input DigitalContentInput { + """Use default digital content settings for this product.""" + useDefaultSettings: Boolean! + + """ + Determines how many times a download link can be accessed by a customer. + """ + maxDownloads: Int + + """ + Determines for how many days a download link is active since it was generated. + """ + urlValidDays: Int + + """Overwrite default automatic_fulfillment setting for variant.""" + automaticFulfillment: Boolean + + """ + Fields required to update the digital content metadata. + + Added in Saleor 3.8. + """ + metadata: [MetadataInput!] + + """ + Fields required to update the digital content private metadata. + + Added in Saleor 3.8. + """ + privateMetadata: [MetadataInput!] +} + +""" +Generate new URL to digital content. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type DigitalContentUrlCreate { + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! + digitalContentUrl: DigitalContentUrl +} + +input DigitalContentUrlCreateInput { + """Digital content ID which URL will belong to.""" + content: ID! +} + +""" +Creates a new variant for a product. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type ProductVariantCreate { + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! + productVariant: ProductVariant +} + +input ProductVariantCreateInput { + """List of attributes specific to this variant.""" + attributes: [AttributeValueInput!]! + + """Stock keeping unit.""" + sku: String + + """Variant name.""" + name: String + + """ + Determines if the inventory of this variant should be tracked. If false, the quantity won't change when customers buy this item. + """ + trackInventory: Boolean + + """Weight of the Product Variant.""" + weight: WeightScalar + + """ + Determines if variant is in preorder. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + preorder: PreorderSettingsInput + + """ + Determines maximum quantity of `ProductVariant`,that can be bought in a single checkout. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + quantityLimitPerCustomer: Int + + """ + Fields required to update the product variant metadata. + + Added in Saleor 3.8. + """ + metadata: [MetadataInput!] + + """ + Fields required to update the product variant private metadata. + + Added in Saleor 3.8. + """ + privateMetadata: [MetadataInput!] + + """ + External ID of this product variant. + + Added in Saleor 3.10. + """ + externalReference: String + + """Product ID of which type is the variant.""" + product: ID! + + """Stocks of a product available for sale.""" + stocks: [StockInput!] +} + +input PreorderSettingsInput { + """The global threshold for preorder variant.""" + globalThreshold: Int + + """The end date for preorder.""" + endDate: DateTime +} + +input StockInput { + """Warehouse in which stock is located.""" + warehouse: ID! + + """Quantity of items available for sell.""" + quantity: Int! +} + +""" +Deletes a product variant. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type ProductVariantDelete { + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! + productVariant: ProductVariant +} + +""" +Creates product variants for a given product. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type ProductVariantBulkCreate { + """Returns how many objects were created.""" + count: Int! + + """List of the created variants.This field will be removed in Saleor 4.0.""" + productVariants: [ProductVariant!]! + + """ + List of the created variants. + + Added in Saleor 3.11. + """ + results: [ProductVariantBulkResult!]! + bulkProductErrors: [BulkProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [BulkProductError!]! +} + +type ProductVariantBulkResult { + """Product variant data.""" + productVariant: ProductVariant + + """List of errors occurred on create attempt.""" + errors: [ProductVariantBulkError!] +} + +type ProductVariantBulkError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: ProductVariantBulkErrorCode! + + """List of attributes IDs which causes the error.""" + attributes: [ID!] + + """List of attribute values IDs which causes the error.""" + values: [ID!] + + """List of warehouse IDs which causes the error.""" + warehouses: [ID!] + + """ + List of stocks IDs which causes the error. + + Added in Saleor 3.12. + """ + stocks: [ID!] + + """ + List of channel IDs which causes the error. + + Added in Saleor 3.12. + """ + channels: [ID!] + + """List of channel listings IDs which causes the error.""" + channelListings: [ID!] +} + +"""An enumeration.""" +enum ProductVariantBulkErrorCode { + ATTRIBUTE_ALREADY_ASSIGNED + ATTRIBUTE_CANNOT_BE_ASSIGNED + ATTRIBUTE_VARIANTS_DISABLED + DUPLICATED_INPUT_ITEM + GRAPHQL_ERROR + INVALID + INVALID_PRICE + NOT_PRODUCTS_VARIANT + NOT_FOUND + REQUIRED + UNIQUE + PRODUCT_NOT_ASSIGNED_TO_CHANNEL +} + +type BulkProductError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: ProductErrorCode! + + """List of attributes IDs which causes the error.""" + attributes: [ID!] + + """List of attribute values IDs which causes the error.""" + values: [ID!] + + """Index of an input list item that caused the error.""" + index: Int + + """List of warehouse IDs which causes the error.""" + warehouses: [ID!] + + """List of channel IDs which causes the error.""" + channels: [ID!] +} + +input ProductVariantBulkCreateInput { + """List of attributes specific to this variant.""" + attributes: [BulkAttributeValueInput!]! + + """Stock keeping unit.""" + sku: String + + """Variant name.""" + name: String + + """ + Determines if the inventory of this variant should be tracked. If false, the quantity won't change when customers buy this item. + """ + trackInventory: Boolean + + """Weight of the Product Variant.""" + weight: WeightScalar + + """ + Determines if variant is in preorder. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + preorder: PreorderSettingsInput + + """ + Determines maximum quantity of `ProductVariant`,that can be bought in a single checkout. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + quantityLimitPerCustomer: Int + + """ + Fields required to update the product variant metadata. + + Added in Saleor 3.8. + """ + metadata: [MetadataInput!] + + """ + Fields required to update the product variant private metadata. + + Added in Saleor 3.8. + """ + privateMetadata: [MetadataInput!] + + """ + External ID of this product variant. + + Added in Saleor 3.10. + """ + externalReference: String + + """Stocks of a product available for sale.""" + stocks: [StockInput!] + + """List of prices assigned to channels.""" + channelListings: [ProductVariantChannelListingAddInput!] +} + +input BulkAttributeValueInput { + """ID of the selected attribute.""" + id: ID + + """ + The value or slug of an attribute to resolve. If the passed value is non-existent, it will be created.This field will be removed in Saleor 4.0. + """ + values: [String!] + + """ + Attribute value ID. + + Added in Saleor 3.12. + """ + dropdown: AttributeValueSelectableTypeInput + + """ + Attribute value ID. + + Added in Saleor 3.12. + """ + swatch: AttributeValueSelectableTypeInput + + """ + List of attribute value IDs. + + Added in Saleor 3.12. + """ + multiselect: [AttributeValueSelectableTypeInput!] + + """ + Numeric value of an attribute. + + Added in Saleor 3.12. + """ + numeric: String + + """ + URL of the file attribute. Every time, a new value is created. + + Added in Saleor 3.12. + """ + file: String + + """ + File content type. + + Added in Saleor 3.12. + """ + contentType: String + + """ + List of entity IDs that will be used as references. + + Added in Saleor 3.12. + """ + references: [ID!] + + """ + Text content in JSON format. + + Added in Saleor 3.12. + """ + richText: JSONString + + """ + Plain text content. + + Added in Saleor 3.12. + """ + plainText: String + + """ + The boolean value of an attribute to resolve. If the passed value is non-existent, it will be created. + """ + boolean: Boolean + + """ + Represents the date value of the attribute value. + + Added in Saleor 3.12. + """ + date: Date + + """ + Represents the date/time value of the attribute value. + + Added in Saleor 3.12. + """ + dateTime: DateTime +} + +input ProductVariantChannelListingAddInput { + """ID of a channel.""" + channelId: ID! + + """Price of the particular variant in channel.""" + price: PositiveDecimal! + + """Cost price of the variant in channel.""" + costPrice: PositiveDecimal + + """ + The threshold for preorder variant in channel. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + preorderThreshold: Int +} + +""" +Update multiple product variants. + +Added in Saleor 3.11. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type ProductVariantBulkUpdate { + """Returns how many objects were updated.""" + count: Int! + + """List of the updated variants.""" + results: [ProductVariantBulkResult!]! + errors: [ProductVariantBulkError!]! +} + +""" +Input fields to update product variants. + +Added in Saleor 3.11. +""" +input ProductVariantBulkUpdateInput { + """List of attributes specific to this variant.""" + attributes: [BulkAttributeValueInput!] + + """Stock keeping unit.""" + sku: String + + """Variant name.""" + name: String + + """ + Determines if the inventory of this variant should be tracked. If false, the quantity won't change when customers buy this item. + """ + trackInventory: Boolean + + """Weight of the Product Variant.""" + weight: WeightScalar + + """ + Determines if variant is in preorder. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + preorder: PreorderSettingsInput + + """ + Determines maximum quantity of `ProductVariant`,that can be bought in a single checkout. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + quantityLimitPerCustomer: Int + + """ + Fields required to update the product variant metadata. + + Added in Saleor 3.8. + """ + metadata: [MetadataInput!] + + """ + Fields required to update the product variant private metadata. + + Added in Saleor 3.8. + """ + privateMetadata: [MetadataInput!] + + """ + External ID of this product variant. + + Added in Saleor 3.10. + """ + externalReference: String + + """ + Stocks input. + + Added in Saleor 3.12. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + stocks: ProductVariantStocksUpdateInput + + """ + Channel listings input. + + Added in Saleor 3.12. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + channelListings: ProductVariantChannelListingUpdateInput + + """ID of the product variant to update.""" + id: ID! +} + +input ProductVariantStocksUpdateInput { + """List of warehouses to create stocks.""" + create: [StockInput!] + + """List of stocks to update.""" + update: [StockUpdateInput!] + + """List of stocks to remove.""" + remove: [ID!] +} + +input StockUpdateInput { + """Stock.""" + stock: ID! + + """Quantity of items available for sell.""" + quantity: Int! +} + +input ProductVariantChannelListingUpdateInput { + """List of channels to create variant channel listings.""" + create: [ProductVariantChannelListingAddInput!] + + """List of channel listings to update.""" + update: [ChannelListingUpdateInput!] + + """List of channel listings to remove.""" + remove: [ID!] +} + +input ChannelListingUpdateInput { + """ID of a channel listing.""" + channelListing: ID! + + """Price of the particular variant in channel.""" + price: PositiveDecimal + + """Cost price of the variant in channel.""" + costPrice: PositiveDecimal + + """The threshold for preorder variant in channel.""" + preorderThreshold: Int +} + +""" +Deletes product variants. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type ProductVariantBulkDelete { + """Returns how many objects were affected.""" + count: Int! + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! +} + +""" +Creates stocks for product variant. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type ProductVariantStocksCreate { + """Updated product variant.""" + productVariant: ProductVariant + bulkStockErrors: [BulkStockError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [BulkStockError!]! +} + +type BulkStockError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: ProductErrorCode! + + """List of attributes IDs which causes the error.""" + attributes: [ID!] + + """List of attribute values IDs which causes the error.""" + values: [ID!] + + """Index of an input list item that caused the error.""" + index: Int +} + +""" +Delete stocks from product variant. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type ProductVariantStocksDelete { + """Updated product variant.""" + productVariant: ProductVariant + stockErrors: [StockError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [StockError!]! +} + +type StockError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: StockErrorCode! +} + +"""An enumeration.""" +enum StockErrorCode { + ALREADY_EXISTS + GRAPHQL_ERROR + INVALID + NOT_FOUND + REQUIRED + UNIQUE +} + +""" +Update stocks for product variant. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type ProductVariantStocksUpdate { + """Updated product variant.""" + productVariant: ProductVariant + bulkStockErrors: [BulkStockError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [BulkStockError!]! +} + +""" +Updates an existing variant for product. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type ProductVariantUpdate { + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! + productVariant: ProductVariant +} + +input ProductVariantInput { + """List of attributes specific to this variant.""" + attributes: [AttributeValueInput!] + + """Stock keeping unit.""" + sku: String + + """Variant name.""" + name: String + + """ + Determines if the inventory of this variant should be tracked. If false, the quantity won't change when customers buy this item. + """ + trackInventory: Boolean + + """Weight of the Product Variant.""" + weight: WeightScalar + + """ + Determines if variant is in preorder. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + preorder: PreorderSettingsInput + + """ + Determines maximum quantity of `ProductVariant`,that can be bought in a single checkout. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + quantityLimitPerCustomer: Int + + """ + Fields required to update the product variant metadata. + + Added in Saleor 3.8. + """ + metadata: [MetadataInput!] + + """ + Fields required to update the product variant private metadata. + + Added in Saleor 3.8. + """ + privateMetadata: [MetadataInput!] + + """ + External ID of this product variant. + + Added in Saleor 3.10. + """ + externalReference: String +} + +""" +Set default variant for a product. Mutation triggers PRODUCT_UPDATED webhook. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type ProductVariantSetDefault { + product: Product + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! +} + +""" +Creates/updates translations for a product variant. + +Requires one of the following permissions: MANAGE_TRANSLATIONS. +""" +type ProductVariantTranslate { + translationErrors: [TranslationError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [TranslationError!]! + productVariant: ProductVariant +} + +input NameTranslationInput { + name: String +} + +""" +Manage product variant prices in channels. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type ProductVariantChannelListingUpdate { + """An updated product variant instance.""" + variant: ProductVariant + productChannelListingErrors: [ProductChannelListingError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductChannelListingError!]! +} + +""" +Reorder product variant attribute values. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type ProductVariantReorderAttributeValues { + """Product variant from which attribute values are reordered.""" + productVariant: ProductVariant + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! +} + +""" +Deactivates product variant preorder. It changes all preorder allocation into regular allocation. + +Added in Saleor 3.1. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type ProductVariantPreorderDeactivate { + """Product variant with ended preorder.""" + productVariant: ProductVariant + errors: [ProductError!]! +} + +""" +Assign an media to a product variant. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type VariantMediaAssign { + productVariant: ProductVariant + media: ProductMedia + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! +} + +""" +Unassign an media from a product variant. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type VariantMediaUnassign { + productVariant: ProductVariant + media: ProductMedia + productErrors: [ProductError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ProductError!]! +} + +""" +Captures the authorized payment amount. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type PaymentCapture { + """Updated payment.""" + payment: Payment + paymentErrors: [PaymentError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [PaymentError!]! +} + +type PaymentError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: PaymentErrorCode! + + """List of variant IDs which causes the error.""" + variants: [ID!] +} + +"""An enumeration.""" +enum PaymentErrorCode { + BILLING_ADDRESS_NOT_SET + GRAPHQL_ERROR + INVALID + NOT_FOUND + REQUIRED + UNIQUE + PARTIAL_PAYMENT_NOT_ALLOWED + SHIPPING_ADDRESS_NOT_SET + INVALID_SHIPPING_METHOD + SHIPPING_METHOD_NOT_SET + PAYMENT_ERROR + NOT_SUPPORTED_GATEWAY + CHANNEL_INACTIVE + BALANCE_CHECK_ERROR + CHECKOUT_EMAIL_NOT_SET + UNAVAILABLE_VARIANT_IN_CHANNEL + NO_CHECKOUT_LINES +} + +""" +Refunds the captured payment amount. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type PaymentRefund { + """Updated payment.""" + payment: Payment + paymentErrors: [PaymentError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [PaymentError!]! +} + +""" +Voids the authorized payment. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type PaymentVoid { + """Updated payment.""" + payment: Payment + paymentErrors: [PaymentError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [PaymentError!]! +} + +"""Initializes payment process when it is required by gateway.""" +type PaymentInitialize { + initializedPayment: PaymentInitialized + paymentErrors: [PaymentError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [PaymentError!]! +} + +""" +Server-side data generated by a payment gateway. Optional step when the payment provider requires an additional action to initialize payment session. +""" +type PaymentInitialized { + """ID of a payment gateway.""" + gateway: String! + + """Payment gateway name.""" + name: String! + + """Initialized data by gateway.""" + data: JSONString +} + +"""Check payment balance.""" +type PaymentCheckBalance { + """Response from the gateway.""" + data: JSONString + paymentErrors: [PaymentError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [PaymentError!]! +} + +input PaymentCheckBalanceInput { + """An ID of a payment gateway to check.""" + gatewayId: String! + + """Payment method name.""" + method: String! + + """Slug of a channel for which the data should be returned.""" + channel: String! + + """Information about card.""" + card: CardInput! +} + +input CardInput { + """ + Payment method nonce, a token returned by the appropriate provider's SDK. + """ + code: String! + + """Card security code.""" + cvc: String + + """Information about currency and amount.""" + money: MoneyInput! +} + +input MoneyInput { + """Currency code.""" + currency: String! + + """Amount of money.""" + amount: PositiveDecimal! +} + +""" +Create transaction for checkout or order. + +Added in Saleor 3.4. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires one of the following permissions: HANDLE_PAYMENTS. +""" +type TransactionCreate { + transaction: TransactionItem + errors: [TransactionCreateError!]! +} + +type TransactionCreateError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: TransactionCreateErrorCode! +} + +"""An enumeration.""" +enum TransactionCreateErrorCode { + INVALID + GRAPHQL_ERROR + NOT_FOUND + INCORRECT_CURRENCY + METADATA_KEY_REQUIRED + UNIQUE +} + +input TransactionCreateInput { + """ + Status of the transaction. + + DEPRECATED: this field will be removed in Saleor 3.14 (Preview Feature). The `status` is not needed. The amounts can be used to define the current status of transactions. + """ + status: String + + """ + Payment type used for this transaction. + + DEPRECATED: this field will be removed in Saleor 3.14 (Preview Feature). Use `name` and `message` instead. + """ + type: String + + """ + Payment name of the transaction. + + Added in Saleor 3.13. + """ + name: String + + """ + The message of the transaction. + + Added in Saleor 3.13. + """ + message: String + + """ + Reference of the transaction. + + DEPRECATED: this field will be removed in Saleor 3.14 (Preview Feature). Use `pspReference` instead. + """ + reference: String + + """ + PSP Reference of the transaction. + + Added in Saleor 3.13. + """ + pspReference: String + + """List of all possible actions for the transaction""" + availableActions: [TransactionActionEnum!] + + """Amount authorized by this transaction.""" + amountAuthorized: MoneyInput + + """Amount charged by this transaction.""" + amountCharged: MoneyInput + + """Amount refunded by this transaction.""" + amountRefunded: MoneyInput + + """ + Amount voided by this transaction. + + DEPRECATED: this field will be removed in Saleor 3.14 (Preview Feature). Use `amountCanceled` instead. + """ + amountVoided: MoneyInput + + """ + Amount canceled by this transaction. + + Added in Saleor 3.13. + """ + amountCanceled: MoneyInput + + """Payment public metadata.""" + metadata: [MetadataInput!] + + """Payment private metadata.""" + privateMetadata: [MetadataInput!] + + """ + The url that will allow to redirect user to payment provider page with transaction event details. + + Added in Saleor 3.13. + """ + externalUrl: String +} + +input TransactionEventInput { + """ + Current status of the payment transaction. + + DEPRECATED: this field will be removed in Saleor 3.14 (Preview Feature). Status will be calculated by Saleor. + """ + status: TransactionStatus + + """ + Reference of the transaction. + + DEPRECATED: this field will be removed in Saleor 3.14 (Preview Feature). Use `pspReference` instead. + """ + reference: String + + """ + PSP Reference related to this action. + + Added in Saleor 3.13. + """ + pspReference: String + + """ + Name of the transaction. + + DEPRECATED: this field will be removed in Saleor 3.14 (Preview Feature). Use `message` instead. `name` field will be added to `message`. + """ + name: String + + """ + The message related to the event. + + Added in Saleor 3.13. + """ + message: String +} + +""" +Create transaction for checkout or order. + +Added in Saleor 3.4. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires the following permissions: OWNER and HANDLE_PAYMENTS. +""" +type TransactionUpdate { + transaction: TransactionItem + errors: [TransactionUpdateError!]! +} + +type TransactionUpdateError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: TransactionUpdateErrorCode! +} + +"""An enumeration.""" +enum TransactionUpdateErrorCode { + INVALID + GRAPHQL_ERROR + NOT_FOUND + INCORRECT_CURRENCY + METADATA_KEY_REQUIRED + UNIQUE +} + +input TransactionUpdateInput { + """ + Status of the transaction. + + DEPRECATED: this field will be removed in Saleor 3.14 (Preview Feature). The `status` is not needed. The amounts can be used to define the current status of transactions. + """ + status: String + + """ + Payment type used for this transaction. + + DEPRECATED: this field will be removed in Saleor 3.14 (Preview Feature). Use `name` and `message` instead. + """ + type: String + + """ + Payment name of the transaction. + + Added in Saleor 3.13. + """ + name: String + + """ + The message of the transaction. + + Added in Saleor 3.13. + """ + message: String + + """ + Reference of the transaction. + + DEPRECATED: this field will be removed in Saleor 3.14 (Preview Feature). Use `pspReference` instead. + """ + reference: String + + """ + PSP Reference of the transaction. + + Added in Saleor 3.13. + """ + pspReference: String + + """List of all possible actions for the transaction""" + availableActions: [TransactionActionEnum!] + + """Amount authorized by this transaction.""" + amountAuthorized: MoneyInput + + """Amount charged by this transaction.""" + amountCharged: MoneyInput + + """Amount refunded by this transaction.""" + amountRefunded: MoneyInput + + """ + Amount voided by this transaction. + + DEPRECATED: this field will be removed in Saleor 3.14 (Preview Feature). Use `amountCanceled` instead. + """ + amountVoided: MoneyInput + + """ + Amount canceled by this transaction. + + Added in Saleor 3.13. + """ + amountCanceled: MoneyInput + + """Payment public metadata.""" + metadata: [MetadataInput!] + + """Payment private metadata.""" + privateMetadata: [MetadataInput!] + + """ + The url that will allow to redirect user to payment provider page with transaction event details. + + Added in Saleor 3.13. + """ + externalUrl: String +} + +""" +Request an action for payment transaction. + +Added in Saleor 3.4. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires one of the following permissions: HANDLE_PAYMENTS. +""" +type TransactionRequestAction { + transaction: TransactionItem + errors: [TransactionRequestActionError!]! +} + +type TransactionRequestActionError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: TransactionRequestActionErrorCode! +} + +"""An enumeration.""" +enum TransactionRequestActionErrorCode { + INVALID + GRAPHQL_ERROR + NOT_FOUND + MISSING_TRANSACTION_ACTION_REQUEST_WEBHOOK +} + +""" +Report the event for the transaction. + +Added in Saleor 3.13. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires the following permissions: OWNER and HANDLE_PAYMENTS. +""" +type TransactionEventReport { + """Defines if the reported event hasn't been processed earlier.""" + alreadyProcessed: Boolean + + """The transaction related to the reported event.""" + transaction: TransactionItem + + """ + The event assigned to this report. if `alreadyProcessed` is set to `true`, the previously processed event will be returned. + """ + transactionEvent: TransactionEvent + errors: [TransactionEventReportError!]! +} + +type TransactionEventReportError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: TransactionEventReportErrorCode! +} + +"""An enumeration.""" +enum TransactionEventReportErrorCode { + INVALID + GRAPHQL_ERROR + NOT_FOUND + INCORRECT_DETAILS + ALREADY_EXISTS +} + +""" +Initializes a payment gateway session. It triggers the webhook `PAYMENT_GATEWAY_INITIALIZE_SESSION`, to the requested `paymentGateways`. If `paymentGateways` is not provided, the webhook will be send to all subscribed payment gateways. + +Added in Saleor 3.13. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type PaymentGatewayInitialize { + gatewayConfigs: [PaymentGatewayConfig!] + errors: [PaymentGatewayInitializeError!]! +} + +type PaymentGatewayConfig { + """The app identifier.""" + id: String! + + """The JSON data required to initialize the payment gateway.""" + data: JSON + errors: [PaymentGatewayConfigError!] +} + +scalar JSON + +type PaymentGatewayConfigError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: PaymentGatewayConfigErrorCode! +} + +"""An enumeration.""" +enum PaymentGatewayConfigErrorCode { + GRAPHQL_ERROR + INVALID + NOT_FOUND +} + +type PaymentGatewayInitializeError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: PaymentGatewayInitializeErrorCode! +} + +"""An enumeration.""" +enum PaymentGatewayInitializeErrorCode { + GRAPHQL_ERROR + INVALID + NOT_FOUND +} + +input PaymentGatewayToInitialize { + """The identifier of the payment gateway app to initialize.""" + id: String! + + """The data that will be passed to the payment gateway.""" + data: JSON +} + +""" +Initializes a transaction session. It triggers the webhook `TRANSACTION_INITIALIZE_SESSION`, to the requested `paymentGateways`. + +Added in Saleor 3.13. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type TransactionInitialize { + """The initialized transaction.""" + transaction: TransactionItem + + """The event created for the initialized transaction.""" + transactionEvent: TransactionEvent + + """The JSON data required to finalize the payment.""" + data: JSON + errors: [TransactionInitializeError!]! +} + +type TransactionInitializeError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: TransactionInitializeErrorCode! +} + +"""An enumeration.""" +enum TransactionInitializeErrorCode { + GRAPHQL_ERROR + INVALID + NOT_FOUND +} + +""" +Processes a transaction session. It triggers the webhook `TRANSACTION_PROCESS_SESSION`, to the assigned `paymentGateways`. + +Added in Saleor 3.13. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type TransactionProcess { + """The processed transaction.""" + transaction: TransactionItem + + """The event created for the processed transaction.""" + transactionEvent: TransactionEvent + + """The json data required to finalize the payment.""" + data: JSON + errors: [TransactionProcessError!]! +} + +type TransactionProcessError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: TransactionProcessErrorCode! +} + +"""An enumeration.""" +enum TransactionProcessErrorCode { + GRAPHQL_ERROR + INVALID + NOT_FOUND + TRANSACTION_ALREADY_PROCESSED + MISSING_PAYMENT_APP_RELATION + MISSING_PAYMENT_APP +} + +""" +Creates a new page. + +Requires one of the following permissions: MANAGE_PAGES. +""" +type PageCreate { + pageErrors: [PageError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [PageError!]! + page: Page +} + +type PageError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: PageErrorCode! + + """List of attributes IDs which causes the error.""" + attributes: [ID!] + + """List of attribute values IDs which causes the error.""" + values: [ID!] +} + +"""An enumeration.""" +enum PageErrorCode { + GRAPHQL_ERROR + INVALID + NOT_FOUND + REQUIRED + UNIQUE + DUPLICATED_INPUT_ITEM + ATTRIBUTE_ALREADY_ASSIGNED +} + +input PageCreateInput { + """Page internal name.""" + slug: String + + """Page title.""" + title: String + + """ + Page content. + + Rich text format. For reference see https://editorjs.io/ + """ + content: JSONString + + """List of attributes.""" + attributes: [AttributeValueInput!] + + """Determines if page is visible in the storefront.""" + isPublished: Boolean + + """ + Publication date. ISO 8601 standard. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `publishedAt` field instead. + """ + publicationDate: String + + """ + Publication date time. ISO 8601 standard. + + Added in Saleor 3.3. + """ + publishedAt: DateTime + + """Search engine optimization fields.""" + seo: SeoInput + + """ID of the page type that page belongs to.""" + pageType: ID! +} + +""" +Deletes a page. + +Requires one of the following permissions: MANAGE_PAGES. +""" +type PageDelete { + pageErrors: [PageError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [PageError!]! + page: Page +} + +""" +Deletes pages. + +Requires one of the following permissions: MANAGE_PAGES. +""" +type PageBulkDelete { + """Returns how many objects were affected.""" + count: Int! + pageErrors: [PageError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [PageError!]! +} + +""" +Publish pages. + +Requires one of the following permissions: MANAGE_PAGES. +""" +type PageBulkPublish { + """Returns how many objects were affected.""" + count: Int! + pageErrors: [PageError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [PageError!]! +} + +""" +Updates an existing page. + +Requires one of the following permissions: MANAGE_PAGES. +""" +type PageUpdate { + pageErrors: [PageError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [PageError!]! + page: Page +} + +input PageInput { + """Page internal name.""" + slug: String + + """Page title.""" + title: String + + """ + Page content. + + Rich text format. For reference see https://editorjs.io/ + """ + content: JSONString + + """List of attributes.""" + attributes: [AttributeValueInput!] + + """Determines if page is visible in the storefront.""" + isPublished: Boolean + + """ + Publication date. ISO 8601 standard. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `publishedAt` field instead. + """ + publicationDate: String + + """ + Publication date time. ISO 8601 standard. + + Added in Saleor 3.3. + """ + publishedAt: DateTime + + """Search engine optimization fields.""" + seo: SeoInput +} + +""" +Creates/updates translations for a page. + +Requires one of the following permissions: MANAGE_TRANSLATIONS. +""" +type PageTranslate { + translationErrors: [TranslationError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [TranslationError!]! + page: PageTranslatableContent +} + +input PageTranslationInput { + seoTitle: String + seoDescription: String + title: String + + """ + Translated page content. + + Rich text format. For reference see https://editorjs.io/ + """ + content: JSONString +} + +""" +Create a new page type. + +Requires one of the following permissions: MANAGE_PAGE_TYPES_AND_ATTRIBUTES. +""" +type PageTypeCreate { + pageErrors: [PageError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [PageError!]! + pageType: PageType +} + +input PageTypeCreateInput { + """Name of the page type.""" + name: String + + """Page type slug.""" + slug: String + + """List of attribute IDs to be assigned to the page type.""" + addAttributes: [ID!] +} + +""" +Update page type. + +Requires one of the following permissions: MANAGE_PAGE_TYPES_AND_ATTRIBUTES. +""" +type PageTypeUpdate { + pageErrors: [PageError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [PageError!]! + pageType: PageType +} + +input PageTypeUpdateInput { + """Name of the page type.""" + name: String + + """Page type slug.""" + slug: String + + """List of attribute IDs to be assigned to the page type.""" + addAttributes: [ID!] + + """List of attribute IDs to be assigned to the page type.""" + removeAttributes: [ID!] +} + +""" +Delete a page type. + +Requires one of the following permissions: MANAGE_PAGE_TYPES_AND_ATTRIBUTES. +""" +type PageTypeDelete { + pageErrors: [PageError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [PageError!]! + pageType: PageType +} + +""" +Delete page types. + +Requires one of the following permissions: MANAGE_PAGE_TYPES_AND_ATTRIBUTES. +""" +type PageTypeBulkDelete { + """Returns how many objects were affected.""" + count: Int! + pageErrors: [PageError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [PageError!]! +} + +""" +Assign attributes to a given page type. + +Requires one of the following permissions: MANAGE_PAGE_TYPES_AND_ATTRIBUTES. +""" +type PageAttributeAssign { + """The updated page type.""" + pageType: PageType + pageErrors: [PageError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [PageError!]! +} + +""" +Unassign attributes from a given page type. + +Requires one of the following permissions: MANAGE_PAGE_TYPES_AND_ATTRIBUTES. +""" +type PageAttributeUnassign { + """The updated page type.""" + pageType: PageType + pageErrors: [PageError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [PageError!]! +} + +""" +Reorder the attributes of a page type. + +Requires one of the following permissions: MANAGE_PAGE_TYPES_AND_ATTRIBUTES. +""" +type PageTypeReorderAttributes { + """Page type from which attributes are reordered.""" + pageType: PageType + pageErrors: [PageError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [PageError!]! +} + +""" +Reorder page attribute values. + +Requires one of the following permissions: MANAGE_PAGES. +""" +type PageReorderAttributeValues { + """Page from which attribute values are reordered.""" + page: Page + pageErrors: [PageError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [PageError!]! +} + +""" +Completes creating an order. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type DraftOrderComplete { + """Completed order.""" + order: Order + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! +} + +""" +Creates a new draft order. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type DraftOrderCreate { + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! + order: Order +} + +input DraftOrderCreateInput { + """Billing address of the customer.""" + billingAddress: AddressInput + + """Customer associated with the draft order.""" + user: ID + + """Email address of the customer.""" + userEmail: String + + """Discount amount for the order.""" + discount: PositiveDecimal + + """Shipping address of the customer.""" + shippingAddress: AddressInput + + """ID of a selected shipping method.""" + shippingMethod: ID + + """ID of the voucher associated with the order.""" + voucher: ID + + """A note from a customer. Visible by customers in the order summary.""" + customerNote: String + + """ID of the channel associated with the order.""" + channelId: ID + + """ + URL of a view where users should be redirected to see the order details. URL in RFC 1808 format. + """ + redirectUrl: String + + """ + External ID of this order. + + Added in Saleor 3.10. + """ + externalReference: String + + """Variant line input consisting of variant ID and quantity of products.""" + lines: [OrderLineCreateInput!] +} + +input OrderLineCreateInput { + """Number of variant items ordered.""" + quantity: Int! + + """Product variant ID.""" + variantId: ID! + + """ + Flag that allow force splitting the same variant into multiple lines by skipping the matching logic. + + Added in Saleor 3.6. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + forceNewLine: Boolean = false +} + +""" +Deletes a draft order. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type DraftOrderDelete { + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! + order: Order +} + +""" +Deletes draft orders. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type DraftOrderBulkDelete { + """Returns how many objects were affected.""" + count: Int! + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! +} + +""" +Deletes order lines. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type DraftOrderLinesBulkDelete { + """Returns how many objects were affected.""" + count: Int! + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! +} + +""" +Updates a draft order. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type DraftOrderUpdate { + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! + order: Order +} + +input DraftOrderInput { + """Billing address of the customer.""" + billingAddress: AddressInput + + """Customer associated with the draft order.""" + user: ID + + """Email address of the customer.""" + userEmail: String + + """Discount amount for the order.""" + discount: PositiveDecimal + + """Shipping address of the customer.""" + shippingAddress: AddressInput + + """ID of a selected shipping method.""" + shippingMethod: ID + + """ID of the voucher associated with the order.""" + voucher: ID + + """A note from a customer. Visible by customers in the order summary.""" + customerNote: String + + """ID of the channel associated with the order.""" + channelId: ID + + """ + URL of a view where users should be redirected to see the order details. URL in RFC 1808 format. + """ + redirectUrl: String + + """ + External ID of this order. + + Added in Saleor 3.10. + """ + externalReference: String +} + +""" +Adds note to the order. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type OrderAddNote { + """Order with the note added.""" + order: Order + + """Order note created.""" + event: OrderEvent + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! +} + +input OrderAddNoteInput { + """Note message.""" + message: String! +} + +""" +Cancel an order. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type OrderCancel { + """Canceled order.""" + order: Order + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! +} + +""" +Capture an order. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type OrderCapture { + """Captured order.""" + order: Order + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! +} + +""" +Confirms an unconfirmed order by changing status to unfulfilled. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type OrderConfirm { + order: Order + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! +} + +""" +Creates new fulfillments for an order. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type OrderFulfill { + """List of created fulfillments.""" + fulfillments: [Fulfillment!] + + """Fulfilled order.""" + order: Order + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! +} + +input OrderFulfillInput { + """List of items informing how to fulfill the order.""" + lines: [OrderFulfillLineInput!]! + + """If true, send an email notification to the customer.""" + notifyCustomer: Boolean + + """If true, then allow proceed fulfillment when stock is exceeded.""" + allowStockToBeExceeded: Boolean = false + + """ + Fulfillment tracking number. + + Added in Saleor 3.6. + """ + trackingNumber: String +} + +input OrderFulfillLineInput { + """The ID of the order line.""" + orderLineId: ID + + """List of stock items to create.""" + stocks: [OrderFulfillStockInput!]! +} + +input OrderFulfillStockInput { + """The number of line items to be fulfilled from given warehouse.""" + quantity: Int! + + """ID of the warehouse from which the item will be fulfilled.""" + warehouse: ID! +} + +""" +Cancels existing fulfillment and optionally restocks items. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type FulfillmentCancel { + """A canceled fulfillment.""" + fulfillment: Fulfillment + + """Order which fulfillment was cancelled.""" + order: Order + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! +} + +input FulfillmentCancelInput { + """ + ID of a warehouse where items will be restocked. Optional when fulfillment is in WAITING_FOR_APPROVAL state. + """ + warehouseId: ID +} + +""" +Approve existing fulfillment. + +Added in Saleor 3.1. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type FulfillmentApprove { + """An approved fulfillment.""" + fulfillment: Fulfillment + + """Order which fulfillment was approved.""" + order: Order + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! +} + +""" +Updates a fulfillment for an order. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type FulfillmentUpdateTracking { + """A fulfillment with updated tracking.""" + fulfillment: Fulfillment + + """Order for which fulfillment was updated.""" + order: Order + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! +} + +input FulfillmentUpdateTrackingInput { + """Fulfillment tracking number.""" + trackingNumber: String + + """If true, send an email notification to the customer.""" + notifyCustomer: Boolean = false +} + +""" +Refund products. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type FulfillmentRefundProducts { + """A refunded fulfillment.""" + fulfillment: Fulfillment + + """Order which fulfillment was refunded.""" + order: Order + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! +} + +input OrderRefundProductsInput { + """List of unfulfilled lines to refund.""" + orderLines: [OrderRefundLineInput!] + + """List of fulfilled lines to refund.""" + fulfillmentLines: [OrderRefundFulfillmentLineInput!] + + """The total amount of refund when the value is provided manually.""" + amountToRefund: PositiveDecimal + + """ + If true, Saleor will refund shipping costs. If amountToRefund is providedincludeShippingCosts will be ignored. + """ + includeShippingCosts: Boolean = false +} + +input OrderRefundLineInput { + """The ID of the order line to refund.""" + orderLineId: ID! + + """The number of items to be refunded.""" + quantity: Int! +} + +input OrderRefundFulfillmentLineInput { + """The ID of the fulfillment line to refund.""" + fulfillmentLineId: ID! + + """The number of items to be refunded.""" + quantity: Int! +} + +""" +Return products. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type FulfillmentReturnProducts { + """A return fulfillment.""" + returnFulfillment: Fulfillment + + """A replace fulfillment.""" + replaceFulfillment: Fulfillment + + """Order which fulfillment was returned.""" + order: Order + + """A draft order which was created for products with replace flag.""" + replaceOrder: Order + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! +} + +input OrderReturnProductsInput { + """List of unfulfilled lines to return.""" + orderLines: [OrderReturnLineInput!] + + """List of fulfilled lines to return.""" + fulfillmentLines: [OrderReturnFulfillmentLineInput!] + + """The total amount of refund when the value is provided manually.""" + amountToRefund: PositiveDecimal + + """ + If true, Saleor will refund shipping costs. If amountToRefund is providedincludeShippingCosts will be ignored. + """ + includeShippingCosts: Boolean = false + + """If true, Saleor will call refund action for all lines.""" + refund: Boolean = false +} + +input OrderReturnLineInput { + """The ID of the order line to return.""" + orderLineId: ID! + + """The number of items to be returned.""" + quantity: Int! + + """Determines, if the line should be added to replace order.""" + replace: Boolean = false +} + +input OrderReturnFulfillmentLineInput { + """The ID of the fulfillment line to return.""" + fulfillmentLineId: ID! + + """The number of items to be returned.""" + quantity: Int! + + """Determines, if the line should be added to replace order.""" + replace: Boolean = false +} + +""" +Adds granted refund to the order. + +Added in Saleor 3.13. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type OrderGrantRefundCreate { + """Order which has assigned new grant refund.""" + order: Order + + """Created granted refund.""" + grantedRefund: OrderGrantedRefund + errors: [OrderGrantRefundCreateError!]! +} + +type OrderGrantRefundCreateError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: OrderGrantRefundCreateErrorCode! +} + +"""An enumeration.""" +enum OrderGrantRefundCreateErrorCode { + GRAPHQL_ERROR + NOT_FOUND +} + +input OrderGrantRefundCreateInput { + """Amount of the granted refund.""" + amount: Decimal! + + """Reason of the granted refund.""" + reason: String +} + +""" +Custom Decimal implementation. + +Returns Decimal as a float in the API, +parses float to the Decimal on the way back. +""" +scalar Decimal + +""" +Updates granted refund. + +Added in Saleor 3.13. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type OrderGrantRefundUpdate { + """Order which has assigned updated grant refund.""" + order: Order + + """Created granted refund.""" + grantedRefund: OrderGrantedRefund + errors: [OrderGrantRefundUpdateError!]! + orderGrantedRefund: OrderGrantedRefund +} + +type OrderGrantRefundUpdateError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: OrderGrantRefundUpdateErrorCode! +} + +"""An enumeration.""" +enum OrderGrantRefundUpdateErrorCode { + GRAPHQL_ERROR + NOT_FOUND + REQUIRED +} + +input OrderGrantRefundUpdateInput { + """Amount of the granted refund.""" + amount: Decimal + + """Reason of the granted refund.""" + reason: String +} + +""" +Create order lines for an order. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type OrderLinesCreate { + """Related order.""" + order: Order + + """List of added order lines.""" + orderLines: [OrderLine!] + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! +} + +""" +Deletes an order line from an order. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type OrderLineDelete { + """A related order.""" + order: Order + + """An order line that was deleted.""" + orderLine: OrderLine + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! +} + +""" +Updates an order line of an order. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type OrderLineUpdate { + """Related order.""" + order: Order + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! + orderLine: OrderLine +} + +input OrderLineInput { + """Number of variant items ordered.""" + quantity: Int! +} + +""" +Adds discount to the order. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type OrderDiscountAdd { + """Order which has been discounted.""" + order: Order + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! +} + +input OrderDiscountCommonInput { + """Type of the discount: fixed or percent""" + valueType: DiscountValueTypeEnum! + + """Value of the discount. Can store fixed value or percent value""" + value: PositiveDecimal! + + """Explanation for the applied discount.""" + reason: String +} + +""" +Update discount for the order. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type OrderDiscountUpdate { + """Order which has been discounted.""" + order: Order + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! +} + +""" +Remove discount from the order. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type OrderDiscountDelete { + """Order which has removed discount.""" + order: Order + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! +} + +""" +Update discount for the order line. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type OrderLineDiscountUpdate { + """Order line which has been discounted.""" + orderLine: OrderLine + + """Order which is related to the discounted line.""" + order: Order + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! +} + +""" +Remove discount applied to the order line. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type OrderLineDiscountRemove { + """Order line which has removed discount.""" + orderLine: OrderLine + + """Order which is related to line which has removed discount.""" + order: Order + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! +} + +""" +Mark order as manually paid. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type OrderMarkAsPaid { + """Order marked as paid.""" + order: Order + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! +} + +""" +Refund an order. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type OrderRefund { + """A refunded order.""" + order: Order + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! +} + +""" +Updates an order. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type OrderUpdate { + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! + order: Order +} + +input OrderUpdateInput { + """Billing address of the customer.""" + billingAddress: AddressInput + + """Email address of the customer.""" + userEmail: String + + """Shipping address of the customer.""" + shippingAddress: AddressInput + + """ + External ID of this order. + + Added in Saleor 3.10. + """ + externalReference: String +} + +""" +Updates a shipping method of the order. Requires shipping method ID to update, when null is passed then currently assigned shipping method is removed. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type OrderUpdateShipping { + """Order with updated shipping method.""" + order: Order + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! +} + +input OrderUpdateShippingInput { + """ + ID of the selected shipping method, pass null to remove currently assigned shipping method. + """ + shippingMethod: ID +} + +""" +Void an order. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type OrderVoid { + """A voided order.""" + order: Order + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! +} + +""" +Cancels orders. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type OrderBulkCancel { + """Returns how many objects were affected.""" + count: Int! + orderErrors: [OrderError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [OrderError!]! +} + +""" +Delete metadata of an object. To use it, you need to have access to the modified object. +""" +type DeleteMetadata { + metadataErrors: [MetadataError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [MetadataError!]! + item: ObjectWithMetadata +} + +type MetadataError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: MetadataErrorCode! +} + +"""An enumeration.""" +enum MetadataErrorCode { + GRAPHQL_ERROR + INVALID + NOT_FOUND + REQUIRED + NOT_UPDATED +} + +""" +Delete object's private metadata. To use it, you need to be an authenticated staff user or an app and have access to the modified object. +""" +type DeletePrivateMetadata { + metadataErrors: [MetadataError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [MetadataError!]! + item: ObjectWithMetadata +} + +""" +Updates metadata of an object. To use it, you need to have access to the modified object. +""" +type UpdateMetadata { + metadataErrors: [MetadataError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [MetadataError!]! + item: ObjectWithMetadata +} + +""" +Updates private metadata of an object. To use it, you need to be an authenticated staff user or an app and have access to the modified object. +""" +type UpdatePrivateMetadata { + metadataErrors: [MetadataError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [MetadataError!]! + item: ObjectWithMetadata +} + +""" +Assigns storefront's navigation menus. + +Requires one of the following permissions: MANAGE_MENUS, MANAGE_SETTINGS. +""" +type AssignNavigation { + """Assigned navigation menu.""" + menu: Menu + menuErrors: [MenuError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [MenuError!]! +} + +type MenuError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: MenuErrorCode! +} + +"""An enumeration.""" +enum MenuErrorCode { + CANNOT_ASSIGN_NODE + GRAPHQL_ERROR + INVALID + INVALID_MENU_ITEM + NO_MENU_ITEM_PROVIDED + NOT_FOUND + REQUIRED + TOO_MANY_MENU_ITEMS + UNIQUE +} + +enum NavigationType { + """Main storefront navigation.""" + MAIN + + """Secondary storefront navigation.""" + SECONDARY +} + +""" +Creates a new Menu. + +Requires one of the following permissions: MANAGE_MENUS. +""" +type MenuCreate { + menuErrors: [MenuError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [MenuError!]! + menu: Menu +} + +input MenuCreateInput { + """Name of the menu.""" + name: String! + + """Slug of the menu. Will be generated if not provided.""" + slug: String + + """List of menu items.""" + items: [MenuItemInput!] +} + +input MenuItemInput { + """Name of the menu item.""" + name: String + + """URL of the pointed item.""" + url: String + + """Category to which item points.""" + category: ID + + """Collection to which item points.""" + collection: ID + + """Page to which item points.""" + page: ID +} + +""" +Deletes a menu. + +Requires one of the following permissions: MANAGE_MENUS. +""" +type MenuDelete { + menuErrors: [MenuError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [MenuError!]! + menu: Menu +} + +""" +Deletes menus. + +Requires one of the following permissions: MANAGE_MENUS. +""" +type MenuBulkDelete { + """Returns how many objects were affected.""" + count: Int! + menuErrors: [MenuError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [MenuError!]! +} + +""" +Updates a menu. + +Requires one of the following permissions: MANAGE_MENUS. +""" +type MenuUpdate { + menuErrors: [MenuError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [MenuError!]! + menu: Menu +} + +input MenuInput { + """Name of the menu.""" + name: String + + """Slug of the menu.""" + slug: String +} + +""" +Creates a new menu item. + +Requires one of the following permissions: MANAGE_MENUS. +""" +type MenuItemCreate { + menuErrors: [MenuError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [MenuError!]! + menuItem: MenuItem +} + +input MenuItemCreateInput { + """Name of the menu item.""" + name: String! + + """URL of the pointed item.""" + url: String + + """Category to which item points.""" + category: ID + + """Collection to which item points.""" + collection: ID + + """Page to which item points.""" + page: ID + + """Menu to which item belongs.""" + menu: ID! + + """ID of the parent menu. If empty, menu will be top level menu.""" + parent: ID +} + +""" +Deletes a menu item. + +Requires one of the following permissions: MANAGE_MENUS. +""" +type MenuItemDelete { + menuErrors: [MenuError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [MenuError!]! + menuItem: MenuItem +} + +""" +Deletes menu items. + +Requires one of the following permissions: MANAGE_MENUS. +""" +type MenuItemBulkDelete { + """Returns how many objects were affected.""" + count: Int! + menuErrors: [MenuError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [MenuError!]! +} + +""" +Updates a menu item. + +Requires one of the following permissions: MANAGE_MENUS. +""" +type MenuItemUpdate { + menuErrors: [MenuError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [MenuError!]! + menuItem: MenuItem +} + +""" +Creates/updates translations for a menu item. + +Requires one of the following permissions: MANAGE_TRANSLATIONS. +""" +type MenuItemTranslate { + translationErrors: [TranslationError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [TranslationError!]! + menuItem: MenuItem +} + +""" +Moves items of menus. + +Requires one of the following permissions: MANAGE_MENUS. +""" +type MenuItemMove { + """Assigned menu to move within.""" + menu: Menu + menuErrors: [MenuError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [MenuError!]! +} + +input MenuItemMoveInput { + """The menu item ID to move.""" + itemId: ID! + + """ID of the parent menu. If empty, menu will be top level menu.""" + parentId: ID + + """ + The new relative sorting position of the item (from -inf to +inf). 1 moves the item one position forward, -1 moves the item one position backward, 0 leaves the item unchanged. + """ + sortOrder: Int +} + +""" +Request an invoice for the order using plugin. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type InvoiceRequest { + """Order related to an invoice.""" + order: Order + invoiceErrors: [InvoiceError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [InvoiceError!]! + invoice: Invoice +} + +type InvoiceError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: InvoiceErrorCode! +} + +"""An enumeration.""" +enum InvoiceErrorCode { + REQUIRED + NOT_READY + URL_NOT_SET + EMAIL_NOT_SET + NUMBER_NOT_SET + NOT_FOUND + INVALID_STATUS + NO_INVOICE_PLUGIN +} + +""" +Requests deletion of an invoice. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type InvoiceRequestDelete { + invoiceErrors: [InvoiceError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [InvoiceError!]! + invoice: Invoice +} + +""" +Creates a ready to send invoice. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type InvoiceCreate { + invoiceErrors: [InvoiceError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [InvoiceError!]! + invoice: Invoice +} + +input InvoiceCreateInput { + """Invoice number.""" + number: String! + + """URL of an invoice to download.""" + url: String! +} + +""" +Deletes an invoice. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type InvoiceDelete { + invoiceErrors: [InvoiceError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [InvoiceError!]! + invoice: Invoice +} + +""" +Updates an invoice. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type InvoiceUpdate { + invoiceErrors: [InvoiceError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [InvoiceError!]! + invoice: Invoice +} + +input UpdateInvoiceInput { + """Invoice number""" + number: String + + """URL of an invoice to download.""" + url: String +} + +""" +Send an invoice notification to the customer. + +Requires one of the following permissions: MANAGE_ORDERS. +""" +type InvoiceSendNotification { + invoiceErrors: [InvoiceError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [InvoiceError!]! + invoice: Invoice +} + +""" +Activate a gift card. + +Requires one of the following permissions: MANAGE_GIFT_CARD. +""" +type GiftCardActivate { + """Activated gift card.""" + giftCard: GiftCard + giftCardErrors: [GiftCardError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [GiftCardError!]! +} + +type GiftCardError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: GiftCardErrorCode! + + """List of tag values that cause the error.""" + tags: [String!] +} + +"""An enumeration.""" +enum GiftCardErrorCode { + ALREADY_EXISTS + GRAPHQL_ERROR + INVALID + NOT_FOUND + REQUIRED + UNIQUE + EXPIRED_GIFT_CARD + DUPLICATED_INPUT_ITEM +} + +""" +Creates a new gift card. + +Requires one of the following permissions: MANAGE_GIFT_CARD. +""" +type GiftCardCreate { + giftCardErrors: [GiftCardError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [GiftCardError!]! + giftCard: GiftCard +} + +input GiftCardCreateInput { + """ + The gift card tags to add. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + addTags: [String!] + + """ + The gift card expiry date. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + expiryDate: Date + + """ + Start date of the gift card in ISO 8601 format. + + DEPRECATED: this field will be removed in Saleor 4.0. + """ + startDate: Date + + """ + End date of the gift card in ISO 8601 format. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `expiryDate` from `expirySettings` instead. + """ + endDate: Date + + """Balance of the gift card.""" + balance: PriceInput! + + """Email of the customer to whom gift card will be sent.""" + userEmail: String + + """ + Slug of a channel from which the email should be sent. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + channel: String + + """ + Determine if gift card is active. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + isActive: Boolean! + + """ + Code to use the gift card. + + DEPRECATED: this field will be removed in Saleor 4.0. The code is now auto generated. + """ + code: String + + """ + The gift card note from the staff member. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + note: String +} + +input PriceInput { + """Currency code.""" + currency: String! + + """Amount of money.""" + amount: PositiveDecimal! +} + +""" +Delete gift card. + +Added in Saleor 3.1. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires one of the following permissions: MANAGE_GIFT_CARD. +""" +type GiftCardDelete { + giftCardErrors: [GiftCardError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [GiftCardError!]! + giftCard: GiftCard +} + +""" +Deactivate a gift card. + +Requires one of the following permissions: MANAGE_GIFT_CARD. +""" +type GiftCardDeactivate { + """Deactivated gift card.""" + giftCard: GiftCard + giftCardErrors: [GiftCardError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [GiftCardError!]! +} + +""" +Update a gift card. + +Requires one of the following permissions: MANAGE_GIFT_CARD. +""" +type GiftCardUpdate { + giftCardErrors: [GiftCardError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [GiftCardError!]! + giftCard: GiftCard +} + +input GiftCardUpdateInput { + """ + The gift card tags to add. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + addTags: [String!] + + """ + The gift card expiry date. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + expiryDate: Date + + """ + Start date of the gift card in ISO 8601 format. + + DEPRECATED: this field will be removed in Saleor 4.0. + """ + startDate: Date + + """ + End date of the gift card in ISO 8601 format. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `expiryDate` from `expirySettings` instead. + """ + endDate: Date + + """ + The gift card tags to remove. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + removeTags: [String!] + + """ + The gift card balance amount. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + balanceAmount: PositiveDecimal +} + +""" +Resend a gift card. + +Added in Saleor 3.1. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires one of the following permissions: MANAGE_GIFT_CARD. +""" +type GiftCardResend { + """Gift card which has been sent.""" + giftCard: GiftCard + errors: [GiftCardError!]! +} + +input GiftCardResendInput { + """ID of a gift card to resend.""" + id: ID! + + """Email to which gift card should be send.""" + email: String + + """Slug of a channel from which the email should be sent.""" + channel: String! +} + +""" +Adds note to the gift card. + +Added in Saleor 3.1. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires one of the following permissions: MANAGE_GIFT_CARD. +""" +type GiftCardAddNote { + """Gift card with the note added.""" + giftCard: GiftCard + + """Gift card note created.""" + event: GiftCardEvent + errors: [GiftCardError!]! +} + +input GiftCardAddNoteInput { + """Note message.""" + message: String! +} + +""" +Create gift cards. + +Added in Saleor 3.1. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires one of the following permissions: MANAGE_GIFT_CARD. +""" +type GiftCardBulkCreate { + """Returns how many objects were created.""" + count: Int! + + """List of created gift cards.""" + giftCards: [GiftCard!]! + errors: [GiftCardError!]! +} + +input GiftCardBulkCreateInput { + """The number of cards to issue.""" + count: Int! + + """Balance of the gift card.""" + balance: PriceInput! + + """The gift card tags.""" + tags: [String!] + + """The gift card expiry date.""" + expiryDate: Date + + """Determine if gift card is active.""" + isActive: Boolean! +} + +""" +Delete gift cards. + +Added in Saleor 3.1. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires one of the following permissions: MANAGE_GIFT_CARD. +""" +type GiftCardBulkDelete { + """Returns how many objects were affected.""" + count: Int! + errors: [GiftCardError!]! +} + +""" +Activate gift cards. + +Added in Saleor 3.1. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires one of the following permissions: MANAGE_GIFT_CARD. +""" +type GiftCardBulkActivate { + """Returns how many objects were affected.""" + count: Int! + errors: [GiftCardError!]! +} + +""" +Deactivate gift cards. + +Added in Saleor 3.1. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires one of the following permissions: MANAGE_GIFT_CARD. +""" +type GiftCardBulkDeactivate { + """Returns how many objects were affected.""" + count: Int! + errors: [GiftCardError!]! +} + +""" +Update plugin configuration. + +Requires one of the following permissions: MANAGE_PLUGINS. +""" +type PluginUpdate { + plugin: Plugin + pluginsErrors: [PluginError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [PluginError!]! +} + +type PluginError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: PluginErrorCode! +} + +"""An enumeration.""" +enum PluginErrorCode { + GRAPHQL_ERROR + INVALID + PLUGIN_MISCONFIGURED + NOT_FOUND + REQUIRED + UNIQUE +} + +input PluginUpdateInput { + """Indicates whether the plugin should be enabled.""" + active: Boolean + + """Configuration of the plugin.""" + configuration: [ConfigurationItemInput!] +} + +input ConfigurationItemInput { + """Name of the field to update.""" + name: String! + + """Value of the given field to update.""" + value: String +} + +""" +Trigger sending a notification with the notify plugin method. Serializes nodes provided as ids parameter and includes this data in the notification payload. + +Added in Saleor 3.1. +""" +type ExternalNotificationTrigger { + errors: [ExternalNotificationError!]! +} + +type ExternalNotificationError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: ExternalNotificationErrorCodes! +} + +"""An enumeration.""" +enum ExternalNotificationErrorCodes { + REQUIRED + INVALID_MODEL_TYPE + NOT_FOUND + CHANNEL_INACTIVE +} + +input ExternalNotificationTriggerInput { + """ + The list of customers or orders node IDs that will be serialized and included in the notification payload. + """ + ids: [ID!]! + + """ + Additional payload that will be merged with the one based on the bussines object ID. + """ + extraPayload: JSONString + + """ + External event type. This field is passed to a plugin as an event type. + """ + externalEventType: String! +} + +""" +Creates a new sale. + +Requires one of the following permissions: MANAGE_DISCOUNTS. +""" +type SaleCreate { + discountErrors: [DiscountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [DiscountError!]! + sale: Sale +} + +type DiscountError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """List of products IDs which causes the error.""" + products: [ID!] + + """The error code.""" + code: DiscountErrorCode! + + """List of channels IDs which causes the error.""" + channels: [ID!] +} + +"""An enumeration.""" +enum DiscountErrorCode { + ALREADY_EXISTS + GRAPHQL_ERROR + INVALID + NOT_FOUND + REQUIRED + UNIQUE + CANNOT_MANAGE_PRODUCT_WITHOUT_VARIANT + DUPLICATED_INPUT_ITEM +} + +input SaleInput { + """Voucher name.""" + name: String + + """Fixed or percentage.""" + type: DiscountValueTypeEnum + + """Value of the voucher.""" + value: PositiveDecimal + + """Products related to the discount.""" + products: [ID!] + variants: [ID!] + + """Categories related to the discount.""" + categories: [ID!] + + """Collections related to the discount.""" + collections: [ID!] + + """Start date of the voucher in ISO 8601 format.""" + startDate: DateTime + + """End date of the voucher in ISO 8601 format.""" + endDate: DateTime +} + +""" +Deletes a sale. + +Requires one of the following permissions: MANAGE_DISCOUNTS. +""" +type SaleDelete { + discountErrors: [DiscountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [DiscountError!]! + sale: Sale +} + +""" +Deletes sales. + +Requires one of the following permissions: MANAGE_DISCOUNTS. +""" +type SaleBulkDelete { + """Returns how many objects were affected.""" + count: Int! + discountErrors: [DiscountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [DiscountError!]! +} + +""" +Updates a sale. + +Requires one of the following permissions: MANAGE_DISCOUNTS. +""" +type SaleUpdate { + discountErrors: [DiscountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [DiscountError!]! + sale: Sale +} + +""" +Adds products, categories, collections to a voucher. + +Requires one of the following permissions: MANAGE_DISCOUNTS. +""" +type SaleAddCatalogues { + """Sale of which catalogue IDs will be modified.""" + sale: Sale + discountErrors: [DiscountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [DiscountError!]! +} + +input CatalogueInput { + """Products related to the discount.""" + products: [ID!] + + """Categories related to the discount.""" + categories: [ID!] + + """Collections related to the discount.""" + collections: [ID!] + + """ + Product variant related to the discount. + + Added in Saleor 3.1. + """ + variants: [ID!] +} + +""" +Removes products, categories, collections from a sale. + +Requires one of the following permissions: MANAGE_DISCOUNTS. +""" +type SaleRemoveCatalogues { + """Sale of which catalogue IDs will be modified.""" + sale: Sale + discountErrors: [DiscountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [DiscountError!]! +} + +""" +Creates/updates translations for a sale. + +Requires one of the following permissions: MANAGE_TRANSLATIONS. +""" +type SaleTranslate { + translationErrors: [TranslationError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [TranslationError!]! + sale: Sale +} + +""" +Manage sale's availability in channels. + +Requires one of the following permissions: MANAGE_DISCOUNTS. +""" +type SaleChannelListingUpdate { + """An updated sale instance.""" + sale: Sale + discountErrors: [DiscountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [DiscountError!]! +} + +input SaleChannelListingInput { + """List of channels to which the sale should be assigned.""" + addChannels: [SaleChannelListingAddInput!] + + """List of channels from which the sale should be unassigned.""" + removeChannels: [ID!] +} + +input SaleChannelListingAddInput { + """ID of a channel.""" + channelId: ID! + + """The value of the discount.""" + discountValue: PositiveDecimal! +} + +""" +Creates a new voucher. + +Requires one of the following permissions: MANAGE_DISCOUNTS. +""" +type VoucherCreate { + discountErrors: [DiscountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [DiscountError!]! + voucher: Voucher +} + +input VoucherInput { + """Voucher type: PRODUCT, CATEGORY SHIPPING or ENTIRE_ORDER.""" + type: VoucherTypeEnum + + """Voucher name.""" + name: String + + """Code to use the voucher.""" + code: String + + """Start date of the voucher in ISO 8601 format.""" + startDate: DateTime + + """End date of the voucher in ISO 8601 format.""" + endDate: DateTime + + """Choices: fixed or percentage.""" + discountValueType: DiscountValueTypeEnum + + """Products discounted by the voucher.""" + products: [ID!] + + """ + Variants discounted by the voucher. + + Added in Saleor 3.1. + """ + variants: [ID!] + + """Collections discounted by the voucher.""" + collections: [ID!] + + """Categories discounted by the voucher.""" + categories: [ID!] + + """Minimal quantity of checkout items required to apply the voucher.""" + minCheckoutItemsQuantity: Int + + """Country codes that can be used with the shipping voucher.""" + countries: [String!] + + """Voucher should be applied to the cheapest item or entire order.""" + applyOncePerOrder: Boolean + + """Voucher should be applied once per customer.""" + applyOncePerCustomer: Boolean + + """Voucher can be used only by staff user.""" + onlyForStaff: Boolean + + """Limit number of times this voucher can be used in total.""" + usageLimit: Int +} + +""" +Deletes a voucher. + +Requires one of the following permissions: MANAGE_DISCOUNTS. +""" +type VoucherDelete { + discountErrors: [DiscountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [DiscountError!]! + voucher: Voucher +} + +""" +Deletes vouchers. + +Requires one of the following permissions: MANAGE_DISCOUNTS. +""" +type VoucherBulkDelete { + """Returns how many objects were affected.""" + count: Int! + discountErrors: [DiscountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [DiscountError!]! +} + +""" +Updates a voucher. + +Requires one of the following permissions: MANAGE_DISCOUNTS. +""" +type VoucherUpdate { + discountErrors: [DiscountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [DiscountError!]! + voucher: Voucher +} + +""" +Adds products, categories, collections to a voucher. + +Requires one of the following permissions: MANAGE_DISCOUNTS. +""" +type VoucherAddCatalogues { + """Voucher of which catalogue IDs will be modified.""" + voucher: Voucher + discountErrors: [DiscountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [DiscountError!]! +} + +""" +Removes products, categories, collections from a voucher. + +Requires one of the following permissions: MANAGE_DISCOUNTS. +""" +type VoucherRemoveCatalogues { + """Voucher of which catalogue IDs will be modified.""" + voucher: Voucher + discountErrors: [DiscountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [DiscountError!]! +} + +""" +Creates/updates translations for a voucher. + +Requires one of the following permissions: MANAGE_TRANSLATIONS. +""" +type VoucherTranslate { + translationErrors: [TranslationError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [TranslationError!]! + voucher: Voucher +} + +""" +Manage voucher's availability in channels. + +Requires one of the following permissions: MANAGE_DISCOUNTS. +""" +type VoucherChannelListingUpdate { + """An updated voucher instance.""" + voucher: Voucher + discountErrors: [DiscountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [DiscountError!]! +} + +input VoucherChannelListingInput { + """List of channels to which the voucher should be assigned.""" + addChannels: [VoucherChannelListingAddInput!] + + """List of channels from which the voucher should be unassigned.""" + removeChannels: [ID!] +} + +input VoucherChannelListingAddInput { + """ID of a channel.""" + channelId: ID! + + """Value of the voucher.""" + discountValue: PositiveDecimal + + """Min purchase amount required to apply the voucher.""" + minAmountSpent: PositiveDecimal +} + +""" +Export products to csv file. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type ExportProducts { + """ + The newly created export file job which is responsible for export data. + """ + exportFile: ExportFile + exportErrors: [ExportError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ExportError!]! +} + +type ExportError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: ExportErrorCode! +} + +"""An enumeration.""" +enum ExportErrorCode { + GRAPHQL_ERROR + INVALID + NOT_FOUND + REQUIRED +} + +input ExportProductsInput { + """Determine which products should be exported.""" + scope: ExportScope! + + """Filtering options for products.""" + filter: ProductFilterInput + + """List of products IDs to export.""" + ids: [ID!] + + """Input with info about fields which should be exported.""" + exportInfo: ExportInfoInput + + """Type of exported file.""" + fileType: FileTypesEnum! +} + +enum ExportScope { + """Export all products.""" + ALL + + """Export products with given ids.""" + IDS + + """Export the filtered products.""" + FILTER +} + +input ExportInfoInput { + """List of attribute ids witch should be exported.""" + attributes: [ID!] + + """List of warehouse ids witch should be exported.""" + warehouses: [ID!] + + """List of channels ids which should be exported.""" + channels: [ID!] + + """List of product fields witch should be exported.""" + fields: [ProductFieldEnum!] +} + +enum ProductFieldEnum { + NAME + DESCRIPTION + PRODUCT_TYPE + CATEGORY + PRODUCT_WEIGHT + COLLECTIONS + CHARGE_TAXES + PRODUCT_MEDIA + VARIANT_ID + VARIANT_SKU + VARIANT_WEIGHT + VARIANT_MEDIA +} + +"""An enumeration.""" +enum FileTypesEnum { + CSV + XLSX +} + +""" +Export gift cards to csv file. + +Added in Saleor 3.1. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires one of the following permissions: MANAGE_GIFT_CARD. +""" +type ExportGiftCards { + """ + The newly created export file job which is responsible for export data. + """ + exportFile: ExportFile + errors: [ExportError!]! +} + +input ExportGiftCardsInput { + """Determine which gift cards should be exported.""" + scope: ExportScope! + + """Filtering options for gift cards.""" + filter: GiftCardFilterInput + + """List of gift cards IDs to export.""" + ids: [ID!] + + """Type of exported file.""" + fileType: FileTypesEnum! +} + +""" +Upload a file. This mutation must be sent as a `multipart` request. More detailed specs of the upload format can be found here: https://github.com/jaydenseric/graphql-multipart-request-spec + +Requires one of the following permissions: AUTHENTICATED_APP, AUTHENTICATED_STAFF_USER. +""" +type FileUpload { + uploadedFile: File + uploadErrors: [UploadError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [UploadError!]! +} + +type UploadError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: UploadErrorCode! +} + +"""An enumeration.""" +enum UploadErrorCode { + GRAPHQL_ERROR +} + +"""Adds a gift card or a voucher to a checkout.""" +type CheckoutAddPromoCode { + """The checkout with the added gift card or voucher.""" + checkout: Checkout + checkoutErrors: [CheckoutError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [CheckoutError!]! +} + +type CheckoutError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: CheckoutErrorCode! + + """List of varint IDs which causes the error.""" + variants: [ID!] + + """List of line Ids which cause the error.""" + lines: [ID!] + + """A type of address that causes the error.""" + addressType: AddressTypeEnum +} + +"""An enumeration.""" +enum CheckoutErrorCode { + BILLING_ADDRESS_NOT_SET + CHECKOUT_NOT_FULLY_PAID + GRAPHQL_ERROR + PRODUCT_NOT_PUBLISHED + PRODUCT_UNAVAILABLE_FOR_PURCHASE + INSUFFICIENT_STOCK + INVALID + INVALID_SHIPPING_METHOD + NOT_FOUND + PAYMENT_ERROR + QUANTITY_GREATER_THAN_LIMIT + REQUIRED + SHIPPING_ADDRESS_NOT_SET + SHIPPING_METHOD_NOT_APPLICABLE + DELIVERY_METHOD_NOT_APPLICABLE + SHIPPING_METHOD_NOT_SET + SHIPPING_NOT_REQUIRED + TAX_ERROR + UNIQUE + VOUCHER_NOT_APPLICABLE + GIFT_CARD_NOT_APPLICABLE + ZERO_QUANTITY + MISSING_CHANNEL_SLUG + CHANNEL_INACTIVE + UNAVAILABLE_VARIANT_IN_CHANNEL + EMAIL_NOT_SET + NO_LINES + INACTIVE_PAYMENT +} + +"""Update billing address in the existing checkout.""" +type CheckoutBillingAddressUpdate { + """An updated checkout.""" + checkout: Checkout + checkoutErrors: [CheckoutError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [CheckoutError!]! +} + +input CheckoutAddressValidationRules { + """ + Determines if an error should be raised when the provided address doesn't have all the required fields. The list of required fields is dynamic and depends on the country code (use the `addressValidationRules` query to fetch them). Note: country code is mandatory for all addresses regardless of the rules provided in this input. + """ + checkRequiredFields: Boolean = true + + """ + Determines if an error should be raised when the provided address doesn't match the expected format. Example: using letters for postal code when the numbers are expected. + """ + checkFieldsFormat: Boolean = true + + """ + Determines if Saleor should apply normalization on address fields. Example: converting city field to uppercase letters. + """ + enableFieldsNormalization: Boolean = true +} + +""" +Completes the checkout. As a result a new order is created and a payment charge is made. This action requires a successful payment before it can be performed. In case additional confirmation step as 3D secure is required confirmationNeeded flag will be set to True and no order created until payment is confirmed with second call of this mutation. +""" +type CheckoutComplete { + """Placed order.""" + order: Order + + """ + Set to true if payment needs to be confirmed before checkout is complete. + """ + confirmationNeeded: Boolean! + + """Confirmation data used to process additional authorization steps.""" + confirmationData: JSONString + checkoutErrors: [CheckoutError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [CheckoutError!]! +} + +"""Create a new checkout.""" +type CheckoutCreate { + """ + Whether the checkout was created or the current active one was returned. Refer to checkoutLinesAdd and checkoutLinesUpdate to merge a cart with an active checkout. + """ + created: Boolean @deprecated(reason: "This field will be removed in Saleor 4.0. Always returns `true`.") + checkoutErrors: [CheckoutError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [CheckoutError!]! + checkout: Checkout +} + +input CheckoutCreateInput { + """Slug of a channel in which to create a checkout.""" + channel: String + + """ + A list of checkout lines, each containing information about an item in the checkout. + """ + lines: [CheckoutLineInput!]! + + """The customer's email address.""" + email: String + + """ + The mailing address to where the checkout will be shipped. Note: the address will be ignored if the checkout doesn't contain shippable items. + """ + shippingAddress: AddressInput + + """Billing address of the customer.""" + billingAddress: AddressInput + + """Checkout language code.""" + languageCode: LanguageCodeEnum + + """ + The checkout validation rules that can be changed. + + Added in Saleor 3.5. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + validationRules: CheckoutValidationRules +} + +input CheckoutLineInput { + """The number of items purchased.""" + quantity: Int! + + """ID of the product variant.""" + variantId: ID! + + """ + Custom price of the item. Can be set only by apps with `HANDLE_CHECKOUTS` permission. When the line with the same variant will be provided multiple times, the last price will be used. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + price: PositiveDecimal + + """ + Flag that allow force splitting the same variant into multiple lines by skipping the matching logic. + + Added in Saleor 3.6. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + forceNewLine: Boolean = false + + """ + Fields required to update the object's metadata. + + Added in Saleor 3.8. + """ + metadata: [MetadataInput!] +} + +input CheckoutValidationRules { + """ + The validation rules that can be applied to provided shipping address data. + """ + shippingAddress: CheckoutAddressValidationRules + + """ + The validation rules that can be applied to provided billing address data. + """ + billingAddress: CheckoutAddressValidationRules +} + +""" +Sets the customer as the owner of the checkout. + +Requires one of the following permissions: AUTHENTICATED_APP, AUTHENTICATED_USER. +""" +type CheckoutCustomerAttach { + """An updated checkout.""" + checkout: Checkout + checkoutErrors: [CheckoutError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [CheckoutError!]! +} + +""" +Removes the user assigned as the owner of the checkout. + +Requires one of the following permissions: AUTHENTICATED_APP, AUTHENTICATED_USER. +""" +type CheckoutCustomerDetach { + """An updated checkout.""" + checkout: Checkout + checkoutErrors: [CheckoutError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [CheckoutError!]! +} + +"""Updates email address in the existing checkout object.""" +type CheckoutEmailUpdate { + """An updated checkout.""" + checkout: Checkout + checkoutErrors: [CheckoutError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [CheckoutError!]! +} + +"""Deletes a CheckoutLine.""" +type CheckoutLineDelete { + """An updated checkout.""" + checkout: Checkout + checkoutErrors: [CheckoutError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [CheckoutError!]! +} + +"""Deletes checkout lines.""" +type CheckoutLinesDelete { + """An updated checkout.""" + checkout: Checkout + errors: [CheckoutError!]! +} + +""" +Adds a checkout line to the existing checkout.If line was already in checkout, its quantity will be increased. +""" +type CheckoutLinesAdd { + """An updated checkout.""" + checkout: Checkout + checkoutErrors: [CheckoutError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [CheckoutError!]! +} + +"""Updates checkout line in the existing checkout.""" +type CheckoutLinesUpdate { + """An updated checkout.""" + checkout: Checkout + checkoutErrors: [CheckoutError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [CheckoutError!]! +} + +input CheckoutLineUpdateInput { + """ + ID of the product variant. + + DEPRECATED: this field will be removed in Saleor 4.0. Use `lineId` instead. + """ + variantId: ID + + """ + The number of items purchased. Optional for apps, required for any other users. + """ + quantity: Int + + """ + Custom price of the item. Can be set only by apps with `HANDLE_CHECKOUTS` permission. When the line with the same variant will be provided multiple times, the last price will be used. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + price: PositiveDecimal + + """ + ID of the line. + + Added in Saleor 3.6. + """ + lineId: ID +} + +"""Remove a gift card or a voucher from a checkout.""" +type CheckoutRemovePromoCode { + """The checkout with the removed gift card or voucher.""" + checkout: Checkout + checkoutErrors: [CheckoutError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [CheckoutError!]! +} + +"""Create a new payment for given checkout.""" +type CheckoutPaymentCreate { + """Related checkout object.""" + checkout: Checkout + + """A newly created payment.""" + payment: Payment + paymentErrors: [PaymentError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [PaymentError!]! +} + +input PaymentInput { + """A gateway to use with that payment.""" + gateway: String! + + """ + Client-side generated payment token, representing customer's billing data in a secure manner. + """ + token: String + + """ + Total amount of the transaction, including all taxes and discounts. If no amount is provided, the checkout total will be used. + """ + amount: PositiveDecimal + + """ + URL of a storefront view where user should be redirected after requiring additional actions. Payment with additional actions will not be finished if this field is not provided. + """ + returnUrl: String + + """ + Payment store type. + + Added in Saleor 3.1. + """ + storePaymentMethod: StorePaymentMethodEnum = NONE + + """ + User public metadata. + + Added in Saleor 3.1. + """ + metadata: [MetadataInput!] +} + +"""Enum representing the type of a payment storage in a gateway.""" +enum StorePaymentMethodEnum { + """ + On session storage type. The payment is stored only to be reused when the customer is present in the checkout flow. + """ + ON_SESSION + + """ + Off session storage type. The payment is stored to be reused even if the customer is absent. + """ + OFF_SESSION + + """Storage is disabled. The payment is not stored.""" + NONE +} + +"""Update shipping address in the existing checkout.""" +type CheckoutShippingAddressUpdate { + """An updated checkout.""" + checkout: Checkout + checkoutErrors: [CheckoutError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [CheckoutError!]! +} + +"""Updates the shipping method of the checkout.""" +type CheckoutShippingMethodUpdate { + """An updated checkout.""" + checkout: Checkout + checkoutErrors: [CheckoutError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [CheckoutError!]! +} + +""" +Updates the delivery method (shipping method or pick up point) of the checkout. + +Added in Saleor 3.1. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type CheckoutDeliveryMethodUpdate { + """An updated checkout.""" + checkout: Checkout + errors: [CheckoutError!]! +} + +"""Update language code in the existing checkout.""" +type CheckoutLanguageCodeUpdate { + """An updated checkout.""" + checkout: Checkout + checkoutErrors: [CheckoutError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [CheckoutError!]! +} + +""" +Create new order from existing checkout. Requires the following permissions: AUTHENTICATED_APP and HANDLE_CHECKOUTS. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type OrderCreateFromCheckout { + """Placed order.""" + order: Order + errors: [OrderCreateFromCheckoutError!]! +} + +type OrderCreateFromCheckoutError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: OrderCreateFromCheckoutErrorCode! + + """List of variant IDs which causes the error.""" + variants: [ID!] + + """List of line Ids which cause the error.""" + lines: [ID!] +} + +"""An enumeration.""" +enum OrderCreateFromCheckoutErrorCode { + GRAPHQL_ERROR + CHECKOUT_NOT_FOUND + CHANNEL_INACTIVE + INSUFFICIENT_STOCK + VOUCHER_NOT_APPLICABLE + GIFT_CARD_NOT_APPLICABLE + TAX_ERROR + SHIPPING_METHOD_NOT_SET + BILLING_ADDRESS_NOT_SET + SHIPPING_ADDRESS_NOT_SET + INVALID_SHIPPING_METHOD + NO_LINES + EMAIL_NOT_SET + UNAVAILABLE_VARIANT_IN_CHANNEL +} + +""" +Creates new channel. + +Requires one of the following permissions: MANAGE_CHANNELS. +""" +type ChannelCreate { + channelErrors: [ChannelError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ChannelError!]! + channel: Channel +} + +type ChannelError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: ChannelErrorCode! + + """List of shipping zone IDs which causes the error.""" + shippingZones: [ID!] + + """List of warehouses IDs which causes the error.""" + warehouses: [ID!] +} + +"""An enumeration.""" +enum ChannelErrorCode { + ALREADY_EXISTS + GRAPHQL_ERROR + INVALID + NOT_FOUND + REQUIRED + UNIQUE + CHANNELS_CURRENCY_MUST_BE_THE_SAME + CHANNEL_WITH_ORDERS + DUPLICATED_INPUT_ITEM +} + +input ChannelCreateInput { + """isActive flag.""" + isActive: Boolean + + """ + The channel stock settings. + + Added in Saleor 3.7. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + stockSettings: StockSettingsInput + + """List of shipping zones to assign to the channel.""" + addShippingZones: [ID!] + + """ + List of warehouses to assign to the channel. + + Added in Saleor 3.5. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + addWarehouses: [ID!] + + """ + The channel order settings + + Added in Saleor 3.12. + """ + orderSettings: OrderSettingsInput + + """Name of the channel.""" + name: String! + + """Slug of the channel.""" + slug: String! + + """Currency of the channel.""" + currencyCode: String! + + """ + Default country for the channel. Default country can be used in checkout to determine the stock quantities or calculate taxes when the country was not explicitly provided. + + Added in Saleor 3.1. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + defaultCountry: CountryCode! +} + +input StockSettingsInput { + """ + Allocation strategy options. Strategy defines the preference of warehouses for allocations and reservations. + """ + allocationStrategy: AllocationStrategyEnum! +} + +input OrderSettingsInput { + """ + When disabled, all new orders from checkout will be marked as unconfirmed. When enabled orders from checkout will become unfulfilled immediately. By default set to True + """ + automaticallyConfirmAllNewOrders: Boolean + + """ + When enabled, all non-shippable gift card orders will be fulfilled automatically. By defualt set to True. + """ + automaticallyFulfillNonShippableGiftCard: Boolean + + """ + Determine what strategy will be used to mark the order as paid. Based on the choosen option the proper object will be created and attached to the order, when order is manualy marked as paid. + `PAYMENT_FLOW` - [default option] creates the `Payment` object. + `TRANSACTION_FLOW` - creates the `TransactionItem` object. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + markAsPaidStrategy: MarkAsPaidStrategyEnum + + """ + Determine the transaction flow strategy to be used. Include the selected option in the payload sent to the payment app, as a requested action for the transaction. + + Added in Saleor 3.13. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + defaultTransactionFlowStrategy: TransactionFlowStrategyEnum +} + +""" +Update a channel. + +Requires one of the following permissions: MANAGE_CHANNELS. +Requires one of the following permissions when updating only orderSettings field: MANAGE_CHANNELS, MANAGE_ORDERS. +""" +type ChannelUpdate { + channelErrors: [ChannelError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ChannelError!]! + channel: Channel +} + +input ChannelUpdateInput { + """isActive flag.""" + isActive: Boolean + + """ + The channel stock settings. + + Added in Saleor 3.7. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + stockSettings: StockSettingsInput + + """List of shipping zones to assign to the channel.""" + addShippingZones: [ID!] + + """ + List of warehouses to assign to the channel. + + Added in Saleor 3.5. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + addWarehouses: [ID!] + + """ + The channel order settings + + Added in Saleor 3.12. + """ + orderSettings: OrderSettingsInput + + """Name of the channel.""" + name: String + + """Slug of the channel.""" + slug: String + + """ + Default country for the channel. Default country can be used in checkout to determine the stock quantities or calculate taxes when the country was not explicitly provided. + + Added in Saleor 3.1. + """ + defaultCountry: CountryCode + + """List of shipping zones to unassign from the channel.""" + removeShippingZones: [ID!] + + """ + List of warehouses to unassign from the channel. + + Added in Saleor 3.5. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + removeWarehouses: [ID!] +} + +""" +Delete a channel. Orders associated with the deleted channel will be moved to the target channel. Checkouts, product availability, and pricing will be removed. + +Requires one of the following permissions: MANAGE_CHANNELS. +""" +type ChannelDelete { + channelErrors: [ChannelError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ChannelError!]! + channel: Channel +} + +input ChannelDeleteInput { + """ID of channel to migrate orders from origin channel.""" + channelId: ID! +} + +""" +Activate a channel. + +Requires one of the following permissions: MANAGE_CHANNELS. +""" +type ChannelActivate { + """Activated channel.""" + channel: Channel + channelErrors: [ChannelError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ChannelError!]! +} + +""" +Deactivate a channel. + +Requires one of the following permissions: MANAGE_CHANNELS. +""" +type ChannelDeactivate { + """Deactivated channel.""" + channel: Channel + channelErrors: [ChannelError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [ChannelError!]! +} + +""" +Reorder the warehouses of a channel. + +Added in Saleor 3.7. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. + +Requires one of the following permissions: MANAGE_CHANNELS. +""" +type ChannelReorderWarehouses { + """Channel within the warehouses are reordered.""" + channel: Channel + errors: [ChannelError!]! +} + +"""Creates an attribute.""" +type AttributeCreate { + attribute: Attribute + attributeErrors: [AttributeError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AttributeError!]! +} + +type AttributeError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: AttributeErrorCode! +} + +"""An enumeration.""" +enum AttributeErrorCode { + ALREADY_EXISTS + GRAPHQL_ERROR + INVALID + NOT_FOUND + REQUIRED + UNIQUE +} + +input AttributeCreateInput { + """The input type to use for entering attribute values in the dashboard.""" + inputType: AttributeInputTypeEnum + + """The entity type which can be used as a reference.""" + entityType: AttributeEntityTypeEnum + + """Name of an attribute displayed in the interface.""" + name: String! + + """Internal representation of an attribute name.""" + slug: String + + """The attribute type.""" + type: AttributeTypeEnum! + + """The unit of attribute values.""" + unit: MeasurementUnitsEnum + + """List of attribute's values.""" + values: [AttributeValueCreateInput!] + + """Whether the attribute requires values to be passed or not.""" + valueRequired: Boolean + + """Whether the attribute is for variants only.""" + isVariantOnly: Boolean + + """Whether the attribute should be visible or not in storefront.""" + visibleInStorefront: Boolean + + """ + Whether the attribute can be filtered in storefront. + + DEPRECATED: this field will be removed in Saleor 4.0. + """ + filterableInStorefront: Boolean + + """Whether the attribute can be filtered in dashboard.""" + filterableInDashboard: Boolean + + """ + The position of the attribute in the storefront navigation (0 by default). + + DEPRECATED: this field will be removed in Saleor 4.0. + """ + storefrontSearchPosition: Int + + """ + Whether the attribute can be displayed in the admin product list. + + DEPRECATED: this field will be removed in Saleor 4.0. + """ + availableInGrid: Boolean + + """ + External ID of this attribute. + + Added in Saleor 3.10. + """ + externalReference: String +} + +input AttributeValueCreateInput { + """ + Represent value of the attribute value (e.g. color values for swatch attributes). + """ + value: String + + """ + Represents the text of the attribute value, includes formatting. + + Rich text format. For reference see https://editorjs.io/ + + DEPRECATED: this field will be removed in Saleor 4.0.The rich text attribute hasn't got predefined value, so can be specified only from instance that supports the given attribute. + """ + richText: JSONString + + """ + Represents the text of the attribute value, plain text without formating. + + DEPRECATED: this field will be removed in Saleor 4.0.The plain text attribute hasn't got predefined value, so can be specified only from instance that supports the given attribute. + """ + plainText: String + + """URL of the file attribute. Every time, a new value is created.""" + fileUrl: String + + """File content type.""" + contentType: String + + """ + External ID of this attribute value. + + Added in Saleor 3.10. + """ + externalReference: String + + """Name of a value displayed in the interface.""" + name: String! +} + +""" +Deletes an attribute. + +Requires one of the following permissions: MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. +""" +type AttributeDelete { + attributeErrors: [AttributeError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AttributeError!]! + attribute: Attribute +} + +""" +Updates attribute. + +Requires one of the following permissions: MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. +""" +type AttributeUpdate { + attribute: Attribute + attributeErrors: [AttributeError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AttributeError!]! +} + +input AttributeUpdateInput { + """Name of an attribute displayed in the interface.""" + name: String + + """Internal representation of an attribute name.""" + slug: String + + """The unit of attribute values.""" + unit: MeasurementUnitsEnum + + """IDs of values to be removed from this attribute.""" + removeValues: [ID!] + + """New values to be created for this attribute.""" + addValues: [AttributeValueUpdateInput!] + + """Whether the attribute requires values to be passed or not.""" + valueRequired: Boolean + + """Whether the attribute is for variants only.""" + isVariantOnly: Boolean + + """Whether the attribute should be visible or not in storefront.""" + visibleInStorefront: Boolean + + """ + Whether the attribute can be filtered in storefront. + + DEPRECATED: this field will be removed in Saleor 4.0. + """ + filterableInStorefront: Boolean + + """Whether the attribute can be filtered in dashboard.""" + filterableInDashboard: Boolean + + """ + The position of the attribute in the storefront navigation (0 by default). + + DEPRECATED: this field will be removed in Saleor 4.0. + """ + storefrontSearchPosition: Int + + """ + Whether the attribute can be displayed in the admin product list. + + DEPRECATED: this field will be removed in Saleor 4.0. + """ + availableInGrid: Boolean + + """ + External ID of this product. + + Added in Saleor 3.10. + """ + externalReference: String +} + +input AttributeValueUpdateInput { + """ + Represent value of the attribute value (e.g. color values for swatch attributes). + """ + value: String + + """ + Represents the text of the attribute value, includes formatting. + + Rich text format. For reference see https://editorjs.io/ + + DEPRECATED: this field will be removed in Saleor 4.0.The rich text attribute hasn't got predefined value, so can be specified only from instance that supports the given attribute. + """ + richText: JSONString + + """ + Represents the text of the attribute value, plain text without formating. + + DEPRECATED: this field will be removed in Saleor 4.0.The plain text attribute hasn't got predefined value, so can be specified only from instance that supports the given attribute. + """ + plainText: String + + """URL of the file attribute. Every time, a new value is created.""" + fileUrl: String + + """File content type.""" + contentType: String + + """ + External ID of this attribute value. + + Added in Saleor 3.10. + """ + externalReference: String + + """Name of a value displayed in the interface.""" + name: String +} + +""" +Creates/updates translations for an attribute. + +Requires one of the following permissions: MANAGE_TRANSLATIONS. +""" +type AttributeTranslate { + translationErrors: [TranslationError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [TranslationError!]! + attribute: Attribute +} + +""" +Deletes attributes. + +Requires one of the following permissions: MANAGE_PAGE_TYPES_AND_ATTRIBUTES. +""" +type AttributeBulkDelete { + """Returns how many objects were affected.""" + count: Int! + attributeErrors: [AttributeError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AttributeError!]! +} + +""" +Deletes values of attributes. + +Requires one of the following permissions: MANAGE_PAGE_TYPES_AND_ATTRIBUTES. +""" +type AttributeValueBulkDelete { + """Returns how many objects were affected.""" + count: Int! + attributeErrors: [AttributeError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AttributeError!]! +} + +""" +Creates a value for an attribute. + +Requires one of the following permissions: MANAGE_PRODUCTS. +""" +type AttributeValueCreate { + """The updated attribute.""" + attribute: Attribute + attributeErrors: [AttributeError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AttributeError!]! + attributeValue: AttributeValue +} + +""" +Deletes a value of an attribute. + +Requires one of the following permissions: MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. +""" +type AttributeValueDelete { + """The updated attribute.""" + attribute: Attribute + attributeErrors: [AttributeError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AttributeError!]! + attributeValue: AttributeValue +} + +""" +Updates value of an attribute. + +Requires one of the following permissions: MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. +""" +type AttributeValueUpdate { + """The updated attribute.""" + attribute: Attribute + attributeErrors: [AttributeError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AttributeError!]! + attributeValue: AttributeValue +} + +""" +Creates/updates translations for an attribute value. + +Requires one of the following permissions: MANAGE_TRANSLATIONS. +""" +type AttributeValueTranslate { + translationErrors: [TranslationError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [TranslationError!]! + attributeValue: AttributeValue +} + +input AttributeValueTranslationInput { + name: String + + """ + Translated text. + + Rich text format. For reference see https://editorjs.io/ + """ + richText: JSONString + + """Translated text.""" + plainText: String +} + +""" +Reorder the values of an attribute. + +Requires one of the following permissions: MANAGE_PRODUCT_TYPES_AND_ATTRIBUTES. +""" +type AttributeReorderValues { + """Attribute from which values are reordered.""" + attribute: Attribute + attributeErrors: [AttributeError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AttributeError!]! +} + +""" +Creates a new app. Requires the following permissions: AUTHENTICATED_STAFF_USER and MANAGE_APPS. +""" +type AppCreate { + """The newly created authentication token.""" + authToken: String + appErrors: [AppError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AppError!]! + app: App +} + +type AppError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: AppErrorCode! + + """List of permissions which causes the error.""" + permissions: [PermissionEnum!] +} + +"""An enumeration.""" +enum AppErrorCode { + FORBIDDEN + GRAPHQL_ERROR + INVALID + INVALID_STATUS + INVALID_PERMISSION + INVALID_URL_FORMAT + INVALID_MANIFEST_FORMAT + INVALID_CUSTOM_HEADERS + MANIFEST_URL_CANT_CONNECT + NOT_FOUND + REQUIRED + UNIQUE + OUT_OF_SCOPE_APP + OUT_OF_SCOPE_PERMISSION +} + +input AppInput { + """Name of the app.""" + name: String + + """List of permission code names to assign to this app.""" + permissions: [PermissionEnum!] +} + +""" +Updates an existing app. + +Requires one of the following permissions: MANAGE_APPS. +""" +type AppUpdate { + appErrors: [AppError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AppError!]! + app: App +} + +""" +Deletes an app. + +Requires one of the following permissions: MANAGE_APPS. +""" +type AppDelete { + appErrors: [AppError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AppError!]! + app: App +} + +""" +Creates a new token. + +Requires one of the following permissions: MANAGE_APPS. +""" +type AppTokenCreate { + """The newly created authentication token.""" + authToken: String + appErrors: [AppError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AppError!]! + appToken: AppToken +} + +input AppTokenInput { + """Name of the token.""" + name: String + + """ID of app.""" + app: ID! +} + +""" +Deletes an authentication token assigned to app. + +Requires one of the following permissions: MANAGE_APPS. +""" +type AppTokenDelete { + appErrors: [AppError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AppError!]! + appToken: AppToken +} + +"""Verify provided app token.""" +type AppTokenVerify { + """Determine if token is valid or not.""" + valid: Boolean! + appErrors: [AppError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AppError!]! +} + +""" +Install new app by using app manifest. Requires the following permissions: AUTHENTICATED_STAFF_USER and MANAGE_APPS. +""" +type AppInstall { + appErrors: [AppError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AppError!]! + appInstallation: AppInstallation +} + +input AppInstallInput { + """Name of the app to install.""" + appName: String + + """Url to app's manifest in JSON format.""" + manifestUrl: String + + """Determine if app will be set active or not.""" + activateAfterInstallation: Boolean = true + + """List of permission code names to assign to this app.""" + permissions: [PermissionEnum!] +} + +""" +Retry failed installation of new app. + +Requires one of the following permissions: MANAGE_APPS. +""" +type AppRetryInstall { + appErrors: [AppError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AppError!]! + appInstallation: AppInstallation +} + +""" +Delete failed installation. + +Requires one of the following permissions: MANAGE_APPS. +""" +type AppDeleteFailedInstallation { + appErrors: [AppError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AppError!]! + appInstallation: AppInstallation +} + +""" +Fetch and validate manifest. + +Requires one of the following permissions: MANAGE_APPS. +""" +type AppFetchManifest { + manifest: Manifest + appErrors: [AppError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AppError!]! +} + +"""The manifest definition.""" +type Manifest { + identifier: String! + version: String! + name: String! + about: String + permissions: [Permission!] + appUrl: String + + """URL to iframe with the configuration for the app.""" + configurationUrl: String @deprecated(reason: "This field will be removed in Saleor 4.0. Use `appUrl` instead.") + tokenTargetUrl: String + + """Description of the data privacy defined for this app.""" + dataPrivacy: String @deprecated(reason: "This field will be removed in Saleor 4.0. Use `dataPrivacyUrl` instead.") + dataPrivacyUrl: String + homepageUrl: String + supportUrl: String + extensions: [AppManifestExtension!]! + + """ + List of the app's webhooks. + + Added in Saleor 3.5. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + webhooks: [AppManifestWebhook!]! + + """ + The audience that will be included in all JWT tokens for the app. + + Added in Saleor 3.8. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + audience: String +} + +type AppManifestExtension { + """List of the app extension's permissions.""" + permissions: [Permission!]! + + """Label of the extension to show in the dashboard.""" + label: String! + + """URL of a view where extension's iframe is placed.""" + url: String! + + """Place where given extension will be mounted.""" + mount: AppExtensionMountEnum! + + """Type of way how app extension will be opened.""" + target: AppExtensionTargetEnum! +} + +type AppManifestWebhook { + """The name of the webhook.""" + name: String! + + """The asynchronous events that webhook wants to subscribe.""" + asyncEvents: [WebhookEventTypeAsyncEnum!] + + """The synchronous events that webhook wants to subscribe.""" + syncEvents: [WebhookEventTypeSyncEnum!] + + """Subscription query of a webhook""" + query: String! + + """The url to receive the payload.""" + targetUrl: String! +} + +""" +Activate the app. + +Requires one of the following permissions: MANAGE_APPS. +""" +type AppActivate { + appErrors: [AppError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AppError!]! + app: App +} + +""" +Deactivate the app. + +Requires one of the following permissions: MANAGE_APPS. +""" +type AppDeactivate { + appErrors: [AppError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AppError!]! + app: App +} + +"""Create JWT token.""" +type CreateToken { + """JWT token, required to authenticate.""" + token: String + + """JWT refresh token, required to re-generate access token.""" + refreshToken: String + + """CSRF token required to re-generate access token.""" + csrfToken: String + + """A user instance.""" + user: User + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! +} + +type AccountError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: AccountErrorCode! + + """A type of address that causes the error.""" + addressType: AddressTypeEnum +} + +"""An enumeration.""" +enum AccountErrorCode { + ACTIVATE_OWN_ACCOUNT + ACTIVATE_SUPERUSER_ACCOUNT + DUPLICATED_INPUT_ITEM + DEACTIVATE_OWN_ACCOUNT + DEACTIVATE_SUPERUSER_ACCOUNT + DELETE_NON_STAFF_USER + DELETE_OWN_ACCOUNT + DELETE_STAFF_ACCOUNT + DELETE_SUPERUSER_ACCOUNT + GRAPHQL_ERROR + INACTIVE + INVALID + INVALID_PASSWORD + LEFT_NOT_MANAGEABLE_PERMISSION + INVALID_CREDENTIALS + NOT_FOUND + OUT_OF_SCOPE_USER + OUT_OF_SCOPE_GROUP + OUT_OF_SCOPE_PERMISSION + PASSWORD_ENTIRELY_NUMERIC + PASSWORD_TOO_COMMON + PASSWORD_TOO_SHORT + PASSWORD_TOO_SIMILAR + REQUIRED + UNIQUE + JWT_SIGNATURE_EXPIRED + JWT_INVALID_TOKEN + JWT_DECODE_ERROR + JWT_MISSING_TOKEN + JWT_INVALID_CSRF_TOKEN + CHANNEL_INACTIVE + MISSING_CHANNEL_SLUG + ACCOUNT_NOT_CONFIRMED +} + +""" +Refresh JWT token. Mutation tries to take refreshToken from the input.If it fails it will try to take refreshToken from the http-only cookie -refreshToken. csrfToken is required when refreshToken is provided as a cookie. +""" +type RefreshToken { + """JWT token, required to authenticate.""" + token: String + + """A user instance.""" + user: User + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! +} + +"""Verify JWT token.""" +type VerifyToken { + """User assigned to token.""" + user: User + + """Determine if token is valid or not.""" + isValid: Boolean! + + """JWT payload.""" + payload: GenericScalar + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! +} + +""" +The `GenericScalar` scalar type represents a generic +GraphQL scalar value that could be: +String, Boolean, Int, Float, List or Object. +""" +scalar GenericScalar + +""" +Deactivate all JWT tokens of the currently authenticated user. + +Requires one of the following permissions: AUTHENTICATED_USER. +""" +type DeactivateAllUserTokens { + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! +} + +"""Prepare external authentication url for user by custom plugin.""" +type ExternalAuthenticationUrl { + """The data returned by authentication plugin.""" + authenticationData: JSONString + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! +} + +"""Obtain external access tokens for user by custom plugin.""" +type ExternalObtainAccessTokens { + """The token, required to authenticate.""" + token: String + + """The refresh token, required to re-generate external access token.""" + refreshToken: String + + """CSRF token required to re-generate external access token.""" + csrfToken: String + + """A user instance.""" + user: User + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! +} + +"""Refresh user's access by custom plugin.""" +type ExternalRefresh { + """The token, required to authenticate.""" + token: String + + """The refresh token, required to re-generate external access token.""" + refreshToken: String + + """CSRF token required to re-generate external access token.""" + csrfToken: String + + """A user instance.""" + user: User + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! +} + +"""Logout user by custom plugin.""" +type ExternalLogout { + """The data returned by authentication plugin.""" + logoutData: JSONString + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! +} + +"""Verify external authentication data by plugin.""" +type ExternalVerify { + """User assigned to data.""" + user: User + + """Determine if authentication data is valid or not.""" + isValid: Boolean! + + """External data.""" + verifyData: JSONString + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! +} + +"""Sends an email with the account password modification link.""" +type RequestPasswordReset { + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! +} + +"""Confirm user account with token sent by email during registration.""" +type ConfirmAccount { + """An activated user account.""" + user: User + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! +} + +""" +Sets the user's password from the token sent by email using the RequestPasswordReset mutation. +""" +type SetPassword { + """JWT token, required to authenticate.""" + token: String + + """JWT refresh token, required to re-generate access token.""" + refreshToken: String + + """CSRF token required to re-generate access token.""" + csrfToken: String + + """A user instance.""" + user: User + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! +} + +""" +Change the password of the logged in user. + +Requires one of the following permissions: AUTHENTICATED_USER. +""" +type PasswordChange { + """A user instance with a new password.""" + user: User + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! +} + +""" +Request email change of the logged in user. + +Requires one of the following permissions: AUTHENTICATED_USER. +""" +type RequestEmailChange { + """A user instance.""" + user: User + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! +} + +""" +Confirm the email change of the logged-in user. + +Requires one of the following permissions: AUTHENTICATED_USER. +""" +type ConfirmEmailChange { + """A user instance with a new email.""" + user: User + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! +} + +""" +Create a new address for the customer. + +Requires one of the following permissions: AUTHENTICATED_USER. +""" +type AccountAddressCreate { + """A user instance for which the address was created.""" + user: User + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! + address: Address +} + +""" +Updates an address of the logged-in user. Requires one of the following permissions: MANAGE_USERS, IS_OWNER. +""" +type AccountAddressUpdate { + """A user object for which the address was edited.""" + user: User + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! + address: Address +} + +""" +Delete an address of the logged-in user. Requires one of the following permissions: MANAGE_USERS, IS_OWNER. +""" +type AccountAddressDelete { + """A user instance for which the address was deleted.""" + user: User + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! + address: Address +} + +""" +Sets a default address for the authenticated user. + +Requires one of the following permissions: AUTHENTICATED_USER. +""" +type AccountSetDefaultAddress { + """An updated user instance.""" + user: User + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! +} + +"""Register a new user.""" +type AccountRegister { + """Informs whether users need to confirm their email address.""" + requiresConfirmation: Boolean + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! + user: User +} + +input AccountRegisterInput { + """Given name.""" + firstName: String + + """Family name.""" + lastName: String + + """User language code.""" + languageCode: LanguageCodeEnum + + """The email address of the user.""" + email: String! + + """Password.""" + password: String! + + """Base of frontend URL that will be needed to create confirmation URL.""" + redirectUrl: String + + """User public metadata.""" + metadata: [MetadataInput!] + + """ + Slug of a channel which will be used to notify users. Optional when only one channel exists. + """ + channel: String +} + +""" +Updates the account of the logged-in user. + +Requires one of the following permissions: AUTHENTICATED_USER. +""" +type AccountUpdate { + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! + user: User +} + +input AccountInput { + """Given name.""" + firstName: String + + """Family name.""" + lastName: String + + """User language code.""" + languageCode: LanguageCodeEnum + + """Billing address of the customer.""" + defaultBillingAddress: AddressInput + + """Shipping address of the customer.""" + defaultShippingAddress: AddressInput +} + +""" +Sends an email with the account removal link for the logged-in user. + +Requires one of the following permissions: AUTHENTICATED_USER. +""" +type AccountRequestDeletion { + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! +} + +""" +Remove user account. + +Requires one of the following permissions: AUTHENTICATED_USER. +""" +type AccountDelete { + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! + user: User +} + +""" +Creates user address. + +Requires one of the following permissions: MANAGE_USERS. +""" +type AddressCreate { + """A user instance for which the address was created.""" + user: User + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! + address: Address +} + +""" +Updates an address. + +Requires one of the following permissions: MANAGE_USERS. +""" +type AddressUpdate { + """A user object for which the address was edited.""" + user: User + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! + address: Address +} + +""" +Deletes an address. + +Requires one of the following permissions: MANAGE_USERS. +""" +type AddressDelete { + """A user instance for which the address was deleted.""" + user: User + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! + address: Address +} + +""" +Sets a default address for the given user. + +Requires one of the following permissions: MANAGE_USERS. +""" +type AddressSetDefault { + """An updated user instance.""" + user: User + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! +} + +""" +Creates a new customer. + +Requires one of the following permissions: MANAGE_USERS. +""" +type CustomerCreate { + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! + user: User +} + +input UserCreateInput { + """Billing address of the customer.""" + defaultBillingAddress: AddressInput + + """Shipping address of the customer.""" + defaultShippingAddress: AddressInput + + """Given name.""" + firstName: String + + """Family name.""" + lastName: String + + """The unique email address of the user.""" + email: String + + """User account is active.""" + isActive: Boolean + + """A note about the user.""" + note: String + + """User language code.""" + languageCode: LanguageCodeEnum + + """ + External ID of the customer. + + Added in Saleor 3.10. + """ + externalReference: String + + """ + URL of a view where users should be redirected to set the password. URL in RFC 1808 format. + """ + redirectUrl: String + + """ + Slug of a channel which will be used for notify user. Optional when only one channel exists. + """ + channel: String +} + +""" +Updates an existing customer. + +Requires one of the following permissions: MANAGE_USERS. +""" +type CustomerUpdate { + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! + user: User +} + +input CustomerInput { + """Billing address of the customer.""" + defaultBillingAddress: AddressInput + + """Shipping address of the customer.""" + defaultShippingAddress: AddressInput + + """Given name.""" + firstName: String + + """Family name.""" + lastName: String + + """The unique email address of the user.""" + email: String + + """User account is active.""" + isActive: Boolean + + """A note about the user.""" + note: String + + """User language code.""" + languageCode: LanguageCodeEnum + + """ + External ID of the customer. + + Added in Saleor 3.10. + """ + externalReference: String +} + +""" +Deletes a customer. + +Requires one of the following permissions: MANAGE_USERS. +""" +type CustomerDelete { + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! + user: User +} + +""" +Deletes customers. + +Requires one of the following permissions: MANAGE_USERS. +""" +type CustomerBulkDelete { + """Returns how many objects were affected.""" + count: Int! + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! +} + +""" +Creates a new staff user. Apps are not allowed to perform this mutation. + +Requires one of the following permissions: MANAGE_STAFF. +""" +type StaffCreate { + staffErrors: [StaffError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [StaffError!]! + user: User +} + +type StaffError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: AccountErrorCode! + + """A type of address that causes the error.""" + addressType: AddressTypeEnum + + """List of permissions which causes the error.""" + permissions: [PermissionEnum!] + + """List of permission group IDs which cause the error.""" + groups: [ID!] + + """List of user IDs which causes the error.""" + users: [ID!] +} + +input StaffCreateInput { + """Given name.""" + firstName: String + + """Family name.""" + lastName: String + + """The unique email address of the user.""" + email: String + + """User account is active.""" + isActive: Boolean + + """A note about the user.""" + note: String + + """List of permission group IDs to which user should be assigned.""" + addGroups: [ID!] + + """ + URL of a view where users should be redirected to set the password. URL in RFC 1808 format. + """ + redirectUrl: String +} + +""" +Updates an existing staff user. Apps are not allowed to perform this mutation. + +Requires one of the following permissions: MANAGE_STAFF. +""" +type StaffUpdate { + staffErrors: [StaffError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [StaffError!]! + user: User +} + +input StaffUpdateInput { + """Given name.""" + firstName: String + + """Family name.""" + lastName: String + + """The unique email address of the user.""" + email: String + + """User account is active.""" + isActive: Boolean + + """A note about the user.""" + note: String + + """List of permission group IDs to which user should be assigned.""" + addGroups: [ID!] + + """List of permission group IDs from which user should be unassigned.""" + removeGroups: [ID!] +} + +""" +Deletes a staff user. Apps are not allowed to perform this mutation. + +Requires one of the following permissions: MANAGE_STAFF. +""" +type StaffDelete { + staffErrors: [StaffError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [StaffError!]! + user: User +} + +""" +Deletes staff users. Apps are not allowed to perform this mutation. + +Requires one of the following permissions: MANAGE_STAFF. +""" +type StaffBulkDelete { + """Returns how many objects were affected.""" + count: Int! + staffErrors: [StaffError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [StaffError!]! +} + +""" +Create a user avatar. Only for staff members. This mutation must be sent as a `multipart` request. More detailed specs of the upload format can be found here: https://github.com/jaydenseric/graphql-multipart-request-spec + +Requires one of the following permissions: AUTHENTICATED_STAFF_USER. +""" +type UserAvatarUpdate { + """An updated user instance.""" + user: User + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! +} + +""" +Deletes a user avatar. Only for staff members. + +Requires one of the following permissions: AUTHENTICATED_STAFF_USER. +""" +type UserAvatarDelete { + """An updated user instance.""" + user: User + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! +} + +""" +Activate or deactivate users. + +Requires one of the following permissions: MANAGE_USERS. +""" +type UserBulkSetActive { + """Returns how many objects were affected.""" + count: Int! + accountErrors: [AccountError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [AccountError!]! +} + +""" +Create new permission group. Apps are not allowed to perform this mutation. + +Requires one of the following permissions: MANAGE_STAFF. +""" +type PermissionGroupCreate { + permissionGroupErrors: [PermissionGroupError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [PermissionGroupError!]! + group: Group +} + +type PermissionGroupError { + """ + Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field. + """ + field: String + + """The error message.""" + message: String + + """The error code.""" + code: PermissionGroupErrorCode! + + """List of permissions which causes the error.""" + permissions: [PermissionEnum!] + + """List of user IDs which causes the error.""" + users: [ID!] +} + +"""An enumeration.""" +enum PermissionGroupErrorCode { + ASSIGN_NON_STAFF_MEMBER + DUPLICATED_INPUT_ITEM + CANNOT_REMOVE_FROM_LAST_GROUP + LEFT_NOT_MANAGEABLE_PERMISSION + OUT_OF_SCOPE_PERMISSION + OUT_OF_SCOPE_USER + REQUIRED + UNIQUE +} + +input PermissionGroupCreateInput { + """List of permission code names to assign to this group.""" + addPermissions: [PermissionEnum!] + + """List of users to assign to this group.""" + addUsers: [ID!] + + """Group name.""" + name: String! +} + +""" +Update permission group. Apps are not allowed to perform this mutation. + +Requires one of the following permissions: MANAGE_STAFF. +""" +type PermissionGroupUpdate { + permissionGroupErrors: [PermissionGroupError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [PermissionGroupError!]! + group: Group +} + +input PermissionGroupUpdateInput { + """List of permission code names to assign to this group.""" + addPermissions: [PermissionEnum!] + + """List of users to assign to this group.""" + addUsers: [ID!] + + """Group name.""" + name: String + + """List of permission code names to unassign from this group.""" + removePermissions: [PermissionEnum!] + + """List of users to unassign from this group.""" + removeUsers: [ID!] +} + +""" +Delete permission group. Apps are not allowed to perform this mutation. + +Requires one of the following permissions: MANAGE_STAFF. +""" +type PermissionGroupDelete { + permissionGroupErrors: [PermissionGroupError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.") + errors: [PermissionGroupError!]! + group: Group +} + +type Subscription { + """ + Look up subscription event. + + Added in Saleor 3.2. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + event: Event +} + +interface Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App +} + +union IssuingPrincipal = App | User + +"""An enumeration.""" +enum DistanceUnitsEnum { + CM + M + KM + FT + YD + INCH +} + +"""An enumeration.""" +enum AreaUnitsEnum { + SQ_CM + SQ_M + SQ_KM + SQ_FT + SQ_YD + SQ_INCH +} + +"""An enumeration.""" +enum VolumeUnitsEnum { + CUBIC_MILLIMETER + CUBIC_CENTIMETER + CUBIC_DECIMETER + CUBIC_METER + LITER + CUBIC_FOOT + CUBIC_INCH + CUBIC_YARD + QT + PINT + FL_OZ + ACRE_IN + ACRE_FT +} + +""" +Event sent when new address is created. + +Added in Saleor 3.5. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type AddressCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The address the event relates to.""" + address: Address +} + +""" +Event sent when address is updated. + +Added in Saleor 3.5. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type AddressUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The address the event relates to.""" + address: Address +} + +""" +Event sent when address is deleted. + +Added in Saleor 3.5. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type AddressDeleted implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The address the event relates to.""" + address: Address +} + +""" +Event sent when new app is installed. + +Added in Saleor 3.4. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type AppInstalled implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The application the event relates to.""" + app: App +} + +""" +Event sent when app is updated. + +Added in Saleor 3.4. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type AppUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The application the event relates to.""" + app: App +} + +""" +Event sent when app is deleted. + +Added in Saleor 3.4. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type AppDeleted implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The application the event relates to.""" + app: App +} + +""" +Event sent when app status has changed. + +Added in Saleor 3.4. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type AppStatusChanged implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The application the event relates to.""" + app: App +} + +""" +Event sent when new attribute is created. + +Added in Saleor 3.5. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type AttributeCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The attribute the event relates to.""" + attribute: Attribute +} + +""" +Event sent when attribute is updated. + +Added in Saleor 3.5. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type AttributeUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The attribute the event relates to.""" + attribute: Attribute +} + +""" +Event sent when attribute is deleted. + +Added in Saleor 3.5. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type AttributeDeleted implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The attribute the event relates to.""" + attribute: Attribute +} + +""" +Event sent when new attribute value is created. + +Added in Saleor 3.5. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type AttributeValueCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The attribute value the event relates to.""" + attributeValue: AttributeValue +} + +""" +Event sent when attribute value is updated. + +Added in Saleor 3.5. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type AttributeValueUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The attribute value the event relates to.""" + attributeValue: AttributeValue +} + +""" +Event sent when attribute value is deleted. + +Added in Saleor 3.5. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type AttributeValueDeleted implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The attribute value the event relates to.""" + attributeValue: AttributeValue +} + +""" +Event sent when new category is created. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type CategoryCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The category the event relates to.""" + category: Category +} + +""" +Event sent when category is updated. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type CategoryUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The category the event relates to.""" + category: Category +} + +""" +Event sent when category is deleted. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type CategoryDeleted implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The category the event relates to.""" + category: Category +} + +""" +Event sent when new channel is created. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type ChannelCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The channel the event relates to.""" + channel: Channel +} + +""" +Event sent when channel is updated. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type ChannelUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The channel the event relates to.""" + channel: Channel +} + +""" +Event sent when channel is deleted. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type ChannelDeleted implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The channel the event relates to.""" + channel: Channel +} + +""" +Event sent when channel status has changed. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type ChannelStatusChanged implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The channel the event relates to.""" + channel: Channel +} + +""" +Event sent when new gift card is created. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type GiftCardCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The gift card the event relates to.""" + giftCard: GiftCard +} + +""" +Event sent when gift card is updated. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type GiftCardUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The gift card the event relates to.""" + giftCard: GiftCard +} + +""" +Event sent when gift card is deleted. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type GiftCardDeleted implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The gift card the event relates to.""" + giftCard: GiftCard +} + +""" +Event sent when gift card status has changed. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type GiftCardStatusChanged implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The gift card the event relates to.""" + giftCard: GiftCard +} + +""" +Event sent when gift card metadata is updated. + +Added in Saleor 3.8. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type GiftCardMetadataUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The gift card the event relates to.""" + giftCard: GiftCard +} + +""" +Event sent when new menu is created. + +Added in Saleor 3.4. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type MenuCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The menu the event relates to.""" + menu( + """Slug of a channel for which the data should be returned.""" + channel: String + ): Menu +} + +""" +Event sent when menu is updated. + +Added in Saleor 3.4. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type MenuUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The menu the event relates to.""" + menu( + """Slug of a channel for which the data should be returned.""" + channel: String + ): Menu +} + +""" +Event sent when menu is deleted. + +Added in Saleor 3.4. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type MenuDeleted implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The menu the event relates to.""" + menu( + """Slug of a channel for which the data should be returned.""" + channel: String + ): Menu +} + +""" +Event sent when new menu item is created. + +Added in Saleor 3.4. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type MenuItemCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The menu item the event relates to.""" + menuItem( + """Slug of a channel for which the data should be returned.""" + channel: String + ): MenuItem +} + +""" +Event sent when menu item is updated. + +Added in Saleor 3.4. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type MenuItemUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The menu item the event relates to.""" + menuItem( + """Slug of a channel for which the data should be returned.""" + channel: String + ): MenuItem +} + +""" +Event sent when menu item is deleted. + +Added in Saleor 3.4. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type MenuItemDeleted implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The menu item the event relates to.""" + menuItem( + """Slug of a channel for which the data should be returned.""" + channel: String + ): MenuItem +} + +""" +Event sent when new order is created. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type OrderCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The order the event relates to.""" + order: Order +} + +""" +Event sent when order is updated. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type OrderUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The order the event relates to.""" + order: Order +} + +""" +Event sent when order is confirmed. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type OrderConfirmed implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The order the event relates to.""" + order: Order +} + +""" +Event sent when order is fully paid. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type OrderFullyPaid implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The order the event relates to.""" + order: Order +} + +""" +Event sent when order is fulfilled. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type OrderFulfilled implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The order the event relates to.""" + order: Order +} + +""" +Event sent when order is canceled. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type OrderCancelled implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The order the event relates to.""" + order: Order +} + +""" +Event sent when order metadata is updated. + +Added in Saleor 3.8. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type OrderMetadataUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The order the event relates to.""" + order: Order +} + +""" +Event sent when new draft order is created. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type DraftOrderCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The order the event relates to.""" + order: Order +} + +""" +Event sent when draft order is updated. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type DraftOrderUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The order the event relates to.""" + order: Order +} + +""" +Event sent when draft order is deleted. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type DraftOrderDeleted implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The order the event relates to.""" + order: Order +} + +""" +Event sent when new product is created. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type ProductCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The product the event relates to.""" + product( + """Slug of a channel for which the data should be returned.""" + channel: String + ): Product + + """The category of the product.""" + category: Category +} + +""" +Event sent when product is updated. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type ProductUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The product the event relates to.""" + product( + """Slug of a channel for which the data should be returned.""" + channel: String + ): Product + + """The category of the product.""" + category: Category +} + +""" +Event sent when product is deleted. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type ProductDeleted implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The product the event relates to.""" + product( + """Slug of a channel for which the data should be returned.""" + channel: String + ): Product + + """The category of the product.""" + category: Category +} + +""" +Event sent when product metadata is updated. + +Added in Saleor 3.8. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type ProductMetadataUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The product the event relates to.""" + product( + """Slug of a channel for which the data should be returned.""" + channel: String + ): Product + + """The category of the product.""" + category: Category +} + +""" +Event sent when new product media is created. + +Added in Saleor 3.12. +""" +type ProductMediaCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The product media the event relates to.""" + productMedia: ProductMedia +} + +""" +Event sent when product media is updated. + +Added in Saleor 3.12. +""" +type ProductMediaUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The product media the event relates to.""" + productMedia: ProductMedia +} + +""" +Event sent when product media is deleted. + +Added in Saleor 3.12. +""" +type ProductMediaDeleted implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The product media the event relates to.""" + productMedia: ProductMedia +} + +""" +Event sent when new product variant is created. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type ProductVariantCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The product variant the event relates to.""" + productVariant( + """Slug of a channel for which the data should be returned.""" + channel: String + ): ProductVariant +} + +""" +Event sent when product variant is updated. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type ProductVariantUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The product variant the event relates to.""" + productVariant( + """Slug of a channel for which the data should be returned.""" + channel: String + ): ProductVariant +} + +""" +Event sent when product variant is out of stock. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type ProductVariantOutOfStock implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The product variant the event relates to.""" + productVariant( + """Slug of a channel for which the data should be returned.""" + channel: String + ): ProductVariant + + """Look up a warehouse.""" + warehouse: Warehouse +} + +""" +Event sent when product variant is back in stock. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type ProductVariantBackInStock implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The product variant the event relates to.""" + productVariant( + """Slug of a channel for which the data should be returned.""" + channel: String + ): ProductVariant + + """Look up a warehouse.""" + warehouse: Warehouse +} + +""" +Event sent when product variant stock is updated. + +Added in Saleor 3.11. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type ProductVariantStockUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The product variant the event relates to.""" + productVariant( + """Slug of a channel for which the data should be returned.""" + channel: String + ): ProductVariant + + """Look up a warehouse.""" + warehouse: Warehouse +} + +""" +Event sent when product variant is deleted. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type ProductVariantDeleted implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The product variant the event relates to.""" + productVariant( + """Slug of a channel for which the data should be returned.""" + channel: String + ): ProductVariant +} + +""" +Event sent when product variant metadata is updated. + +Added in Saleor 3.8. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type ProductVariantMetadataUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The product variant the event relates to.""" + productVariant( + """Slug of a channel for which the data should be returned.""" + channel: String + ): ProductVariant +} + +""" +Event sent when new sale is created. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type SaleCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The sale the event relates to.""" + sale( + """Slug of a channel for which the data should be returned.""" + channel: String + ): Sale +} + +""" +Event sent when sale is updated. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type SaleUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The sale the event relates to.""" + sale( + """Slug of a channel for which the data should be returned.""" + channel: String + ): Sale +} + +""" +Event sent when sale is deleted. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type SaleDeleted implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The sale the event relates to.""" + sale( + """Slug of a channel for which the data should be returned.""" + channel: String + ): Sale +} + +""" +The event informs about the start or end of the sale. + +Added in Saleor 3.5. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type SaleToggle implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """ + The sale the event relates to. + + Added in Saleor 3.5. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + sale( + """Slug of a channel for which the data should be returned.""" + channel: String + ): Sale +} + +""" +Event sent when invoice is requested. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type InvoiceRequested implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The invoice the event relates to.""" + invoice: Invoice + + """ + Order related to the invoice. + + Added in Saleor 3.10. + """ + order: Order! +} + +""" +Event sent when invoice is deleted. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type InvoiceDeleted implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The invoice the event relates to.""" + invoice: Invoice + + """ + Order related to the invoice. + + Added in Saleor 3.10. + """ + order: Order +} + +""" +Event sent when invoice is sent. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type InvoiceSent implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The invoice the event relates to.""" + invoice: Invoice + + """ + Order related to the invoice. + + Added in Saleor 3.10. + """ + order: Order +} + +""" +Event sent when new fulfillment is created. + +Added in Saleor 3.4. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type FulfillmentCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The fulfillment the event relates to.""" + fulfillment: Fulfillment + + """The order the fulfillment belongs to.""" + order: Order +} + +""" +Event sent when fulfillment is canceled. + +Added in Saleor 3.4. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type FulfillmentCanceled implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The fulfillment the event relates to.""" + fulfillment: Fulfillment + + """The order the fulfillment belongs to.""" + order: Order +} + +""" +Event sent when fulfillment is approved. + +Added in Saleor 3.7. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type FulfillmentApproved implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The fulfillment the event relates to.""" + fulfillment: Fulfillment + + """The order the fulfillment belongs to.""" + order: Order +} + +""" +Event sent when fulfillment metadata is updated. + +Added in Saleor 3.8. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type FulfillmentMetadataUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The fulfillment the event relates to.""" + fulfillment: Fulfillment + + """The order the fulfillment belongs to.""" + order: Order +} + +""" +Event sent when new customer user is created. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type CustomerCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The user the event relates to.""" + user: User +} + +""" +Event sent when customer user is updated. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type CustomerUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The user the event relates to.""" + user: User +} + +""" +Event sent when customer user metadata is updated. + +Added in Saleor 3.8. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type CustomerMetadataUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The user the event relates to.""" + user: User +} + +""" +Event sent when new collection is created. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type CollectionCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The collection the event relates to.""" + collection( + """Slug of a channel for which the data should be returned.""" + channel: String + ): Collection +} + +""" +Event sent when collection is updated. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type CollectionUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The collection the event relates to.""" + collection( + """Slug of a channel for which the data should be returned.""" + channel: String + ): Collection +} + +""" +Event sent when collection is deleted. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type CollectionDeleted implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The collection the event relates to.""" + collection( + """Slug of a channel for which the data should be returned.""" + channel: String + ): Collection +} + +""" +Event sent when collection metadata is updated. + +Added in Saleor 3.8. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type CollectionMetadataUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The collection the event relates to.""" + collection( + """Slug of a channel for which the data should be returned.""" + channel: String + ): Collection +} + +""" +Event sent when new checkout is created. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type CheckoutCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The checkout the event relates to.""" + checkout: Checkout +} + +""" +Event sent when checkout is updated. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type CheckoutUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The checkout the event relates to.""" + checkout: Checkout +} + +""" +Event sent when checkout metadata is updated. + +Added in Saleor 3.8. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type CheckoutMetadataUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The checkout the event relates to.""" + checkout: Checkout +} + +""" +Event sent when new page is created. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type PageCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The page the event relates to.""" + page: Page +} + +""" +Event sent when page is updated. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type PageUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The page the event relates to.""" + page: Page +} + +""" +Event sent when page is deleted. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type PageDeleted implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The page the event relates to.""" + page: Page +} + +""" +Event sent when new page type is created. + +Added in Saleor 3.5. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type PageTypeCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The page type the event relates to.""" + pageType: PageType +} + +""" +Event sent when page type is updated. + +Added in Saleor 3.5. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type PageTypeUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The page type the event relates to.""" + pageType: PageType +} + +""" +Event sent when page type is deleted. + +Added in Saleor 3.5. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type PageTypeDeleted implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The page type the event relates to.""" + pageType: PageType +} + +""" +Event sent when new permission group is created. + +Added in Saleor 3.6. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type PermissionGroupCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The permission group the event relates to.""" + permissionGroup: Group +} + +""" +Event sent when permission group is updated. + +Added in Saleor 3.6. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type PermissionGroupUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The permission group the event relates to.""" + permissionGroup: Group +} + +""" +Event sent when permission group is deleted. + +Added in Saleor 3.6. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type PermissionGroupDeleted implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The permission group the event relates to.""" + permissionGroup: Group +} + +""" +Event sent when new shipping price is created. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type ShippingPriceCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The shipping method the event relates to.""" + shippingMethod( + """Slug of a channel for which the data should be returned.""" + channel: String + ): ShippingMethodType + + """The shipping zone the shipping method belongs to.""" + shippingZone( + """Slug of a channel for which the data should be returned.""" + channel: String + ): ShippingZone +} + +""" +Event sent when shipping price is updated. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type ShippingPriceUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The shipping method the event relates to.""" + shippingMethod( + """Slug of a channel for which the data should be returned.""" + channel: String + ): ShippingMethodType + + """The shipping zone the shipping method belongs to.""" + shippingZone( + """Slug of a channel for which the data should be returned.""" + channel: String + ): ShippingZone +} + +""" +Event sent when shipping price is deleted. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type ShippingPriceDeleted implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The shipping method the event relates to.""" + shippingMethod( + """Slug of a channel for which the data should be returned.""" + channel: String + ): ShippingMethodType + + """The shipping zone the shipping method belongs to.""" + shippingZone( + """Slug of a channel for which the data should be returned.""" + channel: String + ): ShippingZone +} + +""" +Event sent when new shipping zone is created. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type ShippingZoneCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The shipping zone the event relates to.""" + shippingZone( + """Slug of a channel for which the data should be returned.""" + channel: String + ): ShippingZone +} + +""" +Event sent when shipping zone is updated. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type ShippingZoneUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The shipping zone the event relates to.""" + shippingZone( + """Slug of a channel for which the data should be returned.""" + channel: String + ): ShippingZone +} + +""" +Event sent when shipping zone is deleted. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type ShippingZoneDeleted implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The shipping zone the event relates to.""" + shippingZone( + """Slug of a channel for which the data should be returned.""" + channel: String + ): ShippingZone +} + +""" +Event sent when shipping zone metadata is updated. + +Added in Saleor 3.8. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type ShippingZoneMetadataUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The shipping zone the event relates to.""" + shippingZone( + """Slug of a channel for which the data should be returned.""" + channel: String + ): ShippingZone +} + +""" +Event sent when new staff user is created. + +Added in Saleor 3.5. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type StaffCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The user the event relates to.""" + user: User +} + +""" +Event sent when staff user is updated. + +Added in Saleor 3.5. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type StaffUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The user the event relates to.""" + user: User +} + +""" +Event sent when staff user is deleted. + +Added in Saleor 3.5. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type StaffDeleted implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The user the event relates to.""" + user: User +} + +""" +Event sent when transaction action is requested. + +Added in Saleor 3.4. + +DEPRECATED: this subscription will be removed in Saleor 3.14 (Preview Feature). Use `TransactionChargeRequested`, `TransactionRefundRequested`, `TransactionCancelationRequested` instead. +""" +type TransactionActionRequest implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """Look up a transaction.""" + transaction: TransactionItem + + """Requested action data.""" + action: TransactionAction! +} + +type TransactionAction { + """Determines the action type.""" + actionType: TransactionActionEnum! + + """Transaction request amount. Null when action type is VOID.""" + amount: PositiveDecimal +} + +""" +Event sent when transaction item metadata is updated. + +Added in Saleor 3.8. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type TransactionItemMetadataUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """ + Look up a transaction. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + transaction: TransactionItem +} + +""" +Event sent when new translation is created. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type TranslationCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The translation the event relates to.""" + translation: TranslationTypes +} + +union TranslationTypes = ProductTranslation | CollectionTranslation | CategoryTranslation | AttributeTranslation | AttributeValueTranslation | ProductVariantTranslation | PageTranslation | ShippingMethodTranslation | SaleTranslation | VoucherTranslation | MenuItemTranslation + +""" +Event sent when translation is updated. + +Added in Saleor 3.2. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type TranslationUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The translation the event relates to.""" + translation: TranslationTypes +} + +""" +Event sent when new voucher is created. + +Added in Saleor 3.4. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type VoucherCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The voucher the event relates to.""" + voucher( + """Slug of a channel for which the data should be returned.""" + channel: String + ): Voucher +} + +""" +Event sent when voucher is updated. + +Added in Saleor 3.4. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type VoucherUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The voucher the event relates to.""" + voucher( + """Slug of a channel for which the data should be returned.""" + channel: String + ): Voucher +} + +""" +Event sent when voucher is deleted. + +Added in Saleor 3.4. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type VoucherDeleted implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The voucher the event relates to.""" + voucher( + """Slug of a channel for which the data should be returned.""" + channel: String + ): Voucher +} + +""" +Event sent when voucher metadata is updated. + +Added in Saleor 3.8. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type VoucherMetadataUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The voucher the event relates to.""" + voucher( + """Slug of a channel for which the data should be returned.""" + channel: String + ): Voucher +} + +""" +Event sent when new warehouse is created. + +Added in Saleor 3.4. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type WarehouseCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The warehouse the event relates to.""" + warehouse: Warehouse +} + +""" +Event sent when warehouse is updated. + +Added in Saleor 3.4. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type WarehouseUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The warehouse the event relates to.""" + warehouse: Warehouse +} + +""" +Event sent when warehouse is deleted. + +Added in Saleor 3.4. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type WarehouseDeleted implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The warehouse the event relates to.""" + warehouse: Warehouse +} + +""" +Event sent when warehouse metadata is updated. + +Added in Saleor 3.8. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type WarehouseMetadataUpdated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The warehouse the event relates to.""" + warehouse: Warehouse +} + +""" +Event sent when thumbnail is created. + +Added in Saleor 3.12. +""" +type ThumbnailCreated implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """ + Thumbnail id. + + Added in Saleor 3.12. + """ + id: ID + + """ + Thumbnail url. + + Added in Saleor 3.12. + """ + url: String + + """ + Object the thumbnail refers to. + + Added in Saleor 3.12. + """ + objectId: ID + + """ + Original media url. + + Added in Saleor 3.12. + """ + mediaUrl: String +} + +""" +Authorize payment. + +Added in Saleor 3.6. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type PaymentAuthorize implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """Look up a payment.""" + payment: Payment +} + +""" +Capture payment. + +Added in Saleor 3.6. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type PaymentCaptureEvent implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """Look up a payment.""" + payment: Payment +} + +""" +Refund payment. + +Added in Saleor 3.6. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type PaymentRefundEvent implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """Look up a payment.""" + payment: Payment +} + +""" +Void payment. + +Added in Saleor 3.6. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type PaymentVoidEvent implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """Look up a payment.""" + payment: Payment +} + +""" +Confirm payment. + +Added in Saleor 3.6. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type PaymentConfirmEvent implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """Look up a payment.""" + payment: Payment +} + +""" +Process payment. + +Added in Saleor 3.6. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type PaymentProcessEvent implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """Look up a payment.""" + payment: Payment +} + +""" +List payment gateways. + +Added in Saleor 3.6. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type PaymentListGateways implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The checkout the event relates to.""" + checkout: Checkout +} + +""" +Event sent when transaction cancelation is requested. + +Added in Saleor 3.13. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type TransactionCancelationRequested implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """Look up a transaction.""" + transaction: TransactionItem + + """Requested action data.""" + action: TransactionAction! +} + +""" +Event sent when transaction charge is requested. + +Added in Saleor 3.13. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type TransactionChargeRequested implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """Look up a transaction.""" + transaction: TransactionItem + + """Requested action data.""" + action: TransactionAction! +} + +""" +Event sent when transaction refund is requested. + +Added in Saleor 3.13. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type TransactionRefundRequested implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """Look up a transaction.""" + transaction: TransactionItem + + """Requested action data.""" + action: TransactionAction! +} + +""" +Filter shipping methods for order. + +Added in Saleor 3.6. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type OrderFilterShippingMethods implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The order the event relates to.""" + order: Order + + """ + Shipping methods that can be used with this checkout. + + Added in Saleor 3.6. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + shippingMethods: [ShippingMethod!] +} + +""" +Filter shipping methods for checkout. + +Added in Saleor 3.6. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type CheckoutFilterShippingMethods implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The checkout the event relates to.""" + checkout: Checkout + + """ + Shipping methods that can be used with this checkout. + + Added in Saleor 3.6. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + shippingMethods: [ShippingMethod!] +} + +""" +List shipping methods for checkout. + +Added in Saleor 3.6. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type ShippingListMethodsForCheckout implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """The checkout the event relates to.""" + checkout: Checkout + + """ + Shipping methods that can be used with this checkout. + + Added in Saleor 3.6. + + Note: this API is currently in Feature Preview and can be subject to changes at later point. + """ + shippingMethods: [ShippingMethod!] +} + +""" +Synchronous webhook for calculating checkout/order taxes. + +Added in Saleor 3.7. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type CalculateTaxes implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + taxBase: TaxableObject! +} + +"""Taxable object.""" +type TaxableObject { + """The source object related to this tax object.""" + sourceObject: TaxSourceObject! + + """Determines if prices contain entered tax..""" + pricesEnteredWithTax: Boolean! + + """The currency of the object.""" + currency: String! + + """The price of shipping method.""" + shippingPrice: Money! + + """The address data.""" + address: Address + + """List of discounts.""" + discounts: [TaxableObjectDiscount!]! + + """List of lines assigned to the object.""" + lines: [TaxableObjectLine!]! + channel: Channel! +} + +"""Taxable object discount.""" +type TaxableObjectDiscount { + """The name of the discount.""" + name: String + + """The amount of the discount.""" + amount: Money! +} + +type TaxableObjectLine { + """The source line related to this tax line.""" + sourceLine: TaxSourceLine! + + """Number of items.""" + quantity: Int! + + """Determines if taxes are being charged for the product.""" + chargeTaxes: Boolean! + + """The product name.""" + productName: String! + + """The variant name.""" + variantName: String! + + """The product sku.""" + productSku: String + + """Price of the single item in the order line.""" + unitPrice: Money! + + """Price of the order line.""" + totalPrice: Money! +} + +union TaxSourceLine = CheckoutLine | OrderLine + +""" +Event sent when user wants to initialize the payment gateway. + +Added in Saleor 3.13. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type PaymentGatewayInitializeSession implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """Checkout or order""" + sourceObject: OrderOrCheckout! + + """Payment gateway data in JSON format, recieved from storefront.""" + data: JSON + + """Amount requested for initializing the payment gateway.""" + amount: PositiveDecimal +} + +union OrderOrCheckout = Checkout | Order + +""" +Event sent when user starts processing the payment. + +Added in Saleor 3.13. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type TransactionInitializeSession implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """Look up a transaction.""" + transaction: TransactionItem! + + """Checkout or order""" + sourceObject: OrderOrCheckout! + + """Payment gateway data in JSON format, recieved from storefront.""" + data: JSON + + """Merchant reference assigned to this payment.""" + merchantReference: String! + + """Action to proceed for the transaction""" + action: TransactionProcessAction! +} + +type TransactionProcessAction { + """Transaction amount to process.""" + amount: PositiveDecimal! + + """Currency of the amount.""" + currency: String! + actionType: TransactionFlowStrategyEnum! +} + +""" +Event sent when user has additional payment action to process. + +Added in Saleor 3.13. + +Note: this API is currently in Feature Preview and can be subject to changes at later point. +""" +type TransactionProcessSession implements Event { + """Time of the event.""" + issuedAt: DateTime + + """Saleor version that triggered the event.""" + version: String + + """The user or application that triggered the event.""" + issuingPrincipal: IssuingPrincipal + + """The application receiving the webhook.""" + recipient: App + + """Look up a transaction.""" + transaction: TransactionItem! + + """Checkout or order""" + sourceObject: OrderOrCheckout! + + """Payment gateway data in JSON format, recieved from storefront.""" + data: JSON + + """Merchant reference assigned to this payment.""" + merchantReference: String! + + """Action to proceed for the transaction""" + action: TransactionProcessAction! +} + +"""_Any value scalar as defined by Federation spec.""" +scalar _Any + +"""_Entity union as defined by Federation spec.""" +union _Entity = App | Address | User | Group | ProductVariant | Product | ProductType | ProductMedia | Category | Collection | PageType + +"""_Service manifest as defined by Federation spec.""" +type _Service { + sdl: String +} diff --git a/graphql/subscriptions/.gitkeep b/graphql/subscriptions/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/graphql/subscriptions/PaymentGatewayInitializeSession.graphql b/graphql/subscriptions/PaymentGatewayInitializeSession.graphql new file mode 100644 index 0000000..73467dc --- /dev/null +++ b/graphql/subscriptions/PaymentGatewayInitializeSession.graphql @@ -0,0 +1,5 @@ +subscription PaymentGatewayInitializeSession { + event { + ...PaymentGatewayInitializeSessionEvent + } +} diff --git a/graphql/subscriptions/TransactionCancelationRequested.graphql b/graphql/subscriptions/TransactionCancelationRequested.graphql new file mode 100644 index 0000000..70082b2 --- /dev/null +++ b/graphql/subscriptions/TransactionCancelationRequested.graphql @@ -0,0 +1,5 @@ +subscription TransactionCancelationRequested { + event { + ...TransactionCancelationRequestedEvent + } +} diff --git a/graphql/subscriptions/TransactionChargeRequested.graphql b/graphql/subscriptions/TransactionChargeRequested.graphql new file mode 100644 index 0000000..7314c24 --- /dev/null +++ b/graphql/subscriptions/TransactionChargeRequested.graphql @@ -0,0 +1,5 @@ +subscription TransactionChargeRequested { + event { + ...TransactionChargeRequestedEvent + } +} diff --git a/graphql/subscriptions/TransactionInitializeSession.graphql b/graphql/subscriptions/TransactionInitializeSession.graphql new file mode 100644 index 0000000..75b6cfa --- /dev/null +++ b/graphql/subscriptions/TransactionInitializeSession.graphql @@ -0,0 +1,5 @@ +subscription TransactionInitializeSession { + event { + ...TransactionInitializeSessionEvent + } +} diff --git a/graphql/subscriptions/TransactionProcessSession.graphql b/graphql/subscriptions/TransactionProcessSession.graphql new file mode 100644 index 0000000..e865fa1 --- /dev/null +++ b/graphql/subscriptions/TransactionProcessSession.graphql @@ -0,0 +1,5 @@ +subscription TransactionProcessSession { + event { + ...TransactionProcessSessionEvent + } +} diff --git a/graphql/subscriptions/TransactionRefundRequested.graphql b/graphql/subscriptions/TransactionRefundRequested.graphql new file mode 100644 index 0000000..4011843 --- /dev/null +++ b/graphql/subscriptions/TransactionRefundRequested.graphql @@ -0,0 +1,5 @@ +subscription TransactionRefundRequested { + event { + ...TransactionRefundRequestedEvent + } +} diff --git a/next-env.d.ts b/next-env.d.ts new file mode 100644 index 0000000..4f11a03 --- /dev/null +++ b/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/next.config.mjs b/next.config.mjs new file mode 100644 index 0000000..f8dd123 --- /dev/null +++ b/next.config.mjs @@ -0,0 +1,31 @@ +// @ts-check +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ +/* eslint-disable @typescript-eslint/no-unsafe-call */ + +import { createVanillaExtractPlugin } from "@vanilla-extract/next-plugin"; +const withVanillaExtract = createVanillaExtractPlugin(); +import { withSentryConfig } from "@sentry/nextjs"; + +/** + * Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. + * This is especially useful for Docker builds. + */ +!process.env.SKIP_ENV_VALIDATION && (await import("./src/lib/env.mjs")); + +/** @type {import('next').NextConfig} */ +const config = { + reactStrictMode: true, + /** @param { import("webpack").Configuration } config */ + webpack(config) { + config.experiments = { ...config.experiments, topLevelAwait: true }; + return config; + }, +}; + +const isSentryEnabled = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN; + +const vanillaExtractConfig = withVanillaExtract(config); + +export default isSentryEnabled + ? withSentryConfig(vanillaExtractConfig, { silent: true }, { hideSourceMaps: true }) + : vanillaExtractConfig; diff --git a/package.json b/package.json new file mode 100644 index 0000000..160fe1e --- /dev/null +++ b/package.json @@ -0,0 +1,152 @@ +{ + "$schema": "https://json.schemastore.org/package.json", + "name": "saleor-app-payment-stripe", + "description": "Saleor App Payment Stripe is a payment integration app that allows merchants using the Saleor e-commerce platform to accept online payments from customers using Stripe as their payment processor.", + "version": "0.4.0", + "private": true, + "repository": "github:saleor/saleor-app-payment-stripe", + "homepage": "https://github.com/saleor/saleor-app-payment-stripe", + "bugs": { + "url": "https://github.com/saleor/saleor-app-payment-stripe/issues", + "email": "hello@saleor.io" + }, + "type": "module", + "scripts": { + "dev": "pnpm generate && next dev", + "build": "pnpm generate && next build", + "deploy": "tsx ./src/deploy.ts", + "start": "next start", + "fetch-schema": "curl https://raw.githubusercontent.com/saleor/saleor/${npm_package_saleor_schemaVersion}/saleor/graphql/schema.graphql > graphql/schema.graphql", + "generate": "pnpm generate:graphql && pnpm generate:schema", + "generate:graphql": "graphql-codegen", + "generate:schema": "pnpm saleor-schema-compiler compile ./src/schemas --definitions ./src/schemas/definitions.json", + "lint": "next lint --fix --dir src", + "lint:ci": "next lint --dir src", + "test": "vitest", + "test:record": "POLLY_MODE=record_missing vitest", + "test:rerecord": "POLLY_MODE=record vitest", + "test:ci": "CI=true vitest --coverage --reporter=json --reporter=default && tsx fix-coverage-report.cjs", + "migrate": "pnpm tsx ./src/run-migrations.ts", + "ts-node-esm": "node --loader ts-node/esm --experimental-specifier-resolution=node", + "prepare": "node -e \"try { require('husky').install() } catch (e) {if (e.code !== 'MODULE_NOT_FOUND') throw e}\"", + "github:release": "pnpm changeset tag && git push --follow-tags" + }, + "saleor": { + "schemaVersion": "3.13" + }, + "dependencies": { + "@hookform/resolvers": "3.3.2", + "@next/env": "14.0.4", + "@radix-ui/react-alert-dialog": "1.0.5", + "@saleor/app-sdk": "0.47.2", + "@saleor/macaw-ui": "0.8.0-pre.123", + "@sentry/nextjs": "7.86.0", + "@t3-oss/env-nextjs": "0.7.1", + "@tanstack/react-query": "4", + "@tanstack/react-query-devtools": "4.36.1", + "@trpc/client": "10.44.1", + "@trpc/next": "10.44.1", + "@trpc/server": "10.44.1", + "@urql/exchange-auth": "1.0.0", + "@vanilla-extract/css": "1.14.0", + "@vanilla-extract/next-plugin": "2.3.2", + "@vanilla-extract/recipes": "0.5.1", + "@vitejs/plugin-react": "4.2.1", + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "bluebird": "3.7.2", + "classnames": "2.3.2", + "eslint-plugin-node": "11.1.0", + "graphql": "16.8.1", + "graphql-tag": "2.12.6", + "jose": "5.1.3", + "jsdom": "23.0.1", + "lodash-es": "4.17.21", + "modern-errors": "7.0.0", + "modern-errors-http": "5.0.0", + "modern-errors-serialize": "6.0.0", + "next": "14.2.10", + "omit-deep-lodash": "1.1.7", + "pino": "8.16.2", + "pino-pretty": "10.2.3", + "react": "18.2.0", + "react-dom": "18.2.0", + "react-hook-form": "7.49.1", + "semver": "7.5.4", + "stripe": "14.8.0", + "stripe-event-types": "3.1.0", + "tsx": "4.6.2", + "url-join": "5.0.0", + "urql": "3.0.4", + "uuidv7": "0.6.3", + "webpack": "5.94.0", + "yup": "1.3.2", + "zod": "3.22.4", + "zustand": "4.4.7" + }, + "devDependencies": { + "@changesets/cli": "2.27.1", + "@graphql-codegen/add": "5.0.0", + "@graphql-codegen/cli": "5.0.0", + "@graphql-codegen/introspection": "4.0.0", + "@graphql-codegen/typed-document-node": "5.0.1", + "@graphql-codegen/typescript": "4.0.1", + "@graphql-codegen/typescript-operations": "4.0.1", + "@graphql-codegen/typescript-urql": "4.0.0", + "@graphql-codegen/urql-introspection": "3.0.0", + "@graphql-typed-document-node/core": "3.2.0", + "@pollyjs/adapter-fetch": "6.0.6", + "@pollyjs/adapter-node-http": "6.0.6", + "@pollyjs/core": "6.0.6", + "@pollyjs/persister-fs": "6.0.6", + "@saleor/eslint-plugin-saleor-app": "0.1.2", + "@saleor/json-schema-compiler": "0.1.2", + "@testing-library/jest-dom": "6.1.5", + "@testing-library/react": "14.1.2", + "@testing-library/react-hooks": "8.0.1", + "@types/bluebird": "3.5.42", + "@types/lodash-es": "4.17.12", + "@types/node": "20.10.4", + "@types/omit-deep-lodash": "1.1.3", + "@types/react": "18.2.45", + "@types/react-dom": "18.2.17", + "@types/semver": "7.5.6", + "@types/setup-polly-jest": "0.5.5", + "@typescript-eslint/eslint-plugin": "6.14.0", + "@typescript-eslint/parser": "6.14.0", + "@vanilla-extract/vite-plugin": "3.9.3", + "@vitest/coverage-v8": "0.34.2", + "vite": "5.0.8", + "dependency-cruiser": "15.5.0", + "eslint": "8.55.0", + "eslint-config-next": "14.0.4", + "eslint-config-prettier": "9.1.0", + "eslint-plugin-import": "2.29.0", + "eslint-plugin-require-form-method": "1.0.2", + "eslint-plugin-testing-library": "6.2.0", + "eslint-plugin-vitest": "0.3.16", + "husky": "8.0.3", + "json-schema-to-typescript": "13.1.1", + "lint-staged": "15.2.0", + "next-test-api-route-handler": "3.1.10", + "prettier": "3.1.1", + "setup-polly-jest": "0.11.0", + "ts-node": "10.9.2", + "typescript": "5.3.3", + "vite-tsconfig-paths": "4.2.2", + "vitest": "0.34.2" + }, + "engines": { + "npm": ">=8.0.0 <10.0.0", + "node": "^20.0.0 || ^22.0.0", + "pnpm": "~8.12.0" + }, + "packageManager": "pnpm@8.12.0", + "pnpm": { + "overrides": { + "@urql/exchange-auth>@urql/core": "3.2.2", + "@typescript-eslint/parser": "$@typescript-eslint/parser", + "vite": "$vite" + } + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..c68b38f --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,12008 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +overrides: + '@urql/exchange-auth>@urql/core': 3.2.2 + '@typescript-eslint/parser': 6.14.0 + vite: 5.0.8 + +dependencies: + '@hookform/resolvers': + specifier: 3.3.2 + version: 3.3.2(react-hook-form@7.49.1) + '@next/env': + specifier: 14.0.4 + version: 14.0.4 + '@radix-ui/react-alert-dialog': + specifier: 1.0.5 + version: 1.0.5(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@saleor/app-sdk': + specifier: 0.47.2 + version: 0.47.2(graphql@16.8.1)(next@14.2.10)(react-dom@18.2.0)(react@18.2.0) + '@saleor/macaw-ui': + specifier: 0.8.0-pre.123 + version: 0.8.0-pre.123(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@sentry/nextjs': + specifier: 7.86.0 + version: 7.86.0(next@14.2.10)(react@18.2.0)(webpack@5.94.0) + '@t3-oss/env-nextjs': + specifier: 0.7.1 + version: 0.7.1(typescript@5.3.3)(zod@3.22.4) + '@tanstack/react-query': + specifier: '4' + version: 4.36.1(react-dom@18.2.0)(react@18.2.0) + '@tanstack/react-query-devtools': + specifier: 4.36.1 + version: 4.36.1(@tanstack/react-query@4.36.1)(react-dom@18.2.0)(react@18.2.0) + '@trpc/client': + specifier: 10.44.1 + version: 10.44.1(@trpc/server@10.44.1) + '@trpc/next': + specifier: 10.44.1 + version: 10.44.1(@tanstack/react-query@4.36.1)(@trpc/client@10.44.1)(@trpc/react-query@10.44.1)(@trpc/server@10.44.1)(next@14.2.10)(react-dom@18.2.0)(react@18.2.0) + '@trpc/server': + specifier: 10.44.1 + version: 10.44.1 + '@urql/exchange-auth': + specifier: 1.0.0 + version: 1.0.0(graphql@16.8.1) + '@vanilla-extract/css': + specifier: 1.14.0 + version: 1.14.0 + '@vanilla-extract/next-plugin': + specifier: 2.3.2 + version: 2.3.2(@types/node@20.10.4)(next@14.2.10)(webpack@5.94.0) + '@vanilla-extract/recipes': + specifier: 0.5.1 + version: 0.5.1(@vanilla-extract/css@1.14.0) + '@vitejs/plugin-react': + specifier: 4.2.1 + version: 4.2.1(vite@5.0.8) + ajv: + specifier: 8.12.0 + version: 8.12.0 + ajv-formats: + specifier: 2.1.1 + version: 2.1.1(ajv@8.12.0) + bluebird: + specifier: 3.7.2 + version: 3.7.2 + classnames: + specifier: 2.3.2 + version: 2.3.2 + eslint-plugin-node: + specifier: 11.1.0 + version: 11.1.0(eslint@8.55.0) + graphql: + specifier: 16.8.1 + version: 16.8.1 + graphql-tag: + specifier: 2.12.6 + version: 2.12.6(graphql@16.8.1) + jose: + specifier: 5.1.3 + version: 5.1.3 + jsdom: + specifier: 23.0.1 + version: 23.0.1 + lodash-es: + specifier: 4.17.21 + version: 4.17.21 + modern-errors: + specifier: 7.0.0 + version: 7.0.0 + modern-errors-http: + specifier: 5.0.0 + version: 5.0.0(modern-errors@7.0.0) + modern-errors-serialize: + specifier: 6.0.0 + version: 6.0.0(modern-errors@7.0.0) + next: + specifier: 14.2.10 + version: 14.2.10(@babel/core@7.23.6)(react-dom@18.2.0)(react@18.2.0) + omit-deep-lodash: + specifier: 1.1.7 + version: 1.1.7 + pino: + specifier: 8.16.2 + version: 8.16.2 + pino-pretty: + specifier: 10.2.3 + version: 10.2.3 + react: + specifier: 18.2.0 + version: 18.2.0 + react-dom: + specifier: 18.2.0 + version: 18.2.0(react@18.2.0) + react-hook-form: + specifier: 7.49.1 + version: 7.49.1(react@18.2.0) + semver: + specifier: 7.5.4 + version: 7.5.4 + stripe: + specifier: 14.8.0 + version: 14.8.0 + stripe-event-types: + specifier: 3.1.0 + version: 3.1.0(stripe@14.8.0) + tsx: + specifier: 4.6.2 + version: 4.6.2 + url-join: + specifier: 5.0.0 + version: 5.0.0 + urql: + specifier: 3.0.4 + version: 3.0.4(graphql@16.8.1)(react@18.2.0) + uuidv7: + specifier: 0.6.3 + version: 0.6.3 + webpack: + specifier: 5.94.0 + version: 5.94.0 + yup: + specifier: 1.3.2 + version: 1.3.2 + zod: + specifier: 3.22.4 + version: 3.22.4 + zustand: + specifier: 4.4.7 + version: 4.4.7(@types/react@18.2.45)(react@18.2.0) + +devDependencies: + '@changesets/cli': + specifier: 2.27.1 + version: 2.27.1 + '@graphql-codegen/add': + specifier: 5.0.0 + version: 5.0.0(graphql@16.8.1) + '@graphql-codegen/cli': + specifier: 5.0.0 + version: 5.0.0(@types/node@20.10.4)(graphql@16.8.1)(typescript@5.3.3) + '@graphql-codegen/introspection': + specifier: 4.0.0 + version: 4.0.0(graphql@16.8.1) + '@graphql-codegen/typed-document-node': + specifier: 5.0.1 + version: 5.0.1(graphql@16.8.1) + '@graphql-codegen/typescript': + specifier: 4.0.1 + version: 4.0.1(graphql@16.8.1) + '@graphql-codegen/typescript-operations': + specifier: 4.0.1 + version: 4.0.1(graphql@16.8.1) + '@graphql-codegen/typescript-urql': + specifier: 4.0.0 + version: 4.0.0(graphql-tag@2.12.6)(graphql@16.8.1) + '@graphql-codegen/urql-introspection': + specifier: 3.0.0 + version: 3.0.0(graphql@16.8.1) + '@graphql-typed-document-node/core': + specifier: 3.2.0 + version: 3.2.0(graphql@16.8.1) + '@pollyjs/adapter-fetch': + specifier: 6.0.6 + version: 6.0.6 + '@pollyjs/adapter-node-http': + specifier: 6.0.6 + version: 6.0.6 + '@pollyjs/core': + specifier: 6.0.6 + version: 6.0.6 + '@pollyjs/persister-fs': + specifier: 6.0.6 + version: 6.0.6 + '@saleor/eslint-plugin-saleor-app': + specifier: 0.1.2 + version: 0.1.2(eslint@8.55.0) + '@saleor/json-schema-compiler': + specifier: 0.1.2 + version: 0.1.2 + '@testing-library/jest-dom': + specifier: 6.1.5 + version: 6.1.5(vitest@0.34.2) + '@testing-library/react': + specifier: 14.1.2 + version: 14.1.2(react-dom@18.2.0)(react@18.2.0) + '@testing-library/react-hooks': + specifier: 8.0.1 + version: 8.0.1(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@types/bluebird': + specifier: 3.5.42 + version: 3.5.42 + '@types/lodash-es': + specifier: 4.17.12 + version: 4.17.12 + '@types/node': + specifier: 20.10.4 + version: 20.10.4 + '@types/omit-deep-lodash': + specifier: 1.1.3 + version: 1.1.3 + '@types/react': + specifier: 18.2.45 + version: 18.2.45 + '@types/react-dom': + specifier: 18.2.17 + version: 18.2.17 + '@types/semver': + specifier: 7.5.6 + version: 7.5.6 + '@types/setup-polly-jest': + specifier: 0.5.5 + version: 0.5.5 + '@typescript-eslint/eslint-plugin': + specifier: 6.14.0 + version: 6.14.0(@typescript-eslint/parser@6.14.0)(eslint@8.55.0)(typescript@5.3.3) + '@typescript-eslint/parser': + specifier: 6.14.0 + version: 6.14.0(eslint@8.55.0)(typescript@5.3.3) + '@vanilla-extract/vite-plugin': + specifier: 3.9.3 + version: 3.9.3(@types/node@20.10.4)(ts-node@10.9.2)(vite@5.0.8) + '@vitest/coverage-v8': + specifier: 0.34.2 + version: 0.34.2(vitest@0.34.2) + dependency-cruiser: + specifier: 15.5.0 + version: 15.5.0 + eslint: + specifier: 8.55.0 + version: 8.55.0 + eslint-config-next: + specifier: 14.0.4 + version: 14.0.4(eslint@8.55.0)(typescript@5.3.3) + eslint-config-prettier: + specifier: 9.1.0 + version: 9.1.0(eslint@8.55.0) + eslint-plugin-import: + specifier: 2.29.0 + version: 2.29.0(@typescript-eslint/parser@6.14.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.55.0) + eslint-plugin-require-form-method: + specifier: 1.0.2 + version: 1.0.2 + eslint-plugin-testing-library: + specifier: 6.2.0 + version: 6.2.0(eslint@8.55.0)(typescript@5.3.3) + eslint-plugin-vitest: + specifier: 0.3.16 + version: 0.3.16(@typescript-eslint/eslint-plugin@6.14.0)(eslint@8.55.0)(typescript@5.3.3)(vitest@0.34.2) + husky: + specifier: 8.0.3 + version: 8.0.3 + json-schema-to-typescript: + specifier: 13.1.1 + version: 13.1.1 + lint-staged: + specifier: 15.2.0 + version: 15.2.0 + next-test-api-route-handler: + specifier: 3.1.10 + version: 3.1.10(next@14.2.10) + prettier: + specifier: 3.1.1 + version: 3.1.1 + setup-polly-jest: + specifier: 0.11.0 + version: 0.11.0(@pollyjs/core@6.0.6) + ts-node: + specifier: 10.9.2 + version: 10.9.2(@types/node@20.10.4)(typescript@5.3.3) + typescript: + specifier: 5.3.3 + version: 5.3.3 + vite: + specifier: 5.0.8 + version: 5.0.8(@types/node@20.10.4) + vite-tsconfig-paths: + specifier: 4.2.2 + version: 4.2.2(typescript@5.3.3)(vite@5.0.8) + vitest: + specifier: 0.34.2 + version: 0.34.2(jsdom@23.0.1) + +packages: + + /@aashutoshrathi/word-wrap@1.2.6: + resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} + engines: {node: '>=0.10.0'} + + /@adobe/css-tools@4.3.2: + resolution: {integrity: sha512-DA5a1C0gD/pLOvhv33YMrbf2FK3oUzwNl9oOJqE4XVjuEtt6XIakRcsd7eLiOSPkp1kTRQGICTA8cKra/vFbjw==} + dev: true + + /@ampproject/remapping@2.2.1: + resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.20 + + /@ardatan/relay-compiler@12.0.0(graphql@16.8.1): + resolution: {integrity: sha512-9anThAaj1dQr6IGmzBMcfzOQKTa5artjuPmw8NYK/fiGEMjADbSguBY2FMDykt+QhilR3wc9VA/3yVju7JHg7Q==} + hasBin: true + peerDependencies: + graphql: '*' + dependencies: + '@babel/core': 7.23.6 + '@babel/generator': 7.23.6 + '@babel/parser': 7.23.6 + '@babel/runtime': 7.23.6 + '@babel/traverse': 7.23.6 + '@babel/types': 7.23.6 + babel-preset-fbjs: 3.4.0(@babel/core@7.23.6) + chalk: 4.1.2 + fb-watchman: 2.0.2 + fbjs: 3.0.5 + glob: 7.2.3 + graphql: 16.8.1 + immutable: 3.7.6 + invariant: 2.2.4 + nullthrows: 1.1.1 + relay-runtime: 12.0.0 + signedsource: 1.0.0 + yargs: 15.4.1 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + /@ardatan/sync-fetch@0.0.1: + resolution: {integrity: sha512-xhlTqH0m31mnsG0tIP4ETgfSB6gXDaYYsUWTrlUV93fFQPI9dd8hE0Ot6MHLCtqgB32hwJAC3YZMWlXZw7AleA==} + engines: {node: '>=14'} + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + dev: true + + /@babel/code-frame@7.23.5: + resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.23.4 + chalk: 2.4.2 + + /@babel/compat-data@7.23.5: + resolution: {integrity: sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==} + engines: {node: '>=6.9.0'} + + /@babel/core@7.23.6: + resolution: {integrity: sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.2.1 + '@babel/code-frame': 7.23.5 + '@babel/generator': 7.23.6 + '@babel/helper-compilation-targets': 7.23.6 + '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.6) + '@babel/helpers': 7.23.6 + '@babel/parser': 7.23.6 + '@babel/template': 7.22.15 + '@babel/traverse': 7.23.6 + '@babel/types': 7.23.6 + convert-source-map: 2.0.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + /@babel/generator@7.23.6: + resolution: {integrity: sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.20 + jsesc: 2.5.2 + + /@babel/helper-annotate-as-pure@7.22.5: + resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + dev: true + + /@babel/helper-compilation-targets@7.23.6: + resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/compat-data': 7.23.5 + '@babel/helper-validator-option': 7.23.5 + browserslist: 4.22.2 + lru-cache: 5.1.1 + semver: 6.3.1 + + /@babel/helper-create-class-features-plugin@7.23.6(@babel/core@7.23.6): + resolution: {integrity: sha512-cBXU1vZni/CpGF29iTu4YRbOZt3Wat6zCoMDxRF1MayiEc4URxOj31tT65HUM0CRpMowA3HCJaAOVOUnMf96cw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-member-expression-to-functions': 7.23.0 + '@babel/helper-optimise-call-expression': 7.22.5 + '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.6) + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + semver: 6.3.1 + dev: true + + /@babel/helper-environment-visitor@7.22.20: + resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} + engines: {node: '>=6.9.0'} + + /@babel/helper-function-name@7.23.0: + resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.22.15 + '@babel/types': 7.23.6 + + /@babel/helper-hoist-variables@7.22.5: + resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + + /@babel/helper-member-expression-to-functions@7.23.0: + resolution: {integrity: sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + dev: true + + /@babel/helper-module-imports@7.22.15: + resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + + /@babel/helper-module-transforms@7.23.3(@babel/core@7.23.6): + resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-module-imports': 7.22.15 + '@babel/helper-simple-access': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/helper-validator-identifier': 7.22.20 + + /@babel/helper-optimise-call-expression@7.22.5: + resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + dev: true + + /@babel/helper-plugin-utils@7.22.5: + resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==} + engines: {node: '>=6.9.0'} + + /@babel/helper-replace-supers@7.22.20(@babel/core@7.23.6): + resolution: {integrity: sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-member-expression-to-functions': 7.23.0 + '@babel/helper-optimise-call-expression': 7.22.5 + dev: true + + /@babel/helper-simple-access@7.22.5: + resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + + /@babel/helper-skip-transparent-expression-wrappers@7.22.5: + resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + dev: true + + /@babel/helper-split-export-declaration@7.22.6: + resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + + /@babel/helper-string-parser@7.23.4: + resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==} + engines: {node: '>=6.9.0'} + + /@babel/helper-validator-identifier@7.22.20: + resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + engines: {node: '>=6.9.0'} + + /@babel/helper-validator-option@7.23.5: + resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} + engines: {node: '>=6.9.0'} + + /@babel/helpers@7.23.6: + resolution: {integrity: sha512-wCfsbN4nBidDRhpDhvcKlzHWCTlgJYUUdSJfzXb2NuBssDSIjc3xcb+znA7l+zYsFljAcGM0aFkN40cR3lXiGA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.22.15 + '@babel/traverse': 7.23.6 + '@babel/types': 7.23.6 + transitivePeerDependencies: + - supports-color + + /@babel/highlight@7.23.4: + resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.22.20 + chalk: 2.4.2 + js-tokens: 4.0.0 + + /@babel/parser@7.23.6: + resolution: {integrity: sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.23.6 + + /@babel/plugin-proposal-class-properties@7.18.6(@babel/core@7.23.6): + resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-create-class-features-plugin': 7.23.6(@babel/core@7.23.6) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-proposal-object-rest-spread@7.20.7(@babel/core@7.23.6): + resolution: {integrity: sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/compat-data': 7.23.5 + '@babel/core': 7.23.6 + '@babel/helper-compilation-targets': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.23.6) + '@babel/plugin-transform-parameters': 7.23.3(@babel/core@7.23.6) + dev: true + + /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.23.6): + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-flow@7.23.3(@babel/core@7.23.6): + resolution: {integrity: sha512-YZiAIpkJAwQXBJLIQbRFayR5c+gJ35Vcz3bg954k7cd73zqjvhacJuL9RbrzPz8qPmZdgqP6EUKwy0PCNhaaPA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-import-assertions@7.23.3(@babel/core@7.23.6): + resolution: {integrity: sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-jsx@7.23.3(@babel/core@7.23.6): + resolution: {integrity: sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.23.6): + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-typescript@7.23.3(@babel/core@7.23.6): + resolution: {integrity: sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + + /@babel/plugin-transform-arrow-functions@7.23.3(@babel/core@7.23.6): + resolution: {integrity: sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-block-scoped-functions@7.23.3(@babel/core@7.23.6): + resolution: {integrity: sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-block-scoping@7.23.4(@babel/core@7.23.6): + resolution: {integrity: sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-classes@7.23.5(@babel/core@7.23.6): + resolution: {integrity: sha512-jvOTR4nicqYC9yzOHIhXG5emiFEOpappSJAl73SDSEDcybD+Puuze8Tnpb9p9qEyYup24tq891gkaygIFvWDqg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-compilation-targets': 7.23.6 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-optimise-call-expression': 7.22.5 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.6) + '@babel/helper-split-export-declaration': 7.22.6 + globals: 11.12.0 + dev: true + + /@babel/plugin-transform-computed-properties@7.23.3(@babel/core@7.23.6): + resolution: {integrity: sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/template': 7.22.15 + dev: true + + /@babel/plugin-transform-destructuring@7.23.3(@babel/core@7.23.6): + resolution: {integrity: sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-flow-strip-types@7.23.3(@babel/core@7.23.6): + resolution: {integrity: sha512-26/pQTf9nQSNVJCrLB1IkHUKyPxR+lMrH2QDPG89+Znu9rAMbtrybdbWeE9bb7gzjmE5iXHEY+e0HUwM6Co93Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-flow': 7.23.3(@babel/core@7.23.6) + dev: true + + /@babel/plugin-transform-for-of@7.23.6(@babel/core@7.23.6): + resolution: {integrity: sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + dev: true + + /@babel/plugin-transform-function-name@7.23.3(@babel/core@7.23.6): + resolution: {integrity: sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-compilation-targets': 7.23.6 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-literals@7.23.3(@babel/core@7.23.6): + resolution: {integrity: sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-member-expression-literals@7.23.3(@babel/core@7.23.6): + resolution: {integrity: sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-modules-commonjs@7.23.3(@babel/core@7.23.6): + resolution: {integrity: sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.6) + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-simple-access': 7.22.5 + dev: true + + /@babel/plugin-transform-object-super@7.23.3(@babel/core@7.23.6): + resolution: {integrity: sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.6) + dev: true + + /@babel/plugin-transform-parameters@7.23.3(@babel/core@7.23.6): + resolution: {integrity: sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-property-literals@7.23.3(@babel/core@7.23.6): + resolution: {integrity: sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-react-display-name@7.23.3(@babel/core@7.23.6): + resolution: {integrity: sha512-GnvhtVfA2OAtzdX58FJxU19rhoGeQzyVndw3GgtdECQvQFXPEZIOVULHVZGAYmOgmqjXpVpfocAbSjh99V/Fqw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-react-jsx-self@7.23.3(@babel/core@7.23.6): + resolution: {integrity: sha512-qXRvbeKDSfwnlJnanVRp0SfuWE5DQhwQr5xtLBzp56Wabyo+4CMosF6Kfp+eOD/4FYpql64XVJ2W0pVLlJZxOQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + dev: false + + /@babel/plugin-transform-react-jsx-source@7.23.3(@babel/core@7.23.6): + resolution: {integrity: sha512-91RS0MDnAWDNvGC6Wio5XYkyWI39FMFO+JK9+4AlgaTH+yWwVTsw7/sn6LK0lH7c5F+TFkpv/3LfCJ1Ydwof/g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + dev: false + + /@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.23.6): + resolution: {integrity: sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-module-imports': 7.22.15 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-jsx': 7.23.3(@babel/core@7.23.6) + '@babel/types': 7.23.6 + dev: true + + /@babel/plugin-transform-shorthand-properties@7.23.3(@babel/core@7.23.6): + resolution: {integrity: sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-spread@7.23.3(@babel/core@7.23.6): + resolution: {integrity: sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + dev: true + + /@babel/plugin-transform-template-literals@7.23.3(@babel/core@7.23.6): + resolution: {integrity: sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/runtime@7.23.6: + resolution: {integrity: sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.14.0 + + /@babel/template@7.22.15: + resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.23.5 + '@babel/parser': 7.23.6 + '@babel/types': 7.23.6 + + /@babel/traverse@7.23.6: + resolution: {integrity: sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.23.5 + '@babel/generator': 7.23.6 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/parser': 7.23.6 + '@babel/types': 7.23.6 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + /@babel/types@7.23.6: + resolution: {integrity: sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.23.4 + '@babel/helper-validator-identifier': 7.22.20 + to-fast-properties: 2.0.0 + + /@bcherny/json-schema-ref-parser@10.0.5-fork: + resolution: {integrity: sha512-E/jKbPoca1tfUPj3iSbitDZTGnq6FUFjkH6L8U2oDwSuwK1WhnnVtCG7oFOTg/DDnyoXbQYUiUiGOibHqaGVnw==} + engines: {node: '>= 16'} + dependencies: + '@jsdevtools/ono': 7.1.3 + '@types/json-schema': 7.0.15 + call-me-maybe: 1.0.2 + js-yaml: 4.1.0 + dev: true + + /@bcoe/v8-coverage@0.2.3: + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + dev: true + + /@changesets/apply-release-plan@7.0.0: + resolution: {integrity: sha512-vfi69JR416qC9hWmFGSxj7N6wA5J222XNBmezSVATPWDVPIF7gkd4d8CpbEbXmRWbVrkoli3oerGS6dcL/BGsQ==} + dependencies: + '@babel/runtime': 7.23.6 + '@changesets/config': 3.0.0 + '@changesets/get-version-range-type': 0.4.0 + '@changesets/git': 3.0.0 + '@changesets/types': 6.0.0 + '@manypkg/get-packages': 1.1.3 + detect-indent: 6.1.0 + fs-extra: 7.0.1 + lodash.startcase: 4.4.0 + outdent: 0.5.0 + prettier: 2.8.8 + resolve-from: 5.0.0 + semver: 7.5.4 + dev: true + + /@changesets/assemble-release-plan@6.0.0: + resolution: {integrity: sha512-4QG7NuisAjisbW4hkLCmGW2lRYdPrKzro+fCtZaILX+3zdUELSvYjpL4GTv0E4aM9Mef3PuIQp89VmHJ4y2bfw==} + dependencies: + '@babel/runtime': 7.23.6 + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.0.0 + '@changesets/types': 6.0.0 + '@manypkg/get-packages': 1.1.3 + semver: 7.5.4 + dev: true + + /@changesets/changelog-git@0.2.0: + resolution: {integrity: sha512-bHOx97iFI4OClIT35Lok3sJAwM31VbUM++gnMBV16fdbtBhgYu4dxsphBF/0AZZsyAHMrnM0yFcj5gZM1py6uQ==} + dependencies: + '@changesets/types': 6.0.0 + dev: true + + /@changesets/cli@2.27.1: + resolution: {integrity: sha512-iJ91xlvRnnrJnELTp4eJJEOPjgpF3NOh4qeQehM6Ugiz9gJPRZ2t+TsXun6E3AMN4hScZKjqVXl0TX+C7AB3ZQ==} + hasBin: true + dependencies: + '@babel/runtime': 7.23.6 + '@changesets/apply-release-plan': 7.0.0 + '@changesets/assemble-release-plan': 6.0.0 + '@changesets/changelog-git': 0.2.0 + '@changesets/config': 3.0.0 + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.0.0 + '@changesets/get-release-plan': 4.0.0 + '@changesets/git': 3.0.0 + '@changesets/logger': 0.1.0 + '@changesets/pre': 2.0.0 + '@changesets/read': 0.6.0 + '@changesets/types': 6.0.0 + '@changesets/write': 0.3.0 + '@manypkg/get-packages': 1.1.3 + '@types/semver': 7.5.6 + ansi-colors: 4.1.3 + chalk: 2.4.2 + ci-info: 3.9.0 + enquirer: 2.4.1 + external-editor: 3.1.0 + fs-extra: 7.0.1 + human-id: 1.0.2 + meow: 6.1.1 + outdent: 0.5.0 + p-limit: 2.3.0 + preferred-pm: 3.1.2 + resolve-from: 5.0.0 + semver: 7.5.4 + spawndamnit: 2.0.0 + term-size: 2.2.1 + tty-table: 4.2.3 + dev: true + + /@changesets/config@3.0.0: + resolution: {integrity: sha512-o/rwLNnAo/+j9Yvw9mkBQOZySDYyOr/q+wptRLcAVGlU6djOeP9v1nlalbL9MFsobuBVQbZCTp+dIzdq+CLQUA==} + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.0.0 + '@changesets/logger': 0.1.0 + '@changesets/types': 6.0.0 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + micromatch: 4.0.5 + dev: true + + /@changesets/errors@0.2.0: + resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} + dependencies: + extendable-error: 0.1.7 + dev: true + + /@changesets/get-dependents-graph@2.0.0: + resolution: {integrity: sha512-cafUXponivK4vBgZ3yLu944mTvam06XEn2IZGjjKc0antpenkYANXiiE6GExV/yKdsCnE8dXVZ25yGqLYZmScA==} + dependencies: + '@changesets/types': 6.0.0 + '@manypkg/get-packages': 1.1.3 + chalk: 2.4.2 + fs-extra: 7.0.1 + semver: 7.5.4 + dev: true + + /@changesets/get-release-plan@4.0.0: + resolution: {integrity: sha512-9L9xCUeD/Tb6L/oKmpm8nyzsOzhdNBBbt/ZNcjynbHC07WW4E1eX8NMGC5g5SbM5z/V+MOrYsJ4lRW41GCbg3w==} + dependencies: + '@babel/runtime': 7.23.6 + '@changesets/assemble-release-plan': 6.0.0 + '@changesets/config': 3.0.0 + '@changesets/pre': 2.0.0 + '@changesets/read': 0.6.0 + '@changesets/types': 6.0.0 + '@manypkg/get-packages': 1.1.3 + dev: true + + /@changesets/get-version-range-type@0.4.0: + resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} + dev: true + + /@changesets/git@3.0.0: + resolution: {integrity: sha512-vvhnZDHe2eiBNRFHEgMiGd2CT+164dfYyrJDhwwxTVD/OW0FUD6G7+4DIx1dNwkwjHyzisxGAU96q0sVNBns0w==} + dependencies: + '@babel/runtime': 7.23.6 + '@changesets/errors': 0.2.0 + '@changesets/types': 6.0.0 + '@manypkg/get-packages': 1.1.3 + is-subdir: 1.2.0 + micromatch: 4.0.5 + spawndamnit: 2.0.0 + dev: true + + /@changesets/logger@0.1.0: + resolution: {integrity: sha512-pBrJm4CQm9VqFVwWnSqKEfsS2ESnwqwH+xR7jETxIErZcfd1u2zBSqrHbRHR7xjhSgep9x2PSKFKY//FAshA3g==} + dependencies: + chalk: 2.4.2 + dev: true + + /@changesets/parse@0.4.0: + resolution: {integrity: sha512-TS/9KG2CdGXS27S+QxbZXgr8uPsP4yNJYb4BC2/NeFUj80Rni3TeD2qwWmabymxmrLo7JEsytXH1FbpKTbvivw==} + dependencies: + '@changesets/types': 6.0.0 + js-yaml: 3.14.1 + dev: true + + /@changesets/pre@2.0.0: + resolution: {integrity: sha512-HLTNYX/A4jZxc+Sq8D1AMBsv+1qD6rmmJtjsCJa/9MSRybdxh0mjbTvE6JYZQ/ZiQ0mMlDOlGPXTm9KLTU3jyw==} + dependencies: + '@babel/runtime': 7.23.6 + '@changesets/errors': 0.2.0 + '@changesets/types': 6.0.0 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + dev: true + + /@changesets/read@0.6.0: + resolution: {integrity: sha512-ZypqX8+/im1Fm98K4YcZtmLKgjs1kDQ5zHpc2U1qdtNBmZZfo/IBiG162RoP0CUF05tvp2y4IspH11PLnPxuuw==} + dependencies: + '@babel/runtime': 7.23.6 + '@changesets/git': 3.0.0 + '@changesets/logger': 0.1.0 + '@changesets/parse': 0.4.0 + '@changesets/types': 6.0.0 + chalk: 2.4.2 + fs-extra: 7.0.1 + p-filter: 2.1.0 + dev: true + + /@changesets/types@4.1.0: + resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} + dev: true + + /@changesets/types@6.0.0: + resolution: {integrity: sha512-b1UkfNulgKoWfqyHtzKS5fOZYSJO+77adgL7DLRDr+/7jhChN+QcHnbjiQVOz/U+Ts3PGNySq7diAItzDgugfQ==} + dev: true + + /@changesets/write@0.3.0: + resolution: {integrity: sha512-slGLb21fxZVUYbyea+94uFiD6ntQW0M2hIKNznFizDhZPDgn2c/fv1UzzlW43RVzh1BEDuIqW6hzlJ1OflNmcw==} + dependencies: + '@babel/runtime': 7.23.6 + '@changesets/types': 6.0.0 + fs-extra: 7.0.1 + human-id: 1.0.2 + prettier: 2.8.8 + dev: true + + /@commander-js/extra-typings@11.0.0(commander@11.0.0): + resolution: {integrity: sha512-06ol6Kn5gPjFY6v0vWOZ84nQwyqhZdaeZCHYH3vhwewjpOEjniF1KHZxh18887G3poWiJ8qyq5pb6ANuiddfPQ==} + peerDependencies: + commander: 11.0.x + dependencies: + commander: 11.0.0 + dev: true + + /@cspotcode/source-map-support@0.8.1: + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + dev: true + + /@dessert-box/core@0.2.0: + resolution: {integrity: sha512-Vqaec6i0cvS1r54kU6CfOQECi6dPWzz6DVVxJABOxqPmVk8fOSy6pIKsK0YyPFGRpZK/FXkJ1YhURUOW1OxOVQ==} + dev: false + + /@dessert-box/react@0.4.0(react@18.2.0): + resolution: {integrity: sha512-r2sqkX4y+fDLtRGGpCitI5ckzLZl3DPMUhKBstf3qoZbfoAVHB0HRHgrfRni3F0qZZgXowR880lL8IDpPpRiGg==} + peerDependencies: + react: '>=16.8.0' + dependencies: + '@dessert-box/core': 0.2.0 + react: 18.2.0 + dev: false + + /@emotion/hash@0.9.1: + resolution: {integrity: sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==} + + /@esbuild/android-arm64@0.17.6: + resolution: {integrity: sha512-YnYSCceN/dUzUr5kdtUzB+wZprCafuD89Hs0Aqv9QSdwhYQybhXTaSTcrl6X/aWThn1a/j0eEpUBGOE7269REg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + optional: true + + /@esbuild/android-arm64@0.18.20: + resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@esbuild/android-arm64@0.19.9: + resolution: {integrity: sha512-q4cR+6ZD0938R19MyEW3jEsMzbb/1rulLXiNAJQADD/XYp7pT+rOS5JGxvpRW8dFDEfjW4wLgC/3FXIw4zYglQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + optional: true + + /@esbuild/android-arm@0.17.6: + resolution: {integrity: sha512-bSC9YVUjADDy1gae8RrioINU6e1lCkg3VGVwm0QQ2E1CWcC4gnMce9+B6RpxuSsrsXsk1yojn7sp1fnG8erE2g==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + optional: true + + /@esbuild/android-arm@0.18.20: + resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@esbuild/android-arm@0.19.9: + resolution: {integrity: sha512-jkYjjq7SdsWuNI6b5quymW0oC83NN5FdRPuCbs9HZ02mfVdAP8B8eeqLSYU3gb6OJEaY5CQabtTFbqBf26H3GA==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + optional: true + + /@esbuild/android-x64@0.17.6: + resolution: {integrity: sha512-MVcYcgSO7pfu/x34uX9u2QIZHmXAB7dEiLQC5bBl5Ryqtpj9lT2sg3gNDEsrPEmimSJW2FXIaxqSQ501YLDsZQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + optional: true + + /@esbuild/android-x64@0.18.20: + resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@esbuild/android-x64@0.19.9: + resolution: {integrity: sha512-KOqoPntWAH6ZxDwx1D6mRntIgZh9KodzgNOy5Ebt9ghzffOk9X2c1sPwtM9P+0eXbefnDhqYfkh5PLP5ULtWFA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + optional: true + + /@esbuild/darwin-arm64@0.17.6: + resolution: {integrity: sha512-bsDRvlbKMQMt6Wl08nHtFz++yoZHsyTOxnjfB2Q95gato+Yi4WnRl13oC2/PJJA9yLCoRv9gqT/EYX0/zDsyMA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + optional: true + + /@esbuild/darwin-arm64@0.18.20: + resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@esbuild/darwin-arm64@0.19.9: + resolution: {integrity: sha512-KBJ9S0AFyLVx2E5D8W0vExqRW01WqRtczUZ8NRu+Pi+87opZn5tL4Y0xT0mA4FtHctd0ZgwNoN639fUUGlNIWw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + optional: true + + /@esbuild/darwin-x64@0.17.6: + resolution: {integrity: sha512-xh2A5oPrYRfMFz74QXIQTQo8uA+hYzGWJFoeTE8EvoZGHb+idyV4ATaukaUvnnxJiauhs/fPx3vYhU4wiGfosg==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + optional: true + + /@esbuild/darwin-x64@0.18.20: + resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@esbuild/darwin-x64@0.19.9: + resolution: {integrity: sha512-vE0VotmNTQaTdX0Q9dOHmMTao6ObjyPm58CHZr1UK7qpNleQyxlFlNCaHsHx6Uqv86VgPmR4o2wdNq3dP1qyDQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + optional: true + + /@esbuild/freebsd-arm64@0.17.6: + resolution: {integrity: sha512-EnUwjRc1inT4ccZh4pB3v1cIhohE2S4YXlt1OvI7sw/+pD+dIE4smwekZlEPIwY6PhU6oDWwITrQQm5S2/iZgg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + optional: true + + /@esbuild/freebsd-arm64@0.18.20: + resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/freebsd-arm64@0.19.9: + resolution: {integrity: sha512-uFQyd/o1IjiEk3rUHSwUKkqZwqdvuD8GevWF065eqgYfexcVkxh+IJgwTaGZVu59XczZGcN/YMh9uF1fWD8j1g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + optional: true + + /@esbuild/freebsd-x64@0.17.6: + resolution: {integrity: sha512-Uh3HLWGzH6FwpviUcLMKPCbZUAFzv67Wj5MTwK6jn89b576SR2IbEp+tqUHTr8DIl0iDmBAf51MVaP7pw6PY5Q==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + optional: true + + /@esbuild/freebsd-x64@0.18.20: + resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/freebsd-x64@0.19.9: + resolution: {integrity: sha512-WMLgWAtkdTbTu1AWacY7uoj/YtHthgqrqhf1OaEWnZb7PQgpt8eaA/F3LkV0E6K/Lc0cUr/uaVP/49iE4M4asA==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + optional: true + + /@esbuild/linux-arm64@0.17.6: + resolution: {integrity: sha512-bUR58IFOMJX523aDVozswnlp5yry7+0cRLCXDsxnUeQYJik1DukMY+apBsLOZJblpH+K7ox7YrKrHmJoWqVR9w==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-arm64@0.18.20: + resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-arm64@0.19.9: + resolution: {integrity: sha512-PiPblfe1BjK7WDAKR1Cr9O7VVPqVNpwFcPWgfn4xu0eMemzRp442hXyzF/fSwgrufI66FpHOEJk0yYdPInsmyQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-arm@0.17.6: + resolution: {integrity: sha512-7YdGiurNt7lqO0Bf/U9/arrPWPqdPqcV6JCZda4LZgEn+PTQ5SMEI4MGR52Bfn3+d6bNEGcWFzlIxiQdS48YUw==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-arm@0.18.20: + resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-arm@0.19.9: + resolution: {integrity: sha512-C/ChPohUYoyUaqn1h17m/6yt6OB14hbXvT8EgM1ZWaiiTYz7nWZR0SYmMnB5BzQA4GXl3BgBO1l8MYqL/He3qw==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-ia32@0.17.6: + resolution: {integrity: sha512-ujp8uoQCM9FRcbDfkqECoARsLnLfCUhKARTP56TFPog8ie9JG83D5GVKjQ6yVrEVdMie1djH86fm98eY3quQkQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-ia32@0.18.20: + resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-ia32@0.19.9: + resolution: {integrity: sha512-f37i/0zE0MjDxijkPSQw1CO/7C27Eojqb+r3BbHVxMLkj8GCa78TrBZzvPyA/FNLUMzP3eyHCVkAopkKVja+6Q==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-loong64@0.17.6: + resolution: {integrity: sha512-y2NX1+X/Nt+izj9bLoiaYB9YXT/LoaQFYvCkVD77G/4F+/yuVXYCWz4SE9yr5CBMbOxOfBcy/xFL4LlOeNlzYQ==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-loong64@0.18.20: + resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-loong64@0.19.9: + resolution: {integrity: sha512-t6mN147pUIf3t6wUt3FeumoOTPfmv9Cc6DQlsVBpB7eCpLOqQDyWBP1ymXn1lDw4fNUSb/gBcKAmvTP49oIkaA==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-mips64el@0.17.6: + resolution: {integrity: sha512-09AXKB1HDOzXD+j3FdXCiL/MWmZP0Ex9eR8DLMBVcHorrWJxWmY8Nms2Nm41iRM64WVx7bA/JVHMv081iP2kUA==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-mips64el@0.18.20: + resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-mips64el@0.19.9: + resolution: {integrity: sha512-jg9fujJTNTQBuDXdmAg1eeJUL4Jds7BklOTkkH80ZgQIoCTdQrDaHYgbFZyeTq8zbY+axgptncko3v9p5hLZtw==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-ppc64@0.17.6: + resolution: {integrity: sha512-AmLhMzkM8JuqTIOhxnX4ubh0XWJIznEynRnZAVdA2mMKE6FAfwT2TWKTwdqMG+qEaeyDPtfNoZRpJbD4ZBv0Tg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-ppc64@0.18.20: + resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-ppc64@0.19.9: + resolution: {integrity: sha512-tkV0xUX0pUUgY4ha7z5BbDS85uI7ABw3V1d0RNTii7E9lbmV8Z37Pup2tsLV46SQWzjOeyDi1Q7Wx2+QM8WaCQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-riscv64@0.17.6: + resolution: {integrity: sha512-Y4Ri62PfavhLQhFbqucysHOmRamlTVK10zPWlqjNbj2XMea+BOs4w6ASKwQwAiqf9ZqcY9Ab7NOU4wIgpxwoSQ==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-riscv64@0.18.20: + resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-riscv64@0.19.9: + resolution: {integrity: sha512-DfLp8dj91cufgPZDXr9p3FoR++m3ZJ6uIXsXrIvJdOjXVREtXuQCjfMfvmc3LScAVmLjcfloyVtpn43D56JFHg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-s390x@0.17.6: + resolution: {integrity: sha512-SPUiz4fDbnNEm3JSdUW8pBJ/vkop3M1YwZAVwvdwlFLoJwKEZ9L98l3tzeyMzq27CyepDQ3Qgoba44StgbiN5Q==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-s390x@0.18.20: + resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-s390x@0.19.9: + resolution: {integrity: sha512-zHbglfEdC88KMgCWpOl/zc6dDYJvWGLiUtmPRsr1OgCViu3z5GncvNVdf+6/56O2Ca8jUU+t1BW261V6kp8qdw==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-x64@0.17.6: + resolution: {integrity: sha512-a3yHLmOodHrzuNgdpB7peFGPx1iJ2x6m+uDvhP2CKdr2CwOaqEFMeSqYAHU7hG+RjCq8r2NFujcd/YsEsFgTGw==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/linux-x64@0.18.20: + resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-x64@0.19.9: + resolution: {integrity: sha512-JUjpystGFFmNrEHQnIVG8hKwvA2DN5o7RqiO1CVX8EN/F/gkCjkUMgVn6hzScpwnJtl2mPR6I9XV1oW8k9O+0A==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + optional: true + + /@esbuild/netbsd-x64@0.17.6: + resolution: {integrity: sha512-EanJqcU/4uZIBreTrnbnre2DXgXSa+Gjap7ifRfllpmyAU7YMvaXmljdArptTHmjrkkKm9BK6GH5D5Yo+p6y5A==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + optional: true + + /@esbuild/netbsd-x64@0.18.20: + resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/netbsd-x64@0.19.9: + resolution: {integrity: sha512-GThgZPAwOBOsheA2RUlW5UeroRfESwMq/guy8uEe3wJlAOjpOXuSevLRd70NZ37ZrpO6RHGHgEHvPg1h3S1Jug==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + optional: true + + /@esbuild/openbsd-x64@0.17.6: + resolution: {integrity: sha512-xaxeSunhQRsTNGFanoOkkLtnmMn5QbA0qBhNet/XLVsc+OVkpIWPHcr3zTW2gxVU5YOHFbIHR9ODuaUdNza2Vw==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + optional: true + + /@esbuild/openbsd-x64@0.18.20: + resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/openbsd-x64@0.19.9: + resolution: {integrity: sha512-Ki6PlzppaFVbLnD8PtlVQfsYw4S9n3eQl87cqgeIw+O3sRr9IghpfSKY62mggdt1yCSZ8QWvTZ9jo9fjDSg9uw==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + optional: true + + /@esbuild/sunos-x64@0.17.6: + resolution: {integrity: sha512-gnMnMPg5pfMkZvhHee21KbKdc6W3GR8/JuE0Da1kjwpK6oiFU3nqfHuVPgUX2rsOx9N2SadSQTIYV1CIjYG+xw==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + optional: true + + /@esbuild/sunos-x64@0.18.20: + resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: false + optional: true + + /@esbuild/sunos-x64@0.19.9: + resolution: {integrity: sha512-MLHj7k9hWh4y1ddkBpvRj2b9NCBhfgBt3VpWbHQnXRedVun/hC7sIyTGDGTfsGuXo4ebik2+3ShjcPbhtFwWDw==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + optional: true + + /@esbuild/win32-arm64@0.17.6: + resolution: {integrity: sha512-G95n7vP1UnGJPsVdKXllAJPtqjMvFYbN20e8RK8LVLhlTiSOH1sd7+Gt7rm70xiG+I5tM58nYgwWrLs6I1jHqg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + optional: true + + /@esbuild/win32-arm64@0.18.20: + resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@esbuild/win32-arm64@0.19.9: + resolution: {integrity: sha512-GQoa6OrQ8G08guMFgeXPH7yE/8Dt0IfOGWJSfSH4uafwdC7rWwrfE6P9N8AtPGIjUzdo2+7bN8Xo3qC578olhg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + optional: true + + /@esbuild/win32-ia32@0.17.6: + resolution: {integrity: sha512-96yEFzLhq5bv9jJo5JhTs1gI+1cKQ83cUpyxHuGqXVwQtY5Eq54ZEsKs8veKtiKwlrNimtckHEkj4mRh4pPjsg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + optional: true + + /@esbuild/win32-ia32@0.18.20: + resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@esbuild/win32-ia32@0.19.9: + resolution: {integrity: sha512-UOozV7Ntykvr5tSOlGCrqU3NBr3d8JqPes0QWN2WOXfvkWVGRajC+Ym0/Wj88fUgecUCLDdJPDF0Nna2UK3Qtg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + optional: true + + /@esbuild/win32-x64@0.17.6: + resolution: {integrity: sha512-n6d8MOyUrNp6G4VSpRcgjs5xj4A91svJSaiwLIDWVWEsZtpN5FA9NlBbZHDmAJc2e8e6SF4tkBD3HAvPF+7igA==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + optional: true + + /@esbuild/win32-x64@0.18.20: + resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@esbuild/win32-x64@0.19.9: + resolution: {integrity: sha512-oxoQgglOP7RH6iasDrhY+R/3cHrfwIDvRlT4CGChflq6twk8iENeVvMJjmvBb94Ik1Z+93iGO27err7w6l54GQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + optional: true + + /@eslint-community/eslint-utils@4.4.0(eslint@8.55.0): + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 8.55.0 + eslint-visitor-keys: 3.4.3 + + /@eslint-community/regexpp@4.10.0: + resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + /@eslint/eslintrc@2.1.4: + resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.6.1 + globals: 13.24.0 + ignore: 5.3.0 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + /@eslint/js@8.55.0: + resolution: {integrity: sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + /@floating-ui/core@0.7.3: + resolution: {integrity: sha512-buc8BXHmG9l82+OQXOFU3Kr2XQx9ys01U/Q9HMIrZ300iLc8HLMgh7dcCqgYzAzf4BkoQvDcXf5Y+CuEZ5JBYg==} + dev: false + + /@floating-ui/core@1.5.2: + resolution: {integrity: sha512-Ii3MrfY/GAIN3OhXNzpCKaLxHQfJF9qvwq/kEJYdqDxeIHa01K8sldugal6TmeeXl+WMvhv9cnVzUTaFFJF09A==} + dependencies: + '@floating-ui/utils': 0.1.6 + dev: false + + /@floating-ui/dom@0.5.4: + resolution: {integrity: sha512-419BMceRLq0RrmTSDxn8hf9R3VCJv2K9PUfugh5JyEFmdjzDo+e8U5EdR8nzKq8Yj1htzLm3b6eQEEam3/rrtg==} + dependencies: + '@floating-ui/core': 0.7.3 + dev: false + + /@floating-ui/dom@1.5.3: + resolution: {integrity: sha512-ClAbQnEqJAKCJOEbbLo5IUlZHkNszqhuxS4fHAVxRPXPya6Ysf2G8KypnYcOTpx6I8xcgF9bbHb6g/2KpbV8qA==} + dependencies: + '@floating-ui/core': 1.5.2 + '@floating-ui/utils': 0.1.6 + dev: false + + /@floating-ui/react-dom-interactions@0.5.0(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-rfON7mkHjCeogd0BSXPa8GBp1TMxEytJQqGVlCouSUonJ4POqdHsqcxRnCh0yAaGVaL/nB/J1vq28V4RdoLszg==} + deprecated: Package renamed to @floating-ui/react + dependencies: + '@floating-ui/react-dom': 0.7.2(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + aria-hidden: 1.2.3 + use-isomorphic-layout-effect: 1.1.2(@types/react@18.2.45)(react@18.2.0) + transitivePeerDependencies: + - '@types/react' + - react + - react-dom + dev: false + + /@floating-ui/react-dom@0.7.2(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-1T0sJcpHgX/u4I1OzIEhlcrvkUN8ln39nz7fMoE/2HDHrPiMFoOGR7++GYyfUmIQHkkrTinaeQsO3XWubjSvGg==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + dependencies: + '@floating-ui/dom': 0.5.4 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + use-isomorphic-layout-effect: 1.1.2(@types/react@18.2.45)(react@18.2.0) + transitivePeerDependencies: + - '@types/react' + dev: false + + /@floating-ui/react-dom@2.0.4(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-CF8k2rgKeh/49UrnIBs4BdxPUV6vize/Db1d/YbCLyp9GiVZ0BEwf5AiDSxJRCr6yOkGqTFHtmrULxkEfYZ7dQ==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + dependencies: + '@floating-ui/dom': 1.5.3 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@floating-ui/utils@0.1.6: + resolution: {integrity: sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==} + dev: false + + /@graphql-codegen/add@5.0.0(graphql@16.8.1): + resolution: {integrity: sha512-ynWDOsK2yxtFHwcJTB9shoSkUd7YXd6ZE57f0nk7W5cu/nAgxZZpEsnTPEpZB/Mjf14YRGe2uJHQ7AfElHjqUQ==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 5.0.1(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.5.3 + dev: true + + /@graphql-codegen/cli@5.0.0(@types/node@20.10.4)(graphql@16.8.1)(typescript@5.3.3): + resolution: {integrity: sha512-A7J7+be/a6e+/ul2KI5sfJlpoqeqwX8EzktaKCeduyVKgOLA6W5t+NUGf6QumBDXU8PEOqXk3o3F+RAwCWOiqA==} + hasBin: true + peerDependencies: + '@parcel/watcher': ^2.1.0 + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + peerDependenciesMeta: + '@parcel/watcher': + optional: true + dependencies: + '@babel/generator': 7.23.6 + '@babel/template': 7.22.15 + '@babel/types': 7.23.6 + '@graphql-codegen/core': 4.0.0(graphql@16.8.1) + '@graphql-codegen/plugin-helpers': 5.0.1(graphql@16.8.1) + '@graphql-tools/apollo-engine-loader': 8.0.0(graphql@16.8.1) + '@graphql-tools/code-file-loader': 8.0.3(graphql@16.8.1) + '@graphql-tools/git-loader': 8.0.3(graphql@16.8.1) + '@graphql-tools/github-loader': 8.0.0(@types/node@20.10.4)(graphql@16.8.1) + '@graphql-tools/graphql-file-loader': 8.0.0(graphql@16.8.1) + '@graphql-tools/json-file-loader': 8.0.0(graphql@16.8.1) + '@graphql-tools/load': 8.0.1(graphql@16.8.1) + '@graphql-tools/prisma-loader': 8.0.2(@types/node@20.10.4)(graphql@16.8.1) + '@graphql-tools/url-loader': 8.0.1(@types/node@20.10.4)(graphql@16.8.1) + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + '@whatwg-node/fetch': 0.8.8 + chalk: 4.1.2 + cosmiconfig: 8.3.6(typescript@5.3.3) + debounce: 1.2.1 + detect-indent: 6.1.0 + graphql: 16.8.1 + graphql-config: 5.0.3(@types/node@20.10.4)(graphql@16.8.1)(typescript@5.3.3) + inquirer: 8.2.6 + is-glob: 4.0.3 + jiti: 1.21.0 + json-to-pretty-yaml: 1.2.2 + listr2: 4.0.5 + log-symbols: 4.1.0 + micromatch: 4.0.5 + shell-quote: 1.8.1 + string-env-interpolation: 1.0.1 + ts-log: 2.2.5 + tslib: 2.6.2 + yaml: 2.3.4 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - bufferutil + - cosmiconfig-toml-loader + - encoding + - enquirer + - supports-color + - typescript + - utf-8-validate + dev: true + + /@graphql-codegen/core@4.0.0(graphql@16.8.1): + resolution: {integrity: sha512-JAGRn49lEtSsZVxeIlFVIRxts2lWObR+OQo7V2LHDJ7ohYYw3ilv7nJ8pf8P4GTg/w6ptcYdSdVVdkI8kUHB/Q==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 5.0.1(graphql@16.8.1) + '@graphql-tools/schema': 10.0.2(graphql@16.8.1) + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.5.3 + dev: true + + /@graphql-codegen/introspection@4.0.0(graphql@16.8.1): + resolution: {integrity: sha512-t9g3AkK99dfHblMWtG4ynUM9+A7JrWq5110zSpNV2wlSnv0+bRKagDW8gozwgXfR5i1IIG8QDjJZ6VgXQVqCZw==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 5.0.1(graphql@16.8.1) + '@graphql-codegen/visitor-plugin-common': 4.0.1(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.5.3 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + /@graphql-codegen/plugin-helpers@2.7.2(graphql@16.8.1): + resolution: {integrity: sha512-kln2AZ12uii6U59OQXdjLk5nOlh1pHis1R98cDZGFnfaiAbX9V3fxcZ1MMJkB7qFUymTALzyjZoXXdyVmPMfRg==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-tools/utils': 8.13.1(graphql@16.8.1) + change-case-all: 1.0.14 + common-tags: 1.8.2 + graphql: 16.8.1 + import-from: 4.0.0 + lodash: 4.17.21 + tslib: 2.4.1 + dev: true + + /@graphql-codegen/plugin-helpers@3.1.2(graphql@16.8.1): + resolution: {integrity: sha512-emOQiHyIliVOIjKVKdsI5MXj312zmRDwmHpyUTZMjfpvxq/UVAHUJIVdVf+lnjjrI+LXBTgMlTWTgHQfmICxjg==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + change-case-all: 1.0.15 + common-tags: 1.8.2 + graphql: 16.8.1 + import-from: 4.0.0 + lodash: 4.17.21 + tslib: 2.4.1 + dev: true + + /@graphql-codegen/plugin-helpers@5.0.1(graphql@16.8.1): + resolution: {integrity: sha512-6L5sb9D8wptZhnhLLBcheSPU7Tg//DGWgc5tQBWX46KYTOTQHGqDpv50FxAJJOyFVJrveN9otWk9UT9/yfY4ww==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + change-case-all: 1.0.15 + common-tags: 1.8.2 + graphql: 16.8.1 + import-from: 4.0.0 + lodash: 4.17.21 + tslib: 2.5.3 + dev: true + + /@graphql-codegen/schema-ast@4.0.0(graphql@16.8.1): + resolution: {integrity: sha512-WIzkJFa9Gz28FITAPILbt+7A8+yzOyd1NxgwFh7ie+EmO9a5zQK6UQ3U/BviirguXCYnn+AR4dXsoDrSrtRA1g==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 5.0.1(graphql@16.8.1) + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.5.3 + dev: true + + /@graphql-codegen/typed-document-node@5.0.1(graphql@16.8.1): + resolution: {integrity: sha512-VFkhCuJnkgtbbgzoCAwTdJe2G1H6sd3LfCrDqWUrQe53y2ukfSb5Ov1PhAIkCBStKCMQBUY9YgGz9GKR40qQ8g==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 5.0.1(graphql@16.8.1) + '@graphql-codegen/visitor-plugin-common': 4.0.1(graphql@16.8.1) + auto-bind: 4.0.0 + change-case-all: 1.0.15 + graphql: 16.8.1 + tslib: 2.5.3 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + /@graphql-codegen/typescript-operations@4.0.1(graphql@16.8.1): + resolution: {integrity: sha512-GpUWWdBVUec/Zqo23aFLBMrXYxN2irypHqDcKjN78JclDPdreasAEPcIpMfqf4MClvpmvDLy4ql+djVAwmkjbw==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 5.0.1(graphql@16.8.1) + '@graphql-codegen/typescript': 4.0.1(graphql@16.8.1) + '@graphql-codegen/visitor-plugin-common': 4.0.1(graphql@16.8.1) + auto-bind: 4.0.0 + graphql: 16.8.1 + tslib: 2.5.3 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + /@graphql-codegen/typescript-urql@4.0.0(graphql-tag@2.12.6)(graphql@16.8.1): + resolution: {integrity: sha512-l15f44zxU5r1yiIpzLzgDQf2JLmTT+ZrFv7D4kQVAAXquPRN+Bdei1V9VAcatISb5bcHNxmdrXIRMtWKPwVwTg==} + engines: {node: '>= 16.0.0'} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + graphql-tag: ^2.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 3.1.2(graphql@16.8.1) + '@graphql-codegen/visitor-plugin-common': 2.13.1(graphql@16.8.1) + auto-bind: 4.0.0 + graphql: 16.8.1 + graphql-tag: 2.12.6(graphql@16.8.1) + tslib: 2.6.2 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + /@graphql-codegen/typescript@4.0.1(graphql@16.8.1): + resolution: {integrity: sha512-3YziQ21dCVdnHb+Us1uDb3pA6eG5Chjv0uTK+bt9dXeMlwYBU8MbtzvQTo4qvzWVC1AxSOKj0rgfNu1xCXqJyA==} + peerDependencies: + graphql: ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 5.0.1(graphql@16.8.1) + '@graphql-codegen/schema-ast': 4.0.0(graphql@16.8.1) + '@graphql-codegen/visitor-plugin-common': 4.0.1(graphql@16.8.1) + auto-bind: 4.0.0 + graphql: 16.8.1 + tslib: 2.5.3 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + /@graphql-codegen/urql-introspection@3.0.0(graphql@16.8.1): + resolution: {integrity: sha512-DBYfG3CO3G6MTzp+/FaXuxYS6cFSkpDMwxXKoJVqKR0jIGd/ev3Gh1pTgqxndcBu8oV9xjiaBQglKCge0EqLpQ==} + engines: {node: '>= 16.0.0'} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 3.1.2(graphql@16.8.1) + '@urql/introspection': 0.3.3(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.6.2 + dev: true + + /@graphql-codegen/visitor-plugin-common@2.13.1(graphql@16.8.1): + resolution: {integrity: sha512-mD9ufZhDGhyrSaWQGrU1Q1c5f01TeWtSWy/cDwXYjJcHIj1Y/DG2x0tOflEfCvh5WcnmHNIw4lzDsg1W7iFJEg==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 2.7.2(graphql@16.8.1) + '@graphql-tools/optimize': 1.4.0(graphql@16.8.1) + '@graphql-tools/relay-operation-optimizer': 6.5.18(graphql@16.8.1) + '@graphql-tools/utils': 8.13.1(graphql@16.8.1) + auto-bind: 4.0.0 + change-case-all: 1.0.14 + dependency-graph: 0.11.0 + graphql: 16.8.1 + graphql-tag: 2.12.6(graphql@16.8.1) + parse-filepath: 1.0.2 + tslib: 2.4.1 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + /@graphql-codegen/visitor-plugin-common@4.0.1(graphql@16.8.1): + resolution: {integrity: sha512-Bi/1z0nHg4QMsAqAJhds+ForyLtk7A3HQOlkrZNm3xEkY7lcBzPtiOTLBtvziwopBsXUxqeSwVjOOFPLS5Yw1Q==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 5.0.1(graphql@16.8.1) + '@graphql-tools/optimize': 2.0.0(graphql@16.8.1) + '@graphql-tools/relay-operation-optimizer': 7.0.0(graphql@16.8.1) + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + auto-bind: 4.0.0 + change-case-all: 1.0.15 + dependency-graph: 0.11.0 + graphql: 16.8.1 + graphql-tag: 2.12.6(graphql@16.8.1) + parse-filepath: 1.0.2 + tslib: 2.5.3 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + /@graphql-tools/apollo-engine-loader@8.0.0(graphql@16.8.1): + resolution: {integrity: sha512-axQTbN5+Yxs1rJ6cWQBOfw3AEeC+fvIuZSfJLPLLvFJLj4pUm9fhxey/g6oQZAAQJqKPfw+tLDUQvnfvRK8Kmg==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@ardatan/sync-fetch': 0.0.1 + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + '@whatwg-node/fetch': 0.9.14 + graphql: 16.8.1 + tslib: 2.6.2 + transitivePeerDependencies: + - encoding + dev: true + + /@graphql-tools/batch-execute@9.0.2(graphql@16.8.1): + resolution: {integrity: sha512-Y2uwdZI6ZnatopD/SYfZ1eGuQFI7OU2KGZ2/B/7G9ISmgMl5K+ZZWz/PfIEXeiHirIDhyk54s4uka5rj2xwKqQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + dataloader: 2.2.2 + graphql: 16.8.1 + tslib: 2.6.2 + value-or-promise: 1.0.12 + dev: true + + /@graphql-tools/code-file-loader@8.0.3(graphql@16.8.1): + resolution: {integrity: sha512-gVnnlWs0Ua+5FkuHHEriFUOI3OIbHv6DS1utxf28n6NkfGMJldC4j0xlJRY0LS6dWK34IGYgD4HelKYz2l8KiA==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/graphql-tag-pluck': 8.1.0(graphql@16.8.1) + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + globby: 11.1.0 + graphql: 16.8.1 + tslib: 2.6.2 + unixify: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@graphql-tools/delegate@10.0.3(graphql@16.8.1): + resolution: {integrity: sha512-Jor9oazZ07zuWkykD3OOhT/2XD74Zm6Ar0ENZMk75MDD51wB2UWUIMljtHxbJhV5A6UBC2v8x6iY0xdCGiIlyw==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/batch-execute': 9.0.2(graphql@16.8.1) + '@graphql-tools/executor': 1.2.0(graphql@16.8.1) + '@graphql-tools/schema': 10.0.2(graphql@16.8.1) + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + dataloader: 2.2.2 + graphql: 16.8.1 + tslib: 2.6.2 + dev: true + + /@graphql-tools/executor-graphql-ws@1.1.0(graphql@16.8.1): + resolution: {integrity: sha512-yM67SzwE8rYRpm4z4AuGtABlOp9mXXVy6sxXnTJRoYIdZrmDbKVfIY+CpZUJCqS0FX3xf2+GoHlsj7Qswaxgcg==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + '@types/ws': 8.5.10 + graphql: 16.8.1 + graphql-ws: 5.14.2(graphql@16.8.1) + isomorphic-ws: 5.0.0(ws@8.15.1) + tslib: 2.6.2 + ws: 8.15.1 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + + /@graphql-tools/executor-http@1.0.5(@types/node@20.10.4)(graphql@16.8.1): + resolution: {integrity: sha512-roQyDLOAywyaCTPOhwXiT/WDr0bfuVhqOXjECsnrIl/1TMPDUYjiT2sW6Gz6pqnYMmokdhyvlV6D5d7WtIrKsA==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + '@repeaterjs/repeater': 3.0.5 + '@whatwg-node/fetch': 0.9.14 + extract-files: 11.0.0 + graphql: 16.8.1 + meros: 1.3.0(@types/node@20.10.4) + tslib: 2.6.2 + value-or-promise: 1.0.12 + transitivePeerDependencies: + - '@types/node' + dev: true + + /@graphql-tools/executor-legacy-ws@1.0.5(graphql@16.8.1): + resolution: {integrity: sha512-w54AZ7zkNuvpyV09FH+eGHnnAmaxhBVHg4Yh2ICcsMfRg0brkLt77PlbjBuxZ4HY8XZnKJaYWf+tKazQZtkQtg==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + '@types/ws': 8.5.10 + graphql: 16.8.1 + isomorphic-ws: 5.0.0(ws@8.15.1) + tslib: 2.6.2 + ws: 8.15.1 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + + /@graphql-tools/executor@1.2.0(graphql@16.8.1): + resolution: {integrity: sha512-SKlIcMA71Dha5JnEWlw4XxcaJ+YupuXg0QCZgl2TOLFz4SkGCwU/geAsJvUJFwK2RbVLpQv/UMq67lOaBuwDtg==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) + '@repeaterjs/repeater': 3.0.5 + graphql: 16.8.1 + tslib: 2.6.2 + value-or-promise: 1.0.12 + dev: true + + /@graphql-tools/git-loader@8.0.3(graphql@16.8.1): + resolution: {integrity: sha512-Iz9KbRUAkuOe8JGTS0qssyJ+D5Snle17W+z9anwWrLFrkBhHrRFUy5AdjZqgJuhls0x30QkZBnnCtnHDBdQ4nA==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/graphql-tag-pluck': 8.1.0(graphql@16.8.1) + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + graphql: 16.8.1 + is-glob: 4.0.3 + micromatch: 4.0.5 + tslib: 2.6.2 + unixify: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@graphql-tools/github-loader@8.0.0(@types/node@20.10.4)(graphql@16.8.1): + resolution: {integrity: sha512-VuroArWKcG4yaOWzV0r19ElVIV6iH6UKDQn1MXemND0xu5TzrFme0kf3U9o0YwNo0kUYEk9CyFM0BYg4he17FA==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@ardatan/sync-fetch': 0.0.1 + '@graphql-tools/executor-http': 1.0.5(@types/node@20.10.4)(graphql@16.8.1) + '@graphql-tools/graphql-tag-pluck': 8.1.0(graphql@16.8.1) + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + '@whatwg-node/fetch': 0.9.14 + graphql: 16.8.1 + tslib: 2.6.2 + value-or-promise: 1.0.12 + transitivePeerDependencies: + - '@types/node' + - encoding + - supports-color + dev: true + + /@graphql-tools/graphql-file-loader@8.0.0(graphql@16.8.1): + resolution: {integrity: sha512-wRXj9Z1IFL3+zJG1HWEY0S4TXal7+s1vVhbZva96MSp0kbb/3JBF7j0cnJ44Eq0ClccMgGCDFqPFXty4JlpaPg==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/import': 7.0.0(graphql@16.8.1) + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + globby: 11.1.0 + graphql: 16.8.1 + tslib: 2.6.2 + unixify: 1.0.0 + dev: true + + /@graphql-tools/graphql-tag-pluck@8.1.0(graphql@16.8.1): + resolution: {integrity: sha512-kt5l6H/7QxQcIaewInTcune6NpATojdFEW98/8xWcgmy7dgXx5vU9e0AicFZIH+ewGyZzTpwFqO2RI03roxj2w==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@babel/core': 7.23.6 + '@babel/parser': 7.23.6 + '@babel/plugin-syntax-import-assertions': 7.23.3(@babel/core@7.23.6) + '@babel/traverse': 7.23.6 + '@babel/types': 7.23.6 + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.6.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@graphql-tools/import@7.0.0(graphql@16.8.1): + resolution: {integrity: sha512-NVZiTO8o1GZs6OXzNfjB+5CtQtqsZZpQOq+Uu0w57kdUkT4RlQKlwhT8T81arEsbV55KpzkpFsOZP7J1wdmhBw==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + graphql: 16.8.1 + resolve-from: 5.0.0 + tslib: 2.6.2 + dev: true + + /@graphql-tools/json-file-loader@8.0.0(graphql@16.8.1): + resolution: {integrity: sha512-ki6EF/mobBWJjAAC84xNrFMhNfnUFD6Y0rQMGXekrUgY0NdeYXHU0ZUgHzC9O5+55FslqUmAUHABePDHTyZsLg==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + globby: 11.1.0 + graphql: 16.8.1 + tslib: 2.6.2 + unixify: 1.0.0 + dev: true + + /@graphql-tools/load@8.0.1(graphql@16.8.1): + resolution: {integrity: sha512-qSMsKngJhDqRbuWyo3NvakEFqFL6+eSjy8ooJ1o5qYD26N7dqXkKzIMycQsX7rBK19hOuINAUSaRcVWH6hTccw==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/schema': 10.0.2(graphql@16.8.1) + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + graphql: 16.8.1 + p-limit: 3.1.0 + tslib: 2.6.2 + dev: true + + /@graphql-tools/merge@9.0.1(graphql@16.8.1): + resolution: {integrity: sha512-hIEExWO9fjA6vzsVjJ3s0cCQ+Q/BEeMVJZtMXd7nbaVefVy0YDyYlEkeoYYNV3NVVvu1G9lr6DM1Qd0DGo9Caw==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.6.2 + dev: true + + /@graphql-tools/optimize@1.4.0(graphql@16.8.1): + resolution: {integrity: sha512-dJs/2XvZp+wgHH8T5J2TqptT9/6uVzIYvA6uFACha+ufvdMBedkfR4b4GbT8jAKLRARiqRTxy3dctnwkTM2tdw==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + graphql: 16.8.1 + tslib: 2.6.2 + dev: true + + /@graphql-tools/optimize@2.0.0(graphql@16.8.1): + resolution: {integrity: sha512-nhdT+CRGDZ+bk68ic+Jw1OZ99YCDIKYA5AlVAnBHJvMawSx9YQqQAIj4refNc1/LRieGiuWvhbG3jvPVYho0Dg==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + graphql: 16.8.1 + tslib: 2.6.2 + dev: true + + /@graphql-tools/prisma-loader@8.0.2(@types/node@20.10.4)(graphql@16.8.1): + resolution: {integrity: sha512-8d28bIB0bZ9Bj0UOz9sHagVPW+6AHeqvGljjERtwCnWl8OCQw2c2pNboYXISLYUG5ub76r4lDciLLTU+Ks7Q0w==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/url-loader': 8.0.1(@types/node@20.10.4)(graphql@16.8.1) + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + '@types/js-yaml': 4.0.9 + '@types/json-stable-stringify': 1.0.36 + '@whatwg-node/fetch': 0.9.14 + chalk: 4.1.2 + debug: 4.3.4 + dotenv: 16.3.1 + graphql: 16.8.1 + graphql-request: 6.1.0(graphql@16.8.1) + http-proxy-agent: 7.0.0 + https-proxy-agent: 7.0.2 + jose: 5.1.3 + js-yaml: 4.1.0 + json-stable-stringify: 1.1.0 + lodash: 4.17.21 + scuid: 1.1.0 + tslib: 2.6.2 + yaml-ast-parser: 0.0.43 + transitivePeerDependencies: + - '@types/node' + - bufferutil + - encoding + - supports-color + - utf-8-validate + dev: true + + /@graphql-tools/relay-operation-optimizer@6.5.18(graphql@16.8.1): + resolution: {integrity: sha512-mc5VPyTeV+LwiM+DNvoDQfPqwQYhPV/cl5jOBjTgSniyaq8/86aODfMkrE2OduhQ5E00hqrkuL2Fdrgk0w1QJg==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@ardatan/relay-compiler': 12.0.0(graphql@16.8.1) + '@graphql-tools/utils': 9.2.1(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.6.2 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + /@graphql-tools/relay-operation-optimizer@7.0.0(graphql@16.8.1): + resolution: {integrity: sha512-UNlJi5y3JylhVWU4MBpL0Hun4Q7IoJwv9xYtmAz+CgRa066szzY7dcuPfxrA7cIGgG/Q6TVsKsYaiF4OHPs1Fw==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@ardatan/relay-compiler': 12.0.0(graphql@16.8.1) + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.6.2 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + /@graphql-tools/schema@10.0.2(graphql@16.8.1): + resolution: {integrity: sha512-TbPsIZnWyDCLhgPGnDjt4hosiNU2mF/rNtSk5BVaXWnZqvKJ6gzJV4fcHcvhRIwtscDMW2/YTnK6dLVnk8pc4w==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/merge': 9.0.1(graphql@16.8.1) + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.6.2 + value-or-promise: 1.0.12 + dev: true + + /@graphql-tools/url-loader@8.0.1(@types/node@20.10.4)(graphql@16.8.1): + resolution: {integrity: sha512-B2k8KQEkEQmfV1zhurT5GLoXo8jbXP+YQHUayhCSxKYlRV7j/1Fhp1b21PDM8LXIDGlDRXaZ0FbWKOs7eYXDuQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@ardatan/sync-fetch': 0.0.1 + '@graphql-tools/delegate': 10.0.3(graphql@16.8.1) + '@graphql-tools/executor-graphql-ws': 1.1.0(graphql@16.8.1) + '@graphql-tools/executor-http': 1.0.5(@types/node@20.10.4)(graphql@16.8.1) + '@graphql-tools/executor-legacy-ws': 1.0.5(graphql@16.8.1) + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + '@graphql-tools/wrap': 10.0.1(graphql@16.8.1) + '@types/ws': 8.5.10 + '@whatwg-node/fetch': 0.9.14 + graphql: 16.8.1 + isomorphic-ws: 5.0.0(ws@8.15.1) + tslib: 2.6.2 + value-or-promise: 1.0.12 + ws: 8.15.1 + transitivePeerDependencies: + - '@types/node' + - bufferutil + - encoding + - utf-8-validate + dev: true + + /@graphql-tools/utils@10.0.11(graphql@16.8.1): + resolution: {integrity: sha512-vVjXgKn6zjXIlYBd7yJxCVMYGb5j18gE3hx3Qw3mNsSEsYQXbJbPdlwb7Fc9FogsJei5AaqiQerqH4kAosp1nQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) + cross-inspect: 1.0.0 + dset: 3.1.3 + graphql: 16.8.1 + tslib: 2.6.2 + dev: true + + /@graphql-tools/utils@8.13.1(graphql@16.8.1): + resolution: {integrity: sha512-qIh9yYpdUFmctVqovwMdheVNJqFh+DQNWIhX87FJStfXYnmweBUDATok9fWPleKeFwxnW8IapKmY8m8toJEkAw==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + graphql: 16.8.1 + tslib: 2.6.2 + dev: true + + /@graphql-tools/utils@9.2.1(graphql@16.8.1): + resolution: {integrity: sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.6.2 + dev: true + + /@graphql-tools/wrap@10.0.1(graphql@16.8.1): + resolution: {integrity: sha512-Cw6hVrKGM2OKBXeuAGltgy4tzuqQE0Nt7t/uAqnuokSXZhMHXJUb124Bnvxc2gPZn5chfJSDafDe4Cp8ZAVJgg==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/delegate': 10.0.3(graphql@16.8.1) + '@graphql-tools/schema': 10.0.2(graphql@16.8.1) + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + graphql: 16.8.1 + tslib: 2.6.2 + value-or-promise: 1.0.12 + dev: true + + /@graphql-typed-document-node/core@3.2.0(graphql@16.8.1): + resolution: {integrity: sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + graphql: 16.8.1 + dev: true + + /@hookform/resolvers@3.3.2(react-hook-form@7.49.1): + resolution: {integrity: sha512-Tw+GGPnBp+5DOsSg4ek3LCPgkBOuOgS5DsDV7qsWNH9LZc433kgsWICjlsh2J9p04H2K66hsXPPb9qn9ILdUtA==} + peerDependencies: + react-hook-form: ^7.0.0 + dependencies: + react-hook-form: 7.49.1(react@18.2.0) + dev: false + + /@humanwhocodes/config-array@0.11.13: + resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 2.0.1 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + /@humanwhocodes/module-importer@1.0.1: + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + /@humanwhocodes/object-schema@2.0.1: + resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==} + + /@istanbuljs/schema@0.1.3: + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + dev: true + + /@jest/schemas@29.6.3: + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@sinclair/typebox': 0.27.8 + dev: true + + /@jridgewell/gen-mapping@0.3.3: + resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.20 + + /@jridgewell/resolve-uri@3.1.1: + resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} + engines: {node: '>=6.0.0'} + + /@jridgewell/set-array@1.1.2: + resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} + engines: {node: '>=6.0.0'} + + /@jridgewell/source-map@0.3.5: + resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==} + dependencies: + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.20 + dev: false + + /@jridgewell/sourcemap-codec@1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + + /@jridgewell/trace-mapping@0.3.20: + resolution: {integrity: sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==} + dependencies: + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 + + /@jridgewell/trace-mapping@0.3.9: + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + dependencies: + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /@jsdevtools/ono@7.1.3: + resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==} + dev: true + + /@kamilkisiela/fast-url-parser@1.1.4: + resolution: {integrity: sha512-gbkePEBupNydxCelHCESvFSFM8XPh1Zs/OAVRW/rKpEqPAl5PbOM90Si8mv9bvnR53uPD2s/FiRxdvSejpRJew==} + dev: true + + /@manypkg/find-root@1.1.0: + resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} + dependencies: + '@babel/runtime': 7.23.6 + '@types/node': 12.20.55 + find-up: 4.1.0 + fs-extra: 8.1.0 + dev: true + + /@manypkg/get-packages@1.1.3: + resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} + dependencies: + '@babel/runtime': 7.23.6 + '@changesets/types': 4.1.0 + '@manypkg/find-root': 1.1.0 + fs-extra: 8.1.0 + globby: 11.1.0 + read-yaml-file: 1.1.0 + dev: true + + /@next/env@14.0.4: + resolution: {integrity: sha512-irQnbMLbUNQpP1wcE5NstJtbuA/69kRfzBrpAD7Gsn8zm/CY6YQYc3HQBz8QPxwISG26tIm5afvvVbu508oBeQ==} + dev: false + + /@next/env@14.2.10: + resolution: {integrity: sha512-dZIu93Bf5LUtluBXIv4woQw2cZVZ2DJTjax5/5DOs3lzEOeKLy7GxRSr4caK9/SCPdaW6bCgpye6+n4Dh9oJPw==} + + /@next/eslint-plugin-next@14.0.4: + resolution: {integrity: sha512-U3qMNHmEZoVmHA0j/57nRfi3AscXNvkOnxDmle/69Jz/G0o/gWjXTDdlgILZdrxQ0Lw/jv2mPW8PGy0EGIHXhQ==} + dependencies: + glob: 7.1.7 + dev: true + + /@next/swc-darwin-arm64@14.2.10: + resolution: {integrity: sha512-V3z10NV+cvMAfxQUMhKgfQnPbjw+Ew3cnr64b0lr8MDiBJs3eLnM6RpGC46nhfMZsiXgQngCJKWGTC/yDcgrDQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + optional: true + + /@next/swc-darwin-x64@14.2.10: + resolution: {integrity: sha512-Y0TC+FXbFUQ2MQgimJ/7Ina2mXIKhE7F+GUe1SgnzRmwFY3hX2z8nyVCxE82I2RicspdkZnSWMn4oTjIKz4uzA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + requiresBuild: true + optional: true + + /@next/swc-linux-arm64-gnu@14.2.10: + resolution: {integrity: sha512-ZfQ7yOy5zyskSj9rFpa0Yd7gkrBnJTkYVSya95hX3zeBG9E55Z6OTNPn1j2BTFWvOVVj65C3T+qsjOyVI9DQpA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + optional: true + + /@next/swc-linux-arm64-musl@14.2.10: + resolution: {integrity: sha512-n2i5o3y2jpBfXFRxDREr342BGIQCJbdAUi/K4q6Env3aSx8erM9VuKXHw5KNROK9ejFSPf0LhoSkU/ZiNdacpQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + optional: true + + /@next/swc-linux-x64-gnu@14.2.10: + resolution: {integrity: sha512-GXvajAWh2woTT0GKEDlkVhFNxhJS/XdDmrVHrPOA83pLzlGPQnixqxD8u3bBB9oATBKB//5e4vpACnx5Vaxdqg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + optional: true + + /@next/swc-linux-x64-musl@14.2.10: + resolution: {integrity: sha512-opFFN5B0SnO+HTz4Wq4HaylXGFV+iHrVxd3YvREUX9K+xfc4ePbRrxqOuPOFjtSuiVouwe6uLeDtabjEIbkmDA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + optional: true + + /@next/swc-win32-arm64-msvc@14.2.10: + resolution: {integrity: sha512-9NUzZuR8WiXTvv+EiU/MXdcQ1XUvFixbLIMNQiVHuzs7ZIFrJDLJDaOF1KaqttoTujpcxljM/RNAOmw1GhPPQQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + requiresBuild: true + optional: true + + /@next/swc-win32-ia32-msvc@14.2.10: + resolution: {integrity: sha512-fr3aEbSd1GeW3YUMBkWAu4hcdjZ6g4NBl1uku4gAn661tcxd1bHs1THWYzdsbTRLcCKLjrDZlNp6j2HTfrw+Bg==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + requiresBuild: true + optional: true + + /@next/swc-win32-x64-msvc@14.2.10: + resolution: {integrity: sha512-UjeVoRGKNL2zfbcQ6fscmgjBAS/inHBh63mjIlfPg/NG8Yn2ztqylXt5qilYb6hoHIwaU2ogHknHWWmahJjgZQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + requiresBuild: true + optional: true + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.15.0 + + /@opentelemetry/api@1.7.0: + resolution: {integrity: sha512-AdY5wvN0P2vXBi3b29hxZgSFvdhdxPB9+f0B6s//P9Q8nibRWeA3cHm8UmLpio9ABigkVHJ5NMPk+Mz8VCCyrw==} + engines: {node: '>=8.0.0'} + dev: false + + /@opentelemetry/semantic-conventions@1.18.1: + resolution: {integrity: sha512-+NLGHr6VZwcgE/2lw8zDIufOCGnzsA5CbQIMleXZTrgkBd0TanCX+MiDYJ1TOS4KL/Tqk0nFRxawnaYr6pkZkA==} + engines: {node: '>=14'} + dev: false + + /@peculiar/asn1-schema@2.3.8: + resolution: {integrity: sha512-ULB1XqHKx1WBU/tTFIA+uARuRoBVZ4pNdOA878RDrRbBfBGcSzi5HBkdScC6ZbHn8z7L8gmKCgPC1LHRrP46tA==} + dependencies: + asn1js: 3.0.5 + pvtsutils: 1.3.5 + tslib: 2.6.2 + dev: true + + /@peculiar/json-schema@1.1.12: + resolution: {integrity: sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==} + engines: {node: '>=8.0.0'} + dependencies: + tslib: 2.6.2 + dev: true + + /@peculiar/webcrypto@1.4.3: + resolution: {integrity: sha512-VtaY4spKTdN5LjJ04im/d/joXuvLbQdgy5Z4DXF4MFZhQ+MTrejbNMkfZBp1Bs3O5+bFqnJgyGdPuZQflvIa5A==} + engines: {node: '>=10.12.0'} + dependencies: + '@peculiar/asn1-schema': 2.3.8 + '@peculiar/json-schema': 1.1.12 + pvtsutils: 1.3.5 + tslib: 2.6.2 + webcrypto-core: 1.7.7 + dev: true + + /@pollyjs/adapter-fetch@6.0.6: + resolution: {integrity: sha512-euWzM5TnA2jptdJgjIkEd/Q2hNFB652XivPKerWpLMFB13IKlrERX9wn2Dw3pquDAP0LvXH1qVBZt5DK0Xhzyg==} + dependencies: + '@pollyjs/adapter': 6.0.6 + '@pollyjs/utils': 6.0.6 + detect-node: 2.1.0 + to-arraybuffer: 1.0.1 + dev: true + + /@pollyjs/adapter-node-http@6.0.6: + resolution: {integrity: sha512-jdJG7oncmSHZAtVMmRgOxh5A56b7G8H9ULlk/ZaVJ+jNrlFXhLmPpx8OQoSF4Cuq2ugdiWmwmAjFXHStcpY3Mw==} + dependencies: + '@pollyjs/adapter': 6.0.6 + '@pollyjs/utils': 6.0.6 + lodash-es: 4.17.21 + nock: 13.4.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@pollyjs/adapter@6.0.6: + resolution: {integrity: sha512-szhys0NiFQqCJDMC0kpDyjhLqSI7aWc6m6iATCRKgcMcN/7QN85pb3GmRzvnNV8+/Bi2AUSCwxZljcsKhbYVWQ==} + dependencies: + '@pollyjs/utils': 6.0.6 + dev: true + + /@pollyjs/core@6.0.6: + resolution: {integrity: sha512-1ZZcmojW8iSFmvHGeLlvuudM3WiDV842FsVvtPAo3HoAYE6jCNveLHJ+X4qvonL4enj1SyTF3hXA107UkQFQrA==} + dependencies: + '@pollyjs/utils': 6.0.6 + '@sindresorhus/fnv1a': 2.0.1 + blueimp-md5: 2.19.0 + fast-json-stable-stringify: 2.1.0 + is-absolute-url: 3.0.3 + lodash-es: 4.17.21 + loglevel: 1.8.1 + route-recognizer: 0.3.4 + slugify: 1.6.6 + dev: true + + /@pollyjs/node-server@6.0.6: + resolution: {integrity: sha512-nkP1+hdNoVOlrRz9R84haXVsaSmo8Xmq7uYK9GeUMSLQy4Fs55ZZ9o2KI6vRA8F6ZqJSbC31xxwwIoTkjyP7Vg==} + dependencies: + '@pollyjs/utils': 6.0.6 + body-parser: 1.20.2 + cors: 2.8.5 + express: 4.18.2 + fs-extra: 10.1.0 + http-graceful-shutdown: 3.1.13 + morgan: 1.10.0 + nocache: 3.0.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@pollyjs/persister-fs@6.0.6: + resolution: {integrity: sha512-/ALVgZiH2zGqwLkW0Mntc0Oq1v7tR8LS8JD2SAyIsHpnSXeBUnfPWwjAuYw0vqORHFVEbwned6MBRFfvU/3qng==} + dependencies: + '@pollyjs/node-server': 6.0.6 + '@pollyjs/persister': 6.0.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@pollyjs/persister@6.0.6: + resolution: {integrity: sha512-9KB1p+frvYvFGur4ifzLnFKFLXAMXrhAhCnVhTnkG2WIqqQPT7y+mKBV/DKCmYFx8GPA9FiNGqt2pB53uJpIdw==} + dependencies: + '@pollyjs/utils': 6.0.6 + '@types/set-cookie-parser': 2.4.7 + bowser: 2.11.0 + fast-json-stable-stringify: 2.1.0 + lodash-es: 4.17.21 + set-cookie-parser: 2.6.0 + utf8-byte-length: 1.0.4 + dev: true + + /@pollyjs/utils@6.0.6: + resolution: {integrity: sha512-nhVJoI3nRgRimE0V2DVSvsXXNROUH6iyJbroDu4IdsOIOFC1Ds0w+ANMB4NMwFaqE+AisWOmXFzwAGdAfyiQVg==} + dependencies: + qs: 6.11.2 + url-parse: 1.5.10 + dev: true + + /@radix-ui/number@1.0.1: + resolution: {integrity: sha512-T5gIdVO2mmPW3NNhjNgEP3cqMXjXL9UbO0BzWcXfvdBs+BohbQxvd/K5hSVKmn9/lbTdsQVKbUcP5WLCwvUbBg==} + dependencies: + '@babel/runtime': 7.23.6 + dev: false + + /@radix-ui/primitive@1.0.1: + resolution: {integrity: sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==} + dependencies: + '@babel/runtime': 7.23.6 + dev: false + + /@radix-ui/react-accordion@1.1.2(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-fDG7jcoNKVjSK6yfmuAs0EnPDro0WMXIhMtXdTBWqEioVW206ku+4Lw07e+13lUkFkpoEQ2PdeMIAGpdqEAmDg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-collapsible': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-direction': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-alert-dialog@1.0.5(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-OrVIOcZL0tl6xibeuGt5/+UxoT2N27KCFOPjFyfXMnchxSHZ/OW7cCX2nGlIYJrbHK/fczPcFzAwvNBB6XBNMA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-dialog': 1.0.5(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.45)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-arrow@1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-checkbox@1.0.4(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-CBuGQa52aAYnADZVt/KBQzXrwx6TqnlwtcIPGtVt5JkkzQwMOLJjPukimhfKEr4GQNd43C+djUh5Ikopj8pSLg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-use-previous': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-use-size': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-collapsible@1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-collection@1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.45)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.45)(react@18.2.0): + resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@types/react': 18.2.45 + react: 18.2.0 + dev: false + + /@radix-ui/react-context@1.0.1(@types/react@18.2.45)(react@18.2.0): + resolution: {integrity: sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@types/react': 18.2.45 + react: 18.2.0 + dev: false + + /@radix-ui/react-dialog@1.0.5(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + aria-hidden: 1.2.3 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-remove-scroll: 2.5.5(@types/react@18.2.45)(react@18.2.0) + dev: false + + /@radix-ui/react-direction@1.0.1(@types/react@18.2.45)(react@18.2.0): + resolution: {integrity: sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@types/react': 18.2.45 + react: 18.2.0 + dev: false + + /@radix-ui/react-dismissable-layer@1.0.4(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-7UpBa/RKMoHJYjie1gkF1DlK8l1fdU/VKDpoS3rCCo8YBJR294GwcEHyxHw72yvphJ7ld0AXEcSLAzY2F/WyCg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@18.2.45)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-dismissable-layer@1.0.5(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@18.2.45)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-dropdown-menu@2.0.6(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-i6TuFOoWmLWq+M/eCLGd/bQ2HfAX1RJgvrBQ6AQLmzfvsLdefxbWu8G9zczcPFfcSPehz9GcpF6K9QYreFV8hA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-menu': 2.0.6(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-focus-guards@1.0.1(@types/react@18.2.45)(react@18.2.0): + resolution: {integrity: sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@types/react': 18.2.45 + react: 18.2.0 + dev: false + + /@radix-ui/react-focus-scope@1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-upXdPfqI4islj2CslyfUBNlaJCPybbqRHAi1KER7Isel9Q2AtSJ0zRBZv8mWQiFXD2nyAJ4BhC3yXgZ6kMBSrQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-focus-scope@1.0.4(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-id@1.0.1(@types/react@18.2.45)(react@18.2.0): + resolution: {integrity: sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@types/react': 18.2.45 + react: 18.2.0 + dev: false + + /@radix-ui/react-menu@2.0.6(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-BVkFLS+bUC8HcImkRKPSiVumA1VPOOEC5WBMiT+QAVsPzW1FJzI9KnqgGxVDPBcql5xXrHkD3JOVoXWEXD8SYA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-direction': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-popper': 1.1.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-roving-focus': 1.0.4(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + aria-hidden: 1.2.3 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-remove-scroll: 2.5.5(@types/react@18.2.45)(react@18.2.0) + dev: false + + /@radix-ui/react-popover@1.0.7(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-shtvVnlsxT6faMnK/a7n0wptwBD23xc1Z5mdrtKLwVEfsEMXodS0r5s0/g5P0hX//EKYZS2sxUjqfzlg52ZSnQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-focus-scope': 1.0.4(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-popper': 1.1.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + aria-hidden: 1.2.3 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-remove-scroll: 2.5.5(@types/react@18.2.45)(react@18.2.0) + dev: false + + /@radix-ui/react-popper@1.1.2(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-1CnGGfFi/bbqtJZZ0P/NQY20xdG3E0LALJaLUEoKwPLwl6PPPfbeiCqMVQnhoFRAxjJj4RpBRJzDmUgsex2tSg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@floating-ui/react-dom': 2.0.4(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-arrow': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-use-rect': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-use-size': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/rect': 1.0.1 + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-popper@1.1.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@floating-ui/react-dom': 2.0.4(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-arrow': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-use-rect': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-use-size': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/rect': 1.0.1 + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-portal@1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-xLYZeHrWoPmA5mEKEfZZevoVRK/Q43GfzRXkWV6qawIWWK8t6ifIiLQdd7rmQ4Vk1bmI21XhqF9BN3jWf+phpA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-portal@1.0.4(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-presence@1.0.1(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-primitive@1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.45)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-radio-group@1.1.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-x+yELayyefNeKeTx4fjK6j99Fs6c4qKm3aY38G3swQVTN6xMpsrbigC0uHs2L//g8q4qR7qOcww8430jJmi2ag==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-direction': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-roving-focus': 1.0.4(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-use-previous': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-use-size': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-roving-focus@1.0.4(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-direction': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-select@1.2.2(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-zI7McXr8fNaSrUY9mZe4x/HC0jTLY9fWNhO1oLWYMQGDXuV4UCivIGTxwioSzO0ZCYX9iSLyWmAh/1TOmX3Cnw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/number': 1.0.1 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-direction': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.4(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-focus-guards': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-focus-scope': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-popper': 1.1.2(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-portal': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-use-previous': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-visually-hidden': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + aria-hidden: 1.2.3 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-remove-scroll: 2.5.5(@types/react@18.2.45)(react@18.2.0) + dev: false + + /@radix-ui/react-slot@1.0.2(@types/react@18.2.45)(react@18.2.0): + resolution: {integrity: sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@types/react': 18.2.45 + react: 18.2.0 + dev: false + + /@radix-ui/react-toggle@1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-Pkqg3+Bc98ftZGsl60CLANXQBBQ4W3mTFS9EJvNxKMZ7magklKV69/id1mlAlOFDDfHvlCms0fx8fA4CMKDJHg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-tooltip@1.0.7(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-lPh5iKNFVQ/jav/j6ZrWq3blfDJ0OH9R6FlNUHPMqdLuQ9vwDgFsRxvl8b7Asuy5c8xmoojHUxKHQSOAvMHxyw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-popper': 1.1.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@radix-ui/react-visually-hidden': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.2.45)(react@18.2.0): + resolution: {integrity: sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@types/react': 18.2.45 + react: 18.2.0 + dev: false + + /@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.2.45)(react@18.2.0): + resolution: {integrity: sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@types/react': 18.2.45 + react: 18.2.0 + dev: false + + /@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.2.45)(react@18.2.0): + resolution: {integrity: sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@types/react': 18.2.45 + react: 18.2.0 + dev: false + + /@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.2.45)(react@18.2.0): + resolution: {integrity: sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@types/react': 18.2.45 + react: 18.2.0 + dev: false + + /@radix-ui/react-use-previous@1.0.1(@types/react@18.2.45)(react@18.2.0): + resolution: {integrity: sha512-cV5La9DPwiQ7S0gf/0qiD6YgNqM5Fk97Kdrlc5yBcrF3jyEZQwm7vYFqMo4IfeHgJXsRaMvLABFtd0OVEmZhDw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@types/react': 18.2.45 + react: 18.2.0 + dev: false + + /@radix-ui/react-use-rect@1.0.1(@types/react@18.2.45)(react@18.2.0): + resolution: {integrity: sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/rect': 1.0.1 + '@types/react': 18.2.45 + react: 18.2.0 + dev: false + + /@radix-ui/react-use-size@1.0.1(@types/react@18.2.45)(react@18.2.0): + resolution: {integrity: sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.45)(react@18.2.0) + '@types/react': 18.2.45 + react: 18.2.0 + dev: false + + /@radix-ui/react-visually-hidden@1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@radix-ui/rect@1.0.1: + resolution: {integrity: sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ==} + dependencies: + '@babel/runtime': 7.23.6 + dev: false + + /@repeaterjs/repeater@3.0.5: + resolution: {integrity: sha512-l3YHBLAol6d/IKnB9LhpD0cEZWAoe3eFKUyTYWmFmCO2Q/WOckxLQAUyMZWwZV2M/m3+4vgRoaolFqaII82/TA==} + dev: true + + /@rollup/plugin-commonjs@24.0.0(rollup@2.78.0): + resolution: {integrity: sha512-0w0wyykzdyRRPHOb0cQt14mIBLujfAv6GgP6g8nvg/iBxEm112t3YPPq+Buqe2+imvElTka+bjNlJ/gB56TD8g==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.68.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@rollup/pluginutils': 5.1.0(rollup@2.78.0) + commondir: 1.0.1 + estree-walker: 2.0.2 + glob: 8.1.0 + is-reference: 1.2.1 + magic-string: 0.27.0 + rollup: 2.78.0 + dev: false + + /@rollup/pluginutils@5.1.0(rollup@2.78.0): + resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@types/estree': 1.0.5 + estree-walker: 2.0.2 + picomatch: 2.3.1 + rollup: 2.78.0 + dev: false + + /@rollup/rollup-android-arm-eabi@4.9.0: + resolution: {integrity: sha512-+1ge/xmaJpm1KVBuIH38Z94zj9fBD+hp+/5WLaHgyY8XLq1ibxk/zj6dTXaqM2cAbYKq8jYlhHd6k05If1W5xA==} + cpu: [arm] + os: [android] + requiresBuild: true + optional: true + + /@rollup/rollup-android-arm64@4.9.0: + resolution: {integrity: sha512-im6hUEyQ7ZfoZdNvtwgEJvBWZYauC9KVKq1w58LG2Zfz6zMd8gRrbN+xCVoqA2hv/v6fm9lp5LFGJ3za8EQH3A==} + cpu: [arm64] + os: [android] + requiresBuild: true + optional: true + + /@rollup/rollup-darwin-arm64@4.9.0: + resolution: {integrity: sha512-u7aTMskN6Dmg1lCT0QJ+tINRt+ntUrvVkhbPfFz4bCwRZvjItx2nJtwJnJRlKMMaQCHRjrNqHRDYvE4mBm3DlQ==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + optional: true + + /@rollup/rollup-darwin-x64@4.9.0: + resolution: {integrity: sha512-8FvEl3w2ExmpcOmX5RJD0yqXcVSOqAJJUJ29Lca29Ik+3zPS1yFimr2fr5JSZ4Z5gt8/d7WqycpgkX9nocijSw==} + cpu: [x64] + os: [darwin] + requiresBuild: true + optional: true + + /@rollup/rollup-linux-arm-gnueabihf@4.9.0: + resolution: {integrity: sha512-lHoKYaRwd4gge+IpqJHCY+8Vc3hhdJfU6ukFnnrJasEBUvVlydP8PuwndbWfGkdgSvZhHfSEw6urrlBj0TSSfg==} + cpu: [arm] + os: [linux] + requiresBuild: true + optional: true + + /@rollup/rollup-linux-arm64-gnu@4.9.0: + resolution: {integrity: sha512-JbEPfhndYeWHfOSeh4DOFvNXrj7ls9S/2omijVsao+LBPTPayT1uKcK3dHW3MwDJ7KO11t9m2cVTqXnTKpeaiw==} + cpu: [arm64] + os: [linux] + requiresBuild: true + optional: true + + /@rollup/rollup-linux-arm64-musl@4.9.0: + resolution: {integrity: sha512-ahqcSXLlcV2XUBM3/f/C6cRoh7NxYA/W7Yzuv4bDU1YscTFw7ay4LmD7l6OS8EMhTNvcrWGkEettL1Bhjf+B+w==} + cpu: [arm64] + os: [linux] + requiresBuild: true + optional: true + + /@rollup/rollup-linux-riscv64-gnu@4.9.0: + resolution: {integrity: sha512-uwvOYNtLw8gVtrExKhdFsYHA/kotURUmZYlinH2VcQxNCQJeJXnkmWgw2hI9Xgzhgu7J9QvWiq9TtTVwWMDa+w==} + cpu: [riscv64] + os: [linux] + requiresBuild: true + optional: true + + /@rollup/rollup-linux-x64-gnu@4.9.0: + resolution: {integrity: sha512-m6pkSwcZZD2LCFHZX/zW2aLIISyzWLU3hrLLzQKMI12+OLEzgruTovAxY5sCZJkipklaZqPy/2bEEBNjp+Y7xg==} + cpu: [x64] + os: [linux] + requiresBuild: true + optional: true + + /@rollup/rollup-linux-x64-musl@4.9.0: + resolution: {integrity: sha512-VFAC1RDRSbU3iOF98X42KaVicAfKf0m0OvIu8dbnqhTe26Kh6Ym9JrDulz7Hbk7/9zGc41JkV02g+p3BivOdAg==} + cpu: [x64] + os: [linux] + requiresBuild: true + optional: true + + /@rollup/rollup-win32-arm64-msvc@4.9.0: + resolution: {integrity: sha512-9jPgMvTKXARz4inw6jezMLA2ihDBvgIU9Ml01hjdVpOcMKyxFBJrn83KVQINnbeqDv0+HdO1c09hgZ8N0s820Q==} + cpu: [arm64] + os: [win32] + requiresBuild: true + optional: true + + /@rollup/rollup-win32-ia32-msvc@4.9.0: + resolution: {integrity: sha512-WE4pT2kTXQN2bAv40Uog0AsV7/s9nT9HBWXAou8+++MBCnY51QS02KYtm6dQxxosKi1VIz/wZIrTQO5UP2EW+Q==} + cpu: [ia32] + os: [win32] + requiresBuild: true + optional: true + + /@rollup/rollup-win32-x64-msvc@4.9.0: + resolution: {integrity: sha512-aPP5Q5AqNGuT0tnuEkK/g4mnt3ZhheiXrDIiSVIHN9mcN21OyXDVbEMqmXPE7e2OplNLDkcvV+ZoGJa2ZImFgw==} + cpu: [x64] + os: [win32] + requiresBuild: true + optional: true + + /@rushstack/eslint-patch@1.6.0: + resolution: {integrity: sha512-2/U3GXA6YiPYQDLGwtGlnNgKYBSwCFIHf8Y9LUY5VATHdtbLlU0Y1R3QoBnT0aB4qv/BEiVVsj7LJXoQCgJ2vA==} + dev: true + + /@saleor/app-sdk@0.47.2(graphql@16.8.1)(next@14.2.10)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-ctGbL9R5dmAYEMQHr+ir2OcvPCEmM3SDZX6isKBYLiO6CqKB7P8SNPjxlPBSiafC17ZcoKjim0oMhfqqcz3Srg==} + peerDependencies: + '@vercel/kv': ^1.0.0 + graphql: '>=16.6.0' + next: '>=12' + react: '>=17' + react-dom: '>=17' + peerDependenciesMeta: + '@vercel/kv': + optional: true + dependencies: + '@opentelemetry/api': 1.7.0 + '@opentelemetry/semantic-conventions': 1.18.1 + debug: 4.3.4 + graphql: 16.8.1 + jose: 4.14.4 + next: 14.2.10(@babel/core@7.23.6)(react-dom@18.2.0)(react@18.2.0) + raw-body: 2.5.2 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + retes: 0.33.0 + uuid: 9.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /@saleor/eslint-plugin-saleor-app@0.1.2(eslint@8.55.0): + resolution: {integrity: sha512-xbnUztIM1cwHh3Z0bLolg62IsPDJ13ciYoR1Ha3Goqi/0KnyPY054y/4FCLNvApreKdwu674y0Eh92sIbDD7Zg==} + engines: {node: '>=16 <19', pnpm: '>=8'} + dependencies: + '@changesets/cli': 2.27.1 + '@typescript-eslint/utils': 5.62.0(eslint@8.55.0)(typescript@5.3.3) + tsutils: 3.21.0(typescript@5.3.3) + typescript: 5.3.3 + transitivePeerDependencies: + - eslint + - supports-color + dev: true + + /@saleor/json-schema-compiler@0.1.2: + resolution: {integrity: sha512-NcbcF+rWq15x1wwRjz2VB23UHqO2mq8vbPumhM5jLKHYvBFdc1phhmD+MEC4ABsq9Gq2ZQxlFQzrFXOs29P7ew==} + hasBin: true + dependencies: + '@commander-js/extra-typings': 11.0.0(commander@11.0.0) + ajv: 8.12.0 + ajv-formats: 2.1.1(ajv@8.12.0) + commander: 11.0.0 + figlet: 1.6.0 + json-schema-to-typescript: 13.0.2 + dev: true + + /@saleor/macaw-ui@0.8.0-pre.123(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-8QsTPKizs4XjbHo6T2xn7LR9Y0lQBndSgJ0msVe19XSrkdkKdOarNGEIfoxsVMOKxss3cD7SYmeRMRNGOtNfSA==} + engines: {node: 16 || 18 || 20, pnpm: '>=8'} + peerDependencies: + '@types/react': ^16.9.0 || ^17.0.0 || ^18.0.0 + '@types/react-dom': ^16.9.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + '@dessert-box/react': 0.4.0(react@18.2.0) + '@floating-ui/react-dom-interactions': 0.5.0(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-accordion': 1.1.2(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-checkbox': 1.0.4(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-dialog': 1.0.5(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-dropdown-menu': 2.0.6(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-popover': 1.0.7(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-radio-group': 1.1.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-select': 1.2.2(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-toggle': 1.0.3(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-tooltip': 1.0.7(@types/react-dom@18.2.17)(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.45 + '@types/react-dom': 18.2.17 + '@vanilla-extract/css-utils': 0.1.3 + clsx: 1.2.1 + downshift: 6.1.12(react@18.2.0) + downshift7: /downshift@7.6.0(react@18.2.0) + lodash-es: 4.17.21 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-inlinesvg: 3.0.3(react@18.2.0) + dev: false + + /@sentry-internal/feedback@7.86.0: + resolution: {integrity: sha512-6rl0JYjmAKnhm4/fuFaROh4Ht8oi9f6ZeIcViCuGJcrGICZJJY0s+R77XJI78rNa82PYFrSCcnWXcGji4T8E7g==} + engines: {node: '>=12'} + dependencies: + '@sentry/core': 7.86.0 + '@sentry/types': 7.86.0 + '@sentry/utils': 7.86.0 + dev: false + + /@sentry-internal/tracing@7.86.0: + resolution: {integrity: sha512-b4dUsNWlPWRwakGwR7bhOkqiFlqQszH1hhVFwrm/8s3kqEBZ+E4CeIfCvuHBHQ1cM/fx55xpXX/BU163cy+3iQ==} + engines: {node: '>=8'} + dependencies: + '@sentry/core': 7.86.0 + '@sentry/types': 7.86.0 + '@sentry/utils': 7.86.0 + dev: false + + /@sentry/browser@7.86.0: + resolution: {integrity: sha512-nfYWpVOmug+W7KJO7/xhA1JScMZcYHcoOVHLsUFm4znx51U4qZEk+zZDM11Q2Nw6MuDyEYg6bsH1QCwaoC6nLw==} + engines: {node: '>=8'} + dependencies: + '@sentry-internal/feedback': 7.86.0 + '@sentry-internal/tracing': 7.86.0 + '@sentry/core': 7.86.0 + '@sentry/replay': 7.86.0 + '@sentry/types': 7.86.0 + '@sentry/utils': 7.86.0 + dev: false + + /@sentry/cli@1.77.1: + resolution: {integrity: sha512-OtJ7U9LeuPUAY/xow9wwcjM9w42IJIpDtClTKI/RliE685vd/OJUIpiAvebHNthDYpQynvwb/0iuF4fonh+CKw==} + engines: {node: '>= 8'} + hasBin: true + requiresBuild: true + dependencies: + https-proxy-agent: 5.0.1 + mkdirp: 0.5.6 + node-fetch: 2.7.0 + progress: 2.0.3 + proxy-from-env: 1.1.0 + which: 2.0.2 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + + /@sentry/core@7.86.0: + resolution: {integrity: sha512-SbLvqd1bRYzhDS42u7GMnmbDMfth/zRiLElQWbLK/shmuZzTcfQSwNNdF4Yj+VfjOkqPFgGmICHSHVUc9dh01g==} + engines: {node: '>=8'} + dependencies: + '@sentry/types': 7.86.0 + '@sentry/utils': 7.86.0 + dev: false + + /@sentry/integrations@7.86.0: + resolution: {integrity: sha512-BStRH1yBhhUsvmCXWx88/1+cY93l4B+3RW60RPeYcupvUQ1DJ8qxfN918+nA9XoZt9XELXvs8USCqqynG/aEkg==} + engines: {node: '>=8'} + dependencies: + '@sentry/core': 7.86.0 + '@sentry/types': 7.86.0 + '@sentry/utils': 7.86.0 + localforage: 1.10.0 + dev: false + + /@sentry/nextjs@7.86.0(next@14.2.10)(react@18.2.0)(webpack@5.94.0): + resolution: {integrity: sha512-pdRTt3ELLlpyKKtvumSiqFeTImdSAnoII1JSNwJvmWz9+3MRsvBW/Ee4r19WxK07Y/nxPxyPaIuUmbsXnjkt1A==} + engines: {node: '>=8'} + peerDependencies: + next: ^10.0.8 || ^11.0 || ^12.0 || ^13.0 || ^14.0 + react: 16.x || 17.x || 18.x + webpack: '>= 4.0.0' + peerDependenciesMeta: + webpack: + optional: true + dependencies: + '@rollup/plugin-commonjs': 24.0.0(rollup@2.78.0) + '@sentry/core': 7.86.0 + '@sentry/integrations': 7.86.0 + '@sentry/node': 7.86.0 + '@sentry/react': 7.86.0(react@18.2.0) + '@sentry/types': 7.86.0 + '@sentry/utils': 7.86.0 + '@sentry/vercel-edge': 7.86.0 + '@sentry/webpack-plugin': 1.21.0 + chalk: 3.0.0 + next: 14.2.10(@babel/core@7.23.6)(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + resolve: 1.22.8 + rollup: 2.78.0 + stacktrace-parser: 0.1.10 + webpack: 5.94.0 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + + /@sentry/node@7.86.0: + resolution: {integrity: sha512-cB1bn/LMn2Km97Y3hv63xwWxT50/G5ixGuSxTZ3dCQM6VDhmZoCuC5NGT3itVvaRd6upQXRZa5W0Zgyh0HXKig==} + engines: {node: '>=8'} + dependencies: + '@sentry-internal/tracing': 7.86.0 + '@sentry/core': 7.86.0 + '@sentry/types': 7.86.0 + '@sentry/utils': 7.86.0 + https-proxy-agent: 5.0.1 + transitivePeerDependencies: + - supports-color + dev: false + + /@sentry/react@7.86.0(react@18.2.0): + resolution: {integrity: sha512-2bHi+YcG4cT+4xHXXzv+AZpU3pdPUlDBorSgHOpa9At4yxr17UWW2f8bP9wPYRgj+NEIM3YhDgR46FlBu9GSKg==} + engines: {node: '>=8'} + peerDependencies: + react: 15.x || 16.x || 17.x || 18.x + dependencies: + '@sentry/browser': 7.86.0 + '@sentry/types': 7.86.0 + '@sentry/utils': 7.86.0 + hoist-non-react-statics: 3.3.2 + react: 18.2.0 + dev: false + + /@sentry/replay@7.86.0: + resolution: {integrity: sha512-YYZO8bfQSx1H87Te/zzyHPLHvExWiYwUfMWW68yGX+PPZIIzxaM81/iCQHkoucxlvuPCOtxCgf7RSMbsnqEa8g==} + engines: {node: '>=12'} + dependencies: + '@sentry-internal/tracing': 7.86.0 + '@sentry/core': 7.86.0 + '@sentry/types': 7.86.0 + '@sentry/utils': 7.86.0 + dev: false + + /@sentry/types@7.86.0: + resolution: {integrity: sha512-pGAt0+bMfWgo0KG2epthfNV4Wae03tURpoxNjGo5Fr4cXxvLTSijSAQ6rmmO4bXBJ7+rErEjX30g30o/eEdP9g==} + engines: {node: '>=8'} + dev: false + + /@sentry/utils@7.86.0: + resolution: {integrity: sha512-6PejFtw9VTFFy5vu0ks+U7Ozkqz+eMt+HN8AZKBKErYzX5/xs0kpkOcSRpu3ETdTYcZf8VAmLVgFgE2BE+3WuQ==} + engines: {node: '>=8'} + dependencies: + '@sentry/types': 7.86.0 + dev: false + + /@sentry/vercel-edge@7.86.0: + resolution: {integrity: sha512-+MPb93DXIeYIoaFTT1YpC0myIkXW3xtxhQ7y7QwqS7k6x1zBb34OVCGitdE6+o85RV83sFMMiBxrfKNLt5Ht0A==} + engines: {node: '>=8'} + dependencies: + '@sentry-internal/tracing': 7.86.0 + '@sentry/core': 7.86.0 + '@sentry/types': 7.86.0 + '@sentry/utils': 7.86.0 + dev: false + + /@sentry/webpack-plugin@1.21.0: + resolution: {integrity: sha512-x0PYIMWcsTauqxgl7vWUY6sANl+XGKtx7DCVnnY7aOIIlIna0jChTAPANTfA2QrK+VK+4I/4JxatCEZBnXh3Og==} + engines: {node: '>= 8'} + dependencies: + '@sentry/cli': 1.77.1 + webpack-sources: 3.2.3 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + + /@sinclair/typebox@0.27.8: + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + dev: true + + /@sindresorhus/fnv1a@2.0.1: + resolution: {integrity: sha512-suq9tRQ6bkpMukTG5K5z0sPWB7t0zExMzZCdmYm6xTSSIm/yCKNm7VCL36wVeyTsFr597/UhU1OAYdHGMDiHrw==} + engines: {node: '>=10'} + dev: true + + /@swc/counter@0.1.3: + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + + /@swc/helpers@0.5.5: + resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==} + dependencies: + '@swc/counter': 0.1.3 + tslib: 2.6.2 + + /@t3-oss/env-core@0.7.1(typescript@5.3.3)(zod@3.22.4): + resolution: {integrity: sha512-3+SQt39OlmSaRLqYVFv8uRm1BpFepM5TIiMytRqO9cjH+wB77o6BIJdeyM5h5U4qLBMEzOJWCY4MBaU/rLwbYw==} + peerDependencies: + typescript: '>=4.7.2' + zod: ^3.0.0 + peerDependenciesMeta: + typescript: + optional: true + dependencies: + typescript: 5.3.3 + zod: 3.22.4 + dev: false + + /@t3-oss/env-nextjs@0.7.1(typescript@5.3.3)(zod@3.22.4): + resolution: {integrity: sha512-tQDbNLGCOvKGi+JoGuJ/CJInJI7/kLWJqtgGppAKS7ZFLdVOqZYR/uRjxlXOWPnxmUKF8VswOAsq7fXUpNZDhA==} + peerDependencies: + typescript: '>=4.7.2' + zod: ^3.0.0 + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@t3-oss/env-core': 0.7.1(typescript@5.3.3)(zod@3.22.4) + typescript: 5.3.3 + zod: 3.22.4 + dev: false + + /@tanstack/match-sorter-utils@8.8.4: + resolution: {integrity: sha512-rKH8LjZiszWEvmi01NR72QWZ8m4xmXre0OOwlRGnjU01Eqz/QnN+cqpty2PJ0efHblq09+KilvyR7lsbzmXVEw==} + engines: {node: '>=12'} + dependencies: + remove-accents: 0.4.2 + dev: false + + /@tanstack/query-core@4.36.1: + resolution: {integrity: sha512-DJSilV5+ytBP1FbFcEJovv4rnnm/CokuVvrBEtW/Va9DvuJ3HksbXUJEpI0aV1KtuL4ZoO9AVE6PyNLzF7tLeA==} + dev: false + + /@tanstack/react-query-devtools@4.36.1(@tanstack/react-query@4.36.1)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-WYku83CKP3OevnYSG8Y/QO9g0rT75v1om5IvcWUwiUZJ4LanYGLVCZ8TdFG5jfsq4Ej/lu2wwDAULEUnRIMBSw==} + peerDependencies: + '@tanstack/react-query': ^4.36.1 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + '@tanstack/match-sorter-utils': 8.8.4 + '@tanstack/react-query': 4.36.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + superjson: 1.13.3 + use-sync-external-store: 1.2.0(react@18.2.0) + dev: false + + /@tanstack/react-query@4.36.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-y7ySVHFyyQblPl3J3eQBWpXZkliroki3ARnBKsdJchlgt7yJLRDUcf4B8soufgiYt3pEQIkBWBx1N9/ZPIeUWw==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-native: '*' + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + dependencies: + '@tanstack/query-core': 4.36.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + use-sync-external-store: 1.2.0(react@18.2.0) + dev: false + + /@testing-library/dom@9.3.3: + resolution: {integrity: sha512-fB0R+fa3AUqbLHWyxXa2kGVtf1Fe1ZZFr0Zp6AIbIAzXb2mKbEXl+PCQNUOaq5lbTab5tfctfXRNsWXxa2f7Aw==} + engines: {node: '>=14'} + dependencies: + '@babel/code-frame': 7.23.5 + '@babel/runtime': 7.23.6 + '@types/aria-query': 5.0.4 + aria-query: 5.1.3 + chalk: 4.1.2 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + pretty-format: 27.5.1 + dev: true + + /@testing-library/jest-dom@6.1.5(vitest@0.34.2): + resolution: {integrity: sha512-3y04JLW+EceVPy2Em3VwNr95dOKqA8DhR0RJHhHKDZNYXcVXnEK7WIrpj4eYU8SVt/qYZ2aRWt/WgQ+grNES8g==} + engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + peerDependencies: + '@jest/globals': '>= 28' + '@types/jest': '>= 28' + jest: '>= 28' + vitest: '>= 0.32' + peerDependenciesMeta: + '@jest/globals': + optional: true + '@types/jest': + optional: true + jest: + optional: true + vitest: + optional: true + dependencies: + '@adobe/css-tools': 4.3.2 + '@babel/runtime': 7.23.6 + aria-query: 5.3.0 + chalk: 3.0.0 + css.escape: 1.5.1 + dom-accessibility-api: 0.5.16 + lodash: 4.17.21 + redent: 3.0.0 + vitest: 0.34.2(jsdom@23.0.1) + dev: true + + /@testing-library/react-hooks@8.0.1(@types/react@18.2.45)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-Aqhl2IVmLt8IovEVarNDFuJDVWVvhnr9/GCU6UUnrYXwgDFF9h2L2o2P9KBni1AST5sT6riAyoukFLyjQUgD/g==} + engines: {node: '>=12'} + peerDependencies: + '@types/react': ^16.9.0 || ^17.0.0 + react: ^16.9.0 || ^17.0.0 + react-dom: ^16.9.0 || ^17.0.0 + react-test-renderer: ^16.9.0 || ^17.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + react-dom: + optional: true + react-test-renderer: + optional: true + dependencies: + '@babel/runtime': 7.23.6 + '@types/react': 18.2.45 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-error-boundary: 3.1.4(react@18.2.0) + dev: true + + /@testing-library/react@14.1.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-z4p7DVBTPjKM5qDZ0t5ZjzkpSNb+fZy1u6bzO7kk8oeGagpPCAtgh4cx1syrfp7a+QWkM021jGqjJaxJJnXAZg==} + engines: {node: '>=14'} + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + dependencies: + '@babel/runtime': 7.23.6 + '@testing-library/dom': 9.3.3 + '@types/react-dom': 18.2.17 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: true + + /@trpc/client@10.44.1(@trpc/server@10.44.1): + resolution: {integrity: sha512-vTWsykNcgz1LnwePVl2fKZnhvzP9N3GaaLYPkfGINo314ZOS0OBqe9x0ytB2LLUnRVTAAZ2WoONzARd8nHiqrA==} + peerDependencies: + '@trpc/server': 10.44.1 + dependencies: + '@trpc/server': 10.44.1 + dev: false + + /@trpc/next@10.44.1(@tanstack/react-query@4.36.1)(@trpc/client@10.44.1)(@trpc/react-query@10.44.1)(@trpc/server@10.44.1)(next@14.2.10)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-ez2oYUzmaQ+pGch627sRBfeEk3h+UIwNicR8WjTAM54TPcdP5W9ZyWCyO5HZTEfjHgGixYM4tCIxewdKOWY9yA==} + peerDependencies: + '@tanstack/react-query': ^4.18.0 + '@trpc/client': 10.44.1 + '@trpc/react-query': 10.44.1 + '@trpc/server': 10.44.1 + next: '*' + react: '>=16.8.0' + react-dom: '>=16.8.0' + dependencies: + '@tanstack/react-query': 4.36.1(react-dom@18.2.0)(react@18.2.0) + '@trpc/client': 10.44.1(@trpc/server@10.44.1) + '@trpc/react-query': 10.44.1(@tanstack/react-query@4.36.1)(@trpc/client@10.44.1)(@trpc/server@10.44.1)(react-dom@18.2.0)(react@18.2.0) + '@trpc/server': 10.44.1 + next: 14.2.10(@babel/core@7.23.6)(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-ssr-prepass: 1.5.0(react@18.2.0) + dev: false + + /@trpc/react-query@10.44.1(@tanstack/react-query@4.36.1)(@trpc/client@10.44.1)(@trpc/server@10.44.1)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-Sgi/v0YtdunOXjBRi7om9gILGkOCFYXPzn5KqLuEHiZw5dr5w4qGHFwCeMAvndZxmwfblJrl1tk2AznmsVu8MA==} + peerDependencies: + '@tanstack/react-query': ^4.18.0 + '@trpc/client': 10.44.1 + '@trpc/server': 10.44.1 + react: '>=16.8.0' + react-dom: '>=16.8.0' + dependencies: + '@tanstack/react-query': 4.36.1(react-dom@18.2.0)(react@18.2.0) + '@trpc/client': 10.44.1(@trpc/server@10.44.1) + '@trpc/server': 10.44.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@trpc/server@10.44.1: + resolution: {integrity: sha512-mF7B+K6LjuboX8I1RZgKE5GA/fJhsJ8tKGK2UBt3Bwik7hepEPb4NJgNr7vO6BK5IYwPdBLRLTctRw6XZx0sRg==} + engines: {node: '>=18.0.0'} + dev: false + + /@tsconfig/node10@1.0.9: + resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} + dev: true + + /@tsconfig/node12@1.0.11: + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + dev: true + + /@tsconfig/node14@1.0.3: + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + dev: true + + /@tsconfig/node16@1.0.4: + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + dev: true + + /@types/aria-query@5.0.4: + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + dev: true + + /@types/babel__core@7.20.5: + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + dependencies: + '@babel/parser': 7.23.6 + '@babel/types': 7.23.6 + '@types/babel__generator': 7.6.7 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.4 + dev: false + + /@types/babel__generator@7.6.7: + resolution: {integrity: sha512-6Sfsq+EaaLrw4RmdFWE9Onp63TOUue71AWb4Gpa6JxzgTYtimbM086WnYTy2U67AofR++QKCo08ZP6pwx8YFHQ==} + dependencies: + '@babel/types': 7.23.6 + dev: false + + /@types/babel__template@7.4.4: + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + dependencies: + '@babel/parser': 7.23.6 + '@babel/types': 7.23.6 + dev: false + + /@types/babel__traverse@7.20.4: + resolution: {integrity: sha512-mSM/iKUk5fDDrEV/e83qY+Cr3I1+Q3qqTuEn++HAWYjEa1+NxZr6CNrcJGf2ZTnq4HoFGC3zaTPZTobCzCFukA==} + dependencies: + '@babel/types': 7.23.6 + dev: false + + /@types/bluebird@3.5.42: + resolution: {integrity: sha512-Jhy+MWRlro6UjVi578V/4ZGNfeCOcNCp0YaFNIUGFKlImowqwb1O/22wDVk3FDGMLqxdpOV3qQHD5fPEH4hK6A==} + dev: true + + /@types/chai-subset@1.3.5: + resolution: {integrity: sha512-c2mPnw+xHtXDoHmdtcCXGwyLMiauiAyxWMzhGpqHC4nqI/Y5G2XhTampslK2rb59kpcuHon03UH8W6iYUzw88A==} + dependencies: + '@types/chai': 4.3.11 + dev: true + + /@types/chai@4.3.11: + resolution: {integrity: sha512-qQR1dr2rGIHYlJulmr8Ioq3De0Le9E4MJ5AiaeAETJJpndT1uUNHsGFK3L/UIu+rbkQSdj8J/w2bCsBZc/Y5fQ==} + dev: true + + /@types/estree@1.0.5: + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + dev: false + + /@types/glob@7.2.0: + resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} + dependencies: + '@types/minimatch': 5.1.2 + '@types/node': 20.10.4 + dev: true + + /@types/istanbul-lib-coverage@2.0.6: + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + dev: true + + /@types/js-yaml@4.0.9: + resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==} + dev: true + + /@types/json-schema@7.0.15: + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + /@types/json-stable-stringify@1.0.36: + resolution: {integrity: sha512-b7bq23s4fgBB76n34m2b3RBf6M369B0Z9uRR8aHTMd8kZISRkmDEpPD8hhpYvDFzr3bJCPES96cm3Q6qRNDbQw==} + dev: true + + /@types/json5@0.0.29: + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + dev: true + + /@types/lodash-es@4.17.12: + resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} + dependencies: + '@types/lodash': 4.14.202 + dev: true + + /@types/lodash@4.14.202: + resolution: {integrity: sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==} + dev: true + + /@types/minimatch@5.1.2: + resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} + dev: true + + /@types/minimist@1.2.5: + resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} + dev: true + + /@types/node@12.20.55: + resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} + dev: true + + /@types/node@20.10.4: + resolution: {integrity: sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==} + dependencies: + undici-types: 5.26.5 + + /@types/normalize-package-data@2.4.4: + resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + dev: true + + /@types/omit-deep-lodash@1.1.3: + resolution: {integrity: sha512-nhnPtCg8zChkEhdkcY2bznImoPZGZ2XQUTM715XJImuoHdHSsucsbyJjd4UVERzsnNW4bUffMcAeqsQmXAic+w==} + dev: true + + /@types/prettier@2.7.3: + resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==} + dev: true + + /@types/prop-types@15.7.11: + resolution: {integrity: sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==} + + /@types/react-dom@18.2.17: + resolution: {integrity: sha512-rvrT/M7Df5eykWFxn6MYt5Pem/Dbyc1N8Y0S9Mrkw2WFCRiqUgw9P7ul2NpwsXCSM1DVdENzdG9J5SreqfAIWg==} + dependencies: + '@types/react': 18.2.45 + + /@types/react@18.2.45: + resolution: {integrity: sha512-TtAxCNrlrBp8GoeEp1npd5g+d/OejJHFxS3OWmrPBMFaVQMSN0OFySozJio5BHxTuTeug00AVXVAjfDSfk+lUg==} + dependencies: + '@types/prop-types': 15.7.11 + '@types/scheduler': 0.16.8 + csstype: 3.1.3 + + /@types/scheduler@0.16.8: + resolution: {integrity: sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==} + + /@types/semver@7.5.6: + resolution: {integrity: sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==} + dev: true + + /@types/set-cookie-parser@2.4.7: + resolution: {integrity: sha512-+ge/loa0oTozxip6zmhRIk8Z/boU51wl9Q6QdLZcokIGMzY5lFXYy/x7Htj2HTC6/KZP1hUbZ1ekx8DYXICvWg==} + dependencies: + '@types/node': 20.10.4 + dev: true + + /@types/setup-polly-jest@0.5.5: + resolution: {integrity: sha512-kbuM19M8EAkbgzCG3kuXo+IoxrQcgIPHm54WmxcqlHgOy9A7esTFfrUwu/WiOsUcoUiZSzm3F3aQJuihR09wAA==} + dependencies: + '@pollyjs/adapter': 6.0.6 + '@pollyjs/core': 6.0.6 + '@pollyjs/persister': 6.0.6 + dev: true + + /@types/ws@8.5.10: + resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} + dependencies: + '@types/node': 20.10.4 + dev: true + + /@typescript-eslint/eslint-plugin@6.14.0(@typescript-eslint/parser@6.14.0)(eslint@8.55.0)(typescript@5.3.3): + resolution: {integrity: sha512-1ZJBykBCXaSHG94vMMKmiHoL0MhNHKSVlcHVYZNw+BKxufhqQVTOawNpwwI1P5nIFZ/4jLVop0mcY6mJJDFNaw==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + '@typescript-eslint/parser': 6.14.0 + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@eslint-community/regexpp': 4.10.0 + '@typescript-eslint/parser': 6.14.0(eslint@8.55.0)(typescript@5.3.3) + '@typescript-eslint/scope-manager': 6.14.0 + '@typescript-eslint/type-utils': 6.14.0(eslint@8.55.0)(typescript@5.3.3) + '@typescript-eslint/utils': 6.14.0(eslint@8.55.0)(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.14.0 + debug: 4.3.4 + eslint: 8.55.0 + graphemer: 1.4.0 + ignore: 5.3.0 + natural-compare: 1.4.0 + semver: 7.5.4 + ts-api-utils: 1.0.3(typescript@5.3.3) + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/parser@6.14.0(eslint@8.55.0)(typescript@5.3.3): + resolution: {integrity: sha512-QjToC14CKacd4Pa7JK4GeB/vHmWFJckec49FR4hmIRf97+KXole0T97xxu9IFiPxVQ1DBWrQ5wreLwAGwWAVQA==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 6.14.0 + '@typescript-eslint/types': 6.14.0 + '@typescript-eslint/typescript-estree': 6.14.0(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.14.0 + debug: 4.3.4 + eslint: 8.55.0 + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/scope-manager@5.62.0: + resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 + dev: true + + /@typescript-eslint/scope-manager@6.14.0: + resolution: {integrity: sha512-VT7CFWHbZipPncAZtuALr9y3EuzY1b1t1AEkIq2bTXUPKw+pHoXflGNG5L+Gv6nKul1cz1VH8fz16IThIU0tdg==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.14.0 + '@typescript-eslint/visitor-keys': 6.14.0 + dev: true + + /@typescript-eslint/type-utils@6.14.0(eslint@8.55.0)(typescript@5.3.3): + resolution: {integrity: sha512-x6OC9Q7HfYKqjnuNu5a7kffIYs3No30isapRBJl1iCHLitD8O0lFbRcVGiOcuyN837fqXzPZ1NS10maQzZMKqw==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 6.14.0(typescript@5.3.3) + '@typescript-eslint/utils': 6.14.0(eslint@8.55.0)(typescript@5.3.3) + debug: 4.3.4 + eslint: 8.55.0 + ts-api-utils: 1.0.3(typescript@5.3.3) + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/types@5.62.0: + resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@typescript-eslint/types@6.14.0: + resolution: {integrity: sha512-uty9H2K4Xs8E47z3SnXEPRNDfsis8JO27amp2GNCnzGETEW3yTqEIVg5+AI7U276oGF/tw6ZA+UesxeQ104ceA==} + engines: {node: ^16.0.0 || >=18.0.0} + dev: true + + /@typescript-eslint/typescript-estree@5.62.0(typescript@5.3.3): + resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.5.4 + tsutils: 3.21.0(typescript@5.3.3) + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/typescript-estree@6.14.0(typescript@5.3.3): + resolution: {integrity: sha512-yPkaLwK0yH2mZKFE/bXkPAkkFgOv15GJAUzgUVonAbv0Hr4PK/N2yaA/4XQbTZQdygiDkpt5DkxPELqHguNvyw==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 6.14.0 + '@typescript-eslint/visitor-keys': 6.14.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.5.4 + ts-api-utils: 1.0.3(typescript@5.3.3) + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils@5.62.0(eslint@8.55.0)(typescript@5.3.3): + resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.55.0) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.6 + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.3.3) + eslint: 8.55.0 + eslint-scope: 5.1.1 + semver: 7.5.4 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/utils@6.14.0(eslint@8.55.0)(typescript@5.3.3): + resolution: {integrity: sha512-XwRTnbvRr7Ey9a1NT6jqdKX8y/atWG+8fAIu3z73HSP8h06i3r/ClMhmaF/RGWGW1tHJEwij1uEg2GbEmPYvYg==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.55.0) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.6 + '@typescript-eslint/scope-manager': 6.14.0 + '@typescript-eslint/types': 6.14.0 + '@typescript-eslint/typescript-estree': 6.14.0(typescript@5.3.3) + eslint: 8.55.0 + semver: 7.5.4 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/visitor-keys@5.62.0: + resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.62.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@typescript-eslint/visitor-keys@6.14.0: + resolution: {integrity: sha512-fB5cw6GRhJUz03MrROVuj5Zm/Q+XWlVdIsFj+Zb1Hvqouc8t+XP2H5y53QYU/MGtd2dPg6/vJJlhoX3xc2ehfw==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.14.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@ungap/structured-clone@1.2.0: + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + + /@urql/core@3.2.2(graphql@16.8.1): + resolution: {integrity: sha512-i046Cz8cZ4xIzGMTyHZrbdgzcFMcKD7+yhCAH5FwWBRjcKrc+RjEOuR9X5AMuBvr8c6IAaE92xAqa4wmlGfWTQ==} + peerDependencies: + graphql: ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + graphql: 16.8.1 + wonka: 6.3.4 + dev: false + + /@urql/exchange-auth@1.0.0(graphql@16.8.1): + resolution: {integrity: sha512-79hqPQab+ifeINOxvQykvqub4ixWHBEIagN4U67ijcHGMfp3c4yEWRk4IJMPwF+OMT7LrRFuv+jRIZTQn/9VwQ==} + peerDependencies: + graphql: ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@urql/core': 3.2.2(graphql@16.8.1) + graphql: 16.8.1 + wonka: 6.3.4 + dev: false + + /@urql/introspection@0.3.3(graphql@16.8.1): + resolution: {integrity: sha512-tekSLLqWnusfV6V7xaEnLJQSdXOD/lWy7f8JYQwrX+88Md+voGSCSx5WJXI7KLBN3Tat2OV08tAr8UROykls4Q==} + peerDependencies: + graphql: ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + graphql: 16.8.1 + dev: true + + /@vanilla-extract/babel-plugin-debug-ids@1.0.3: + resolution: {integrity: sha512-vm4jYu1xhSa6ofQ9AhIpR3DkAp4c+eoR1Rpm8/TQI4DmWbmGbOjYRcqV0aWsfaIlNhN4kFuxFMKBNN9oG6iRzA==} + dependencies: + '@babel/core': 7.23.6 + transitivePeerDependencies: + - supports-color + + /@vanilla-extract/css-utils@0.1.3: + resolution: {integrity: sha512-PZAcHROlgtCUGI2y0JntdNwvPwCNyeVnkQu6KTYKdmxBbK3w72XJUmLFYapfaFfgami4I9CTLnrJTPdtmS3gpw==} + dev: false + + /@vanilla-extract/css@1.14.0: + resolution: {integrity: sha512-rYfm7JciWZ8PFzBM/HDiE2GLnKI3xJ6/vdmVJ5BSgcCZ5CxRlM9Cjqclni9lGzF3eMOijnUhCd/KV8TOzyzbMA==} + dependencies: + '@emotion/hash': 0.9.1 + '@vanilla-extract/private': 1.0.3 + chalk: 4.1.2 + css-what: 6.1.0 + cssesc: 3.0.0 + csstype: 3.1.3 + deep-object-diff: 1.1.9 + deepmerge: 4.3.1 + media-query-parser: 2.0.2 + modern-ahocorasick: 1.0.1 + outdent: 0.8.0 + + /@vanilla-extract/integration@6.2.4(@types/node@20.10.4): + resolution: {integrity: sha512-+AfymNMVq9sEUe0OJpdCokmPZg4Zi6CqKaW/PnUOfDwEn53ighHOMOBl5hAgxYR8Kiz9NG43Bn00mkjWlFi+ng==} + dependencies: + '@babel/core': 7.23.6 + '@babel/plugin-syntax-typescript': 7.23.3(@babel/core@7.23.6) + '@vanilla-extract/babel-plugin-debug-ids': 1.0.3 + '@vanilla-extract/css': 1.14.0 + esbuild: 0.17.6 + eval: 0.1.8 + find-up: 5.0.0 + javascript-stringify: 2.1.0 + lodash: 4.17.21 + mlly: 1.4.2 + outdent: 0.8.0 + vite: 5.0.8(@types/node@20.10.4) + vite-node: 0.28.5(@types/node@20.10.4) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + + /@vanilla-extract/next-plugin@2.3.2(@types/node@20.10.4)(next@14.2.10)(webpack@5.94.0): + resolution: {integrity: sha512-wBulJAhmr8guYo5YxrfsA1T/TQ3tbMJjNtE6QrVZvs1NTnT9/WAmf4IVrbUvQbH+LBj5LXO8dRzueGPAvepSng==} + peerDependencies: + next: '>=12.1.7' + dependencies: + '@vanilla-extract/webpack-plugin': 2.3.1(@types/node@20.10.4)(webpack@5.94.0) + next: 14.2.10(@babel/core@7.23.6)(react-dom@18.2.0)(react@18.2.0) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + - webpack + dev: false + + /@vanilla-extract/private@1.0.3: + resolution: {integrity: sha512-17kVyLq3ePTKOkveHxXuIJZtGYs+cSoev7BlP+Lf4916qfDhk/HBjvlYDe8egrea7LNPHKwSZJK/bzZC+Q6AwQ==} + + /@vanilla-extract/recipes@0.5.1(@vanilla-extract/css@1.14.0): + resolution: {integrity: sha512-7dCuBgPQQ/89siQ0w2lkfjgkmToPUUDzFlHf5DRmt9ykiiycfA52tmPJ2RI/mr7jXi7U/vEN2aGP9QJSXEpGlA==} + peerDependencies: + '@vanilla-extract/css': ^1.0.0 + dependencies: + '@vanilla-extract/css': 1.14.0 + dev: false + + /@vanilla-extract/vite-plugin@3.9.3(@types/node@20.10.4)(ts-node@10.9.2)(vite@5.0.8): + resolution: {integrity: sha512-bGyHG98OYTRs5roLRv7LDeyRnD72+vBLonk8cC9VG/xd6hsiHPPj5GyBwoKElT7DyDRfapxWLwLlhgYynrW2Fw==} + peerDependencies: + vite: 5.0.8 + dependencies: + '@vanilla-extract/integration': 6.2.4(@types/node@20.10.4) + outdent: 0.8.0 + postcss: 8.4.32 + postcss-load-config: 4.0.2(postcss@8.4.32)(ts-node@10.9.2) + vite: 5.0.8(@types/node@20.10.4) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + - ts-node + dev: true + + /@vanilla-extract/webpack-plugin@2.3.1(@types/node@20.10.4)(webpack@5.94.0): + resolution: {integrity: sha512-S767iP+S67Uh+BsTe+u60BMbtRqZAxzjK7gYd6a+1hcbMKznYxdQMeP2qs9wr+NhRqZFrNxewo3/ztMnN85TOg==} + peerDependencies: + webpack: ^4.30.0 || ^5.20.2 + dependencies: + '@vanilla-extract/integration': 6.2.4(@types/node@20.10.4) + chalk: 4.1.2 + debug: 4.3.4 + loader-utils: 2.0.4 + webpack: 5.94.0 + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + dev: false + + /@vitejs/plugin-react@4.2.1(vite@5.0.8): + resolution: {integrity: sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: 5.0.8 + dependencies: + '@babel/core': 7.23.6 + '@babel/plugin-transform-react-jsx-self': 7.23.3(@babel/core@7.23.6) + '@babel/plugin-transform-react-jsx-source': 7.23.3(@babel/core@7.23.6) + '@types/babel__core': 7.20.5 + react-refresh: 0.14.0 + vite: 5.0.8(@types/node@20.10.4) + transitivePeerDependencies: + - supports-color + dev: false + + /@vitest/coverage-v8@0.34.2(vitest@0.34.2): + resolution: {integrity: sha512-3VuDZPeGGd1zWtc0Tdj9cHSbFc8IQ0ffnWp9MlhItOkziN6HEf219meZ9cZheg/hJXrXb+Fi2bMu7GeCAfL4yA==} + peerDependencies: + vitest: '>=0.32.0 <1' + dependencies: + '@ampproject/remapping': 2.2.1 + '@bcoe/v8-coverage': 0.2.3 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.6 + magic-string: 0.30.5 + picocolors: 1.0.0 + std-env: 3.6.0 + test-exclude: 6.0.0 + v8-to-istanbul: 9.2.0 + vitest: 0.34.2(jsdom@23.0.1) + transitivePeerDependencies: + - supports-color + dev: true + + /@vitest/expect@0.34.2: + resolution: {integrity: sha512-EZm2dMNlLyIfDMha17QHSQcg2KjeAZaXd65fpPzXY5bvnfx10Lcaz3N55uEe8PhF+w4pw+hmrlHLLlRn9vkBJg==} + dependencies: + '@vitest/spy': 0.34.2 + '@vitest/utils': 0.34.2 + chai: 4.3.10 + dev: true + + /@vitest/runner@0.34.2: + resolution: {integrity: sha512-8ydGPACVX5tK3Dl0SUwxfdg02h+togDNeQX3iXVFYgzF5odxvaou7HnquALFZkyVuYskoaHUOqOyOLpOEj5XTA==} + dependencies: + '@vitest/utils': 0.34.2 + p-limit: 4.0.0 + pathe: 1.1.1 + dev: true + + /@vitest/snapshot@0.34.2: + resolution: {integrity: sha512-qhQ+xy3u4mwwLxltS4Pd4SR+XHv4EajiTPNY3jkIBLUApE6/ce72neJPSUQZ7bL3EBuKI+NhvzhGj3n5baRQUQ==} + dependencies: + magic-string: 0.30.5 + pathe: 1.1.1 + pretty-format: 29.7.0 + dev: true + + /@vitest/spy@0.34.2: + resolution: {integrity: sha512-yd4L9OhfH6l0Av7iK3sPb3MykhtcRN5c5K5vm1nTbuN7gYn+yvUVVsyvzpHrjqS7EWqn9WsPJb7+0c3iuY60tA==} + dependencies: + tinyspy: 2.2.0 + dev: true + + /@vitest/utils@0.34.2: + resolution: {integrity: sha512-Lzw+kAsTPubhoQDp1uVAOP6DhNia1GMDsI9jgB0yMn+/nDaPieYQ88lKqz/gGjSHL4zwOItvpehec9OY+rS73w==} + dependencies: + diff-sequences: 29.6.3 + loupe: 2.3.7 + pretty-format: 29.7.0 + dev: true + + /@webassemblyjs/ast@1.12.1: + resolution: {integrity: sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==} + dependencies: + '@webassemblyjs/helper-numbers': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + dev: false + + /@webassemblyjs/floating-point-hex-parser@1.11.6: + resolution: {integrity: sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==} + dev: false + + /@webassemblyjs/helper-api-error@1.11.6: + resolution: {integrity: sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==} + dev: false + + /@webassemblyjs/helper-buffer@1.12.1: + resolution: {integrity: sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==} + dev: false + + /@webassemblyjs/helper-numbers@1.11.6: + resolution: {integrity: sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==} + dependencies: + '@webassemblyjs/floating-point-hex-parser': 1.11.6 + '@webassemblyjs/helper-api-error': 1.11.6 + '@xtuc/long': 4.2.2 + dev: false + + /@webassemblyjs/helper-wasm-bytecode@1.11.6: + resolution: {integrity: sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==} + dev: false + + /@webassemblyjs/helper-wasm-section@1.12.1: + resolution: {integrity: sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==} + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/helper-buffer': 1.12.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/wasm-gen': 1.12.1 + dev: false + + /@webassemblyjs/ieee754@1.11.6: + resolution: {integrity: sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==} + dependencies: + '@xtuc/ieee754': 1.2.0 + dev: false + + /@webassemblyjs/leb128@1.11.6: + resolution: {integrity: sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==} + dependencies: + '@xtuc/long': 4.2.2 + dev: false + + /@webassemblyjs/utf8@1.11.6: + resolution: {integrity: sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==} + dev: false + + /@webassemblyjs/wasm-edit@1.12.1: + resolution: {integrity: sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==} + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/helper-buffer': 1.12.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/helper-wasm-section': 1.12.1 + '@webassemblyjs/wasm-gen': 1.12.1 + '@webassemblyjs/wasm-opt': 1.12.1 + '@webassemblyjs/wasm-parser': 1.12.1 + '@webassemblyjs/wast-printer': 1.12.1 + dev: false + + /@webassemblyjs/wasm-gen@1.12.1: + resolution: {integrity: sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==} + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/ieee754': 1.11.6 + '@webassemblyjs/leb128': 1.11.6 + '@webassemblyjs/utf8': 1.11.6 + dev: false + + /@webassemblyjs/wasm-opt@1.12.1: + resolution: {integrity: sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==} + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/helper-buffer': 1.12.1 + '@webassemblyjs/wasm-gen': 1.12.1 + '@webassemblyjs/wasm-parser': 1.12.1 + dev: false + + /@webassemblyjs/wasm-parser@1.12.1: + resolution: {integrity: sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==} + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/helper-api-error': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/ieee754': 1.11.6 + '@webassemblyjs/leb128': 1.11.6 + '@webassemblyjs/utf8': 1.11.6 + dev: false + + /@webassemblyjs/wast-printer@1.12.1: + resolution: {integrity: sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==} + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@xtuc/long': 4.2.2 + dev: false + + /@whatwg-node/events@0.0.3: + resolution: {integrity: sha512-IqnKIDWfXBJkvy/k6tzskWTc2NK3LcqHlb+KHGCrjOCH4jfQckRX0NAiIcC/vIqQkzLYw2r2CTSwAxcrtcD6lA==} + dev: true + + /@whatwg-node/events@0.1.1: + resolution: {integrity: sha512-AyQEn5hIPV7Ze+xFoXVU3QTHXVbWPrzaOkxtENMPMuNL6VVHrp4hHfDt9nrQpjO7BgvuM95dMtkycX5M/DZR3w==} + engines: {node: '>=16.0.0'} + dev: true + + /@whatwg-node/fetch@0.8.8: + resolution: {integrity: sha512-CdcjGC2vdKhc13KKxgsc6/616BQ7ooDIgPeTuAiE8qfCnS0mGzcfCOoZXypQSz73nxI+GWc7ZReIAVhxoE1KCg==} + dependencies: + '@peculiar/webcrypto': 1.4.3 + '@whatwg-node/node-fetch': 0.3.6 + busboy: 1.6.0 + urlpattern-polyfill: 8.0.2 + web-streams-polyfill: 3.2.1 + dev: true + + /@whatwg-node/fetch@0.9.14: + resolution: {integrity: sha512-wurZC82zzZwXRDSW0OS9l141DynaJQh7Yt0FD1xZ8niX7/Et/7RoiLiltbVU1fSF1RR9z6ndEaTUQBAmddTm1w==} + engines: {node: '>=16.0.0'} + dependencies: + '@whatwg-node/node-fetch': 0.5.2 + urlpattern-polyfill: 9.0.0 + dev: true + + /@whatwg-node/node-fetch@0.3.6: + resolution: {integrity: sha512-w9wKgDO4C95qnXZRwZTfCmLWqyRnooGjcIwG0wADWjw9/HN0p7dtvtgSvItZtUyNteEvgTrd8QojNEqV6DAGTA==} + dependencies: + '@whatwg-node/events': 0.0.3 + busboy: 1.6.0 + fast-querystring: 1.1.2 + fast-url-parser: 1.1.3 + tslib: 2.6.2 + dev: true + + /@whatwg-node/node-fetch@0.5.2: + resolution: {integrity: sha512-uVYCnmWoCiGbv5AtnSx5nZ1kQJ+U8f269/yHB62y7wXPdjYx6o4sBSefnfwUI8HNf4rf16VbvGR/AzuABhDD5g==} + engines: {node: '>=16.0.0'} + dependencies: + '@kamilkisiela/fast-url-parser': 1.1.4 + '@whatwg-node/events': 0.1.1 + busboy: 1.6.0 + fast-querystring: 1.1.2 + tslib: 2.6.2 + dev: true + + /@xtuc/ieee754@1.2.0: + resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} + dev: false + + /@xtuc/long@4.2.2: + resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} + dev: false + + /abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + dependencies: + event-target-shim: 5.0.1 + dev: false + + /accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + dev: true + + /acorn-import-attributes@1.9.5(acorn@8.11.2): + resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} + peerDependencies: + acorn: ^8 + dependencies: + acorn: 8.11.2 + dev: false + + /acorn-jsx-walk@2.0.0: + resolution: {integrity: sha512-uuo6iJj4D4ygkdzd6jPtcxs8vZgDX9YFIkqczGImoypX2fQ4dVImmu3UzA4ynixCIMTrEOWW+95M2HuBaCEOVA==} + dev: true + + /acorn-jsx@5.3.2(acorn@8.11.2): + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.11.2 + + /acorn-loose@8.4.0: + resolution: {integrity: sha512-M0EUka6rb+QC4l9Z3T0nJEzNOO7JcoJlYMrBlyBCiFSXRyxjLKayd4TbQs2FDRWQU1h9FR7QVNHt+PEaoNL5rQ==} + engines: {node: '>=0.4.0'} + dependencies: + acorn: 8.11.2 + dev: true + + /acorn-walk@8.3.0: + resolution: {integrity: sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==} + engines: {node: '>=0.4.0'} + dev: true + + /acorn-walk@8.3.1: + resolution: {integrity: sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==} + engines: {node: '>=0.4.0'} + dev: true + + /acorn@8.11.2: + resolution: {integrity: sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==} + engines: {node: '>=0.4.0'} + hasBin: true + + /agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + + /agent-base@7.1.0: + resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==} + engines: {node: '>= 14'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + + /aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 + dev: true + + /ajv-formats@2.1.1(ajv@8.12.0): + resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + dependencies: + ajv: 8.12.0 + + /ajv-keywords@3.5.2(ajv@6.12.6): + resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} + peerDependencies: + ajv: ^6.9.1 + dependencies: + ajv: 6.12.6 + dev: false + + /ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + /ajv@8.12.0: + resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + + /ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + dev: true + + /ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.21.3 + dev: true + + /ansi-escapes@6.2.0: + resolution: {integrity: sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==} + engines: {node: '>=14.16'} + dependencies: + type-fest: 3.13.1 + dev: true + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + /ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + dev: true + + /ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + + /ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + dev: true + + /ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + dev: true + + /any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + dev: true + + /arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + dev: true + + /argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: true + + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + /aria-hidden@1.2.3: + resolution: {integrity: sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ==} + engines: {node: '>=10'} + dependencies: + tslib: 2.6.2 + dev: false + + /aria-query@5.1.3: + resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==} + dependencies: + deep-equal: 2.2.3 + dev: true + + /aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + dependencies: + dequal: 2.0.3 + dev: true + + /array-buffer-byte-length@1.0.0: + resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} + dependencies: + call-bind: 1.0.5 + is-array-buffer: 3.0.2 + dev: true + + /array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + dev: true + + /array-includes@3.1.7: + resolution: {integrity: sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 + is-string: 1.0.7 + dev: true + + /array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true + + /array.prototype.findlastindex@1.2.3: + resolution: {integrity: sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + es-shim-unscopables: 1.0.2 + get-intrinsic: 1.2.2 + dev: true + + /array.prototype.flat@1.3.2: + resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + es-shim-unscopables: 1.0.2 + dev: true + + /array.prototype.flatmap@1.3.2: + resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + es-shim-unscopables: 1.0.2 + dev: true + + /array.prototype.tosorted@1.1.2: + resolution: {integrity: sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + es-shim-unscopables: 1.0.2 + get-intrinsic: 1.2.2 + dev: true + + /arraybuffer.prototype.slice@1.0.2: + resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 + is-array-buffer: 3.0.2 + is-shared-array-buffer: 1.0.2 + dev: true + + /arrify@1.0.1: + resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} + engines: {node: '>=0.10.0'} + dev: true + + /asap@2.0.6: + resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + dev: true + + /asn1js@3.0.5: + resolution: {integrity: sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==} + engines: {node: '>=12.0.0'} + dependencies: + pvtsutils: 1.3.5 + pvutils: 1.1.3 + tslib: 2.6.2 + dev: true + + /assertion-error@1.1.0: + resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + dev: true + + /ast-types-flow@0.0.8: + resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} + dev: true + + /astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + dev: true + + /asynciterator.prototype@1.0.0: + resolution: {integrity: sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==} + dependencies: + has-symbols: 1.0.3 + dev: true + + /asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + /atomic-sleep@1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} + dev: false + + /auto-bind@4.0.0: + resolution: {integrity: sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ==} + engines: {node: '>=8'} + dev: true + + /available-typed-arrays@1.0.5: + resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} + engines: {node: '>= 0.4'} + dev: true + + /axe-core@4.7.0: + resolution: {integrity: sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==} + engines: {node: '>=4'} + dev: true + + /axobject-query@3.2.1: + resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==} + dependencies: + dequal: 2.0.3 + dev: true + + /babel-plugin-syntax-trailing-function-commas@7.0.0-beta.0: + resolution: {integrity: sha512-Xj9XuRuz3nTSbaTXWv3itLOcxyF4oPD8douBBmj7U9BBC6nEBYfyOJYQMf/8PJAFotC62UY5dFfIGEPr7WswzQ==} + dev: true + + /babel-preset-fbjs@3.4.0(@babel/core@7.23.6): + resolution: {integrity: sha512-9ywCsCvo1ojrw0b+XYk7aFvTH6D9064t0RIL1rtMf3nsa02Xw41MS7sZw216Im35xj/UY0PDBQsa1brUDDF1Ow==} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.6 + '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.23.6) + '@babel/plugin-proposal-object-rest-spread': 7.20.7(@babel/core@7.23.6) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.23.6) + '@babel/plugin-syntax-flow': 7.23.3(@babel/core@7.23.6) + '@babel/plugin-syntax-jsx': 7.23.3(@babel/core@7.23.6) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.23.6) + '@babel/plugin-transform-arrow-functions': 7.23.3(@babel/core@7.23.6) + '@babel/plugin-transform-block-scoped-functions': 7.23.3(@babel/core@7.23.6) + '@babel/plugin-transform-block-scoping': 7.23.4(@babel/core@7.23.6) + '@babel/plugin-transform-classes': 7.23.5(@babel/core@7.23.6) + '@babel/plugin-transform-computed-properties': 7.23.3(@babel/core@7.23.6) + '@babel/plugin-transform-destructuring': 7.23.3(@babel/core@7.23.6) + '@babel/plugin-transform-flow-strip-types': 7.23.3(@babel/core@7.23.6) + '@babel/plugin-transform-for-of': 7.23.6(@babel/core@7.23.6) + '@babel/plugin-transform-function-name': 7.23.3(@babel/core@7.23.6) + '@babel/plugin-transform-literals': 7.23.3(@babel/core@7.23.6) + '@babel/plugin-transform-member-expression-literals': 7.23.3(@babel/core@7.23.6) + '@babel/plugin-transform-modules-commonjs': 7.23.3(@babel/core@7.23.6) + '@babel/plugin-transform-object-super': 7.23.3(@babel/core@7.23.6) + '@babel/plugin-transform-parameters': 7.23.3(@babel/core@7.23.6) + '@babel/plugin-transform-property-literals': 7.23.3(@babel/core@7.23.6) + '@babel/plugin-transform-react-display-name': 7.23.3(@babel/core@7.23.6) + '@babel/plugin-transform-react-jsx': 7.23.4(@babel/core@7.23.6) + '@babel/plugin-transform-shorthand-properties': 7.23.3(@babel/core@7.23.6) + '@babel/plugin-transform-spread': 7.23.3(@babel/core@7.23.6) + '@babel/plugin-transform-template-literals': 7.23.3(@babel/core@7.23.6) + babel-plugin-syntax-trailing-function-commas: 7.0.0-beta.0 + dev: true + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + /base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + /basic-auth@2.0.1: + resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==} + engines: {node: '>= 0.8'} + dependencies: + safe-buffer: 5.1.2 + dev: true + + /better-path-resolve@1.0.0: + resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} + engines: {node: '>=4'} + dependencies: + is-windows: 1.0.2 + dev: true + + /big.js@5.2.2: + resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} + dev: false + + /bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: true + + /bluebird@3.7.2: + resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + dev: false + + /blueimp-md5@2.19.0: + resolution: {integrity: sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==} + dev: true + + /body-parser@1.20.1: + resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.11.0 + raw-body: 2.5.1 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /body-parser@1.20.2: + resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.11.0 + raw-body: 2.5.2 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /bowser@2.11.0: + resolution: {integrity: sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==} + dev: true + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + /brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + dev: false + + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /breakword@1.0.6: + resolution: {integrity: sha512-yjxDAYyK/pBvws9H4xKYpLDpYKEH6CzrBPAuXq3x18I+c/2MkVtT3qAr7Oloi6Dss9qNhPVueAAVU1CSeNDIXw==} + dependencies: + wcwidth: 1.0.1 + dev: true + + /browserslist@4.22.2: + resolution: {integrity: sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001668 + electron-to-chromium: 1.4.612 + node-releases: 2.0.14 + update-browserslist-db: 1.0.13(browserslist@4.22.2) + + /bser@2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + dependencies: + node-int64: 0.4.0 + dev: true + + /buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + /buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: true + + /buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: false + + /busboy@1.6.0: + resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} + engines: {node: '>=10.16.0'} + dependencies: + streamsearch: 1.1.0 + + /bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + /cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + /call-bind@1.0.5: + resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==} + dependencies: + function-bind: 1.1.2 + get-intrinsic: 1.2.2 + set-function-length: 1.1.1 + + /call-me-maybe@1.0.2: + resolution: {integrity: sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==} + dev: true + + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + /camel-case@4.1.2: + resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} + dependencies: + pascal-case: 3.1.2 + tslib: 2.6.2 + dev: true + + /camelcase-keys@6.2.2: + resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} + engines: {node: '>=8'} + dependencies: + camelcase: 5.3.1 + map-obj: 4.3.0 + quick-lru: 4.0.1 + dev: true + + /camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + dev: true + + /caniuse-lite@1.0.30001668: + resolution: {integrity: sha512-nWLrdxqCdblixUO+27JtGJJE/txpJlyUy5YN1u53wLZkP0emYCo5zgS6QYft7VUYR42LGgi/S5hdLZTrnyIddw==} + + /capital-case@1.0.4: + resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==} + dependencies: + no-case: 3.0.4 + tslib: 2.6.2 + upper-case-first: 2.0.2 + dev: true + + /chai@4.3.10: + resolution: {integrity: sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==} + engines: {node: '>=4'} + dependencies: + assertion-error: 1.1.0 + check-error: 1.0.3 + deep-eql: 4.1.3 + get-func-name: 2.0.2 + loupe: 2.3.7 + pathval: 1.1.1 + type-detect: 4.0.8 + dev: true + + /chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + /chalk@3.0.0: + resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + /chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: true + + /change-case-all@1.0.14: + resolution: {integrity: sha512-CWVm2uT7dmSHdO/z1CXT/n47mWonyypzBbuCy5tN7uMg22BsfkhwT6oHmFCAk+gL1LOOxhdbB9SZz3J1KTY3gA==} + dependencies: + change-case: 4.1.2 + is-lower-case: 2.0.2 + is-upper-case: 2.0.2 + lower-case: 2.0.2 + lower-case-first: 2.0.2 + sponge-case: 1.0.1 + swap-case: 2.0.2 + title-case: 3.0.3 + upper-case: 2.0.2 + upper-case-first: 2.0.2 + dev: true + + /change-case-all@1.0.15: + resolution: {integrity: sha512-3+GIFhk3sNuvFAJKU46o26OdzudQlPNBCu1ZQi3cMeMHhty1bhDxu2WrEilVNYaGvqUtR1VSigFcJOiS13dRhQ==} + dependencies: + change-case: 4.1.2 + is-lower-case: 2.0.2 + is-upper-case: 2.0.2 + lower-case: 2.0.2 + lower-case-first: 2.0.2 + sponge-case: 1.0.1 + swap-case: 2.0.2 + title-case: 3.0.3 + upper-case: 2.0.2 + upper-case-first: 2.0.2 + dev: true + + /change-case@4.1.2: + resolution: {integrity: sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==} + dependencies: + camel-case: 4.1.2 + capital-case: 1.0.4 + constant-case: 3.0.4 + dot-case: 3.0.4 + header-case: 2.0.4 + no-case: 3.0.4 + param-case: 3.0.4 + pascal-case: 3.1.2 + path-case: 3.0.4 + sentence-case: 3.0.4 + snake-case: 3.0.4 + tslib: 2.6.2 + dev: true + + /chardet@0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + dev: true + + /check-error@1.0.3: + resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} + dependencies: + get-func-name: 2.0.2 + dev: true + + /chrome-trace-event@1.0.3: + resolution: {integrity: sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==} + engines: {node: '>=6.0'} + dev: false + + /ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + dev: true + + /classnames@2.3.2: + resolution: {integrity: sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==} + dev: false + + /clean-stack@2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + dev: true + + /cli-color@2.0.3: + resolution: {integrity: sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ==} + engines: {node: '>=0.10'} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + es6-iterator: 2.0.3 + memoizee: 0.4.15 + timers-ext: 0.1.7 + dev: true + + /cli-cursor@3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + dependencies: + restore-cursor: 3.1.0 + dev: true + + /cli-cursor@4.0.0: + resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + restore-cursor: 4.0.0 + dev: true + + /cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + dev: true + + /cli-truncate@2.1.0: + resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} + engines: {node: '>=8'} + dependencies: + slice-ansi: 3.0.0 + string-width: 4.2.3 + dev: true + + /cli-truncate@4.0.0: + resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} + engines: {node: '>=18'} + dependencies: + slice-ansi: 5.0.0 + string-width: 7.0.0 + dev: true + + /cli-width@3.0.0: + resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} + engines: {node: '>= 10'} + dev: true + + /client-only@0.0.1: + resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} + + /cliui@6.0.0: + resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + dev: true + + /cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: true + + /clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + dev: true + + /clsx@1.2.1: + resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} + engines: {node: '>=6'} + dev: false + + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + /colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + + /combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + + /commander@11.0.0: + resolution: {integrity: sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==} + engines: {node: '>=16'} + dev: true + + /commander@11.1.0: + resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} + engines: {node: '>=16'} + dev: true + + /commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + dev: false + + /common-tags@1.8.2: + resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} + engines: {node: '>=4.0.0'} + dev: true + + /commondir@1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + dev: false + + /compute-scroll-into-view@1.0.20: + resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==} + dev: false + + /compute-scroll-into-view@2.0.4: + resolution: {integrity: sha512-y/ZA3BGnxoM/QHHQ2Uy49CLtnWPbt4tTPpEEZiEmmiWBFKjej7nEyH8Ryz54jH0MLXflUYA3Er2zUxPSJu5R+g==} + dev: false + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + /constant-case@3.0.4: + resolution: {integrity: sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==} + dependencies: + no-case: 3.0.4 + tslib: 2.6.2 + upper-case: 2.0.2 + dev: true + + /content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + dev: true + + /convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + /cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + dev: true + + /cookie@0.5.0: + resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} + engines: {node: '>= 0.6'} + dev: true + + /copy-anything@3.0.5: + resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} + engines: {node: '>=12.13'} + dependencies: + is-what: 4.1.16 + dev: false + + /core-js@3.34.0: + resolution: {integrity: sha512-aDdvlDder8QmY91H88GzNi9EtQi2TjvQhpCX6B1v/dAZHU1AuLgHvRh54RiOerpEhEW46Tkf+vgAViB/CWC0ag==} + requiresBuild: true + dev: true + + /cors@2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + dev: true + + /cosmiconfig@8.3.6(typescript@5.3.3): + resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + import-fresh: 3.3.0 + js-yaml: 4.1.0 + parse-json: 5.2.0 + path-type: 4.0.0 + typescript: 5.3.3 + dev: true + + /create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + dev: true + + /cross-fetch@3.1.8: + resolution: {integrity: sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==} + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + dev: true + + /cross-inspect@1.0.0: + resolution: {integrity: sha512-4PFfn4b5ZN6FMNGSZlyb7wUhuN8wvj8t/VQHZdM4JsDcruGJ8L2kf9zao98QIrBPFCpdk27qst/AGTl7pL3ypQ==} + engines: {node: '>=16.0.0'} + dependencies: + tslib: 2.6.2 + dev: true + + /cross-spawn@5.1.0: + resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} + dependencies: + lru-cache: 4.1.5 + shebang-command: 1.2.0 + which: 1.3.1 + dev: true + + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + /css-what@6.1.0: + resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} + engines: {node: '>= 6'} + + /css.escape@1.5.1: + resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} + dev: true + + /cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + /cssstyle@3.0.0: + resolution: {integrity: sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==} + engines: {node: '>=14'} + dependencies: + rrweb-cssom: 0.6.0 + + /csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + /csv-generate@3.4.3: + resolution: {integrity: sha512-w/T+rqR0vwvHqWs/1ZyMDWtHHSJaN06klRqJXBEpDJaM/+dZkso0OKh1VcuuYvK3XM53KysVNq8Ko/epCK8wOw==} + dev: true + + /csv-parse@4.16.3: + resolution: {integrity: sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg==} + dev: true + + /csv-stringify@5.6.5: + resolution: {integrity: sha512-PjiQ659aQ+fUTQqSrd1XEDnOr52jh30RBurfzkscaE2tPaFsDH5wOAHJiw8XAHphRknCwMUE9KRayc4K/NbO8A==} + dev: true + + /csv@5.5.3: + resolution: {integrity: sha512-QTaY0XjjhTQOdguARF0lGKm5/mEq9PD9/VhZZegHDIBq2tQwgNpHc3dneD4mGo2iJs+fTKv5Bp0fZ+BRuY3Z0g==} + engines: {node: '>= 0.1.90'} + dependencies: + csv-generate: 3.4.3 + csv-parse: 4.16.3 + csv-stringify: 5.6.5 + stream-transform: 2.1.3 + dev: true + + /d@1.0.1: + resolution: {integrity: sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==} + dependencies: + es5-ext: 0.10.62 + type: 1.2.0 + dev: true + + /damerau-levenshtein@1.0.8: + resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} + dev: true + + /data-urls@5.0.0: + resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} + engines: {node: '>=18'} + dependencies: + whatwg-mimetype: 4.0.0 + whatwg-url: 14.0.0 + + /dataloader@2.2.2: + resolution: {integrity: sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g==} + dev: true + + /dateformat@4.6.3: + resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} + dev: false + + /debounce@1.2.1: + resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==} + dev: true + + /debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + dev: true + + /debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + dev: true + + /debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + + /decamelize-keys@1.1.1: + resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} + engines: {node: '>=0.10.0'} + dependencies: + decamelize: 1.2.0 + map-obj: 1.0.1 + dev: true + + /decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + dev: true + + /decimal.js@10.4.3: + resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} + + /deep-eql@4.1.3: + resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} + engines: {node: '>=6'} + dependencies: + type-detect: 4.0.8 + dev: true + + /deep-equal@2.2.3: + resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + call-bind: 1.0.5 + es-get-iterator: 1.1.3 + get-intrinsic: 1.2.2 + is-arguments: 1.1.1 + is-array-buffer: 3.0.2 + is-date-object: 1.0.5 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.2 + isarray: 2.0.5 + object-is: 1.1.5 + object-keys: 1.1.1 + object.assign: 4.1.5 + regexp.prototype.flags: 1.5.1 + side-channel: 1.0.4 + which-boxed-primitive: 1.0.2 + which-collection: 1.0.1 + which-typed-array: 1.1.13 + dev: true + + /deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + /deep-object-diff@1.1.9: + resolution: {integrity: sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA==} + + /deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + + /defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + dependencies: + clone: 1.0.4 + dev: true + + /define-data-property@1.1.1: + resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + + /define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + has-property-descriptors: 1.0.1 + object-keys: 1.1.1 + dev: true + + /delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + /depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + /dependency-cruiser@15.5.0: + resolution: {integrity: sha512-f6pY7rh6IHl39pLHdA9CUg3LzbJRDPeZXGa1q0A4v7qTy3CDP8xOg0gsecFglurvsB6kuIYkUSW1PUtfyVkEOA==} + engines: {node: ^18.17||>=20} + hasBin: true + dependencies: + acorn: 8.11.2 + acorn-jsx: 5.3.2(acorn@8.11.2) + acorn-jsx-walk: 2.0.0 + acorn-loose: 8.4.0 + acorn-walk: 8.3.0 + ajv: 8.12.0 + chalk: 5.3.0 + commander: 11.1.0 + enhanced-resolve: 5.15.0 + figures: 6.0.1 + ignore: 5.3.0 + indent-string: 5.0.0 + interpret: 3.1.1 + is-installed-globally: 1.0.0 + json5: 2.2.3 + lodash: 4.17.21 + picomatch: 3.0.1 + prompts: 2.4.2 + rechoir: 0.8.0 + safe-regex: 2.1.1 + semver: 7.5.4 + semver-try-require: 6.2.3 + teamcity-service-messages: 0.1.14 + tsconfig-paths-webpack-plugin: 4.1.0 + watskeburt: 2.0.2 + wrap-ansi: 9.0.0 + dev: true + + /dependency-graph@0.11.0: + resolution: {integrity: sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==} + engines: {node: '>= 0.6.0'} + dev: true + + /dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + dev: true + + /destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dev: true + + /detect-indent@6.1.0: + resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} + engines: {node: '>=8'} + dev: true + + /detect-node-es@1.1.0: + resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} + dev: false + + /detect-node@2.1.0: + resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} + dev: true + + /diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: true + + /diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + dev: true + + /dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + + /doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + + /dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + dev: true + + /dot-case@3.0.4: + resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} + dependencies: + no-case: 3.0.4 + tslib: 2.6.2 + dev: true + + /dotenv@16.3.1: + resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==} + engines: {node: '>=12'} + dev: true + + /downshift@6.1.12(react@18.2.0): + resolution: {integrity: sha512-7XB/iaSJVS4T8wGFT3WRXmSF1UlBHAA40DshZtkrIscIN+VC+Lh363skLxFTvJwtNgHxAMDGEHT4xsyQFWL+UA==} + peerDependencies: + react: '>=16.12.0' + dependencies: + '@babel/runtime': 7.23.6 + compute-scroll-into-view: 1.0.20 + prop-types: 15.8.1 + react: 18.2.0 + react-is: 17.0.2 + tslib: 2.6.2 + dev: false + + /downshift@7.6.0(react@18.2.0): + resolution: {integrity: sha512-VSoTVynTAsabou/hbZ6HJHUVhtBiVOjQoBsCPcQq5eAROIGP+9XKMp9asAKQ3cEcUP4oe0fFdD2pziUjhFY33Q==} + peerDependencies: + react: '>=16.12.0' + dependencies: + '@babel/runtime': 7.23.6 + compute-scroll-into-view: 2.0.4 + prop-types: 15.8.1 + react: 18.2.0 + react-is: 17.0.2 + tslib: 2.6.2 + dev: false + + /dset@3.1.3: + resolution: {integrity: sha512-20TuZZHCEZ2O71q9/+8BwKwZ0QtD9D8ObhrihJPr+vLLYlSuAU3/zL4cSlgbfeoGHTjCSJBa7NGcrF9/Bx/WJQ==} + engines: {node: '>=4'} + dev: true + + /ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + dev: true + + /electron-to-chromium@1.4.612: + resolution: {integrity: sha512-dM8BMtXtlH237ecSMnYdYuCkib2QHq0kpWfUnavjdYsyr/6OsAwg5ZGUfnQ9KD1Ga4QgB2sqXlB2NT8zy2GnVg==} + + /emoji-regex@10.3.0: + resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} + dev: true + + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: true + + /emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: true + + /emojis-list@3.0.0: + resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} + engines: {node: '>= 4'} + dev: false + + /encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + dev: true + + /end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + dependencies: + once: 1.4.0 + dev: false + + /enhanced-resolve@5.15.0: + resolution: {integrity: sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==} + engines: {node: '>=10.13.0'} + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + dev: true + + /enhanced-resolve@5.17.1: + resolution: {integrity: sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==} + engines: {node: '>=10.13.0'} + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + dev: false + + /enquirer@2.4.1: + resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} + engines: {node: '>=8.6'} + dependencies: + ansi-colors: 4.1.3 + strip-ansi: 6.0.1 + dev: true + + /entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + /error-class-utils@4.0.0: + resolution: {integrity: sha512-przSMatQ20oCvuiKYOX9hHDsXMA2AhFrGRCiR7RwoixDzu7ChsWx41XshLBpGKc+qgC2FOSvOX69FNFaBYArhg==} + engines: {node: '>=18.18.0'} + dev: false + + /error-custom-class@10.0.0: + resolution: {integrity: sha512-h7MOqDeh8ajUMXifi+d0dRz32sOg10VpsXMZGUVTNrXnNR9nIT7J1aCkkXfaA3cukq22QgbAdCu5T3HmaOy91g==} + engines: {node: '>=18.18.0'} + dependencies: + error-class-utils: 4.0.0 + dev: false + + /error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: true + + /error-http-response@3.0.0: + resolution: {integrity: sha512-gbMVRomf9srnU6SwoQsYfFparRI1efhZGsGmlKgAKdDp26jceLRYWELp5GlA8y1PDNkR/p7lrlXNRXYDmnNJoQ==} + engines: {node: '>=18.18.0'} + dependencies: + is-plain-obj: 4.1.0 + normalize-exception: 3.0.0 + safe-json-value: 3.0.0 + dev: false + + /error-serializer@7.0.0: + resolution: {integrity: sha512-VKXwvqgZEDBKmxLUrAzOW6mLtlBnwvvIBDCe0vYnybOYMikWN2uUC+8edKFYMYgbvp8ouTlPM/VPC26G+XVvoQ==} + engines: {node: '>=18.18.0'} + dependencies: + is-error-instance: 3.0.0 + is-plain-obj: 4.1.0 + normalize-exception: 3.0.0 + safe-json-value: 3.0.0 + set-error-class: 3.0.0 + dev: false + + /es-abstract@1.22.3: + resolution: {integrity: sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + arraybuffer.prototype.slice: 1.0.2 + available-typed-arrays: 1.0.5 + call-bind: 1.0.5 + es-set-tostringtag: 2.0.2 + es-to-primitive: 1.2.1 + function.prototype.name: 1.1.6 + get-intrinsic: 1.2.2 + get-symbol-description: 1.0.0 + globalthis: 1.0.3 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + has-proto: 1.0.1 + has-symbols: 1.0.3 + hasown: 2.0.0 + internal-slot: 1.0.6 + is-array-buffer: 3.0.2 + is-callable: 1.2.7 + is-negative-zero: 2.0.2 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.2 + is-string: 1.0.7 + is-typed-array: 1.1.12 + is-weakref: 1.0.2 + object-inspect: 1.13.1 + object-keys: 1.1.1 + object.assign: 4.1.5 + regexp.prototype.flags: 1.5.1 + safe-array-concat: 1.0.1 + safe-regex-test: 1.0.0 + string.prototype.trim: 1.2.8 + string.prototype.trimend: 1.0.7 + string.prototype.trimstart: 1.0.7 + typed-array-buffer: 1.0.0 + typed-array-byte-length: 1.0.0 + typed-array-byte-offset: 1.0.0 + typed-array-length: 1.0.4 + unbox-primitive: 1.0.2 + which-typed-array: 1.1.13 + dev: true + + /es-get-iterator@1.1.3: + resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + has-symbols: 1.0.3 + is-arguments: 1.1.1 + is-map: 2.0.2 + is-set: 2.0.2 + is-string: 1.0.7 + isarray: 2.0.5 + stop-iteration-iterator: 1.0.0 + dev: true + + /es-iterator-helpers@1.0.15: + resolution: {integrity: sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==} + dependencies: + asynciterator.prototype: 1.0.0 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + es-set-tostringtag: 2.0.2 + function-bind: 1.1.2 + get-intrinsic: 1.2.2 + globalthis: 1.0.3 + has-property-descriptors: 1.0.1 + has-proto: 1.0.1 + has-symbols: 1.0.3 + internal-slot: 1.0.6 + iterator.prototype: 1.1.2 + safe-array-concat: 1.0.1 + dev: true + + /es-module-lexer@1.4.1: + resolution: {integrity: sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==} + dev: false + + /es-set-tostringtag@2.0.2: + resolution: {integrity: sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + has-tostringtag: 1.0.0 + hasown: 2.0.0 + dev: true + + /es-shim-unscopables@1.0.2: + resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} + dependencies: + hasown: 2.0.0 + dev: true + + /es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + dependencies: + is-callable: 1.2.7 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + dev: true + + /es5-ext@0.10.62: + resolution: {integrity: sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==} + engines: {node: '>=0.10'} + requiresBuild: true + dependencies: + es6-iterator: 2.0.3 + es6-symbol: 3.1.3 + next-tick: 1.1.0 + dev: true + + /es6-iterator@2.0.3: + resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + es6-symbol: 3.1.3 + dev: true + + /es6-symbol@3.1.3: + resolution: {integrity: sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==} + dependencies: + d: 1.0.1 + ext: 1.7.0 + dev: true + + /es6-weak-map@2.0.3: + resolution: {integrity: sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + es6-iterator: 2.0.3 + es6-symbol: 3.1.3 + dev: true + + /esbuild@0.17.6: + resolution: {integrity: sha512-TKFRp9TxrJDdRWfSsSERKEovm6v30iHnrjlcGhLBOtReE28Yp1VSBRfO3GTaOFMoxsNerx4TjrhzSuma9ha83Q==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.17.6 + '@esbuild/android-arm64': 0.17.6 + '@esbuild/android-x64': 0.17.6 + '@esbuild/darwin-arm64': 0.17.6 + '@esbuild/darwin-x64': 0.17.6 + '@esbuild/freebsd-arm64': 0.17.6 + '@esbuild/freebsd-x64': 0.17.6 + '@esbuild/linux-arm': 0.17.6 + '@esbuild/linux-arm64': 0.17.6 + '@esbuild/linux-ia32': 0.17.6 + '@esbuild/linux-loong64': 0.17.6 + '@esbuild/linux-mips64el': 0.17.6 + '@esbuild/linux-ppc64': 0.17.6 + '@esbuild/linux-riscv64': 0.17.6 + '@esbuild/linux-s390x': 0.17.6 + '@esbuild/linux-x64': 0.17.6 + '@esbuild/netbsd-x64': 0.17.6 + '@esbuild/openbsd-x64': 0.17.6 + '@esbuild/sunos-x64': 0.17.6 + '@esbuild/win32-arm64': 0.17.6 + '@esbuild/win32-ia32': 0.17.6 + '@esbuild/win32-x64': 0.17.6 + + /esbuild@0.18.20: + resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.18.20 + '@esbuild/android-arm64': 0.18.20 + '@esbuild/android-x64': 0.18.20 + '@esbuild/darwin-arm64': 0.18.20 + '@esbuild/darwin-x64': 0.18.20 + '@esbuild/freebsd-arm64': 0.18.20 + '@esbuild/freebsd-x64': 0.18.20 + '@esbuild/linux-arm': 0.18.20 + '@esbuild/linux-arm64': 0.18.20 + '@esbuild/linux-ia32': 0.18.20 + '@esbuild/linux-loong64': 0.18.20 + '@esbuild/linux-mips64el': 0.18.20 + '@esbuild/linux-ppc64': 0.18.20 + '@esbuild/linux-riscv64': 0.18.20 + '@esbuild/linux-s390x': 0.18.20 + '@esbuild/linux-x64': 0.18.20 + '@esbuild/netbsd-x64': 0.18.20 + '@esbuild/openbsd-x64': 0.18.20 + '@esbuild/sunos-x64': 0.18.20 + '@esbuild/win32-arm64': 0.18.20 + '@esbuild/win32-ia32': 0.18.20 + '@esbuild/win32-x64': 0.18.20 + dev: false + + /esbuild@0.19.9: + resolution: {integrity: sha512-U9CHtKSy+EpPsEBa+/A2gMs/h3ylBC0H0KSqIg7tpztHerLi6nrrcoUJAkNCEPumx8yJ+Byic4BVwHgRbN0TBg==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.19.9 + '@esbuild/android-arm64': 0.19.9 + '@esbuild/android-x64': 0.19.9 + '@esbuild/darwin-arm64': 0.19.9 + '@esbuild/darwin-x64': 0.19.9 + '@esbuild/freebsd-arm64': 0.19.9 + '@esbuild/freebsd-x64': 0.19.9 + '@esbuild/linux-arm': 0.19.9 + '@esbuild/linux-arm64': 0.19.9 + '@esbuild/linux-ia32': 0.19.9 + '@esbuild/linux-loong64': 0.19.9 + '@esbuild/linux-mips64el': 0.19.9 + '@esbuild/linux-ppc64': 0.19.9 + '@esbuild/linux-riscv64': 0.19.9 + '@esbuild/linux-s390x': 0.19.9 + '@esbuild/linux-x64': 0.19.9 + '@esbuild/netbsd-x64': 0.19.9 + '@esbuild/openbsd-x64': 0.19.9 + '@esbuild/sunos-x64': 0.19.9 + '@esbuild/win32-arm64': 0.19.9 + '@esbuild/win32-ia32': 0.19.9 + '@esbuild/win32-x64': 0.19.9 + + /escalade@3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + + /escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + dev: true + + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + /escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + /eslint-config-next@14.0.4(eslint@8.55.0)(typescript@5.3.3): + resolution: {integrity: sha512-9/xbOHEQOmQtqvQ1UsTQZpnA7SlDMBtuKJ//S4JnoyK3oGLhILKXdBgu/UO7lQo/2xOykQULS1qQ6p2+EpHgAQ==} + peerDependencies: + eslint: ^7.23.0 || ^8.0.0 + typescript: '>=3.3.1' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@next/eslint-plugin-next': 14.0.4 + '@rushstack/eslint-patch': 1.6.0 + '@typescript-eslint/parser': 6.14.0(eslint@8.55.0)(typescript@5.3.3) + eslint: 8.55.0 + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.14.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.0)(eslint@8.55.0) + eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.14.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.55.0) + eslint-plugin-jsx-a11y: 6.8.0(eslint@8.55.0) + eslint-plugin-react: 7.33.2(eslint@8.55.0) + eslint-plugin-react-hooks: 4.6.0(eslint@8.55.0) + typescript: 5.3.3 + transitivePeerDependencies: + - eslint-import-resolver-webpack + - supports-color + dev: true + + /eslint-config-prettier@9.1.0(eslint@8.55.0): + resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 8.55.0 + dev: true + + /eslint-import-resolver-node@0.3.9: + resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + dependencies: + debug: 3.2.7 + is-core-module: 2.13.1 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.14.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.0)(eslint@8.55.0): + resolution: {integrity: sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '*' + eslint-plugin-import: '*' + dependencies: + debug: 4.3.4 + enhanced-resolve: 5.15.0 + eslint: 8.55.0 + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.14.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.55.0) + eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.14.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.55.0) + fast-glob: 3.3.2 + get-tsconfig: 4.7.2 + is-core-module: 2.13.1 + is-glob: 4.0.3 + transitivePeerDependencies: + - '@typescript-eslint/parser' + - eslint-import-resolver-node + - eslint-import-resolver-webpack + - supports-color + dev: true + + /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.14.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.55.0): + resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + dependencies: + '@typescript-eslint/parser': 6.14.0(eslint@8.55.0)(typescript@5.3.3) + debug: 3.2.7 + eslint: 8.55.0 + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.14.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.0)(eslint@8.55.0) + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-es@3.0.1(eslint@8.55.0): + resolution: {integrity: sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==} + engines: {node: '>=8.10.0'} + peerDependencies: + eslint: '>=4.19.1' + dependencies: + eslint: 8.55.0 + eslint-utils: 2.1.0 + regexpp: 3.2.0 + dev: false + + /eslint-plugin-import@2.29.0(@typescript-eslint/parser@6.14.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.55.0): + resolution: {integrity: sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + dependencies: + '@typescript-eslint/parser': 6.14.0(eslint@8.55.0)(typescript@5.3.3) + array-includes: 3.1.7 + array.prototype.findlastindex: 1.2.3 + array.prototype.flat: 1.3.2 + array.prototype.flatmap: 1.3.2 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 8.55.0 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.14.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.55.0) + hasown: 2.0.0 + is-core-module: 2.13.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.7 + object.groupby: 1.0.1 + object.values: 1.1.7 + semver: 6.3.1 + tsconfig-paths: 3.14.2 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + + /eslint-plugin-jsx-a11y@6.8.0(eslint@8.55.0): + resolution: {integrity: sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==} + engines: {node: '>=4.0'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 + dependencies: + '@babel/runtime': 7.23.6 + aria-query: 5.3.0 + array-includes: 3.1.7 + array.prototype.flatmap: 1.3.2 + ast-types-flow: 0.0.8 + axe-core: 4.7.0 + axobject-query: 3.2.1 + damerau-levenshtein: 1.0.8 + emoji-regex: 9.2.2 + es-iterator-helpers: 1.0.15 + eslint: 8.55.0 + hasown: 2.0.0 + jsx-ast-utils: 3.3.5 + language-tags: 1.0.9 + minimatch: 3.1.2 + object.entries: 1.1.7 + object.fromentries: 2.0.7 + dev: true + + /eslint-plugin-node@11.1.0(eslint@8.55.0): + resolution: {integrity: sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==} + engines: {node: '>=8.10.0'} + peerDependencies: + eslint: '>=5.16.0' + dependencies: + eslint: 8.55.0 + eslint-plugin-es: 3.0.1(eslint@8.55.0) + eslint-utils: 2.1.0 + ignore: 5.3.0 + minimatch: 3.1.2 + resolve: 1.22.8 + semver: 6.3.1 + dev: false + + /eslint-plugin-react-hooks@4.6.0(eslint@8.55.0): + resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==} + engines: {node: '>=10'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 + dependencies: + eslint: 8.55.0 + dev: true + + /eslint-plugin-react@7.33.2(eslint@8.55.0): + resolution: {integrity: sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==} + engines: {node: '>=4'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 + dependencies: + array-includes: 3.1.7 + array.prototype.flatmap: 1.3.2 + array.prototype.tosorted: 1.1.2 + doctrine: 2.1.0 + es-iterator-helpers: 1.0.15 + eslint: 8.55.0 + estraverse: 5.3.0 + jsx-ast-utils: 3.3.5 + minimatch: 3.1.2 + object.entries: 1.1.7 + object.fromentries: 2.0.7 + object.hasown: 1.1.3 + object.values: 1.1.7 + prop-types: 15.8.1 + resolve: 2.0.0-next.5 + semver: 6.3.1 + string.prototype.matchall: 4.0.10 + dev: true + + /eslint-plugin-require-form-method@1.0.2: + resolution: {integrity: sha512-cdHE+LTMAMwwHo4Rk8ZP/of7t3bekT65wuBmm37Is+if0PzADDN1x6ctPX7k2Xam2XDQdaWvzv6Dg3oJfMZxnA==} + engines: {node: '>=0.10.0'} + dependencies: + requireindex: 1.1.0 + dev: true + + /eslint-plugin-testing-library@6.2.0(eslint@8.55.0)(typescript@5.3.3): + resolution: {integrity: sha512-+LCYJU81WF2yQ+Xu4A135CgK8IszcFcyMF4sWkbiu6Oj+Nel0TrkZq/HvDw0/1WuO3dhDQsZA/OpEMGd0NfcUw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0, npm: '>=6'} + peerDependencies: + eslint: ^7.5.0 || ^8.0.0 + dependencies: + '@typescript-eslint/utils': 5.62.0(eslint@8.55.0)(typescript@5.3.3) + eslint: 8.55.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /eslint-plugin-vitest@0.3.16(@typescript-eslint/eslint-plugin@6.14.0)(eslint@8.55.0)(typescript@5.3.3)(vitest@0.34.2): + resolution: {integrity: sha512-gqsbIZYK0YTiWGyRG2CwAGNA50fuqLkNXGKK2lVmyjBbqBj+rKH7m3JhVQ31AkVX229JkW4vBu0u33PAi5OhTA==} + engines: {node: ^18.0.0 || >= 20.0.0} + peerDependencies: + '@typescript-eslint/eslint-plugin': '*' + eslint: '>=8.0.0' + vitest: '*' + peerDependenciesMeta: + '@typescript-eslint/eslint-plugin': + optional: true + vitest: + optional: true + dependencies: + '@typescript-eslint/eslint-plugin': 6.14.0(@typescript-eslint/parser@6.14.0)(eslint@8.55.0)(typescript@5.3.3) + '@typescript-eslint/utils': 6.14.0(eslint@8.55.0)(typescript@5.3.3) + eslint: 8.55.0 + vitest: 0.34.2(jsdom@23.0.1) + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + + /eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + /eslint-utils@2.1.0: + resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==} + engines: {node: '>=6'} + dependencies: + eslint-visitor-keys: 1.3.0 + dev: false + + /eslint-visitor-keys@1.3.0: + resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==} + engines: {node: '>=4'} + dev: false + + /eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + /eslint@8.55.0: + resolution: {integrity: sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.55.0) + '@eslint-community/regexpp': 4.10.0 + '@eslint/eslintrc': 2.1.4 + '@eslint/js': 8.55.0 + '@humanwhocodes/config-array': 0.11.13 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + '@ungap/structured-clone': 1.2.0 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.24.0 + graphemer: 1.4.0 + ignore: 5.3.0 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.3 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + + /espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.11.2 + acorn-jsx: 5.3.2(acorn@8.11.2) + eslint-visitor-keys: 3.4.3 + + /esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + + /esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + + /estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + + /estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + /estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + dev: false + + /esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + /etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + dev: true + + /eval@0.1.8: + resolution: {integrity: sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw==} + engines: {node: '>= 0.8'} + dependencies: + '@types/node': 20.10.4 + require-like: 0.1.2 + + /event-emitter@0.3.5: + resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + dev: true + + /event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + dev: false + + /eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + dev: true + + /events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + dev: false + + /execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.1.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + dev: true + + /exenv@1.2.2: + resolution: {integrity: sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw==} + dev: false + + /express@4.18.2: + resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==} + engines: {node: '>= 0.10.0'} + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.1 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.5.0 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.2.0 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.1 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.7 + proxy-addr: 2.0.7 + qs: 6.11.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.18.0 + serve-static: 1.15.0 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /ext@1.7.0: + resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} + dependencies: + type: 2.7.2 + dev: true + + /extendable-error@0.1.7: + resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} + dev: true + + /external-editor@3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + dev: true + + /extract-files@11.0.0: + resolution: {integrity: sha512-FuoE1qtbJ4bBVvv94CC7s0oTnKUGvQs+Rjf1L2SJFfS+HTVVjhPFtehPdQ0JiGPqVNfSSZvL5yzHHQq2Z4WNhQ==} + engines: {node: ^12.20 || >= 14.13} + dev: true + + /fast-copy@3.0.1: + resolution: {integrity: sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==} + dev: false + + /fast-decode-uri-component@1.0.1: + resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} + dev: true + + /fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + /fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + /fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + /fast-querystring@1.1.2: + resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==} + dependencies: + fast-decode-uri-component: 1.0.1 + dev: true + + /fast-redact@3.3.0: + resolution: {integrity: sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ==} + engines: {node: '>=6'} + dev: false + + /fast-safe-stringify@2.1.1: + resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + dev: false + + /fast-url-parser@1.1.3: + resolution: {integrity: sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==} + dependencies: + punycode: 1.4.1 + dev: true + + /fastq@1.15.0: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + dependencies: + reusify: 1.0.4 + + /fb-watchman@2.0.2: + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + dependencies: + bser: 2.1.1 + dev: true + + /fbjs-css-vars@1.0.2: + resolution: {integrity: sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==} + dev: true + + /fbjs@3.0.5: + resolution: {integrity: sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg==} + dependencies: + cross-fetch: 3.1.8 + fbjs-css-vars: 1.0.2 + loose-envify: 1.4.0 + object-assign: 4.1.1 + promise: 7.3.1 + setimmediate: 1.0.5 + ua-parser-js: 1.0.37 + transitivePeerDependencies: + - encoding + dev: true + + /figlet@1.6.0: + resolution: {integrity: sha512-31EQGhCEITv6+hi2ORRPyn3bulaV9Fl4xOdR169cBzH/n1UqcxsiSB/noo6SJdD7Kfb1Ljit+IgR1USvF/XbdA==} + engines: {node: '>= 0.4.0'} + hasBin: true + dev: true + + /figures@3.2.0: + resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} + engines: {node: '>=8'} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + + /figures@6.0.1: + resolution: {integrity: sha512-0oY/olScYD4IhQ8u//gCPA4F3mlTn2dacYmiDm/mbDQvpmLjV4uH+zhsQ5IyXRyvqkvtUkXkNdGvg5OFJTCsuQ==} + engines: {node: '>=18'} + dependencies: + is-unicode-supported: 2.0.0 + dev: true + + /file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.2.0 + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /filter-obj@5.1.0: + resolution: {integrity: sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng==} + engines: {node: '>=14.16'} + dev: false + + /finalhandler@1.2.0: + resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} + engines: {node: '>= 0.8'} + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + dev: true + + /find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + /find-yarn-workspace-root2@1.2.16: + resolution: {integrity: sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==} + dependencies: + micromatch: 4.0.5 + pkg-dir: 4.2.0 + dev: true + + /flat-cache@3.2.0: + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flatted: 3.2.9 + keyv: 4.5.4 + rimraf: 3.0.2 + + /flatted@3.2.9: + resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} + + /for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: true + + /form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + + /forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + dev: true + + /fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + dev: true + + /fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + dev: true + + /fs-extra@7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + dev: true + + /fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + dev: true + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + /fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + optional: true + + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + /function.prototype.name@1.1.6: + resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + functions-have-names: 1.2.3 + dev: true + + /functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: true + + /gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + /get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: true + + /get-east-asian-width@1.2.0: + resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} + engines: {node: '>=18'} + dev: true + + /get-func-name@2.0.2: + resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} + dev: true + + /get-intrinsic@1.2.2: + resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==} + dependencies: + function-bind: 1.1.2 + has-proto: 1.0.1 + has-symbols: 1.0.3 + hasown: 2.0.0 + + /get-nonce@1.0.1: + resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} + engines: {node: '>=6'} + dev: false + + /get-stdin@8.0.0: + resolution: {integrity: sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==} + engines: {node: '>=10'} + dev: true + + /get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + dev: true + + /get-symbol-description@1.0.0: + resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + dev: true + + /get-tsconfig@4.7.2: + resolution: {integrity: sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==} + dependencies: + resolve-pkg-maps: 1.0.0 + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + + /glob-promise@4.2.2(glob@7.2.3): + resolution: {integrity: sha512-xcUzJ8NWN5bktoTIX7eOclO1Npxd/dyVqUJxlLIDasT4C7KZyqlPIwkdJ0Ypiy3p2ZKahTjK4M9uC3sNSfNMzw==} + engines: {node: '>=12'} + peerDependencies: + glob: ^7.1.6 + dependencies: + '@types/glob': 7.2.0 + glob: 7.2.3 + dev: true + + /glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + dev: false + + /glob@7.1.7: + resolution: {integrity: sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + /glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.6 + once: 1.4.0 + dev: false + + /global-directory@4.0.1: + resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} + engines: {node: '>=18'} + dependencies: + ini: 4.1.1 + dev: true + + /globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + + /globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + + /globalthis@1.0.3: + resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.1 + dev: true + + /globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.0 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + + /globrex@0.1.2: + resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} + dev: true + + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.2 + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + /grapheme-splitter@1.0.4: + resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} + dev: true + + /graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + /graphql-config@5.0.3(@types/node@20.10.4)(graphql@16.8.1)(typescript@5.3.3): + resolution: {integrity: sha512-BNGZaoxIBkv9yy6Y7omvsaBUHOzfFcII3UN++tpH8MGOKFPFkCPZuwx09ggANMt8FgyWP1Od8SWPmrUEZca4NQ==} + engines: {node: '>= 16.0.0'} + peerDependencies: + cosmiconfig-toml-loader: ^1.0.0 + graphql: ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + peerDependenciesMeta: + cosmiconfig-toml-loader: + optional: true + dependencies: + '@graphql-tools/graphql-file-loader': 8.0.0(graphql@16.8.1) + '@graphql-tools/json-file-loader': 8.0.0(graphql@16.8.1) + '@graphql-tools/load': 8.0.1(graphql@16.8.1) + '@graphql-tools/merge': 9.0.1(graphql@16.8.1) + '@graphql-tools/url-loader': 8.0.1(@types/node@20.10.4)(graphql@16.8.1) + '@graphql-tools/utils': 10.0.11(graphql@16.8.1) + cosmiconfig: 8.3.6(typescript@5.3.3) + graphql: 16.8.1 + jiti: 1.21.0 + minimatch: 4.2.3 + string-env-interpolation: 1.0.1 + tslib: 2.6.2 + transitivePeerDependencies: + - '@types/node' + - bufferutil + - encoding + - typescript + - utf-8-validate + dev: true + + /graphql-request@6.1.0(graphql@16.8.1): + resolution: {integrity: sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==} + peerDependencies: + graphql: 14 - 16 + dependencies: + '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) + cross-fetch: 3.1.8 + graphql: 16.8.1 + transitivePeerDependencies: + - encoding + dev: true + + /graphql-tag@2.12.6(graphql@16.8.1): + resolution: {integrity: sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==} + engines: {node: '>=10'} + peerDependencies: + graphql: ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + graphql: 16.8.1 + tslib: 2.6.2 + + /graphql-ws@5.14.2(graphql@16.8.1): + resolution: {integrity: sha512-LycmCwhZ+Op2GlHz4BZDsUYHKRiiUz+3r9wbhBATMETNlORQJAaFlAgTFoeRh6xQoQegwYwIylVD1Qns9/DA3w==} + engines: {node: '>=10'} + peerDependencies: + graphql: '>=0.11 <=16' + dependencies: + graphql: 16.8.1 + dev: true + + /graphql@16.8.1: + resolution: {integrity: sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==} + engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} + + /hard-rejection@2.1.0: + resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} + engines: {node: '>=6'} + dev: true + + /has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: true + + /has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + /has-property-descriptors@1.0.1: + resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==} + dependencies: + get-intrinsic: 1.2.2 + + /has-proto@1.0.1: + resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + engines: {node: '>= 0.4'} + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + + /has-tostringtag@1.0.0: + resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /hasown@2.0.0: + resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + + /header-case@2.0.4: + resolution: {integrity: sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==} + dependencies: + capital-case: 1.0.4 + tslib: 2.6.2 + dev: true + + /help-me@4.2.0: + resolution: {integrity: sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA==} + dependencies: + glob: 8.1.0 + readable-stream: 3.6.2 + dev: false + + /hoist-non-react-statics@3.3.2: + resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} + dependencies: + react-is: 16.13.1 + dev: false + + /hosted-git-info@2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + dev: true + + /html-encoding-sniffer@4.0.0: + resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} + engines: {node: '>=18'} + dependencies: + whatwg-encoding: 3.1.1 + + /html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + dev: true + + /http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + + /http-graceful-shutdown@3.1.13: + resolution: {integrity: sha512-Ci5LRufQ8AtrQ1U26AevS8QoMXDOhnAHCJI3eZu1com7mZGHxREmw3dNj85ftpQokQCvak8nI2pnFS8zyM1M+Q==} + engines: {node: '>=4.0.0'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /http-proxy-agent@7.0.0: + resolution: {integrity: sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.0 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + + /https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: false + + /https-proxy-agent@7.0.2: + resolution: {integrity: sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.0 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + + /human-id@1.0.2: + resolution: {integrity: sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==} + dev: true + + /human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + dev: true + + /husky@8.0.3: + resolution: {integrity: sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==} + engines: {node: '>=14'} + hasBin: true + dev: true + + /iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + + /iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + + /ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + /ignore@5.3.0: + resolution: {integrity: sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==} + engines: {node: '>= 4'} + + /immediate@3.0.6: + resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + dev: false + + /immutable@3.7.6: + resolution: {integrity: sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw==} + engines: {node: '>=0.8.0'} + dev: true + + /import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + /import-from@4.0.0: + resolution: {integrity: sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ==} + engines: {node: '>=12.2'} + dev: true + + /imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + /indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + dev: true + + /indent-string@5.0.0: + resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} + engines: {node: '>=12'} + dev: true + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + /ini@4.1.1: + resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true + + /inquirer@8.2.6: + resolution: {integrity: sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==} + engines: {node: '>=12.0.0'} + dependencies: + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-width: 3.0.0 + external-editor: 3.1.0 + figures: 3.2.0 + lodash: 4.17.21 + mute-stream: 0.0.8 + ora: 5.4.1 + run-async: 2.4.1 + rxjs: 7.8.1 + string-width: 4.2.3 + strip-ansi: 6.0.1 + through: 2.3.8 + wrap-ansi: 6.2.0 + dev: true + + /internal-slot@1.0.6: + resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + hasown: 2.0.0 + side-channel: 1.0.4 + dev: true + + /interpret@3.1.1: + resolution: {integrity: sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==} + engines: {node: '>=10.13.0'} + dev: true + + /invariant@2.2.4: + resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} + dependencies: + loose-envify: 1.4.0 + + /ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + dev: true + + /is-absolute-url@3.0.3: + resolution: {integrity: sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==} + engines: {node: '>=8'} + dev: true + + /is-absolute@1.0.0: + resolution: {integrity: sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==} + engines: {node: '>=0.10.0'} + dependencies: + is-relative: 1.0.0 + is-windows: 1.0.2 + dev: true + + /is-arguments@1.1.1: + resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + has-tostringtag: 1.0.0 + dev: true + + /is-array-buffer@3.0.2: + resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + is-typed-array: 1.1.12 + dev: true + + /is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: true + + /is-async-function@2.0.0: + resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + dependencies: + has-bigints: 1.0.2 + dev: true + + /is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + has-tostringtag: 1.0.0 + dev: true + + /is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: true + + /is-core-module@2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + dependencies: + hasown: 2.0.0 + + /is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-error-instance@2.0.0: + resolution: {integrity: sha512-5RuM+oFY0P5MRa1nXJo6IcTx9m2VyXYhRtb4h0olsi2GHci4bqZ6akHk+GmCYvDrAR9yInbiYdr2pnoqiOMw/Q==} + engines: {node: '>=16.17.0'} + dev: false + + /is-error-instance@3.0.0: + resolution: {integrity: sha512-K0NeIwAWZGE4KoH1b6xw2+feyE80RqUq0OvZgr8z4gKb1BrF78B9Bo4HWRIe3xMHXbLKkxqhhT6oSNwXFqauJw==} + engines: {node: '>=18.18.0'} + dev: false + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + /is-finalizationregistry@1.0.2: + resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==} + dependencies: + call-bind: 1.0.5 + dev: true + + /is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: true + + /is-fullwidth-code-point@4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + dev: true + + /is-fullwidth-code-point@5.0.0: + resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} + engines: {node: '>=18'} + dependencies: + get-east-asian-width: 1.2.0 + dev: true + + /is-generator-function@1.0.10: + resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + + /is-installed-globally@1.0.0: + resolution: {integrity: sha512-K55T22lfpQ63N4KEN57jZUAaAYqYHEe8veb/TycJRk9DdSCLLcovXz/mL6mOnhQaZsQGwPhuFopdQIlqGSEjiQ==} + engines: {node: '>=18'} + dependencies: + global-directory: 4.0.1 + is-path-inside: 4.0.0 + dev: true + + /is-interactive@1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} + dev: true + + /is-lower-case@2.0.2: + resolution: {integrity: sha512-bVcMJy4X5Og6VZfdOZstSexlEy20Sr0k/p/b2IlQJlfdKAQuMpiv5w2Ccxb8sKdRUNAG1PnHVHjFSdRDVS6NlQ==} + dependencies: + tslib: 2.6.2 + dev: true + + /is-map@2.0.2: + resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==} + dev: true + + /is-negative-zero@2.0.2: + resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} + engines: {node: '>= 0.4'} + dev: true + + /is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + + /is-path-inside@4.0.0: + resolution: {integrity: sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==} + engines: {node: '>=12'} + dev: true + + /is-plain-obj@1.1.0: + resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} + engines: {node: '>=0.10.0'} + dev: true + + /is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + dev: false + + /is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + + /is-promise@2.2.2: + resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} + dev: true + + /is-reference@1.2.1: + resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} + dependencies: + '@types/estree': 1.0.5 + dev: false + + /is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + has-tostringtag: 1.0.0 + dev: true + + /is-relative@1.0.0: + resolution: {integrity: sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==} + engines: {node: '>=0.10.0'} + dependencies: + is-unc-path: 1.0.0 + dev: true + + /is-set@2.0.2: + resolution: {integrity: sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==} + dev: true + + /is-shared-array-buffer@1.0.2: + resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} + dependencies: + call-bind: 1.0.5 + dev: true + + /is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + + /is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-subdir@1.2.0: + resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} + engines: {node: '>=4'} + dependencies: + better-path-resolve: 1.0.0 + dev: true + + /is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /is-typed-array@1.1.12: + resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} + engines: {node: '>= 0.4'} + dependencies: + which-typed-array: 1.1.13 + dev: true + + /is-unc-path@1.0.0: + resolution: {integrity: sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==} + engines: {node: '>=0.10.0'} + dependencies: + unc-path-regex: 0.1.2 + dev: true + + /is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + dev: true + + /is-unicode-supported@2.0.0: + resolution: {integrity: sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==} + engines: {node: '>=18'} + dev: true + + /is-upper-case@2.0.2: + resolution: {integrity: sha512-44pxmxAvnnAOwBg4tHPnkfvgjPwbc5QIsSstNU+YcJ1ovxVzCWpSGosPJOZh/a1tdl81fbgnLc9LLv+x2ywbPQ==} + dependencies: + tslib: 2.6.2 + dev: true + + /is-weakmap@2.0.1: + resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==} + dev: true + + /is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + dependencies: + call-bind: 1.0.5 + dev: true + + /is-weakset@2.0.2: + resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + dev: true + + /is-what@4.1.16: + resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} + engines: {node: '>=12.13'} + dev: false + + /is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + dev: true + + /isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + /isomorphic-ws@5.0.0(ws@8.15.1): + resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==} + peerDependencies: + ws: '*' + dependencies: + ws: 8.15.1 + dev: true + + /istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + dev: true + + /istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + dev: true + + /istanbul-lib-source-maps@4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + dependencies: + debug: 4.3.4 + istanbul-lib-coverage: 3.2.2 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-reports@3.1.6: + resolution: {integrity: sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==} + engines: {node: '>=8'} + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + dev: true + + /iterator.prototype@1.1.2: + resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==} + dependencies: + define-properties: 1.2.1 + get-intrinsic: 1.2.2 + has-symbols: 1.0.3 + reflect.getprototypeof: 1.0.4 + set-function-name: 2.0.1 + dev: true + + /javascript-stringify@2.1.0: + resolution: {integrity: sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==} + + /jest-worker@27.5.1: + resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/node': 20.10.4 + merge-stream: 2.0.0 + supports-color: 8.1.1 + dev: false + + /jiti@1.21.0: + resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} + hasBin: true + dev: true + + /jose@4.14.4: + resolution: {integrity: sha512-j8GhLiKmUAh+dsFXlX1aJCbt5KMibuKb+d7j1JaOJG6s2UjX1PQlW+OKB/sD4a/5ZYF4RcmYmLSndOoU3Lt/3g==} + dev: false + + /jose@5.1.3: + resolution: {integrity: sha512-GPExOkcMsCLBTi1YetY2LmkoY559fss0+0KVa6kOfb2YFe84nAM7Nm/XzuZozah4iHgmBGrCOHL5/cy670SBRw==} + + /joycon@3.1.1: + resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} + engines: {node: '>=10'} + dev: false + + /js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + /js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + dev: true + + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + + /jsdom@23.0.1: + resolution: {integrity: sha512-2i27vgvlUsGEBO9+/kJQRbtqtm+191b5zAZrU/UezVmnC2dlDAFLgDYJvAEi94T4kjsRKkezEtLQTgsNEsW2lQ==} + engines: {node: '>=18'} + peerDependencies: + canvas: ^2.11.2 + peerDependenciesMeta: + canvas: + optional: true + dependencies: + cssstyle: 3.0.0 + data-urls: 5.0.0 + decimal.js: 10.4.3 + form-data: 4.0.0 + html-encoding-sniffer: 4.0.0 + http-proxy-agent: 7.0.0 + https-proxy-agent: 7.0.2 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.7 + parse5: 7.1.2 + rrweb-cssom: 0.6.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 4.1.3 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 3.1.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 14.0.0 + ws: 8.15.1 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + /jsesc@2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + + /json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + /json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + /json-schema-to-typescript@13.0.2: + resolution: {integrity: sha512-TCaEVW4aI2FmMQe7f98mvr3/oiVmXEC1xZjkTZ9L/BSoTXFlC7p64mD5AD2d8XWycNBQZUnHwXL5iVXt1HWwNQ==} + engines: {node: '>=12.0.0'} + hasBin: true + dependencies: + '@bcherny/json-schema-ref-parser': 10.0.5-fork + '@types/json-schema': 7.0.15 + '@types/lodash': 4.14.202 + '@types/prettier': 2.7.3 + cli-color: 2.0.3 + get-stdin: 8.0.0 + glob: 7.2.3 + glob-promise: 4.2.2(glob@7.2.3) + is-glob: 4.0.3 + lodash: 4.17.21 + minimist: 1.2.8 + mkdirp: 1.0.4 + mz: 2.7.0 + prettier: 2.8.8 + dev: true + + /json-schema-to-typescript@13.1.1: + resolution: {integrity: sha512-F3CYhtA7F3yPbb8vF7sFchk/2dnr1/yTKf8RcvoNpjnh67ZS/ZMH1ElLt5KHAtf2/bymiejLQQszszPWEeTdSw==} + engines: {node: '>=12.0.0'} + hasBin: true + dependencies: + '@bcherny/json-schema-ref-parser': 10.0.5-fork + '@types/json-schema': 7.0.15 + '@types/lodash': 4.14.202 + '@types/prettier': 2.7.3 + cli-color: 2.0.3 + get-stdin: 8.0.0 + glob: 7.2.3 + glob-promise: 4.2.2(glob@7.2.3) + is-glob: 4.0.3 + lodash: 4.17.21 + minimist: 1.2.8 + mkdirp: 1.0.4 + mz: 2.7.0 + prettier: 2.8.8 + dev: true + + /json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + /json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + /json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + /json-stable-stringify@1.1.0: + resolution: {integrity: sha512-zfA+5SuwYN2VWqN1/5HZaDzQKLJHaBVMZIIM+wuYjdptkaQsqzDdqjqf+lZZJUuJq1aanHiY8LhH8LmH+qBYJA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + isarray: 2.0.5 + jsonify: 0.0.1 + object-keys: 1.1.1 + dev: true + + /json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + dev: true + + /json-to-pretty-yaml@1.2.2: + resolution: {integrity: sha512-rvm6hunfCcqegwYaG5T4yKJWxc9FXFgBVrcTZ4XfSVRwa5HA/Xs+vB/Eo9treYYHCeNM0nrSUr82V/M31Urc7A==} + engines: {node: '>= 0.2.0'} + dependencies: + remedial: 1.0.8 + remove-trailing-spaces: 1.0.8 + dev: true + + /json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: true + + /json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + /jsonc-parser@3.2.0: + resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} + + /jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + optionalDependencies: + graceful-fs: 4.2.11 + dev: true + + /jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + dev: true + + /jsonify@0.0.1: + resolution: {integrity: sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==} + dev: true + + /jsx-ast-utils@3.3.5: + resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} + engines: {node: '>=4.0'} + dependencies: + array-includes: 3.1.7 + array.prototype.flat: 1.3.2 + object.assign: 4.1.5 + object.values: 1.1.7 + dev: true + + /keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + dependencies: + json-buffer: 3.0.1 + + /kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + dev: true + + /kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + dev: true + + /kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + dev: true + + /language-subtag-registry@0.3.22: + resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==} + dev: true + + /language-tags@1.0.9: + resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} + engines: {node: '>=0.10'} + dependencies: + language-subtag-registry: 0.3.22 + dev: true + + /levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + /lie@3.1.1: + resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==} + dependencies: + immediate: 3.0.6 + dev: false + + /lilconfig@3.0.0: + resolution: {integrity: sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==} + engines: {node: '>=14'} + dev: true + + /lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + dev: true + + /lint-staged@15.2.0: + resolution: {integrity: sha512-TFZzUEV00f+2YLaVPWBWGAMq7So6yQx+GG8YRMDeOEIf95Zn5RyiLMsEiX4KTNl9vq/w+NqRJkLA1kPIo15ufQ==} + engines: {node: '>=18.12.0'} + hasBin: true + dependencies: + chalk: 5.3.0 + commander: 11.1.0 + debug: 4.3.4 + execa: 8.0.1 + lilconfig: 3.0.0 + listr2: 8.0.0 + micromatch: 4.0.5 + pidtree: 0.6.0 + string-argv: 0.3.2 + yaml: 2.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /listr2@4.0.5: + resolution: {integrity: sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==} + engines: {node: '>=12'} + peerDependencies: + enquirer: '>= 2.3.0 < 3' + peerDependenciesMeta: + enquirer: + optional: true + dependencies: + cli-truncate: 2.1.0 + colorette: 2.0.20 + log-update: 4.0.0 + p-map: 4.0.0 + rfdc: 1.3.0 + rxjs: 7.8.1 + through: 2.3.8 + wrap-ansi: 7.0.0 + dev: true + + /listr2@8.0.0: + resolution: {integrity: sha512-u8cusxAcyqAiQ2RhYvV7kRKNLgUvtObIbhOX2NCXqvp1UU32xIg5CT22ykS2TPKJXZWJwtK3IKLiqAGlGNE+Zg==} + engines: {node: '>=18.0.0'} + dependencies: + cli-truncate: 4.0.0 + colorette: 2.0.20 + eventemitter3: 5.0.1 + log-update: 6.0.0 + rfdc: 1.3.0 + wrap-ansi: 9.0.0 + dev: true + + /load-yaml-file@0.2.0: + resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==} + engines: {node: '>=6'} + dependencies: + graceful-fs: 4.2.11 + js-yaml: 3.14.1 + pify: 4.0.1 + strip-bom: 3.0.0 + dev: true + + /loader-runner@4.3.0: + resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} + engines: {node: '>=6.11.5'} + dev: false + + /loader-utils@2.0.4: + resolution: {integrity: sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==} + engines: {node: '>=8.9.0'} + dependencies: + big.js: 5.2.2 + emojis-list: 3.0.0 + json5: 2.2.3 + dev: false + + /local-pkg@0.4.3: + resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==} + engines: {node: '>=14'} + dev: true + + /localforage@1.10.0: + resolution: {integrity: sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==} + dependencies: + lie: 3.1.1 + dev: false + + /locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: true + + /locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + + /lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + + /lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + /lodash.startcase@4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + dev: true + + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + /log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + dev: true + + /log-update@4.0.0: + resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==} + engines: {node: '>=10'} + dependencies: + ansi-escapes: 4.3.2 + cli-cursor: 3.1.0 + slice-ansi: 4.0.0 + wrap-ansi: 6.2.0 + dev: true + + /log-update@6.0.0: + resolution: {integrity: sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==} + engines: {node: '>=18'} + dependencies: + ansi-escapes: 6.2.0 + cli-cursor: 4.0.0 + slice-ansi: 7.1.0 + strip-ansi: 7.1.0 + wrap-ansi: 9.0.0 + dev: true + + /loglevel@1.8.1: + resolution: {integrity: sha512-tCRIJM51SHjAayKwC+QAg8hT8vg6z7GSgLJKGvzuPb1Wc+hLzqtuVLxp6/HzSPOozuK+8ErAhy7U/sVzw8Dgfg==} + engines: {node: '>= 0.6.0'} + dev: true + + /loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + dependencies: + js-tokens: 4.0.0 + + /loupe@2.3.7: + resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} + dependencies: + get-func-name: 2.0.2 + dev: true + + /lower-case-first@2.0.2: + resolution: {integrity: sha512-EVm/rR94FJTZi3zefZ82fLWab+GX14LJN4HrWBcuo6Evmsl9hEfnqxgcHCKb9q+mNf6EVdsjx/qucYFIIB84pg==} + dependencies: + tslib: 2.6.2 + dev: true + + /lower-case@2.0.2: + resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + dependencies: + tslib: 2.6.2 + dev: true + + /lru-cache@4.1.5: + resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} + dependencies: + pseudomap: 1.0.2 + yallist: 2.1.2 + dev: true + + /lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + dependencies: + yallist: 3.1.1 + + /lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + + /lru-queue@0.1.0: + resolution: {integrity: sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==} + dependencies: + es5-ext: 0.10.62 + dev: true + + /lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + dev: true + + /magic-string@0.27.0: + resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + dev: false + + /magic-string@0.30.5: + resolution: {integrity: sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + dependencies: + semver: 7.5.4 + dev: true + + /make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + dev: true + + /map-cache@0.2.2: + resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} + engines: {node: '>=0.10.0'} + dev: true + + /map-obj@1.0.1: + resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} + engines: {node: '>=0.10.0'} + dev: true + + /map-obj@4.3.0: + resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} + engines: {node: '>=8'} + dev: true + + /media-query-parser@2.0.2: + resolution: {integrity: sha512-1N4qp+jE0pL5Xv4uEcwVUhIkwdUO3S/9gML90nqKA7v7FcOS5vUtatfzok9S9U1EJU8dHWlcv95WLnKmmxZI9w==} + dependencies: + '@babel/runtime': 7.23.6 + + /media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + dev: true + + /memoizee@0.4.15: + resolution: {integrity: sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + es6-weak-map: 2.0.3 + event-emitter: 0.3.5 + is-promise: 2.2.2 + lru-queue: 0.1.0 + next-tick: 1.1.0 + timers-ext: 0.1.7 + dev: true + + /meow@6.1.1: + resolution: {integrity: sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg==} + engines: {node: '>=8'} + dependencies: + '@types/minimist': 1.2.5 + camelcase-keys: 6.2.2 + decamelize-keys: 1.1.1 + hard-rejection: 2.1.0 + minimist-options: 4.1.0 + normalize-package-data: 2.5.0 + read-pkg-up: 7.0.1 + redent: 3.0.0 + trim-newlines: 3.0.1 + type-fest: 0.13.1 + yargs-parser: 18.1.3 + dev: true + + /merge-descriptors@1.0.1: + resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} + dev: true + + /merge-error-cause@5.0.0: + resolution: {integrity: sha512-px3J5V6QJnq5j3WC8gQJPOlCnm3IMz6I4IBU7A/D8713Fk8ptKt1UD1tvEksrsivA3vI39lAr2b/H7A3n9MqKA==} + engines: {node: '>=18.18.0'} + dependencies: + normalize-exception: 3.0.0 + set-error-class: 3.0.0 + set-error-props: 6.0.0 + wrap-error-message: 3.0.0 + dev: false + + /merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + + /meros@1.3.0(@types/node@20.10.4): + resolution: {integrity: sha512-2BNGOimxEz5hmjUG2FwoxCt5HN7BXdaWyFqEwxPTrJzVdABtrL4TiHTcsWSFAxPQ/tOnEaQEJh3qWq71QRMY+w==} + engines: {node: '>=13'} + peerDependencies: + '@types/node': '>=13' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + '@types/node': 20.10.4 + dev: true + + /methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + dev: true + + /micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + + /mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + dev: true + + /mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + dev: true + + /min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + dev: true + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + + /minimatch@4.2.3: + resolution: {integrity: sha512-lIUdtK5hdofgCTu3aT0sOaHsYR37viUuIc0rwnnDXImbwFRcumyLMeZaM0t0I/fgxS6s6JMfu0rLD1Wz9pv1ng==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: false + + /minimist-options@4.1.0: + resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} + engines: {node: '>= 6'} + dependencies: + arrify: 1.0.1 + is-plain-obj: 1.1.0 + kind-of: 6.0.3 + dev: true + + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + /mixme@0.5.10: + resolution: {integrity: sha512-5H76ANWinB1H3twpJ6JY8uvAtpmFvHNArpilJAjXRKXSDDLPIMoZArw5SH0q9z+lLs8IrMw7Q2VWpWimFKFT1Q==} + engines: {node: '>= 8.0.0'} + dev: true + + /mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: false + + /mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + dev: true + + /mlly@1.4.2: + resolution: {integrity: sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg==} + dependencies: + acorn: 8.11.2 + pathe: 1.1.1 + pkg-types: 1.0.3 + ufo: 1.3.2 + + /modern-ahocorasick@1.0.1: + resolution: {integrity: sha512-yoe+JbhTClckZ67b2itRtistFKf8yPYelHLc7e5xAwtNAXxM6wJTUx2C7QeVSJFDzKT7bCIFyBVybPMKvmB9AA==} + + /modern-errors-http@5.0.0(modern-errors@7.0.0): + resolution: {integrity: sha512-fjCxjhQ1YydpyRV9XDt2h0pZMar0I0e17T4teu156UxJ3m5ADOaIgo7eQ2Rl+AAdyo52JX1z1a9r7IFOcoHE8g==} + engines: {node: '>=18.18.0'} + peerDependencies: + modern-errors: ^7.0.0 + dependencies: + error-http-response: 3.0.0 + modern-errors: 7.0.0 + dev: false + + /modern-errors-serialize@6.0.0(modern-errors@7.0.0): + resolution: {integrity: sha512-oqfY6NeiZtFcZW4VIoL8fu3xoP/YMswEsUe6cMKZmj6s8M1f8pTVqC5uhQN9sKmTRxDcA6E00V2Cb3NY8b72SQ==} + engines: {node: '>=18.18.0'} + peerDependencies: + modern-errors: ^7.0.0 + dependencies: + error-serializer: 7.0.0 + is-plain-obj: 4.1.0 + modern-errors: 7.0.0 + dev: false + + /modern-errors@7.0.0: + resolution: {integrity: sha512-4H55sVGQe0JxbBIH9ea9QUkY3BDSpxauyWYXB5W4LCeYEvjEScYxnoHp9cFHxeCvUuf1a1lqJILo/H2kRV37og==} + engines: {node: '>=18.18.0'} + dependencies: + error-class-utils: 4.0.0 + error-custom-class: 10.0.0 + filter-obj: 5.1.0 + is-plain-obj: 4.1.0 + merge-error-cause: 5.0.0 + normalize-exception: 3.0.0 + set-error-message: 3.0.0 + set-error-props: 6.0.0 + set-error-stack: 2.0.0 + dev: false + + /morgan@1.10.0: + resolution: {integrity: sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==} + engines: {node: '>= 0.8.0'} + dependencies: + basic-auth: 2.0.1 + debug: 2.6.9 + depd: 2.0.0 + on-finished: 2.3.0 + on-headers: 1.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + dev: true + + /ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + + /ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + dev: true + + /mute-stream@0.0.8: + resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} + dev: true + + /mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + dev: true + + /nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + /natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + /negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + dev: true + + /neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + dev: false + + /next-test-api-route-handler@3.1.10(next@14.2.10): + resolution: {integrity: sha512-Xg14+hTOI8pD61rwprpMhi9ARo6wC/mMFs0lrDbtgQoQMt9TAeRzwLfCi2Q9o3IOWoiyi62S13xjI/89d9SZRg==} + engines: {node: '>=12'} + peerDependencies: + next: '>=9' + dependencies: + cookie: 0.5.0 + core-js: 3.34.0 + next: 14.2.10(@babel/core@7.23.6)(react-dom@18.2.0)(react@18.2.0) + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + dev: true + + /next-tick@1.1.0: + resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} + dev: true + + /next@14.2.10(@babel/core@7.23.6)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-sDDExXnh33cY3RkS9JuFEKaS4HmlWmDKP1VJioucCG6z5KuA008DPsDZOzi8UfqEk3Ii+2NCQSJrfbEWtZZfww==} + engines: {node: '>=18.17.0'} + hasBin: true + peerDependencies: + '@opentelemetry/api': ^1.1.0 + '@playwright/test': ^1.41.2 + react: ^18.2.0 + react-dom: ^18.2.0 + sass: ^1.3.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + '@playwright/test': + optional: true + sass: + optional: true + dependencies: + '@next/env': 14.2.10 + '@swc/helpers': 0.5.5 + busboy: 1.6.0 + caniuse-lite: 1.0.30001668 + graceful-fs: 4.2.11 + postcss: 8.4.31 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + styled-jsx: 5.1.1(@babel/core@7.23.6)(react@18.2.0) + optionalDependencies: + '@next/swc-darwin-arm64': 14.2.10 + '@next/swc-darwin-x64': 14.2.10 + '@next/swc-linux-arm64-gnu': 14.2.10 + '@next/swc-linux-arm64-musl': 14.2.10 + '@next/swc-linux-x64-gnu': 14.2.10 + '@next/swc-linux-x64-musl': 14.2.10 + '@next/swc-win32-arm64-msvc': 14.2.10 + '@next/swc-win32-ia32-msvc': 14.2.10 + '@next/swc-win32-x64-msvc': 14.2.10 + transitivePeerDependencies: + - '@babel/core' + - babel-plugin-macros + + /no-case@3.0.4: + resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + dependencies: + lower-case: 2.0.2 + tslib: 2.6.2 + dev: true + + /nocache@3.0.4: + resolution: {integrity: sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw==} + engines: {node: '>=12.0.0'} + dev: true + + /nock@13.4.0: + resolution: {integrity: sha512-W8NVHjO/LCTNA64yxAPHV/K47LpGYcVzgKd3Q0n6owhwvD0Dgoterc25R4rnZbckJEb6Loxz1f5QMuJpJnbSyQ==} + engines: {node: '>= 10.13'} + dependencies: + debug: 4.3.4 + json-stringify-safe: 5.0.1 + propagate: 2.0.1 + transitivePeerDependencies: + - supports-color + dev: true + + /node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + + /node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + dev: true + + /node-releases@2.0.14: + resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + + /normalize-exception@3.0.0: + resolution: {integrity: sha512-SMZtWSLjls45KBgwvS2jWyXLtOI9j90JyQ6tJstl91Gti4W7QwZyF/nWwlFRz/Cx4Gy70DAtLT0EzXYXcPJJUw==} + engines: {node: '>=16.17.0'} + dependencies: + is-error-instance: 2.0.0 + is-plain-obj: 4.1.0 + dev: false + + /normalize-package-data@2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + dependencies: + hosted-git-info: 2.8.9 + resolve: 1.22.8 + semver: 5.7.2 + validate-npm-package-license: 3.0.4 + dev: true + + /normalize-path@2.1.1: + resolution: {integrity: sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==} + engines: {node: '>=0.10.0'} + dependencies: + remove-trailing-separator: 1.1.0 + dev: true + + /npm-run-path@5.1.0: + resolution: {integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + path-key: 4.0.0 + dev: true + + /nullthrows@1.1.1: + resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==} + dev: true + + /nwsapi@2.2.7: + resolution: {integrity: sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==} + + /object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + /object-inspect@1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + + /object-is@1.1.5: + resolution: {integrity: sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + dev: true + + /object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: true + + /object.assign@4.1.5: + resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: true + + /object.entries@1.1.7: + resolution: {integrity: sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /object.fromentries@2.0.7: + resolution: {integrity: sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /object.groupby@1.0.1: + resolution: {integrity: sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 + dev: true + + /object.hasown@1.1.3: + resolution: {integrity: sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==} + dependencies: + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /object.values@1.1.7: + resolution: {integrity: sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /omit-deep-lodash@1.1.7: + resolution: {integrity: sha512-9m9gleSMoxq3YO8aCq5pGUrqG9rKF0w/P70JHQ1ymjUQA/3+fVa2Stju9XORJKLmyLYEO3zzX40MJYaYl5Og4w==} + engines: {node: '>=0.10.0'} + dependencies: + lodash: 4.17.21 + dev: false + + /on-exit-leak-free@2.1.2: + resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} + engines: {node: '>=14.0.0'} + dev: false + + /on-finished@2.3.0: + resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} + engines: {node: '>= 0.8'} + dependencies: + ee-first: 1.1.1 + dev: true + + /on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + dependencies: + ee-first: 1.1.1 + dev: true + + /on-headers@1.0.2: + resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==} + engines: {node: '>= 0.8'} + dev: true + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + + /onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + dependencies: + mimic-fn: 2.1.0 + dev: true + + /onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + dependencies: + mimic-fn: 4.0.0 + dev: true + + /optionator@0.9.3: + resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + engines: {node: '>= 0.8.0'} + dependencies: + '@aashutoshrathi/word-wrap': 1.2.6 + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + + /ora@5.4.1: + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.9.2 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + dev: true + + /os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + dev: true + + /outdent@0.5.0: + resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} + dev: true + + /outdent@0.8.0: + resolution: {integrity: sha512-KiOAIsdpUTcAXuykya5fnVVT+/5uS0Q1mrkRHcF89tpieSmY33O/tmc54CqwA+bfhbtEfZUNLHaPUiB9X3jt1A==} + + /p-filter@2.1.0: + resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} + engines: {node: '>=8'} + dependencies: + p-map: 2.1.0 + dev: true + + /p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: true + + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + + /p-limit@4.0.0: + resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + yocto-queue: 1.0.0 + dev: true + + /p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: true + + /p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + + /p-map@2.1.0: + resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} + engines: {node: '>=6'} + dev: true + + /p-map@4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + dependencies: + aggregate-error: 3.1.0 + dev: true + + /p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: true + + /param-case@3.0.4: + resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} + dependencies: + dot-case: 3.0.4 + tslib: 2.6.2 + dev: true + + /parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + + /parse-filepath@1.0.2: + resolution: {integrity: sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==} + engines: {node: '>=0.8'} + dependencies: + is-absolute: 1.0.0 + map-cache: 0.2.2 + path-root: 0.1.1 + dev: true + + /parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.23.5 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: true + + /parse5@7.1.2: + resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + dependencies: + entities: 4.5.0 + + /parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + dev: true + + /pascal-case@3.1.2: + resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} + dependencies: + no-case: 3.0.4 + tslib: 2.6.2 + dev: true + + /path-case@3.0.4: + resolution: {integrity: sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==} + dependencies: + dot-case: 3.0.4 + tslib: 2.6.2 + dev: true + + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + /path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + dev: true + + /path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + /path-root-regex@0.1.2: + resolution: {integrity: sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==} + engines: {node: '>=0.10.0'} + dev: true + + /path-root@0.1.1: + resolution: {integrity: sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==} + engines: {node: '>=0.10.0'} + dependencies: + path-root-regex: 0.1.2 + dev: true + + /path-to-regexp@0.1.7: + resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} + dev: true + + /path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: true + + /pathe@1.1.1: + resolution: {integrity: sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==} + + /pathval@1.1.1: + resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + dev: true + + /picocolors@1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + /picomatch@3.0.1: + resolution: {integrity: sha512-I3EurrIQMlRc9IaAZnqRR044Phh2DXY+55o7uJ0V+hYZAcQYSuFWsc9q5PvyDHUSCe1Qxn/iBz+78s86zWnGag==} + engines: {node: '>=10'} + dev: true + + /pidtree@0.6.0: + resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} + engines: {node: '>=0.10'} + hasBin: true + dev: true + + /pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + dev: true + + /pino-abstract-transport@1.1.0: + resolution: {integrity: sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==} + dependencies: + readable-stream: 4.4.2 + split2: 4.2.0 + dev: false + + /pino-pretty@10.2.3: + resolution: {integrity: sha512-4jfIUc8TC1GPUfDyMSlW1STeORqkoxec71yhxIpLDQapUu8WOuoz2TTCoidrIssyz78LZC69whBMPIKCMbi3cw==} + hasBin: true + dependencies: + colorette: 2.0.20 + dateformat: 4.6.3 + fast-copy: 3.0.1 + fast-safe-stringify: 2.1.1 + help-me: 4.2.0 + joycon: 3.1.1 + minimist: 1.2.8 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 1.1.0 + pump: 3.0.0 + readable-stream: 4.4.2 + secure-json-parse: 2.7.0 + sonic-boom: 3.7.0 + strip-json-comments: 3.1.1 + dev: false + + /pino-std-serializers@6.2.2: + resolution: {integrity: sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==} + dev: false + + /pino@8.16.2: + resolution: {integrity: sha512-2advCDGVEvkKu9TTVSa/kWW7Z3htI/sBKEZpqiHk6ive0i/7f5b1rsU8jn0aimxqfnSz5bj/nOYkwhBUn5xxvg==} + hasBin: true + dependencies: + atomic-sleep: 1.0.0 + fast-redact: 3.3.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 1.1.0 + pino-std-serializers: 6.2.2 + process-warning: 2.3.2 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.4.3 + sonic-boom: 3.7.0 + thread-stream: 2.4.1 + dev: false + + /pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + dev: true + + /pkg-types@1.0.3: + resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==} + dependencies: + jsonc-parser: 3.2.0 + mlly: 1.4.2 + pathe: 1.1.1 + + /postcss-load-config@4.0.2(postcss@8.4.32)(ts-node@10.9.2): + resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + dependencies: + lilconfig: 3.0.0 + postcss: 8.4.32 + ts-node: 10.9.2(@types/node@20.10.4)(typescript@5.3.3) + yaml: 2.3.4 + dev: true + + /postcss@8.4.31: + resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.0 + source-map-js: 1.0.2 + + /postcss@8.4.32: + resolution: {integrity: sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.0 + source-map-js: 1.0.2 + + /preferred-pm@3.1.2: + resolution: {integrity: sha512-nk7dKrcW8hfCZ4H6klWcdRknBOXWzNQByJ0oJyX97BOupsYD+FzLS4hflgEu/uPUEHZCuRfMxzCBsuWd7OzT8Q==} + engines: {node: '>=10'} + dependencies: + find-up: 5.0.0 + find-yarn-workspace-root2: 1.2.16 + path-exists: 4.0.0 + which-pm: 2.0.0 + dev: true + + /prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + /prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + dev: true + + /prettier@3.1.1: + resolution: {integrity: sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==} + engines: {node: '>=14'} + hasBin: true + dev: true + + /pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + dev: true + + /pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.2.0 + dev: true + + /process-warning@2.3.2: + resolution: {integrity: sha512-n9wh8tvBe5sFmsqlg+XQhaQLumwpqoAUruLwjCopgTmUBjJ/fjtBsJzKleCaIGBOMXYEhp1YfKl4d7rJ5ZKJGA==} + dev: false + + /process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + dev: false + + /progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + dev: false + + /promise@7.3.1: + resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==} + dependencies: + asap: 2.0.6 + dev: true + + /prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + dev: true + + /prop-types@15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + + /propagate@2.0.1: + resolution: {integrity: sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==} + engines: {node: '>= 8'} + dev: true + + /property-expr@2.0.6: + resolution: {integrity: sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==} + dev: false + + /proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + dev: true + + /proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + dev: false + + /pseudomap@1.0.2: + resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} + dev: true + + /psl@1.9.0: + resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} + + /pump@3.0.0: + resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + dev: false + + /punycode@1.4.1: + resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} + dev: true + + /punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + /pvtsutils@1.3.5: + resolution: {integrity: sha512-ARvb14YB9Nm2Xi6nBq1ZX6dAM0FsJnuk+31aUp4TrcZEdKUlSqOqsxJHUPJDNE3qiIp+iUPEIeR6Je/tgV7zsA==} + dependencies: + tslib: 2.6.2 + dev: true + + /pvutils@1.1.3: + resolution: {integrity: sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==} + engines: {node: '>=6.0.0'} + dev: true + + /qs@6.11.0: + resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.4 + dev: true + + /qs@6.11.2: + resolution: {integrity: sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.4 + + /querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + /quick-format-unescaped@4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + dev: false + + /quick-lru@4.0.1: + resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} + engines: {node: '>=8'} + dev: true + + /randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + dev: true + + /raw-body@2.5.1: + resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: true + + /raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + + /react-dom@18.2.0(react@18.2.0): + resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} + peerDependencies: + react: ^18.2.0 + dependencies: + loose-envify: 1.4.0 + react: 18.2.0 + scheduler: 0.23.0 + + /react-error-boundary@3.1.4(react@18.2.0): + resolution: {integrity: sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==} + engines: {node: '>=10', npm: '>=6'} + peerDependencies: + react: '>=16.13.1' + dependencies: + '@babel/runtime': 7.23.6 + react: 18.2.0 + dev: true + + /react-from-dom@0.6.2(react@18.2.0): + resolution: {integrity: sha512-qvWWTL/4xw4k/Dywd41RBpLQUSq97csuv15qrxN+izNeLYlD9wn5W8LspbfYe5CWbaSdkZ72BsaYBPQf2x4VbQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + react: 18.2.0 + dev: false + + /react-hook-form@7.49.1(react@18.2.0): + resolution: {integrity: sha512-MId71bfWmpyvwuWjVTe2b4DRc0jIYOb/B9tlrotEHTuHlQGeX1x2QXfjNe9UtMi6TqhO0bsSdSWgjcUFh2fSww==} + engines: {node: '>=18', pnpm: '8'} + peerDependencies: + react: ^16.8.0 || ^17 || ^18 + dependencies: + react: 18.2.0 + dev: false + + /react-inlinesvg@3.0.3(react@18.2.0): + resolution: {integrity: sha512-D9wqEyh1+ni07+CP2yaD9nSK11Y2ngd79xudEilX7YHKmUCeP1lXZqFvuLbdOo+m+oEjekd+c0DBc/bj93Lwqg==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + exenv: 1.2.2 + react: 18.2.0 + react-from-dom: 0.6.2(react@18.2.0) + dev: false + + /react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + + /react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + + /react-is@18.2.0: + resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} + dev: true + + /react-refresh@0.14.0: + resolution: {integrity: sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==} + engines: {node: '>=0.10.0'} + dev: false + + /react-remove-scroll-bar@2.3.4(@types/react@18.2.45)(react@18.2.0): + resolution: {integrity: sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.2.45 + react: 18.2.0 + react-style-singleton: 2.2.1(@types/react@18.2.45)(react@18.2.0) + tslib: 2.6.2 + dev: false + + /react-remove-scroll@2.5.5(@types/react@18.2.45)(react@18.2.0): + resolution: {integrity: sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.2.45 + react: 18.2.0 + react-remove-scroll-bar: 2.3.4(@types/react@18.2.45)(react@18.2.0) + react-style-singleton: 2.2.1(@types/react@18.2.45)(react@18.2.0) + tslib: 2.6.2 + use-callback-ref: 1.3.0(@types/react@18.2.45)(react@18.2.0) + use-sidecar: 1.1.2(@types/react@18.2.45)(react@18.2.0) + dev: false + + /react-ssr-prepass@1.5.0(react@18.2.0): + resolution: {integrity: sha512-yFNHrlVEReVYKsLI5lF05tZoHveA5pGzjFbFJY/3pOqqjGOmMmqx83N4hIjN2n6E1AOa+eQEUxs3CgRnPmT0RQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + react: 18.2.0 + dev: false + + /react-style-singleton@2.2.1(@types/react@18.2.45)(react@18.2.0): + resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.2.45 + get-nonce: 1.0.1 + invariant: 2.2.4 + react: 18.2.0 + tslib: 2.6.2 + dev: false + + /react@18.2.0: + resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} + engines: {node: '>=0.10.0'} + dependencies: + loose-envify: 1.4.0 + + /read-pkg-up@7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + read-pkg: 5.2.0 + type-fest: 0.8.1 + dev: true + + /read-pkg@5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + dependencies: + '@types/normalize-package-data': 2.4.4 + normalize-package-data: 2.5.0 + parse-json: 5.2.0 + type-fest: 0.6.0 + dev: true + + /read-yaml-file@1.1.0: + resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} + engines: {node: '>=6'} + dependencies: + graceful-fs: 4.2.11 + js-yaml: 3.14.1 + pify: 4.0.1 + strip-bom: 3.0.0 + dev: true + + /readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + /readable-stream@4.4.2: + resolution: {integrity: sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + abort-controller: 3.0.0 + buffer: 6.0.3 + events: 3.3.0 + process: 0.11.10 + string_decoder: 1.3.0 + dev: false + + /real-require@0.2.0: + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} + engines: {node: '>= 12.13.0'} + dev: false + + /rechoir@0.8.0: + resolution: {integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==} + engines: {node: '>= 10.13.0'} + dependencies: + resolve: 1.22.8 + dev: true + + /redefine-property@3.0.0: + resolution: {integrity: sha512-ccnADJaJkclGGzRuc8kaNBHmoyOwW+Da2DyPQdiccMdlMyvPvCtIa6kN0sKz+JiW43dQEGFiCSNjyObi372ptA==} + engines: {node: '>=18.18.0'} + dependencies: + is-plain-obj: 4.1.0 + dev: false + + /redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + dev: true + + /reflect.getprototypeof@1.0.4: + resolution: {integrity: sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 + globalthis: 1.0.3 + which-builtin-type: 1.1.3 + dev: true + + /regenerator-runtime@0.14.0: + resolution: {integrity: sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==} + + /regexp-tree@0.1.27: + resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} + hasBin: true + dev: true + + /regexp.prototype.flags@1.5.1: + resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + set-function-name: 2.0.1 + dev: true + + /regexpp@3.2.0: + resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} + engines: {node: '>=8'} + dev: false + + /relay-runtime@12.0.0: + resolution: {integrity: sha512-QU6JKr1tMsry22DXNy9Whsq5rmvwr3LSZiiWV/9+DFpuTWvp+WFhobWMc8TC4OjKFfNhEZy7mOiqUAn5atQtug==} + dependencies: + '@babel/runtime': 7.23.6 + fbjs: 3.0.5 + invariant: 2.2.4 + transitivePeerDependencies: + - encoding + dev: true + + /remedial@1.0.8: + resolution: {integrity: sha512-/62tYiOe6DzS5BqVsNpH/nkGlX45C/Sp6V+NtiN6JQNS1Viay7cWkazmRkrQrdFj2eshDe96SIQNIoMxqhzBOg==} + dev: true + + /remove-accents@0.4.2: + resolution: {integrity: sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==} + dev: false + + /remove-trailing-separator@1.1.0: + resolution: {integrity: sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==} + dev: true + + /remove-trailing-spaces@1.0.8: + resolution: {integrity: sha512-O3vsMYfWighyFbTd8hk8VaSj9UAGENxAtX+//ugIst2RMk5e03h6RoIS+0ylsFxY1gvmPuAY/PO4It+gPEeySA==} + dev: true + + /require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: true + + /require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + /require-like@0.1.2: + resolution: {integrity: sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==} + + /require-main-filename@2.0.0: + resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + dev: true + + /requireindex@1.1.0: + resolution: {integrity: sha512-LBnkqsDE7BZKvqylbmn7lTIVdpx4K/QCduRATpO5R+wtPmky/a8pN1bO2D6wXppn1497AJF9mNjqAXr6bdl9jg==} + engines: {node: '>=0.10.5'} + dev: true + + /requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + + /resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + /resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + dev: true + + /resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + /resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + /resolve@2.0.0-next.5: + resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} + hasBin: true + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /restore-cursor@3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + dev: true + + /restore-cursor@4.0.0: + resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + dev: true + + /retes@0.33.0: + resolution: {integrity: sha512-I6V1G2JkJ2JFIFSVuultNXepf7BW8SCaSUOq5IETM2fDjFim5Dg5F1zU/QbplNW0mqkk8QCw+I722v3nPkpRlA==} + dependencies: + busboy: 1.6.0 + zod: 3.22.4 + dev: false + + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + /rfdc@1.3.0: + resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} + dev: true + + /rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + + /rollup@2.78.0: + resolution: {integrity: sha512-4+YfbQC9QEVvKTanHhIAFVUFSRsezvQF8vFOJwtGfb9Bb+r014S+qryr9PSmw8x6sMnPkmFBGAvIFVQxvJxjtg==} + engines: {node: '>=10.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.3 + dev: false + + /rollup@4.9.0: + resolution: {integrity: sha512-bUHW/9N21z64gw8s6tP4c88P382Bq/L5uZDowHlHx6s/QWpjJXivIAbEw6LZthgSvlEizZBfLC4OAvWe7aoF7A==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.9.0 + '@rollup/rollup-android-arm64': 4.9.0 + '@rollup/rollup-darwin-arm64': 4.9.0 + '@rollup/rollup-darwin-x64': 4.9.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.9.0 + '@rollup/rollup-linux-arm64-gnu': 4.9.0 + '@rollup/rollup-linux-arm64-musl': 4.9.0 + '@rollup/rollup-linux-riscv64-gnu': 4.9.0 + '@rollup/rollup-linux-x64-gnu': 4.9.0 + '@rollup/rollup-linux-x64-musl': 4.9.0 + '@rollup/rollup-win32-arm64-msvc': 4.9.0 + '@rollup/rollup-win32-ia32-msvc': 4.9.0 + '@rollup/rollup-win32-x64-msvc': 4.9.0 + fsevents: 2.3.3 + + /route-recognizer@0.3.4: + resolution: {integrity: sha512-2+MhsfPhvauN1O8KaXpXAOfR/fwe8dnUXVM+xw7yt40lJRfPVQxV6yryZm0cgRvAj5fMF/mdRZbL2ptwbs5i2g==} + dev: true + + /rrweb-cssom@0.6.0: + resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==} + + /run-async@2.4.1: + resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} + engines: {node: '>=0.12.0'} + dev: true + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + + /rxjs@7.8.1: + resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} + dependencies: + tslib: 2.6.2 + dev: true + + /safe-array-concat@1.0.1: + resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==} + engines: {node: '>=0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + has-symbols: 1.0.3 + isarray: 2.0.5 + dev: true + + /safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + dev: true + + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + /safe-json-value@3.0.0: + resolution: {integrity: sha512-d9NN/9QDNTfhHr3K1gGdDCn7K0OBvBHrNDwA4PqGPkn6nUmQL7GzMPBC+nmkY7G450B26wkfu7lZTVH7CJ+Jgw==} + engines: {node: '>=18.18.0'} + dependencies: + is-plain-obj: 4.1.0 + normalize-exception: 3.0.0 + dev: false + + /safe-regex-test@1.0.0: + resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + is-regex: 1.1.4 + dev: true + + /safe-regex@2.1.1: + resolution: {integrity: sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==} + dependencies: + regexp-tree: 0.1.27 + dev: true + + /safe-stable-stringify@2.4.3: + resolution: {integrity: sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==} + engines: {node: '>=10'} + dev: false + + /safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + /saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + dependencies: + xmlchars: 2.2.0 + + /scheduler@0.23.0: + resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} + dependencies: + loose-envify: 1.4.0 + + /schema-utils@3.3.0: + resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + ajv-keywords: 3.5.2(ajv@6.12.6) + dev: false + + /scuid@1.1.0: + resolution: {integrity: sha512-MuCAyrGZcTLfQoH2XoBlQ8C6bzwN88XT/0slOGz0pn8+gIP85BOAfYa44ZXQUTOwRwPU0QvgU+V+OSajl/59Xg==} + dev: true + + /secure-json-parse@2.7.0: + resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} + dev: false + + /semver-try-require@6.2.3: + resolution: {integrity: sha512-6q1N/Vr/4/G0EcQ1k4svN5kwfh3MJs4Gfl+zBAVcKn+AeIjKLwTXQ143Y6YHu6xEeN5gSCbCD1/5+NwCipLY5A==} + engines: {node: ^14||^16||>=18} + dependencies: + semver: 7.5.4 + dev: true + + /semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + dev: true + + /semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + /semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + + /send@0.18.0: + resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} + engines: {node: '>= 0.8.0'} + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + dev: true + + /sentence-case@3.0.4: + resolution: {integrity: sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==} + dependencies: + no-case: 3.0.4 + tslib: 2.6.2 + upper-case-first: 2.0.2 + dev: true + + /serialize-javascript@6.0.1: + resolution: {integrity: sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==} + dependencies: + randombytes: 2.1.0 + dev: false + + /serve-static@1.15.0: + resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} + engines: {node: '>= 0.8.0'} + dependencies: + encodeurl: 1.0.2 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.18.0 + transitivePeerDependencies: + - supports-color + dev: true + + /set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + dev: true + + /set-cookie-parser@2.6.0: + resolution: {integrity: sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==} + dev: true + + /set-error-class@3.0.0: + resolution: {integrity: sha512-a2Ham0lVgvzp14cm2Z2LM2Ae1HzxI8G+LX6Rv+eTVzM5+pfPU7UtJBSOXktxoBlqlmaPsZmZRR84qY+CoHt6bg==} + engines: {node: '>=18.18.0'} + dependencies: + normalize-exception: 3.0.0 + dev: false + + /set-error-message@3.0.0: + resolution: {integrity: sha512-CaNAe+/oXwT2XqGtK1plJOZYBi+cpwliSiL8yqO00c3Hvp3w4Tjo95ndv/bEJUM/7sWSw+ctF6J5GbiqF98lFQ==} + engines: {node: '>=18.18.0'} + dependencies: + normalize-exception: 3.0.0 + dev: false + + /set-error-props@6.0.0: + resolution: {integrity: sha512-vJ7lRuvcn5NTbuT7QS8k+dh6AN5y1R/V2xZmlwvB48bJ2b8v46z+dgx5k1VGrB9xt7ZnC98jWcikHb6gyIJgAg==} + engines: {node: '>=18.18.0'} + dependencies: + is-error-instance: 3.0.0 + is-plain-obj: 4.1.0 + redefine-property: 3.0.0 + dev: false + + /set-error-stack@2.0.0: + resolution: {integrity: sha512-mABWr7mmaY1EVBMXWo32t6byRkKclJ3gipglE2+XGBZxDEk0+zVumRfWyAK3s/EB/TbbUm1Gp0H8VvqlFkMa+g==} + engines: {node: '>=16.17.0'} + dependencies: + normalize-exception: 3.0.0 + dev: false + + /set-function-length@1.1.1: + resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + get-intrinsic: 1.2.2 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + + /set-function-name@2.0.1: + resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.1 + dev: true + + /setimmediate@1.0.5: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + dev: true + + /setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + /setup-polly-jest@0.11.0(@pollyjs/core@6.0.6): + resolution: {integrity: sha512-3ywsCFGfCvfi3ZpwYyDc4YDPNiB70QtjODoKFD5hbhza1GMOh0ZzAYUZO9OBmo/1isasynxcS5WzKYMyDJUeZw==} + peerDependencies: + '@pollyjs/core': '*' + dependencies: + '@pollyjs/core': 6.0.6 + dev: true + + /shebang-command@1.2.0: + resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} + engines: {node: '>=0.10.0'} + dependencies: + shebang-regex: 1.0.0 + dev: true + + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + + /shebang-regex@1.0.0: + resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} + engines: {node: '>=0.10.0'} + dev: true + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + /shell-quote@1.8.1: + resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} + dev: true + + /side-channel@1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + object-inspect: 1.13.1 + + /siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + dev: true + + /signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: true + + /signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + dev: true + + /signedsource@1.0.0: + resolution: {integrity: sha512-6+eerH9fEnNmi/hyM1DXcRK3pWdoMQtlkQ+ns0ntzunjKqp5i3sKCc80ym8Fib3iaYhdJUOPdhlJWj1tvge2Ww==} + dev: true + + /sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + dev: true + + /slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true + + /slice-ansi@3.0.0: + resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + dev: true + + /slice-ansi@4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + dev: true + + /slice-ansi@5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 4.0.0 + dev: true + + /slice-ansi@7.1.0: + resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} + engines: {node: '>=18'} + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 5.0.0 + dev: true + + /slugify@1.6.6: + resolution: {integrity: sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==} + engines: {node: '>=8.0.0'} + dev: true + + /smartwrap@2.0.2: + resolution: {integrity: sha512-vCsKNQxb7PnCNd2wY1WClWifAc2lwqsG8OaswpJkVJsvMGcnEntdTCDajZCkk93Ay1U3t/9puJmb525Rg5MZBA==} + engines: {node: '>=6'} + hasBin: true + dependencies: + array.prototype.flat: 1.3.2 + breakword: 1.0.6 + grapheme-splitter: 1.0.4 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + yargs: 15.4.1 + dev: true + + /snake-case@3.0.4: + resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} + dependencies: + dot-case: 3.0.4 + tslib: 2.6.2 + dev: true + + /sonic-boom@3.7.0: + resolution: {integrity: sha512-IudtNvSqA/ObjN97tfgNmOKyDOs4dNcg4cUUsHDebqsgb8wGBBwb31LIgShNO8fye0dFI52X1+tFoKKI6Rq1Gg==} + dependencies: + atomic-sleep: 1.0.0 + dev: false + + /source-map-js@1.0.2: + resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} + engines: {node: '>=0.10.0'} + + /source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + /source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + /spawndamnit@2.0.0: + resolution: {integrity: sha512-j4JKEcncSjFlqIwU5L/rp2N5SIPsdxaRsIv678+TZxZ0SRDJTm8JrxJMjE/XuiEZNEir3S8l0Fa3Ke339WI4qA==} + dependencies: + cross-spawn: 5.1.0 + signal-exit: 3.0.7 + dev: true + + /spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.16 + dev: true + + /spdx-exceptions@2.3.0: + resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} + dev: true + + /spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + dependencies: + spdx-exceptions: 2.3.0 + spdx-license-ids: 3.0.16 + dev: true + + /spdx-license-ids@3.0.16: + resolution: {integrity: sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==} + dev: true + + /split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + dev: false + + /sponge-case@1.0.1: + resolution: {integrity: sha512-dblb9Et4DAtiZ5YSUZHLl4XhH4uK80GhAZrVXdN4O2P4gQ40Wa5UIOPUHlA/nFd2PLblBZWUioLMMAVrgpoYcA==} + dependencies: + tslib: 2.6.2 + dev: true + + /sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: true + + /stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + dev: true + + /stacktrace-parser@0.1.10: + resolution: {integrity: sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==} + engines: {node: '>=6'} + dependencies: + type-fest: 0.7.1 + dev: false + + /statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + + /std-env@3.6.0: + resolution: {integrity: sha512-aFZ19IgVmhdB2uX599ve2kE6BIE3YMnQ6Gp6BURhW/oIzpXGKr878TQfAQZn1+i0Flcc/UKUy1gOlcfaUBCryg==} + dev: true + + /stop-iteration-iterator@1.0.0: + resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} + engines: {node: '>= 0.4'} + dependencies: + internal-slot: 1.0.6 + dev: true + + /stream-transform@2.1.3: + resolution: {integrity: sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==} + dependencies: + mixme: 0.5.10 + dev: true + + /streamsearch@1.1.0: + resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} + engines: {node: '>=10.0.0'} + + /string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + dev: true + + /string-env-interpolation@1.0.1: + resolution: {integrity: sha512-78lwMoCcn0nNu8LszbP1UA7g55OeE4v7rCeWnM5B453rnNr4aq+5it3FEYtZrSEiMvHZOZ9Jlqb0OD0M2VInqg==} + dev: true + + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: true + + /string-width@7.0.0: + resolution: {integrity: sha512-GPQHj7row82Hjo9hKZieKcHIhaAIKOJvFSIZXuCU9OASVZrMNUaZuz++SPVrBjnLsnk4k+z9f2EIypgxf2vNFw==} + engines: {node: '>=18'} + dependencies: + emoji-regex: 10.3.0 + get-east-asian-width: 1.2.0 + strip-ansi: 7.1.0 + dev: true + + /string.prototype.matchall@4.0.10: + resolution: {integrity: sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 + has-symbols: 1.0.3 + internal-slot: 1.0.6 + regexp.prototype.flags: 1.5.1 + set-function-name: 2.0.1 + side-channel: 1.0.4 + dev: true + + /string.prototype.trim@1.2.8: + resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /string.prototype.trimend@1.0.7: + resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /string.prototype.trimstart@1.0.7: + resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + + /strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + dependencies: + ansi-regex: 6.0.1 + dev: true + + /strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + dev: true + + /strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + dev: true + + /strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + dependencies: + min-indent: 1.0.1 + dev: true + + /strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + /strip-literal@1.3.0: + resolution: {integrity: sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==} + dependencies: + acorn: 8.11.2 + dev: true + + /stripe-event-types@3.1.0(stripe@14.8.0): + resolution: {integrity: sha512-jhPNX5FL81QiBFadek3h+PBQKU5Xg3NURTia6tzyqieDStESbvKqOhnA29ECdA1lPB8KSB5/xdK20k6Q1yOejQ==} + peerDependencies: + stripe: '>=10.0.0' + dependencies: + stripe: 14.8.0 + dev: false + + /stripe@14.8.0: + resolution: {integrity: sha512-Qdecqk7lx095BE829NWxrG1+69NjPuHrpZqeR61i2KO00fpKkjMX9TYjwFU+WjQD6ZcNmCGOwNfnz5VnI5bjIg==} + engines: {node: '>=12.*'} + dependencies: + '@types/node': 20.10.4 + qs: 6.11.2 + dev: false + + /styled-jsx@5.1.1(@babel/core@7.23.6)(react@18.2.0): + resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==} + engines: {node: '>= 12.0.0'} + peerDependencies: + '@babel/core': '*' + babel-plugin-macros: '*' + react: '>= 16.8.0 || 17.x.x || ^18.0.0-0' + peerDependenciesMeta: + '@babel/core': + optional: true + babel-plugin-macros: + optional: true + dependencies: + '@babel/core': 7.23.6 + client-only: 0.0.1 + react: 18.2.0 + + /superjson@1.13.3: + resolution: {integrity: sha512-mJiVjfd2vokfDxsQPOwJ/PtanO87LhpYY88ubI5dUB1Ab58Txbyje3+jpm+/83R/fevaq/107NNhtYBLuoTrFg==} + engines: {node: '>=10'} + dependencies: + copy-anything: 3.0.5 + dev: false + + /supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + + /supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + dependencies: + has-flag: 4.0.0 + dev: false + + /supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + /swap-case@2.0.2: + resolution: {integrity: sha512-kc6S2YS/2yXbtkSMunBtKdah4VFETZ8Oh6ONSmSd9bRxhqTrtARUCBUiWXH3xVPpvR7tz2CSnkuXVE42EcGnMw==} + dependencies: + tslib: 2.6.2 + dev: true + + /symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + + /tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + + /teamcity-service-messages@0.1.14: + resolution: {integrity: sha512-29aQwaHqm8RMX74u2o/h1KbMLP89FjNiMxD9wbF2BbWOnbM+q+d1sCEC+MqCc4QW3NJykn77OMpTFw/xTHIc0w==} + dev: true + + /term-size@2.2.1: + resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} + engines: {node: '>=8'} + dev: true + + /terser-webpack-plugin@5.3.10(webpack@5.94.0): + resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==} + engines: {node: '>= 10.13.0'} + peerDependencies: + '@swc/core': '*' + esbuild: '*' + uglify-js: '*' + webpack: ^5.1.0 + peerDependenciesMeta: + '@swc/core': + optional: true + esbuild: + optional: true + uglify-js: + optional: true + dependencies: + '@jridgewell/trace-mapping': 0.3.20 + jest-worker: 27.5.1 + schema-utils: 3.3.0 + serialize-javascript: 6.0.1 + terser: 5.26.0 + webpack: 5.94.0 + dev: false + + /terser@5.26.0: + resolution: {integrity: sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ==} + engines: {node: '>=10'} + hasBin: true + dependencies: + '@jridgewell/source-map': 0.3.5 + acorn: 8.11.2 + commander: 2.20.3 + source-map-support: 0.5.21 + dev: false + + /test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + dev: true + + /text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + + /thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + dependencies: + thenify: 3.3.1 + dev: true + + /thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + dependencies: + any-promise: 1.3.0 + dev: true + + /thread-stream@2.4.1: + resolution: {integrity: sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg==} + dependencies: + real-require: 0.2.0 + dev: false + + /through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + dev: true + + /timers-ext@0.1.7: + resolution: {integrity: sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==} + dependencies: + es5-ext: 0.10.62 + next-tick: 1.1.0 + dev: true + + /tiny-case@1.0.3: + resolution: {integrity: sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==} + dev: false + + /tinybench@2.5.1: + resolution: {integrity: sha512-65NKvSuAVDP/n4CqH+a9w2kTlLReS9vhsAP06MWx+/89nMinJyB2icyl58RIcqCmIggpojIGeuJGhjU1aGMBSg==} + dev: true + + /tinypool@0.7.0: + resolution: {integrity: sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==} + engines: {node: '>=14.0.0'} + dev: true + + /tinyspy@2.2.0: + resolution: {integrity: sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==} + engines: {node: '>=14.0.0'} + dev: true + + /title-case@3.0.3: + resolution: {integrity: sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA==} + dependencies: + tslib: 2.6.2 + dev: true + + /tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + dependencies: + os-tmpdir: 1.0.2 + dev: true + + /to-arraybuffer@1.0.1: + resolution: {integrity: sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==} + dev: true + + /to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + /toposort@2.0.2: + resolution: {integrity: sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==} + dev: false + + /tough-cookie@4.1.3: + resolution: {integrity: sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==} + engines: {node: '>=6'} + dependencies: + psl: 1.9.0 + punycode: 2.3.1 + universalify: 0.2.0 + url-parse: 1.5.10 + + /tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + /tr46@5.0.0: + resolution: {integrity: sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==} + engines: {node: '>=18'} + dependencies: + punycode: 2.3.1 + + /trim-newlines@3.0.1: + resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} + engines: {node: '>=8'} + dev: true + + /ts-api-utils@1.0.3(typescript@5.3.3): + resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==} + engines: {node: '>=16.13.0'} + peerDependencies: + typescript: '>=4.2.0' + dependencies: + typescript: 5.3.3 + dev: true + + /ts-log@2.2.5: + resolution: {integrity: sha512-PGcnJoTBnVGy6yYNFxWVNkdcAuAMstvutN9MgDJIV6L0oG8fB+ZNNy1T+wJzah8RPGor1mZuPQkVfXNDpy9eHA==} + dev: true + + /ts-node@10.9.2(@types/node@20.10.4)(typescript@5.3.3): + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.9 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 20.10.4 + acorn: 8.11.2 + acorn-walk: 8.3.1 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.3.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + dev: true + + /tsconfck@2.1.2(typescript@5.3.3): + resolution: {integrity: sha512-ghqN1b0puy3MhhviwO2kGF8SeMDNhEbnKxjK7h6+fvY9JAxqvXi8y5NAHSQv687OVboS2uZIByzGd45/YxrRHg==} + engines: {node: ^14.13.1 || ^16 || >=18} + hasBin: true + peerDependencies: + typescript: ^4.3.5 || ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + dependencies: + typescript: 5.3.3 + dev: true + + /tsconfig-paths-webpack-plugin@4.1.0: + resolution: {integrity: sha512-xWFISjviPydmtmgeUAuXp4N1fky+VCtfhOkDUFIv5ea7p4wuTomI4QTrXvFBX2S4jZsmyTSrStQl+E+4w+RzxA==} + engines: {node: '>=10.13.0'} + dependencies: + chalk: 4.1.2 + enhanced-resolve: 5.15.0 + tsconfig-paths: 4.2.0 + dev: true + + /tsconfig-paths@3.14.2: + resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==} + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + dev: true + + /tsconfig-paths@4.2.0: + resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} + engines: {node: '>=6'} + dependencies: + json5: 2.2.3 + minimist: 1.2.8 + strip-bom: 3.0.0 + dev: true + + /tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + dev: true + + /tslib@2.4.1: + resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} + dev: true + + /tslib@2.5.3: + resolution: {integrity: sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==} + dev: true + + /tslib@2.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + + /tsutils@3.21.0(typescript@5.3.3): + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + engines: {node: '>= 6'} + peerDependencies: + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + dependencies: + tslib: 1.14.1 + typescript: 5.3.3 + dev: true + + /tsx@4.6.2: + resolution: {integrity: sha512-QPpBdJo+ZDtqZgAnq86iY/PD2KYCUPSUGIunHdGwyII99GKH+f3z3FZ8XNFLSGQIA4I365ui8wnQpl8OKLqcsg==} + engines: {node: '>=18.0.0'} + hasBin: true + dependencies: + esbuild: 0.18.20 + get-tsconfig: 4.7.2 + optionalDependencies: + fsevents: 2.3.3 + dev: false + + /tty-table@4.2.3: + resolution: {integrity: sha512-Fs15mu0vGzCrj8fmJNP7Ynxt5J7praPXqFN0leZeZBXJwkMxv9cb2D454k1ltrtUSJbZ4yH4e0CynsHLxmUfFA==} + engines: {node: '>=8.0.0'} + hasBin: true + dependencies: + chalk: 4.1.2 + csv: 5.5.3 + kleur: 4.1.5 + smartwrap: 2.0.2 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + yargs: 17.7.2 + dev: true + + /type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + + /type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + dev: true + + /type-fest@0.13.1: + resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} + engines: {node: '>=10'} + dev: true + + /type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + + /type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + dev: true + + /type-fest@0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + dev: true + + /type-fest@0.7.1: + resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==} + engines: {node: '>=8'} + dev: false + + /type-fest@0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + dev: true + + /type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + dev: false + + /type-fest@3.13.1: + resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} + engines: {node: '>=14.16'} + dev: true + + /type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + dev: true + + /type@1.2.0: + resolution: {integrity: sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==} + dev: true + + /type@2.7.2: + resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==} + dev: true + + /typed-array-buffer@1.0.0: + resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + is-typed-array: 1.1.12 + dev: true + + /typed-array-byte-length@1.0.0: + resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + for-each: 0.3.3 + has-proto: 1.0.1 + is-typed-array: 1.1.12 + dev: true + + /typed-array-byte-offset@1.0.0: + resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.5 + for-each: 0.3.3 + has-proto: 1.0.1 + is-typed-array: 1.1.12 + dev: true + + /typed-array-length@1.0.4: + resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + dependencies: + call-bind: 1.0.5 + for-each: 0.3.3 + is-typed-array: 1.1.12 + dev: true + + /typescript@5.3.3: + resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==} + engines: {node: '>=14.17'} + hasBin: true + + /ua-parser-js@1.0.37: + resolution: {integrity: sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==} + dev: true + + /ufo@1.3.2: + resolution: {integrity: sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==} + + /unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + dependencies: + call-bind: 1.0.5 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + dev: true + + /unc-path-regex@0.1.2: + resolution: {integrity: sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==} + engines: {node: '>=0.10.0'} + dev: true + + /undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + + /universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + dev: true + + /universalify@0.2.0: + resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} + engines: {node: '>= 4.0.0'} + + /universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + dev: true + + /unixify@1.0.0: + resolution: {integrity: sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg==} + engines: {node: '>=0.10.0'} + dependencies: + normalize-path: 2.1.1 + dev: true + + /unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + /update-browserslist-db@1.0.13(browserslist@4.22.2): + resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.22.2 + escalade: 3.1.1 + picocolors: 1.0.0 + + /upper-case-first@2.0.2: + resolution: {integrity: sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==} + dependencies: + tslib: 2.6.2 + dev: true + + /upper-case@2.0.2: + resolution: {integrity: sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==} + dependencies: + tslib: 2.6.2 + dev: true + + /uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.3.1 + + /url-join@5.0.0: + resolution: {integrity: sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: false + + /url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + + /urlpattern-polyfill@8.0.2: + resolution: {integrity: sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ==} + dev: true + + /urlpattern-polyfill@9.0.0: + resolution: {integrity: sha512-WHN8KDQblxd32odxeIgo83rdVDE2bvdkb86it7bMhYZwWKJz0+O0RK/eZiHYnM+zgt/U7hAHOlCQGfjjvSkw2g==} + dev: true + + /urql@3.0.4(graphql@16.8.1)(react@18.2.0): + resolution: {integrity: sha512-okmQKQ9pF4t8O8iCC5gH9acqfFji5lkhW3nLBjx8WKDd2zZG7PXoUpUK19VQEMK87L6VFBOO/XZ52MMKFEI0AA==} + peerDependencies: + graphql: ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + react: '>= 16.8.0' + dependencies: + '@urql/core': 3.2.2(graphql@16.8.1) + graphql: 16.8.1 + react: 18.2.0 + wonka: 6.3.4 + dev: false + + /use-callback-ref@1.3.0(@types/react@18.2.45)(react@18.2.0): + resolution: {integrity: sha512-3FT9PRuRdbB9HfXhEq35u4oZkvpJ5kuYbpqhCfmiZyReuRgpnhDlbr2ZEnnuS0RrJAPn6l23xjFg9kpDM+Ms7w==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.2.45 + react: 18.2.0 + tslib: 2.6.2 + dev: false + + /use-isomorphic-layout-effect@1.1.2(@types/react@18.2.45)(react@18.2.0): + resolution: {integrity: sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.2.45 + react: 18.2.0 + dev: false + + /use-sidecar@1.1.2(@types/react@18.2.45)(react@18.2.0): + resolution: {integrity: sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': ^16.9.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.2.45 + detect-node-es: 1.1.0 + react: 18.2.0 + tslib: 2.6.2 + dev: false + + /use-sync-external-store@1.2.0(react@18.2.0): + resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + react: 18.2.0 + dev: false + + /utf8-byte-length@1.0.4: + resolution: {integrity: sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA==} + dev: true + + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + /utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + dev: true + + /uuid@9.0.0: + resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} + hasBin: true + dev: false + + /uuidv7@0.6.3: + resolution: {integrity: sha512-zV3eW2NlXTsun/aJ7AixxZjH/byQcH/r3J99MI0dDEkU2cJIBJxhEWUHDTpOaLPRNhebPZoeHuykYREkI9HafA==} + hasBin: true + dev: false + + /v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + dev: true + + /v8-to-istanbul@9.2.0: + resolution: {integrity: sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==} + engines: {node: '>=10.12.0'} + dependencies: + '@jridgewell/trace-mapping': 0.3.20 + '@types/istanbul-lib-coverage': 2.0.6 + convert-source-map: 2.0.0 + dev: true + + /validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + dev: true + + /value-or-promise@1.0.12: + resolution: {integrity: sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q==} + engines: {node: '>=12'} + dev: true + + /vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + dev: true + + /vite-node@0.28.5(@types/node@20.10.4): + resolution: {integrity: sha512-LmXb9saMGlrMZbXTvOveJKwMTBTNUH66c8rJnQ0ZPNX+myPEol64+szRzXtV5ORb0Hb/91yq+/D3oERoyAt6LA==} + engines: {node: '>=v14.16.0'} + hasBin: true + dependencies: + cac: 6.7.14 + debug: 4.3.4 + mlly: 1.4.2 + pathe: 1.1.1 + picocolors: 1.0.0 + source-map: 0.6.1 + source-map-support: 0.5.21 + vite: 5.0.8(@types/node@20.10.4) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + + /vite-node@0.34.2(@types/node@20.10.4): + resolution: {integrity: sha512-JtW249Zm3FB+F7pQfH56uWSdlltCo1IOkZW5oHBzeQo0iX4jtC7o1t9aILMGd9kVekXBP2lfJBEQt9rBh07ebA==} + engines: {node: '>=v14.18.0'} + hasBin: true + dependencies: + cac: 6.7.14 + debug: 4.3.4 + mlly: 1.4.2 + pathe: 1.1.1 + picocolors: 1.0.0 + vite: 5.0.8(@types/node@20.10.4) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + + /vite-tsconfig-paths@4.2.2(typescript@5.3.3)(vite@5.0.8): + resolution: {integrity: sha512-dq0FjyxHHDnp0uS3P12WEOX2W7NeuLzX9AWP38D7Zw2CTbFErapwQVlCiT5DMJcVWKQ1MMdTe92PZl/rBQ7qcw==} + peerDependencies: + vite: 5.0.8 + peerDependenciesMeta: + vite: + optional: true + dependencies: + debug: 4.3.4 + globrex: 0.1.2 + tsconfck: 2.1.2(typescript@5.3.3) + vite: 5.0.8(@types/node@20.10.4) + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /vite@5.0.8(@types/node@20.10.4): + resolution: {integrity: sha512-jYMALd8aeqR3yS9xlHd0OzQJndS9fH5ylVgWdB+pxTwxLKdO1pgC5Dlb398BUxpfaBxa4M9oT7j1g503Gaj5IQ==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + '@types/node': 20.10.4 + esbuild: 0.19.9 + postcss: 8.4.32 + rollup: 4.9.0 + optionalDependencies: + fsevents: 2.3.3 + + /vitest@0.34.2(jsdom@23.0.1): + resolution: {integrity: sha512-WgaIvBbjsSYMq/oiMlXUI7KflELmzM43BEvkdC/8b5CAod4ryAiY2z8uR6Crbi5Pjnu5oOmhKa9sy7uk6paBxQ==} + engines: {node: '>=v14.18.0'} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@vitest/browser': '*' + '@vitest/ui': '*' + happy-dom: '*' + jsdom: '*' + playwright: '*' + safaridriver: '*' + webdriverio: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + playwright: + optional: true + safaridriver: + optional: true + webdriverio: + optional: true + dependencies: + '@types/chai': 4.3.11 + '@types/chai-subset': 1.3.5 + '@types/node': 20.10.4 + '@vitest/expect': 0.34.2 + '@vitest/runner': 0.34.2 + '@vitest/snapshot': 0.34.2 + '@vitest/spy': 0.34.2 + '@vitest/utils': 0.34.2 + acorn: 8.11.2 + acorn-walk: 8.3.1 + cac: 6.7.14 + chai: 4.3.10 + debug: 4.3.4 + jsdom: 23.0.1 + local-pkg: 0.4.3 + magic-string: 0.30.5 + pathe: 1.1.1 + picocolors: 1.0.0 + std-env: 3.6.0 + strip-literal: 1.3.0 + tinybench: 2.5.1 + tinypool: 0.7.0 + vite: 5.0.8(@types/node@20.10.4) + vite-node: 0.34.2(@types/node@20.10.4) + why-is-node-running: 2.2.2 + transitivePeerDependencies: + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + + /w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} + dependencies: + xml-name-validator: 5.0.0 + + /watchpack@2.4.2: + resolution: {integrity: sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==} + engines: {node: '>=10.13.0'} + dependencies: + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + dev: false + + /watskeburt@2.0.2: + resolution: {integrity: sha512-+WhC6hh3ThX7fx78VI4X1mL8ifMTow4j95tLuiUqDP96jnV4Fa4xGIilpeeBAy5hZtbh0n+irgcySkq7iPwZ4w==} + engines: {node: ^18||>=20} + hasBin: true + dev: true + + /wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + dependencies: + defaults: 1.0.4 + dev: true + + /web-streams-polyfill@3.2.1: + resolution: {integrity: sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==} + engines: {node: '>= 8'} + dev: true + + /webcrypto-core@1.7.7: + resolution: {integrity: sha512-7FjigXNsBfopEj+5DV2nhNpfic2vumtjjgPmeDKk45z+MJwXKKfhPB7118Pfzrmh4jqOMST6Ch37iPAHoImg5g==} + dependencies: + '@peculiar/asn1-schema': 2.3.8 + '@peculiar/json-schema': 1.1.12 + asn1js: 3.0.5 + pvtsutils: 1.3.5 + tslib: 2.6.2 + dev: true + + /webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + /webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + + /webpack-sources@3.2.3: + resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} + engines: {node: '>=10.13.0'} + dev: false + + /webpack@5.94.0: + resolution: {integrity: sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==} + engines: {node: '>=10.13.0'} + hasBin: true + peerDependencies: + webpack-cli: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + dependencies: + '@types/estree': 1.0.5 + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/wasm-edit': 1.12.1 + '@webassemblyjs/wasm-parser': 1.12.1 + acorn: 8.11.2 + acorn-import-attributes: 1.9.5(acorn@8.11.2) + browserslist: 4.22.2 + chrome-trace-event: 1.0.3 + enhanced-resolve: 5.17.1 + es-module-lexer: 1.4.1 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.0 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 3.3.0 + tapable: 2.2.1 + terser-webpack-plugin: 5.3.10(webpack@5.94.0) + watchpack: 2.4.2 + webpack-sources: 3.2.3 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + dev: false + + /whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + dependencies: + iconv-lite: 0.6.3 + + /whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + + /whatwg-url@14.0.0: + resolution: {integrity: sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==} + engines: {node: '>=18'} + dependencies: + tr46: 5.0.0 + webidl-conversions: 7.0.0 + + /whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + /which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + dev: true + + /which-builtin-type@1.1.3: + resolution: {integrity: sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==} + engines: {node: '>= 0.4'} + dependencies: + function.prototype.name: 1.1.6 + has-tostringtag: 1.0.0 + is-async-function: 2.0.0 + is-date-object: 1.0.5 + is-finalizationregistry: 1.0.2 + is-generator-function: 1.0.10 + is-regex: 1.1.4 + is-weakref: 1.0.2 + isarray: 2.0.5 + which-boxed-primitive: 1.0.2 + which-collection: 1.0.1 + which-typed-array: 1.1.13 + dev: true + + /which-collection@1.0.1: + resolution: {integrity: sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==} + dependencies: + is-map: 2.0.2 + is-set: 2.0.2 + is-weakmap: 2.0.1 + is-weakset: 2.0.2 + dev: true + + /which-module@2.0.1: + resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} + dev: true + + /which-pm@2.0.0: + resolution: {integrity: sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==} + engines: {node: '>=8.15'} + dependencies: + load-yaml-file: 0.2.0 + path-exists: 4.0.0 + dev: true + + /which-typed-array@1.1.13: + resolution: {integrity: sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.5 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.0 + dev: true + + /which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + + /why-is-node-running@2.2.2: + resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} + engines: {node: '>=8'} + hasBin: true + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + dev: true + + /wonka@6.3.4: + resolution: {integrity: sha512-CjpbqNtBGNAeyNS/9W6q3kSkKE52+FjIj7AkFlLr11s/VWGUu6a2CdYSdGxocIhIVjaW/zchesBQUKPVU69Cqg==} + dev: false + + /wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /wrap-ansi@9.0.0: + resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + engines: {node: '>=18'} + dependencies: + ansi-styles: 6.2.1 + string-width: 7.0.0 + strip-ansi: 7.1.0 + dev: true + + /wrap-error-message@3.0.0: + resolution: {integrity: sha512-QoePG1A6p9t6kY6RjOucIJvItmJfViuDs9C84TifNr8zN2oFmeky8SQ3OkUAY7vfefPPB7TUtKbiXjsV29EhLw==} + engines: {node: '>=18.18.0'} + dependencies: + normalize-exception: 3.0.0 + set-error-message: 3.0.0 + dev: false + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + /ws@8.15.1: + resolution: {integrity: sha512-W5OZiCjXEmk0yZ66ZN82beM5Sz7l7coYxpRkzS+p9PP+ToQry8szKh+61eNktr7EA9DOwvFGhfC605jDHbP6QQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + /xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + + /xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + + /y18n@4.0.3: + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} + dev: true + + /y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + dev: true + + /yallist@2.1.2: + resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} + dev: true + + /yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + /yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + /yaml-ast-parser@0.0.43: + resolution: {integrity: sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==} + dev: true + + /yaml@2.3.4: + resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==} + engines: {node: '>= 14'} + dev: true + + /yargs-parser@18.1.3: + resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} + engines: {node: '>=6'} + dependencies: + camelcase: 5.3.1 + decamelize: 1.2.0 + dev: true + + /yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + dev: true + + /yargs@15.4.1: + resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} + engines: {node: '>=8'} + dependencies: + cliui: 6.0.0 + decamelize: 1.2.0 + find-up: 4.1.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + require-main-filename: 2.0.0 + set-blocking: 2.0.0 + string-width: 4.2.3 + which-module: 2.0.1 + y18n: 4.0.3 + yargs-parser: 18.1.3 + dev: true + + /yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + dependencies: + cliui: 8.0.1 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + dev: true + + /yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + dev: true + + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + /yocto-queue@1.0.0: + resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} + engines: {node: '>=12.20'} + dev: true + + /yup@1.3.2: + resolution: {integrity: sha512-6KCM971iQtJ+/KUaHdrhVr2LDkfhBtFPRnsG1P8F4q3uUVQ2RfEM9xekpha9aA4GXWJevjM10eDcPQ1FfWlmaQ==} + dependencies: + property-expr: 2.0.6 + tiny-case: 1.0.3 + toposort: 2.0.2 + type-fest: 2.19.0 + dev: false + + /zod@3.22.4: + resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} + dev: false + + /zustand@4.4.7(@types/react@18.2.45)(react@18.2.0): + resolution: {integrity: sha512-QFJWJMdlETcI69paJwhSMJz7PPWjVP8Sjhclxmxmxv/RYI7ZOvR5BHX+ktH0we9gTWQMxcne8q1OY8xxz604gw==} + engines: {node: '>=12.7.0'} + peerDependencies: + '@types/react': '>=16.8' + immer: '>=9.0' + react: '>=16.8' + peerDependenciesMeta: + '@types/react': + optional: true + immer: + optional: true + react: + optional: true + dependencies: + '@types/react': 18.2.45 + react: 18.2.0 + use-sync-external-store: 1.2.0(react@18.2.0) + dev: false diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..537d85bffbee82844fc817bf33fce98767ce8f0d GIT binary patch literal 453 zcmV;$0XqJPP)kNO7MTS zw6Th0VIF~_!j`pW|OV$cKd5R zzDEdvHjymLg0AbRR;xl%RTYY&pwVc&gedWzT+=l8zK)AojR-A?S}jP{#I$4;&Qp<=G|_WjgLCX zHG<5%QmL>Ol4)j6MFvHpx?Znr-R*YlS^DrKdxilJ$Fr7}(>-At5#>>EQjeypAz0TT4;Smwdo9;TV vd0_~%j}MJRMA;r*bNM%v01`j~NC46gcy9=st;*9H00000NkvXXu0mjft_RQC literal 0 HcmV?d00001 diff --git a/public/icons/icon-144x144.png b/public/icons/icon-144x144.png new file mode 100644 index 0000000000000000000000000000000000000000..b071ac95a6089c7ae536655fb6b78940ac144aaf GIT binary patch literal 1348 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q4M;wBd$a>caTa()7Bev9?E+!OYxg#aGcd4x z^K@|xskrs_j<-f`uEc@Dr*-@9v-9|9_)J-7bdW*QM`e18VDM9;i3SsQ8o7E&Y6ojd zYR%lCqRgyXKJRg5e|i1uIgh{8)^5F?y8i#F`fC60xAWJ2U01$#>*KDju9g@7#f~co zG;lbuC@={K5}+A7AnI__3@#vZ7&~y%PnL6Wb1&VoBf`tu`{n9MlZ1@*7=H0rlx!#} zE>_jl^b86LQn9qO-174M^+FGC@9rM|Eec1EGRfV&ed+S$rQ5cJxw*Ti78C@uwY53j z{P1A|4-e0YA3t_{`S#7LuFlSVLH*&$6DKNu{ra`2uuw7Qe~zuK?WCzwQ~lmD{NkQ> z=8VtEb?c^m{#fJ|*mcJ`m2?V}sH zIXP!cZ5o-M90`t#(`#>Ue^B_~V&~?g$;Y`J_CGv%`n2)nL(R?1A8Hq1)ZQ)HXRg`!vt3*RNmeH%pq?eCx{2%sd%vvyUz1Kms{aaG7v zn3dG<73WAjZ7)* z&fx)~=Z_pYBA+drcx!Y@uKcnTxFJHg9vRz)csZH|y%aRxUci*ni^b)1_CgT$%B^uI~6_PGGoQuZ)V0KC8SU@p$s}%6043o!NYMSAYbI z%{u0yN12(K6PGVn|4{RA=gysm6<^*?TJWGybi&cevu0`e`uY~t*Z)7w(Drm=&-)K| z?%wrGPF`Hue|oKZAT#TUM;95hGBPIIz8(Fc=I^)mcJ|D?JTvRC3mqO@T-PfX%)8Xwq5i62j{d)w(TlA-S+gU1&!0Ud<>j+Eiznz^wY6^5REiC} zTE3;U|MG3IM8ElF7rHw$_OF)T*v|ziwvHwelF{r5}E+mLr}E< literal 0 HcmV?d00001 diff --git a/public/icons/icon-192x192.png b/public/icons/icon-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..0ed3dd49e2fe178f54fd6ee76e8fe469a4295abe GIT binary patch literal 1761 zcmcgt`#)4^7(Z-sNr~jHY1_(_)r@O{I9gIZVib~{GU?`1LMjw-W=lIu^-(AWL%W4? zn0ol3di#^jP>jz;EKr!#x}1-n1>`F@`F`Qd$^_j%s$^L#&Vil6V!TLz1Bt#NT^N)TK$Bs0o*u~FI_@d^j%c+>Pyuc}Dvn-p4JO)F`BKG0k(k%NY9mVwG zJ$F4vD@jLD27_fYEFTw(oktLf;DRvIJg}h;AKKSKb@fIm2cF(&xo)}@;lR~uM#lKJ z1w~wJHWFltw`WnhHe=4pSRE5#Q*td*J%y_-=rg&)(ZwwKlU7N7-&2HN9W^>IVI6*P3)P~Cy5;$7w*&qoN zA~i+82I3V_1GUww;%%WQ0kZ{JP{`)x(*w`uos=SuZMZSMPybFb=-c3Ms{4lPMRYBe zsG+>9u5)H0Oq6|-64z;sxieYQh%iDCCmS5)`X}XIfpZWrewJ*t|KVDnT!->b329O_ zbJgICR9IXc-c=OD3;DJ>i4h}73oDsiga2verm0NUT=hi|#ACt^a>b8W8VQUHK-rIo z>Y_(O=f8}89Bt2P8e$`0;y-p)A$2r1*aB-xNVTe&2%TfI!7BLCdKU=C(zxrf`sENO zAf)d6&D&Ot+ZNo7SD^b^ug&otR}Bg+==mBDsfonSn!!EHA|0$ScYl`AEN$#s!4Pff z^;Omq86B0Hl|GP=Qi+>|8@5VhQK)qC*8|7GPokzwmLC4Gqj)@biw?sGJrmVG`QG;v1 zrU&0AgZLo-?6{w3aW4*)e)#my*H2u|gM||wj3@z#Q3vYMI~?Y-;Wug%E1+%6HI!ft z$bNBF&O?7WV_MWZh)|I|?~NX@(1c_H=HQL15kn1$^IzZ4K0jzLy+$-&(d!c3GxfI6 zyJ@HxA#FSV&{nR)Ku!0srboRG@5}?C5Y%!7w5gHkj$8zmNqC7WZLF-UZbDT(Jzh=B z2vnTsm_do@44ul~XK=?EvtDNI99vc;C>wsgfW+}q^x;P{dT$=G;U{WFj&hPqd;q$j zkMCb&Qz7pU*b)1|((OVHbtzb}t!#hg zy86Tg2U#9%j-vEQ9{gkGXGz)%Rf8=Dy6+Pyz8J3ceR|lUIiZlKIXdqxd#a}@>;gag z>4@!a@$A;QmE@44Y4*<2V0lE}lR|>YdqnyEza4xQTUh9wHMVs^gxNbTNtIcfz9S&5r)mk3v+7^h5X!ce-p7C?ZdYP3Wj_#RNBt|SBh1-s{P4pe-##=Y__ Q@n->EJA6GVemQjMU&bymm;e9( literal 0 HcmV?d00001 diff --git a/public/icons/icon-256x256.png b/public/icons/icon-256x256.png new file mode 100644 index 0000000000000000000000000000000000000000..e05e60cf9289e31f4afb02031f84b54d41c3a3f4 GIT binary patch literal 2238 zcmb`Jdr(tX9>-7Us5~mPWht-7wadCLUAIvXq67&RyFwj^_+lM|7^S5Q3&_hL3At=t zU=c`ap;A{Ny42#<2UV9sOh{Ou35XEnU0#t~9*r2n29^7p2VGjV<93FPy2mmxVqygKF(40!Y{V6nd=fX~A0Fd(d)khl` zf8Yv$?YZy+`;TQ08^;dajt~G1&U&7Wm=g5a<%&bUE&njQ=w`H!v(LwYJ|zn0H{Sf( ztu5p9*6@uQuq~lA#_|5ddWh;08~k=y)*#Qc)!=V#UJr!1xz5XLFE z?0vA{W@uqSLBU4f{znPgCDZr3mXDojGy+j068qB9Qr^O3J8$rQ>_pRF-r(t!xjZXn zi9cf+Z=87k?~6Qb)jnR&H{m|!E>OZQ@$i5DP5PdlyZ!z1N9t2INfZb)P8T;hMJ5Ps zPLsUu8~YQ=vdvD(07GqkW^uVC-zil|S4(DDkSp*PU9OW~2SZPaBj%cyvS&fFeSd9SV>1jmebo=K_TP!_ z?XT3^bAEz;v2;}U&XRG2`EtBb9zf~)c^G4bDAsXzQL}@!HPxa>xW@;g?-(MYS|*eA z-g>Xba-q~ZHzwzi1a9bK*Fa^iYJ{`S{PWOZfqu`zj6Y>Io0m*2g-*SN0(~7t2(*c$ zO?N(C8&iMZ9PbmiC4f?hNeRMs?EN;P<2-3IkEnHWzUlj%L9=C!)vxvPdd+U+gsN$UUZxLUe;+4|F? z1m5)1t6#aP0I44n>TfAw#tS*p;JrpI(S~T)30>EplyHG4jVyL$IKn*hC$-rm5-hZJ zcy~uwLe6n_=owGqVLSPAqw|m#q-uv+s!2rOUWB3xKIyn}t3D$ds+=#wA%(2UchA#R zpxoNVEnzFab>@x~G3HMs!)Yf>8l0Px<3B_!dZCJMV%Q?uPAb#xcX68nC?RJZBOu%{ zo~XNN+8c}oQG~cQdy+{7Nyr~Z>M#{iglQAVWu#Zk)w$>fqtqjO zho)3FR3Qr`P1!XSXUMtfvcW`j7X=em(@Q-ZSH^(HtHC1tHo~zm;uN2e?qU_yhNSj+ zr0SAM7pD*lfyKsZD_PO<-SOmwDznD3PR%D=R#JCUmo_#LcQPg!_m?%^DyYzjJKjAs zHMcs71g`8EuG?E0RbT#}EyRNE!K|lYoF% zviQvnX;_bgVy~|CD4?bYX6pDU!9zE+3QJ8+-W(ATVOXTAxf7sIYPR+g8*Y$;YqJtk zCQ6ck%n9?@GR8+#K^hcZHM^g-`SZoaCeCky~=`~fj<3uS0Z_+;seWwU_~(LM-A3;3s)CsJRxKL zRCXo$>>nRZbY5dZxFyyxIiEMtod1=a4`(NfS<{`@Dk2?br4YYC0^We0S9YBIQlwLJ zaga&3LV5#Bb>6k!C|%{P0)1+PJ#A={nmltau`vjEU@2P(ex-Ui3y)Jvabje6xcQRH z?_pfm&TUP~qKEvL51&SDxOLE386a4n3HlEb9ilcNnWb zf-eeTT@Mq?usU1>DfHrM0@?6`4@Y9d7tzyFx8hg(@($$2?+lv L^1%HMPk;U&@nQ>& literal 0 HcmV?d00001 diff --git a/public/icons/icon-384x384.png b/public/icons/icon-384x384.png new file mode 100644 index 0000000000000000000000000000000000000000..e4c0d9fa22724ab48ef9d85ba281baa052218427 GIT binary patch literal 3841 zcmb_fYgAKL7QUbq45JoN5y2H7wNa_04)PErprs-r4~GgWkEkffGk_0J5-uw0SSyhV z1?1@ytzb-rAg^4FN)(V-P!Iyd5F?^QLV$2XF89s}9cOi|&it^QA9rP~vvSVf-#*{> z?Xyq&db>|2%_l(+G~HvP+dm*kFID#$eFj#p2rCfqGc9i8_WckPTdn)_+IqNV5H#bC zhugaEk~$ULp4a`iS{N!fTs=gs$#u6G*uAA>7OC8FwNdHw7V9rgm2NTFlTKQ3{d1>v zYt9*6Ugzd^(!;=R1!<8{^kPb$+n&9K)s#JL{ng`zqXiWm;RuI39T_c@OmRu~3LPZi zx+qDy!{~EAQ>ayBf>WSn5HuTtK)MD{sy^hZ2Ngq*FZ3zPe{nkqM!H8#{qylZX8R}8 z|F|90z*P?|`gHuiJK#4Ee^~hBsxE_wCI9!w#4SZTe0HS(($ zD%M|*`V>y36fqMVhaQ@iq!DBo%fNB%V35A=Wrvi|4I4J7aN@vB*ud2X6*eFiIE-t; z@j&l|p^-TWwLG}0XTQj~|79q94o*sqMTHU>+l3bM^7h4Wu{)aA`GDw29`q6}NDLCi zbD$hG0DEbhMv^FDIa4x}_O>TsEMcXA^4^r0S3=X*Y(TA`YRdimHTzqda&20>6D2FL zr}xs}+?9d6*M>;L0+&_|AEY8O<#Q?3yB~eejLMH8+Zc&ya*1f|@a7p4cexkSkYT!> z5%EOHb|$vo^uJ0@K`&P6lG*V9>AEp@xc3az?k0=F@`VlvT-0tH{`k9*(RO;D>6W*-2&zfDEW0G-sY>^T1{#H%1Veo9ITggr?YOHB) zYydfQK0s>ol{JHW&vrV@nn7%PYXs}DOp&p41mgctX|W^c#E#K zvcP2PoN2J1j1PAV7vM zGBPrl_w8dxX9GR~o>&nt$0T>-Lq*-Q1d`|TaD@yAw_**Z&{#o^Itlk#I_;ivXKnxq<~eZ@&wTk(2Gxm&wygOmeU^E%*cLwl|Nt)N^! zfhS8DpIKu|Moxf=n&R=q{xss}tv6NQtm3hn7RG2Zv*2iLQdORQafQOqAGh)^eawC! z%uKwz46-qj(nCUf{nAOP{-`kWdMO4-rqPs6_)R;_W25|FL4Dy|! zj7tt}G1_I2<6=w}TXfYk``XY@JV;?N*4QSpVAN)Cq8=Up;otf=lLa&1k2F$|fexEF zlhqZK4s=!7(A&QkWs$)B^;I-;`(TYc+un*uk$hu&?V6H`gp7UY&ar#9T;0B3FO^5N-+Itv zyKD1GDcMgz0HgEH4nDMfc%9jO4zw>u`!MCL;Dm9j(_n4ufF`-29VlwAI9$SKMRfeK z_pq2US7#AAdL*uI%Co1|sXL=IX{XQZEmYasGPIepu{$DKqm)j2yIbt8XM{gFzfip{ zRPF-fSUF3p4wF+cud`A~_b(W5FjY*`WG!jLEZphPz~}h2aV1q4*Mv`KTYp^YsXADu zI+qP#`V(bY#ItATvJmqeC3Q^W4ouudAZf3i)LMIYbAeOkG(zq11vp!a%a08nonqLs zH6S>vl2y&ITc@{Kt7MNAK9rb+Bwg$ig#W2 zIzP{Mvqmofy$31J&f12gu=uz3$~lljlhcHK^vh>yDQgZ-`k`2;I6jm1vP&V8#{yd> zE%Q#_wkXR4*RlP;fz^`cpvf{%IL}g1cIxMLMD``JhlHauD-0W4=Pk&O&sw3HdNLQTs5F z87dCny?Z^HchrbT7^vs@bSakT%w7MVGlPWPG!q=bRGuOpdzEdhHZ#s#=6eU}8eo+}_NYsiV<&I-~1dRnk!JYCF3y`K0U&Bu2!YW=AUy z7OdQ=>y#hVRZ4+zo|576#S+XbMoLeqt7ne<>fR677#lLA>rLk=>j#e4*RYyh2y8?x zX825l$27XOTiXf`_S8irB_%Z&2Kzz+!bR#5-ki_e{nd{0>kQNa&}OjX4kb9@$x_X{ zF_T0C*CHi@gNc1M&i5PU`9$vxInsYsGmo061)KqjtYmFM5%4YojQRNiqD?89>4Mz` z#;9}eg($`67`oh&Qg2`u^ehe54gtuKUmZ=rQdCbUnqwTLyWWWA$AGSB@t{SN6gVZ? z-TV^#qi1}%a1ce4cKou(gMZ^bZzidD*kmjT3InYdJO!Te*yh)j#JiiE1l>ERtB;DU zS&tI-nCxo6(0NpzO`nU0EfgRF8nWYoWo03CjvP$OdTeCyby;OfFJrA<)#2ec%M&*l z!G2L_cBq4Z00k;aC_o=7VTtlZ&v;iz`$?Uae}FwjXaL*p1J#|2I~GQbtKynVZ`6Lgi%@(9!K ztkR|6Y4`W;c;NyKnohqP^5LXDN~Rt;Go}^V`PM3I@aYvRgmKvDa`)Nykh@S2@7PY? zhk|+l{uMnFa^P?Iq@m-#y|Mofqf9Dc@|R|z-_rWiqtr)Ke|?kzlgK9zav!7rrviUi g`28RQY-bAk^2LV}DF;u3nHKW+*4ypY`klxA1+2=of&c&j literal 0 HcmV?d00001 diff --git a/public/icons/icon-48x48.png b/public/icons/icon-48x48.png new file mode 100644 index 0000000000000000000000000000000000000000..44bd0d33d9e14b1ed14aae6e8b25c57906d4f1f9 GIT binary patch literal 583 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC&H|6fVg`o1T_DVO?cPRl1_s8T zo-U3d8TZ~!U%kpHP@t_`=;-giO*2d+kE9siJhQLW|6y{+S(OMD(PrP~`~-ocDFV%| zAO6XwC3MPMc)Rb!!vi`JVTI@a+_!igU!A=%g6F@b38Mf53i=`3kYVzxw6V%mhxy3k z!h8D#9~S%wd@kCN=31jPvElr4XBDADf!(|3pG>*eWzOrs8N5L-9!20VCzgFEhb2rw$_p)SB)Y?ZCHjkuNU(He!;CL~Q^=wbY^wX_gOPdZq zJaF{fbK|`2vzP9OTW>MfZ_fIgIYqpxx26eJiN)(p-+2H1&KpmQ9{#P{Un~*%>id?} zHgC(M<@(#RwVF4)ahjqs)929Jvc(}sA3D)ZLdJi)s1 z%$y#X2xsLle}r6J-|)TK75Z`4{{!*+wNA75GH^7YpgrC4sg9E;_#Uba0j3NF MPgg&ebxsLQ07d-;cmMzZ literal 0 HcmV?d00001 diff --git a/public/icons/icon-512x512.png b/public/icons/icon-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..d944a7523a1e40ff8eb9e176a2e82c4d02019e29 GIT binary patch literal 5392 zcmc&&eK?f)`hUEXYPYmSL}E`TlCUB}jB&Q4B5F&Km)XtMq&Kz3OT?&7DnzBzD8i~p zg)-j5XoWN~WlF}|R1AhO6UNJ!XXZKgWA}IUJJ+?>)z%;9{Nb9p9^d)i_xHX(_viC@ zzUQ~PInSM=GY3JCxtlhw{{cai;j1z-YbJb1!d^|m$LymUy@C+rNICwe)YA1(3qdq~ z+qC{4JHpzAIs@)_1h-ee>q~ln@!DLsdZqeQm*$y8@tL!qud-wr$EE5RIIleOv@zbw zRmbt6`oFGcE{fS5pb}tpY29X>180&q*!KE_Fj1}4(+)$Gk-R|4uphyvzfUEiletD% zgatJ$r>i0#FcuB{263ED4VjN1(eOt-Y&gO2`b~uy<#;OhF@-5?IwR&j3S5-Rrcsm-R78*><6#cu1gjhL+FP zVeST`nz?k`rJ0MJR(H_WwLY{W%+aE5hk~E3NH>%7g4jgL8KN?xSnjLiN|{}ARz1^QfXA`kK&fsL8)f6mA+08NmIvPq6?Y9w`_jD?bvpN^FE(%r{3e`iU5IoHqKLP#>#lvWn*a%Lz6%Ioxd#F)l0> z7O)Bk3fsEb$cm{#TDg5|RirH0l9I42$HLZ65wNc*b+MjZNTc6dz74csKXQxDD-Ry@ zEckg73gu78s_U^qnh%!SQTyK(Fp=nHx;)AHaNCmzaivy$f?kk-mz-*bF%?rLi&lBg zzp*y>S*Al|v0k4lq9ISC#Vs;@e}T~T0KL#KJVFYW>@P<1%X+U18ADDaWn{C%2f9e= zo?>lk7v>3P50#qxRoH}&3$MvtODv&tPGV_x#Oa~7qB!I2S*gKn-Uz{vJRx&WvtJB5 z#}4K*9qxME>&3An;V1+J*jMHi^RwO4iy@w1#GP^U-EaLbZ#wVD_v<|7hByu*8|gE3 z*BsEuhkU&z&>7Jd(yyWkyc3pr6(i4tA!*srv@1S}y?ggs1a?)lGHIBXng)xPjIP2Y zg%~Owy?O9W-qOj1$Wf74N;ufEDx!f6yU&;8NKVSLruIINMS5U7=l zDn^^`{BS$gKNYI(F3W~}vK`g+9S-3bU?@hU5{^3~y}uZpfuQ-yKMuUgp%6b9A@L1l zM95_riOL7_g!iJ-#vzf_$laZ}ItvY5&kePgXjP={k8fa)h+!yS<&#MfC+T>IQ_V_$ ztDHmad3x#L@zH%0`7{(e$}DHjTcSNz*SZkGXwa8Vx?uAFhMmN@9nfC&hj5@efneV|OwMP|BWEF;lj>dss4KP?RPS=ighr!7K+t-=Fo1Qeib z9BJC0U?)14NK%yc^Vj>k^3|i4IVU_h_sz1*08UoZbhc*dX`x-mxkOBI>f%TV>V?+z z1WL0*gX5PH*UBpAspA{L1g>4TQLKUq8SH{x|J)5Q43dhwD(wv2Qj-CO_;~fefm(8P zOFBcm$K!si6)o5CU)lGbG|DIkIE3|HqpV!oTZBi9Y$NFz94X^p^(_14Hb2nSjXlM= z#p??juGKQBs`bZDHdTnhr0Z9PkHxAxOjZM+>ywVO6DK-?xGJD3q_%fG)4CEZaOD=R-GtQQ^Yq&`Iu2!*x%X;1CmTJ$>F8- zw!nAH0XkLGVSClgSI5XL6(2qr2F%Q-^t-m=!zsSwC3voYJA+G28h#N&Ybevaqfd&m z?~0u0>~G2S4)I`nD`13S5dw?S!Uu9}f(NePoB@xP`-+)ZR58k7*iW-qIGbdO?abX> zduvltY?reYu%S#Iu=Bp>H-t{=_E-14I2JH{#{>nmsRJ(x12`+qWM3ivBa0D%$s@tp z^5)YOc)zaLkGj(_jyM_{Zx6(A;itH_GxwQa8$S(rC&&zw#PV{sXV?&+_8Gfj` zf6DlUBq;+TNqrQ808GN^5Ezwn+=FF!yvuYsM}@X*L;N{_6;4ivhSQ~9TPTW1+4u#3 zw;d2FO?5L?K$cI9;j_!lKc)GIzCS((Rk|pWX6p}ZrYO?Josq4QMiR&cmc>(=D1=y* z!t{MLF>@gosvVo7n1yVHlYM{j{6eF;@uBuOKR2to9)BsWH7_&%ar%z$qvGx*%F*xD z(c4Jap|2dBNmp>Z zz7IEP4dq2rfO9wug_XcpPjL8#@qj5!6Hb_^^qY+^*?cWW{6*v*+%;yjVVqUf+;pglAul zP7Jkc1@$&IMCIQ^4^|`u%|hmwVbtjU=G!h6K(rL!aRMN+mexyIL;OGhVi%^-r0sTk zc)d=vkt%1ex*=tbwRq298^&Aw3%gHx4w}*ZdKb9}TvV#})QkrQ^DC{pj`!WTthNZ4 zW?nRvFM=UX?0ufH3k*gyIF|#j?>e#5hzveCYFeezS+r+Yj9=#Y+NqZZN2Jvl-+RFp^0O3(n%tx+3F2oNdpjkE{!epF1=-6;~y}tsL!tk?% zn#`*t=n6%#30%b+mExhq|`mVw9Eu(03_K*kz#!~R!L>% z&*?*wU{bxUD&oXOQ>+3OoK{m$0HevlS(Amy#LUFAOT(YKM9oK1Wlki)f}g-F`a>JI zZ_cQ~Mqfvd4Zf*YQMbQHd^#9_LzWH($mUS%gVwSj%1g^R&`e*HpZ+?KDYq6eF-0u9 z*dMPT%>MGOD`+wU!?9f6SQe@9J=sRxTug z2|Xmu)(V?GSa>fF=2sX!T%%6186+5H1LvfGewKWAMh341ZRo#7gISdbI7T5uZF^zD zx-GH8?Zvep-qkQ%z#lF{R+OQf_Uftep_E8A*2tIz`I1pe)J_^mWwQP8UqTvqNjQVd zbbNk&4Ws1LVQvBczRG#zJ43S4#j1yvFwn6NwBSW6)(iuL)>fZX>Asg=wKClHrS^8I zxeNo#JUrQ*NGTcV7eMimPOMz;QX58-dDUBcx;R*W1g43><=Yw%v^B)>V%F zt@-w2YRu8@3xqnbin#mf=F|FL{F-bRdZh4hd&@PzX)}u?c=7AH`@4%)x~16%;QYa- zy{$f(Ork|u9eA}OA_xo(B-S{VxVwGhNo>^ zUWcjY1A}s^;BsW%H1DO4GbPO~-C%nX9CbW|i@}6U+oe(Wq^iDj2llkO{4nLgq$VD%i(jlcfdW=X%1}D!KB432 z>1k4dl~oH~Wje(rTOZyHzOau>UvR-fIy+j^WarP!*O!{mh4_HYpwrgc?T1uduUi?1 zh`WaFPp2ypgF9Z>`6#pmr@{y+A)xv1hOWu;)zp_3;-3B*20W4p=4~6)m!+=+B9Cm_ zxpUD(S42K;PmUufz{?`+!`s->iE0p)Q_U>LW+q5xobRI$FDPA@G_du-w=whduHTT- zvC>4G!A`MAdVi1kdhvo3LLhGC-@P}-Dvq=j8gICuqd8Z{>S%gUygjNy2mnui5{; z?e9P6MjU=~*mA>M+wHvXo2Jj)W;ZYLdf}2FO{ahI>;eod3Ji=K4h&2J4FWI*P>cmE z0+BS7(U|Gem9922x_@zOfU(UbZCgB*vviQj3LdFuSxhMG6-hUsgAtEGy&Pd_wmPbi^?adnR ze%4(2{nyNN{dMn_+XWUX%P+5d5MgxmiiOSn^4)Va-qr1o?lP9^Kl!vM&}{Z!4)<_{ z&cpBR=J%V;?$vnrv7)1C=gH-PzIXZiBl0f43^DG@bJ!HjmNe&TRx0(=YZ*z!PC{xWt~$(6979m BJnH}e literal 0 HcmV?d00001 diff --git a/public/icons/icon-96x96.png b/public/icons/icon-96x96.png new file mode 100644 index 0000000000000000000000000000000000000000..055125f44cfcf91b2f47394a11873c19d743a49d GIT binary patch literal 978 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGooCO|{#S9F2yFi%n+P#h93=GUI zo-U3d6}R5bI;&k1C~^Gh-&&72@v++;k?jAC zTYGyqO=;EetbBg4_?6H1=jl)Pow5A7^K0h2PnP%37oWE*ey98T#R~xq+0>Q>1{MY; z0R|2S1_cI2;yDe+nQq;_eKx`nmk zNa^d>uW2&(bPm~D*H>2V{9(a7rHC@@>cB~(=7E5w5{LW`tf67WlhbWbn}PKKfJxY(+)3q+@bv^f+b_& zEyG>@a&mIhcJJQ(|4@1E?##p6zyJEL^6p%}YXfgQ|H?}*x7@jN$3nVpgBb7qvj4w+ z?Rxn~@MVXJcclVcX z-%j1UIa6}NysTeBb$Zi{v!}JKSCRZTpY_J$aNUUIvQrDHs-kR+3x9e<&OU7BVK?9W z>uqso&vyA&oEMsI-@3JA|Ni)M=g;r0URYF8l5%K!Z%Ee%XYLD?^@W9jetv!__4V<5 z{QPsDJ$T^I*WZ6u+x51?QXcy+B1^un4Dr&^(mM0)th(3TpA&TtS#iYMsd7&GlBaIQ txUWv&sn^>Y$#w=70TwdSx&y~P#=G2+E{=6GYk--Q!PC{xWt~$(69C<&wD14` literal 0 HcmV?d00001 diff --git a/public/logo.png b/public/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..db2e2cd115d5218dc1c4cbc0b6aef5861e3be335 GIT binary patch literal 7924 zcmd^E`9IX_+rK_DV;^fFOO_VNk}2s+Vn%yO6tX4Lk)=gMl5OULq9UB?*b?KkIN3ua z+b9l2=#(h?7A5<>%*=B;-(Q~Jo$>jS7RL{X3d;)vfasCK z`%eN8P?Z3J{HU0@{&@)%LSBdMd;mn&to|@aN?wPAn9s>Wdm*P$@dx@KxtW-m0KAA1 zSvkuGpmh7leiN(f*l4F|)S1D=EfYhU4Tlr%IwU;3t1ExS;p!#&pkUwO!h6yom%_0a zLV}w1fh7FF;cOLAiQ6Zh><^8)@i|RZU;b8|T5}f7WDP-B^H!(AWqC86v z=Es%C4TE=AoZ*CwWitLK)t-Qvz0wjHdLv#h8JrhO!*|_Ml*=X8e@=vn9;1E_-Zk$Z zV!YCp+@IG(j3LZIAT&O+mFYjX__6+@WVQfa_9>T3uP{=oF_H-e{?TLW{>mU$UM}6y zY!9!-b0&>il-Yin#mfYE@AE1nfY)bJDYrgKrojl3?G}`ucZ~@H{e>_g=7XVNgEpLd zUb!S{EGxqR+YhJ1*bPKBwL`bdx3Bu2HyeTBO=Xk-^=IcaFctI3WuEmr>dX>G zj}x=e4l#W8Q7SPi_A7#IS0QhKNXt|c#vTfT3=@WL zm_^{C0uV`stMB`sn>sgDg*|pwSTs>E7U(%=G+L<%__j9RBjvk1>%s}Nv1vcHI9zS4 zSkBZ7*hr;!q7^Lo)FF|jZy2}d;BoTlRx;=Bl zc?64DPO1p7{4x|4L~?pB^5e^6^4*rRoOwQIKD0d6P3yL0~S%XL6pc z4C|hGI2=#$m`=@xsQz{g$X}*T@up<(DJqcL<1cbfg1)ZYUn}D9wkZ3nXtNc}@c|_$ zeMFDB6{0p)C;_|Y?xEQvCmZ-%jECWSwXzo3q{mdcoX^zApxkzB7otO0$|Y)G_5@hfD=}`sQmv{@(`kX z6`eWb7=PgO6_?W*_D~KD(tR2lIZU&yGy?&(0pGU@*ROhTJNZhh;DbP?ufM z%(xj;Ydss9VpGuO*=g^j>)RP_9JrMnH232xJr>&#W-{$@DCTo6dqohM&z3Zgx7q2; z7*6}zlutATg{0;`waA}-lltk#4Rfl2fgZ-2xo8%Q;s9x6P2N+5dMmoyck2|tM* zOoD{RT0h3i4Ss97E3zVYt75_Q^O(5^}$B@$6esFbNbmZzOD5f}j z+ihN$FbaWFQb6a=_p6+bThe$Q(=8xJh;y>g(1wJ2gM-0-OPw#vr0&1H8PR=vft4W^ zG{Yz-Vn@>mu;zWuCRt8dd+Vq1;w-_HAKGW}9e)8^ZSYU#NO8xg_`9i}wD6F96`STuR%iX1;YxSXLWsRZYuFCKSe;%Xe)0-XG5gOZx%W z&F^5gulFrcrVo?gR=~%mQbsU?wUz(}+8Hj@<>Kn|#6d|=|B~|XXHB;w)nWsN_YKby z1!1k4DVG}5_Qe=5{I`MoOJgg!N4anWSb_$LRs2b&-KJ;DFC!S|afUvWZ0=87t7lHMqD4>notzf&318d$p zGqpyU?o5IJZSlnyP0I9sRMm``o83>vKS;vxQ=|VFv@6r42vB~1ACu?L1PX@XUE3$c zDFzsR=3Raz>h6tNe}BphX5v32VEC>Uhe%nEM64NciX#CYrK2+Vf0ae^GEbSf9a7zi z%CD%@3S&aSMrb}_un<4U1lN7Qx3FrtKw=arQ z0@0AabyL|vf{1BaFN?u<8nAS|7siuD2)F?nHL86~5Weq6!kh|YNLYj6$J=}!_fm0x zDMV9bfQA^LZTVHP6%saL_?N)}-j{5QttbSAja^K9aSgaX`tje=T8Zntq)g|Mz~1-e zeID4WLUV@Ee@LJ$0q!l)ju=g(h*Y?r$K*yU=jJ|+lytJnO=Z|S-EA^9;MESue5l_> zU9R|=pUCu!AFOSeckCUP3OEETJ;Q7Kx^a=qy?z^_6>l#Lm;1;r+t~^e+ec#a`ZIKM z4M+0gRjd5Po6&J*zvB!2QE#}?>U8(|@`tZF3qzbrYHsdK@A43nc}i%9;6OL0@zHEx z3?6<>5DE|S(O-MN;Ehg8Ms(e7ykIY;`PPI#lq?{}KUHo41zVswNlQexq^zGg=r`-g zbXw1ORUuX$IM-f5CboWg`==|J{u*ufF(0L*>>=al?SM(eq%5g{7Sh9&`Fl2(*Gmho z{_WX$3+CHod8yPhtWTtq{q6{EWhT$UyJc&3%L&r#l0Dsa#N@JVVoZ?%c)4{%*rbMBbeJJcy(XDUH=Cjsv39?I5prw zM1o<-_ARB4g$Ro~4`$0P9TtIrO))QhTfb`8rGUGv)Jaj;_ICle-vo-G9p9^^rCY5|**bX3UudAm$^yEDg=SvNYV*|3 zGH?pnnXoQQe=Ou9Vf4*t+<~*SZ!lf3Loh)S8juk_j+}i{y|U9ph1iB}!5RPO!oOu~ zx7dX4W6*+0b;`p~nM!SVN33 zJo;V4B!ztVYyN@Qvpu85R($^=W6ejlR=nZ{pxZcQ@R2REC5+DnP%?f&Tkndcj27JjVpRgqYGcG?Pt6|LdRV}o<* zyzGHQLbOu&-R(r$7LUpueU;R)tF$k3M3+;!LMTh@t zGR__XZa-7F?Lih{XUs$6fK7eXw_z_Iu5^9Ue@oT&lAv$r#Nv{~@g$(>?3usXDTN=| zIgNEQ4?6&&DOEqdJ+u4SR=-MK7#~y5Bv@!5W~$qTTM`nVk)g!HLJyY`f|;ZIFhr!7 zeU+*Eio04!97Wh|Xs~v;&F0xwzod?m?l_b88=%?LVD0spe*F3S^#p2=tsskx2<(9& zfid?=f<5D6svE} zo;@?*L)>GCS0G2^q@`%xBADRk>zu>kzWNXN2KHoP_mTu+d2 zDee>ms{s1|s)nBe$1T9#Ekw9vby@UA4s!g$NZ1!mO+cVK{N%q5;x6sVI_9XW)3BXm zcy*9i&14gC_uxGR?%c;i#J0kw44sLHu51mWXG=uY>1+NR;jKLFWPQoW-ev3&LQTuK z_R4GBw)0FMdBv#{pZ%L3Xn^Cta=$?TKk3Gy`r}Ind!rWqaSS+L?ZlIxWb({uZpd#` zyo4?G?Ds31~mTIc1qH@Or zOnaHHK3{v2mcKbRr$(MX75~S4tf$>$U`K%miYWK|L>XBUeT_gEf1mGZS5(&JVl}m=)O4o6JSs`fF zL8x+1m*77rS!m#&67&42LQ%k9qBD2oAYiMX=s*zdvT}n=h(XBQs;&mi*smd-JViuA zYMc1Z~q-mK}r-q1PQihq>-0;tGn`hPty6?|dZCUR?XNr!#5N|EL zt4R#LZ2(%bhvcTSbdL9=-#j(3e~DL!&PMu1$n4j^f>PdjO5|P#61>6(&#Jib8wcew zC?|f1Z+>6Hs~G3Aq(f|xAmkl4(2cb@UN+QoDjX*hpIQq{%`=C%^rML4k@Y={jp*8G zu71pJz5Z)kzEEnbQ**>R!6|={d1HDLuW+z({i=0YHd_gJo1VTvs1i{A9Kvey^LNn6 z9b2lj>s~Y*^?aRw@0{T3Toj@v(S(ua8On}O{wy7u6A@bWsY&<{S4nH7AZ^9`A&Py& zPSYNSy!rmQY%onlplWKi!2FwnaJ?btsZ;+;8IHdsxZg)Hw4IXhsrNE_R7R9 zDsN3Hntb}V2nm&V^789P1QxU&McF#qIC)Z;3iU zad8_P(DiziIW8j&-!=g)rsU#yF40NF+iG=qK9~P$C;;V=Igxx3HOV;g@?%)(8Z>H@%D|Au7)E;0dyx=mPk>qzLXir`yr3o|L$UZ`dE22 z1~u=ijZxq}MyG_!1#qk#c*AO_{b2t5_*g2U0C27Dq&lvyiq^%c9P422K8EJOmbpK6 zBenP5?M`Q!UC{E^4i;6~oDm-0gQR!zXFMljjL~YJ4ZNKf<$hFNRT%ip^D!5gSzQs| zQQpj5RHkVyKU_-pL{keX8c9v|O=IO75k{Px>`V8tW3SsjO4vM{pz$p#IfR<=-? zF~zIJ$~Pk|i{mSS4LZSFP!)l@(#%^4L4c8SlWvDmKi|9s-JPh*0oxV14H)zgw7BG! zIG|hmze!DB-fo4Ogg>ZK7q2_5(?Bau+|xBb6l2&M(~ENPjdh0H^pq?ONEINb07!&$ z)X_Pu)i&ieaZXmIP6?uGBUWyy&E;hcm?x5erEf5pI>>NXQBOo_n@u@QMjr2#5h}$; zWUqAoXX9L#6h$|HRs_<(x3~+$d)G`yf|qwvwB4hN^|U@*@al-m+63 z5_V}vtT2{Cy{TD<0zTzyyT^* zVxx0!#OxZB9!Or(<`X7^>4{J;B?B$jC9>zI?jIpp5*BgA-BAc@WEgE^gfs4M@b~Pz z#Ger;L9p&gcD#*r$i2GQ}smN^$s=3=)TC0GO2>S!WR{KbxTB$y~9)fmfi$*`Ix$lH5L5D~Kj zznMOYfMdre3?-F=EXpe~%fvkp%SunRwUvpLJ1~=pH{}FT)J*R^Ns|!XwQ2k(H9)7Y z?)QLRzj*OcOAI%&RT9p3X|@thwy^E)R7UY}epYI(Owh2BG_>8&vdi7|q{yC9XF;jH zW3p`~HTa~?guh#NS#jGwl>DU}xX2gwAf)Gx=7?sujyV5^V&5a%CO&LPwb}N|e{ch@ zW=JMr*bsy7PwZ&@1c&zgP_LS~g6tb){>6&L>;8x9#@qjDiZhZaw(EJAY4>@0c0rbZ zdNr3c9DDj|lil^vFag(ds(|+)OZ@+yNBzH2$?8P*3zW(BzI0X#C8Wtus zL|T}#L{L8>4S!Fz0^HfIR9opP(&GhCv(CDOck_kJ>Md*K-n86ejgr@!MADtFJn%#T zC70P!Ujz_7)>fbs#eHTh>JUx0lxQ&Zw`O)#*(rye~8G`iQAaoq>ED7I0#`=Xqk0K#G;czdSbxHnCCI@m5A z>HqW%LEonI+R4a2x_8-+t`SE|H=WJb1iZo_Xzu1mn^TPbHy2V3lxm&PlS!BT#U=M_ zWfs~>dGXIqroHXRp{RpbJkh6b+8yrjUTSkRz;OD75N3a(?7?o^k!9I!GhybBtoQ&o z-tGVM&BX;iBD+fVP^7gco2G(tB!6jehU6JlO}BmZz2+AzX7ddJ&vEdX@GQA$8)2E= z7d^pJf#ISPikV-2d1eh+wn{^O6h$l>O_M+SfLpoJ(S{S3Yt8@GXGj38II3T^iR(Jk z6F?2#hpBv(7lh9IZ*LjfTphLX!Q&owNdmTHV2Q|>e<=u1$nOQOiJrgYD62BF$P%^O z;_=Fka0j>>IHoxMdf?u|zUyZI3eSFuWPZB}hY_n4{`O}L)od-?Lxkd^H`$lEYY#E+ zB$v?GKvEO~x+{7O>i<0S!tI|L=8vH}TfL7XvZ~{sUvz4ymc|EDf*CVC`h96$mnd+o zRz2F~Jd%w>HI}G2`A) zcZ^7Te}NsRJ=xJVSp{Av42J!t&UF|@mU4Z#)a_g5JM}8km&{!B=r#bF+NVYa%3Bvzh_EuIGjoTI-hfxH|^My5}o#WTPUXlL_3GncNe1ayh;;(0vx zubk!D3^S`_WsKF##egKU%T2S)3a+=BYGj*hO){2bvwAP><30}GPZZ8-dSk<*zXo{Gwk@XJ?ICO`t1!LxLj*j_=ReOAq}YiKjvL literal 0 HcmV?d00001 diff --git a/sentry.client.config.js b/sentry.client.config.js new file mode 100644 index 0000000..b297e4f --- /dev/null +++ b/sentry.client.config.js @@ -0,0 +1,18 @@ +// This file configures the initialization of Sentry on the browser. +// The config you add here will be used whenever a page is visited. +// https://docs.sentry.io/platforms/javascript/guides/nextjs/ + +import * as Sentry from "@sentry/nextjs"; +import { env } from "./src/lib/env.mjs"; + +const SENTRY_DSN = env.NEXT_PUBLIC_SENTRY_DSN; + +Sentry.init({ + dsn: SENTRY_DSN, + // Adjust this value in production, or use tracesSampler for greater control + tracesSampleRate: 1.0, + // ... + // Note: if you want to override the automatic release value, do not set a + // `release` value here - use the environment variable `SENTRY_RELEASE`, so + // that it will also get attached to your source maps +}); diff --git a/sentry.edge.config.js b/sentry.edge.config.js new file mode 100644 index 0000000..4a268a9 --- /dev/null +++ b/sentry.edge.config.js @@ -0,0 +1,16 @@ +// This file configures the initialization of Sentry on the server. +// The config you add here will be used whenever middleware or an Edge route handles a request. +// https://docs.sentry.io/platforms/javascript/guides/nextjs/ + +import * as Sentry from "@sentry/nextjs"; +import { env } from "./src/lib/env.mjs"; + +Sentry.init({ + dsn: env.SENTRY_DSN, + // Adjust this value in production, or use tracesSampler for greater control + tracesSampleRate: 1.0, + // ... + // Note: if you want to override the automatic release value, do not set a + // `release` value here - use the environment variable `SENTRY_RELEASE`, so + // that it will also get attached to your source maps +}); diff --git a/sentry.properties b/sentry.properties new file mode 100644 index 0000000..f875f80 --- /dev/null +++ b/sentry.properties @@ -0,0 +1,4 @@ +defaults.url=https://sentry.io/ +defaults.org=saleor +defaults.project= +cli.executable= diff --git a/sentry.server.config.js b/sentry.server.config.js new file mode 100644 index 0000000..db57299 --- /dev/null +++ b/sentry.server.config.js @@ -0,0 +1,18 @@ +// This file configures the initialization of Sentry on the server. +// The config you add here will be used whenever the server handles a request. +// https://docs.sentry.io/platforms/javascript/guides/nextjs/ + +import * as Sentry from "@sentry/nextjs"; +import { env } from "./src/lib/env.mjs"; + +const SENTRY_DSN = env.SENTRY_DSN || env.NEXT_PUBLIC_SENTRY_DSN; + +Sentry.init({ + dsn: SENTRY_DSN, + // Adjust this value in production, or use tracesSampler for greater control + tracesSampleRate: 1.0, + // ... + // Note: if you want to override the automatic release value, do not set a + // `release` value here - use the environment variable `SENTRY_RELEASE`, so + // that it will also get attached to your source maps +}); diff --git a/src/__tests__/apiTestsUtils.ts b/src/__tests__/apiTestsUtils.ts new file mode 100644 index 0000000..9d9ee52 --- /dev/null +++ b/src/__tests__/apiTestsUtils.ts @@ -0,0 +1,20 @@ +import { type HttpMethod } from "../lib/api-response"; +import { type JSONValue } from "../types"; + +export const host = "https://localhost:4213"; + +export const createRequestMock = ( + method: HttpMethod, + body?: JSONValue, + headers = new Headers(), +) => { + if (body) { + headers.append("Content-Type", "application/json"); + } + + return new Request(`${host}/api/route`, { + method, + headers, + ...(body && { body: JSON.stringify(body) }), + }); +}; diff --git a/src/__tests__/pages/index.test.tsx b/src/__tests__/pages/index.test.tsx new file mode 100644 index 0000000..b110c58 --- /dev/null +++ b/src/__tests__/pages/index.test.tsx @@ -0,0 +1,26 @@ +import { render, screen } from "@testing-library/react"; +import { expect, vi, describe, it } from "vitest"; +import IndexPage from "../../pages"; + +vi.mock("@saleor/app-sdk/app-bridge", () => { + return { + useAppBridge: () => ({ + appBridgeState: {}, + appBridge: {}, + }), + }; +}); + +vi.mock("next/router", () => ({ + useRouter: vi.fn(), +})); + +describe("App", () => { + it("renders text", () => { + render(); + + expect( + screen.getByText("Install this app in your Saleor Dashboard", { exact: false }), + ).toBeInTheDocument(); + }); +}); diff --git a/src/__tests__/polly.ts b/src/__tests__/polly.ts new file mode 100644 index 0000000..a23b15c --- /dev/null +++ b/src/__tests__/polly.ts @@ -0,0 +1,269 @@ +import path from "path"; +import NodeHttpAdapter from "@pollyjs/adapter-node-http"; +import FetchAdapter from "@pollyjs/adapter-fetch"; +import { Polly, type Headers, type PollyConfig } from "@pollyjs/core"; +import FSPersister from "@pollyjs/persister-fs"; +import { afterEach, beforeEach, expect } from "vitest"; +import merge from "lodash-es/merge"; +import omit from "lodash-es/omit"; +import omitDeep from "omit-deep-lodash"; +import { tryJsonParse, tryIgnore } from "../lib/utils"; +import { testEnv } from "@/__tests__/test-env.mjs"; +import { env } from "@/lib/env.mjs"; + +declare module "vitest" { + export interface TestContext { + polly?: Polly; + } +} + +export const omitPathsFromJson = (paths: string[]) => (input: string) => { + return JSON.stringify(omit(JSON.parse(input) as object, paths)); +}; +export const omitPathsFromHeaders = (paths: string[]) => (headers: Headers) => { + return omit(headers, paths); +}; + +const HEADERS_BLACKLIST = new Set([ + "authorization-bearer", + "authorization", + "saleor-signature", + "set-cookie", + "x-api-key", + "x-stripe-client-user-agent", +]); + +const VARIABLES_BLACKLIST = new Set([ + "csrfToken", + "email", + "newEmail", + "newPassword", + "oldPassword", + "password", + "redirectUrl", + "refreshToken", + "token", + "authorisationToken", +]); + +const removeBlacklistedVariables = ( + obj: {} | undefined | string | null, +): {} | undefined | string | null => { + if (!obj || typeof obj === "string") { + return obj; + } + + if ("client_secret" in obj) { + obj.client_secret = "pi_FAKE_CLIENT_SECRET"; + } + + return omitDeep(obj, ...VARIABLES_BLACKLIST); +}; + +/** + * This interface is incomplete + */ +interface PollyRecording { + response: { + content?: { + mimeType: string; + text: string; + }; + cookies: string[]; + headers: Array<{ value: string; name: string }>; + }; + request: { + postData?: { + text: string; + }; + cookies: string[]; + headers: Array<{ value: string; name: string }>; + }; +} + +const responseIsJson = (recording: PollyRecording) => { + return recording.response.content?.mimeType.includes("application/json"); +}; +const requestIsJson = (recording: PollyRecording) => { + return recording.request.headers.some( + ({ name, value }) => + name.toLowerCase() === "content-type" && value.includes("application/json"), + ); +}; + +export const setupRecording = (config?: PollyConfig) => { + Polly.on("create", (polly) => { + /* eslint-disable @typescript-eslint/no-unsafe-assignment */ + /* eslint-disable @typescript-eslint/no-unsafe-member-access */ + /* eslint-disable @typescript-eslint/no-unsafe-call */ + /* eslint-disable @typescript-eslint/no-unsafe-argument */ + /* eslint-disable @typescript-eslint/no-unsafe-return */ + /* eslint-disable @typescript-eslint/no-non-null-assertion */ + polly.server + .any() + // Hide sensitive data in headers or in body + .on("beforePersist", (_req, recording: PollyRecording) => { + recording.response.cookies = []; + + recording.response.headers = recording.response.headers.filter( + (el: Record) => !HEADERS_BLACKLIST.has(el.name), + ); + recording.request.headers = recording.request.headers.filter( + (el: Record) => !HEADERS_BLACKLIST.has(el.name), + ); + + if (recording.request.postData?.text) { + const requestJson = tryJsonParse(recording.request.postData.text); + const filteredRequestJson = removeBlacklistedVariables(requestJson); + recording.request.postData.text = + typeof filteredRequestJson === "string" + ? filteredRequestJson + : JSON.stringify(filteredRequestJson); + } + if (recording.response.content?.text) { + const responseJson = tryJsonParse(recording.response.content.text); + const filteredResponseJson = removeBlacklistedVariables(responseJson); + recording.response.content.text = + typeof filteredResponseJson === "string" + ? filteredResponseJson + : JSON.stringify(filteredResponseJson); + } + }) + // make JSON response and requests more readable + // https://github.com/Netflix/pollyjs/issues/322 + .on("beforePersist", (_req, recording: PollyRecording) => { + if (responseIsJson(recording)) { + tryIgnore( + () => + (recording.response.content!.text = JSON.parse( + recording.response.content!.text, + ) as string), + ); + } + + if (requestIsJson(recording)) { + tryIgnore( + () => + (recording.request.postData!.text = JSON.parse( + recording.request.postData!.text, + ) as string), + ); + } + }) + .on("beforeReplay", (_req, recording: PollyRecording) => { + if (responseIsJson(recording)) { + tryIgnore( + () => + (recording.response.content!.text = JSON.stringify(recording.response.content!.text)), + ); + } + + if (requestIsJson(recording)) { + tryIgnore( + () => + (recording.request.postData!.text = JSON.stringify(recording.request.postData!.text)), + ); + } + }); + /* eslint-enable */ + }); + + const defaultConfig = { + ...getRecordingSettings(), + adapters: [FetchAdapter, NodeHttpAdapter], + persister: FSPersister, + adapterOptions: { + fetch: { + context: globalThis, + }, + }, + persisterOptions: { + fs: {}, + keepUnusedRequests: false, + }, + flushRequestsOnStop: true, + matchRequestsBy: { + url: { + protocol: true, + username: true, + password: true, + hostname: true, + port: true, + pathname: true, + query: true, + hash: false, + }, + body: true, + order: false, + method: true, + headers: { + exclude: [ + "date", + "idempotency-key", + "original-request", + "request-id", + "content-length", + "x-stripe-client-user-agent", + ], + }, + }, + }; + + beforeEach(async (ctx) => { + const { currentTestName } = expect.getState(); + if (!currentTestName) { + throw new Error("This function must be run inside a test case!"); + } + + const recordingsRoot = path.dirname(expect.getState().testPath || ""); + const recordingsDirectory = path.join(recordingsRoot, "__recordings__"); + + const [, ...names] = currentTestName.split(" > "); + const polly = new Polly( + names.join("/"), + merge( + defaultConfig, + { + persisterOptions: { + fs: { + recordingsDir: recordingsDirectory, + }, + }, + }, + config, + ), + ); + ctx.polly = polly; + }); + + afterEach((ctx) => ctx.polly?.flush()); + afterEach((ctx) => ctx.polly?.stop()); +}; + +const getRecordingSettings = (): Pick< + PollyConfig, + "mode" | "recordIfMissing" | "recordFailedRequests" +> => { + // use replay mode by default, override if POLLY_MODE env variable is passed + const mode = env.CI ? "replay" : testEnv.POLLY_MODE; + + if (mode === "record") { + return { + mode: "record", + recordIfMissing: true, + recordFailedRequests: true, + }; + } + if (mode === "record_missing") { + return { + mode: "replay", + recordIfMissing: true, + recordFailedRequests: true, + }; + } + return { + mode: "replay", + recordIfMissing: false, + recordFailedRequests: false, + }; +}; diff --git a/src/__tests__/test-env.mjs b/src/__tests__/test-env.mjs new file mode 100644 index 0000000..babd7ab --- /dev/null +++ b/src/__tests__/test-env.mjs @@ -0,0 +1,51 @@ +import { z } from "zod"; + +const testEnvSchema = z.object({ + // Saleor + TEST_SALEOR_API_URL: z.string().url(), + TEST_SALEOR_APP_TOKEN: z.string(), + TEST_SALEOR_APP_ID: z.string(), + TEST_SALEOR_JWKS: z.string(), + // Payment App + TEST_PAYMENT_APP_SECRET_KEY: z.string(), + TEST_PAYMENT_APP_PUBLISHABLE_KEY: z.string(), + TEST_PAYMENT_APP_WEBHOOK_SECRET: z.string(), + TEST_PAYMENT_APP_WEBHOOK_ID: z.string(), + // Polly.js + POLLY_MODE: z.enum(["record", "record_missing", "replay"]).optional().default("replay"), +}); + +const processEnv = { + // Saleor + TEST_SALEOR_API_URL: process.env.TEST_SALEOR_API_URL, + TEST_SALEOR_APP_TOKEN: process.env.TEST_SALEOR_APP_TOKEN, + TEST_SALEOR_APP_ID: process.env.TEST_SALEOR_APP_ID, + TEST_SALEOR_JWKS: process.env.TEST_SALEOR_JWKS, + // Payment App + TEST_PAYMENT_APP_SECRET_KEY: process.env.TEST_PAYMENT_APP_SECRET_KEY, + TEST_PAYMENT_APP_PUBLISHABLE_KEY: process.env.TEST_PAYMENT_APP_PUBLISHABLE_KEY, + TEST_PAYMENT_APP_WEBHOOK_SECRET: process.env.TEST_PAYMENT_APP_WEBHOOK_SECRET, + TEST_PAYMENT_APP_WEBHOOK_ID: process.env.TEST_PAYMENT_APP_WEBHOOK_ID, + // Polly.js + POLLY_MODE: process.env.POLLY_MODE, +}; + +/* c8 ignore start */ +/** @type z.infer + * @ts-ignore - can't type this properly in jsdoc */ +// eslint-disable-next-line import/no-mutable-exports +let testEnv = process.env; + +if (!!process.env.SKIP_ENV_VALIDATION == false) { + const parsed = testEnvSchema.safeParse(processEnv); + + if (parsed.success === false) { + console.error("❌ Invalid environment variables:", parsed.error.flatten().fieldErrors); + throw new Error("Invalid environment variables"); + } + + testEnv = parsed.data; +} +/* c8 ignore stop */ + +export { testEnv }; diff --git a/src/__tests__/testAPL.ts b/src/__tests__/testAPL.ts new file mode 100644 index 0000000..10be396 --- /dev/null +++ b/src/__tests__/testAPL.ts @@ -0,0 +1,59 @@ +import { + type AplConfiguredResult, + type AplReadyResult, + type APL, + type AuthData, +} from "@saleor/app-sdk/APL"; +import { testEnv } from "@/__tests__/test-env.mjs"; + +export class TestAPL implements APL { + async get(saleorApiUrl: string): Promise { + if (testEnv.TEST_SALEOR_API_URL !== saleorApiUrl) { + return; + } + + return { + saleorApiUrl: testEnv.TEST_SALEOR_API_URL, + domain: new URL(testEnv.TEST_SALEOR_API_URL).hostname, + jwks: "", + appId: testEnv.TEST_SALEOR_APP_ID, + token: testEnv.TEST_SALEOR_APP_TOKEN, + }; + } + + async set(authData: AuthData) { + console.warn("Attempted to save APL authData in test", authData); + } + + async delete() { + console.warn("Attempted to delete APL authData in test"); + } + + async getDomain(): Promise { + return new URL(testEnv.TEST_SALEOR_API_URL).hostname; + } + + async isReady(): Promise { + return { + ready: true, + }; + } + + async getAll() { + return [ + { + saleorApiUrl: testEnv.TEST_SALEOR_API_URL, + domain: new URL(testEnv.TEST_SALEOR_API_URL).hostname, + jwks: "", + appId: testEnv.TEST_SALEOR_APP_ID, + token: testEnv.TEST_SALEOR_APP_TOKEN, + }, + ]; + } + + async isConfigured(): Promise { + return { + configured: true, + }; + } +} diff --git a/src/app-bridge-instance.ts b/src/app-bridge-instance.ts new file mode 100644 index 0000000..777ee6b --- /dev/null +++ b/src/app-bridge-instance.ts @@ -0,0 +1,7 @@ +import { AppBridge } from "@saleor/app-sdk/app-bridge"; + +/** + * Ensure instance is a singleton. + * TODO: This is React 18 issue, consider hiding this workaround inside app-sdk + */ +export const appBridgeInstance = typeof window !== "undefined" ? new AppBridge() : undefined; diff --git a/src/backend-lib/api-route-utils.test.ts b/src/backend-lib/api-route-utils.test.ts new file mode 100644 index 0000000..afc1bc8 --- /dev/null +++ b/src/backend-lib/api-route-utils.test.ts @@ -0,0 +1,294 @@ +import { describe, it, expect, vi } from "vitest"; +import { type ValidateFunction } from "ajv"; +import { type NextApiResponse, type NextApiRequest } from "next/types"; +import { type NextWebhookApiHandler } from "@saleor/app-sdk/handlers/next"; +import { getAuthDataForRequest, getSyncWebhookHandler, validateData } from "./api-route-utils"; +import { testEnv } from "@/__tests__/test-env.mjs"; +import { BaseError, MissingSaleorApiUrlError } from "@/errors"; + +describe("api-route-utils", () => { + describe("validateData", () => { + it("should return data if it validates", async () => { + const data = { a: 1, b: "c" }; + await expect( + validateData(data, (() => true) as unknown as ValidateFunction), + ).resolves.toEqual(data); + }); + + it("should throw error if it doesn't validate", async () => { + const data = { a: 1, b: "c" }; + await expect( + validateData(data, (() => false) as unknown as ValidateFunction), + ).rejects.toMatchInlineSnapshot("[UnknownError: JsonSchemaError]"); + }); + + it("should throw error if it throws", async () => { + const data = { a: 1, b: "c" }; + await expect( + validateData(data, (() => { + throw new Error("some error"); + }) as unknown as ValidateFunction), + ).rejects.toMatchInlineSnapshot("[UnknownError: some error]"); + }); + }); + + describe("getSyncWebhookHandler", () => { + type WebhookContext = Parameters[2]; + + it("should return a function", () => { + expect( + getSyncWebhookHandler( + "TestWebhook", + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + (() => {}) as any, + (() => true) as unknown as ValidateFunction, + () => ({}), + ), + ).toEqual(expect.any(Function)); + }); + + it("calls handler with payload and saleorApiUrl from context", async () => { + const handler = vi.fn(); + const webhookHandler = getSyncWebhookHandler( + "TestWebhook", + handler, + (() => true) as unknown as ValidateFunction, + () => ({}), + ); + + type WebhookContext = Parameters[2]; + + const payload = {}; + const authData = { + saleorApiUrl: testEnv.TEST_SALEOR_API_URL, + }; + + await webhookHandler( + {} as NextApiRequest, + { json() {} } as unknown as NextApiResponse, + { + authData, + payload, + } as unknown as WebhookContext, + ); + + expect(handler).toHaveBeenCalledWith(payload, authData.saleorApiUrl); + }); + + it("returns json with result", async () => { + const handler = vi.fn().mockReturnValue({ + some: "json", + }); + const json = vi.fn(); + const webhookHandler = getSyncWebhookHandler( + "TestWebhook", + handler, + (() => true) as unknown as ValidateFunction, + () => ({}), + ); + + const payload = {}; + const authData = { + saleorApiUrl: testEnv.TEST_SALEOR_API_URL, + }; + + await webhookHandler( + {} as NextApiRequest, + { json } as unknown as NextApiResponse, + { + authData, + payload, + } as unknown as WebhookContext, + ); + + expect(json).toHaveBeenCalledWith({ + some: "json", + }); + }); + + it("catches known errors and returns 200 with details", async () => { + const handler = vi.fn().mockImplementation(() => { + throw new BaseError("This is a known error", { + props: { + errorCode: 123, + statusCode: 422, + }, + errors: [new Error("Initial problem")], + }); + }); + const errorMapper = vi.fn(); + const json = vi.fn(); + const status = vi.fn().mockReturnValue({ json }); + const webhookHandler = getSyncWebhookHandler( + "TestWebhook", + handler, + (() => true) as unknown as ValidateFunction, + errorMapper, + ); + + type WebhookContext = Parameters[2]; + + const payload = {}; + const authData = { + saleorApiUrl: testEnv.TEST_SALEOR_API_URL, + }; + + await webhookHandler( + {} as NextApiRequest, + { json, status } as unknown as NextApiResponse, + { + authData, + payload, + } as unknown as WebhookContext, + ); + + expect(status).toHaveBeenCalledWith(200); + expect(json).toHaveBeenCalled(); + expect(errorMapper.mock.lastCall[1]).toMatchInlineSnapshot(` + { + "errors": [ + { + "code": "BaseError", + "details": {}, + "message": "This is a known error", + }, + { + "code": "Error", + "message": "Initial problem", + }, + ], + "message": "This is a known error", + "sentry": [ + [BaseError: This is a known error], + { + "extra": { + "errors": [ + [Error: Initial problem], + ], + }, + }, + ], + } + `); + }); + + it("catches known errors and responds with whatever the errorMapper returns", async () => { + const handler = vi.fn().mockImplementation(() => { + throw new MissingSaleorApiUrlError("Missing"); + }); + const errorMapper = vi.fn().mockImplementation((payload, error) => { + return { + errors: error.errors, + message: error.message, + }; + }); + const json = vi.fn(); + const status = vi.fn().mockReturnValue({ json }); + const webhookHandler = getSyncWebhookHandler( + "TestWebhook", + handler, + (() => true) as unknown as ValidateFunction, + errorMapper, + ); + + type WebhookContext = Parameters[2]; + + const payload = {}; + const authData = { + saleorApiUrl: testEnv.TEST_SALEOR_API_URL, + }; + + await webhookHandler( + {} as NextApiRequest, + { json, status } as unknown as NextApiResponse, + { + authData, + payload, + } as unknown as WebhookContext, + ); + + expect(status).toHaveBeenCalledWith(200); + expect(json).toHaveBeenCalled(); + expect(json.mock.lastCall[0]).toMatchInlineSnapshot(` + { + "errors": [ + { + "code": "MissingSaleorApiUrlError", + "details": {}, + "message": "Missing", + }, + ], + "message": "Missing", + } + `); + }); + + it("catches unknown errors and returns 500", async () => { + const handler = vi.fn().mockImplementation(() => { + throw new Error("Some error"); + }); + const json = vi.fn(); + const status = vi.fn().mockReturnValue({ json }); + const webhookHandler = getSyncWebhookHandler( + "TestWebhook", + handler, + (() => true) as unknown as ValidateFunction, + () => ({}), + ); + + type WebhookContext = Parameters[2]; + + const payload = {}; + const authData = { + saleorApiUrl: testEnv.TEST_SALEOR_API_URL, + }; + + await webhookHandler( + {} as NextApiRequest, + { json, status } as unknown as NextApiResponse, + { + authData, + payload, + } as unknown as WebhookContext, + ); + + expect(status).toHaveBeenCalledWith(500); + expect(json).toHaveBeenCalled(); + expect(BaseError.normalize(json.mock.lastCall[0])).toMatchInlineSnapshot( + "[BaseError: Some error]", + ); + }); + }); + + describe("getAuthDataForRequest", () => { + it("should throw if there's no saleroApiUrl in the query", async () => { + await expect( + getAuthDataForRequest({ query: {} } as NextApiRequest), + ).rejects.toMatchInlineSnapshot( + "[MissingSaleorApiUrlError: Missing saleorApiUrl query param]", + ); + }); + + it("should throw if data doesn't exist in APL", async () => { + await expect( + getAuthDataForRequest({ query: { saleorApiUrl: "someurl" } } as unknown as NextApiRequest), + ).rejects.toMatchInlineSnapshot("[MissingAuthDataError: APL for someurl not found]"); + }); + + it("should return data from apl if it exists", async () => { + await expect( + getAuthDataForRequest({ + query: { saleorApiUrl: testEnv.TEST_SALEOR_API_URL }, + } as unknown as NextApiRequest), + ).resolves.toMatchInlineSnapshot(` + { + "appId": "123456", + "domain": "saleor.localhost", + "jwks": "", + "saleorApiUrl": "https://saleor.localhost:8080/graphql/", + "token": "123456", + } + `); + }); + }); +}); diff --git a/src/backend-lib/api-route-utils.ts b/src/backend-lib/api-route-utils.ts new file mode 100644 index 0000000..a201dcb --- /dev/null +++ b/src/backend-lib/api-route-utils.ts @@ -0,0 +1,128 @@ +import * as Sentry from "@sentry/nextjs"; + +import { type NextApiRequest, type NextApiResponse } from "next"; +import type { ValidateFunction } from "ajv"; +import { type NextWebhookApiHandler } from "@saleor/app-sdk/handlers/next"; +import { createLogger, redactError } from "../lib/logger"; +import { + JsonSchemaError, + UnknownError, + BaseError, + MissingAuthDataError, + MissingSaleorApiUrlError, +} from "@/errors"; +import { toStringOrEmpty } from "@/lib/utils"; +import { saleorApp } from "@/saleor-app"; + +export const validateData = async (data: unknown, validate: S) => { + type Result = S extends ValidateFunction ? T : never; + try { + const isValid = validate(data); + if (!isValid) { + throw JsonSchemaError.normalize(validate.errors); + } + return data as Result; + } catch (err) { + throw UnknownError.normalize(err); + } +}; + +export function getSyncWebhookHandler>( + name: string, + webhookHandler: (payload: TPayload, saleorApiUrl: string) => Promise, + ResponseSchema: TSchema, + errorMapper: (payload: TPayload, errorResponse: ErrorResponse) => TResult & {}, +): NextWebhookApiHandler { + return async (_req, res: NextApiResponse, ctx) => { + const logger = createLogger( + { + event: ctx.event, + }, + { msgPrefix: `[${name}] ` }, + ); + const { authData, payload } = ctx; + logger.info(`handler called: ${webhookHandler.name}`); + logger.debug({ payload }, "ctx payload"); + + try { + const result = await webhookHandler(payload, authData.saleorApiUrl); + logger.info(`${webhookHandler.name} was successful`); + logger.debug({ result }, "Sending successful response"); + return res.json(await validateData(result, ResponseSchema)); + } catch (err) { + logger.error({ err: redactError(err) }, `${webhookHandler.name} error`); + + const response = errorToResponse(err); + + if (!response) { + Sentry.captureException(err); + const result = BaseError.serialize(err); + logger.debug("Sending error response"); + return res.status(500).json(result); + } + + Sentry.captureException(...response.sentry); + const finalErrorResponse = errorMapper(payload, response); + logger.debug({ finalErrorResponse }, "Sending error response"); + return res.status(200).json(await validateData(finalErrorResponse, ResponseSchema)); + } + }; +} + +type ErrorResponse = Exclude, null>; +const errorToResponse = (err: unknown) => { + const normalizedError = err instanceof BaseError ? err : null; + + if (!normalizedError) { + return null; + } + + const sentry = [ + normalizedError, + { + extra: { + errors: normalizedError.errors, + }, + }, + ] as const; + + const message = normalizedError.message; + + const errors = [ + { + code: normalizedError.name, + message: normalizedError.message, + details: {}, + }, + ...(normalizedError.errors?.map((inner) => { + return { + code: inner.name, + message: inner.message, + }; + }) ?? []), + ]; + + return { + sentry, + errors, + message, + }; +}; + +export const getAuthDataForRequest = async (request: NextApiRequest) => { + const logger = createLogger({}, { msgPrefix: "[getAuthDataForRequest] " }); + + const saleorApiUrl = toStringOrEmpty(request.query.saleorApiUrl); + logger.info(`Got saleorApiUrl=${saleorApiUrl || ""}`); + if (!saleorApiUrl) { + throw new MissingSaleorApiUrlError("Missing saleorApiUrl query param"); + } + + const authData = await saleorApp.apl.get(saleorApiUrl); + logger.debug({ authData }); + if (!authData) { + throw new MissingAuthDataError(`APL for ${saleorApiUrl} not found`); + } + + return authData; +}; diff --git a/src/deploy.ts b/src/deploy.ts new file mode 100644 index 0000000..fce0398 --- /dev/null +++ b/src/deploy.ts @@ -0,0 +1,12 @@ +/* eslint-disable node/no-process-env */ +import { execSync } from "child_process"; + +execSync("pnpm run build", { stdio: "inherit" }); + +if ( + process.env.DEPLOYMENT_ENVIRONMENT === "production" || + process.env.DEPLOYMENT_ENVIRONMENT === "staging" +) { + console.log("Production environment detected, running migrations"); + execSync("pnpm run migrate", { stdio: "inherit" }); +} diff --git a/src/errors.ts b/src/errors.ts new file mode 100644 index 0000000..ec0b75a --- /dev/null +++ b/src/errors.ts @@ -0,0 +1,79 @@ +import { type IncomingHttpHeaders } from "node:http2"; +import { type TRPC_ERROR_CODE_KEY } from "@trpc/server/rpc"; +import ModernError from "modern-errors"; +import ModernErrorsSerialize from "modern-errors-serialize"; + +// Http errors +type CommonProps = { + errorCode?: string; + statusCode?: number; + name?: number; +}; + +export const BaseError = ModernError.subclass("BaseError", { + plugins: [ModernErrorsSerialize], + props: {} as CommonProps, +}); +export const UnknownError = BaseError.subclass("UnknownError"); +export const JsonSchemaError = BaseError.subclass("JsonSchemaError"); +export const MissingSaleorApiUrlError = BaseError.subclass("MissingSaleorApiUrlError"); +export const MissingAuthDataError = BaseError.subclass("MissingAuthDataError"); +export const HttpRequestError = BaseError.subclass("HttpRequestError", { + props: {} as { statusCode: number; body: string; headers: IncomingHttpHeaders }, +}); + +// TRPC Errors +export interface TrpcErrorOptions { + /** HTTP response code returned by TRPC */ + trpcCode?: TRPC_ERROR_CODE_KEY; +} +export const BaseTrpcError = BaseError.subclass("BaseTrpcError", { + props: { trpcCode: "INTERNAL_SERVER_ERROR" } as TrpcErrorOptions, +}); +export const JwtTokenExpiredError = BaseTrpcError.subclass("JwtTokenExpiredError", { + props: { trpcCode: "UNAUTHORIZED" } as TrpcErrorOptions, +}); +export const JwtInvalidError = BaseTrpcError.subclass("JwtInvalidError", { + props: { trpcCode: "UNAUTHORIZED" } as TrpcErrorOptions, +}); +export const ReqMissingSaleorApiUrlError = BaseTrpcError.subclass("ReqMissingSaleorApiUrlError", { + props: { trpcCode: "BAD_REQUEST" } as TrpcErrorOptions, +}); +export const ReqMissingAuthDataError = BaseTrpcError.subclass("ReqMissingSaleorApiUrlError", { + props: { trpcCode: "UNAUTHORIZED" } as TrpcErrorOptions, +}); +export const ReqMissingTokenError = BaseTrpcError.subclass("ReqMissingTokenError", { + props: { trpcCode: "BAD_REQUEST" } as TrpcErrorOptions, +}); +export const ReqMissingAppIdError = BaseTrpcError.subclass("ReqMissingAppIdError", { + props: { trpcCode: "BAD_REQUEST" } as TrpcErrorOptions, +}); + +// TRPC + react-hook-form errors +export interface FieldErrorOptions extends TrpcErrorOptions { + fieldName: string; +} + +export const FieldError = BaseTrpcError.subclass("FieldError", { + props: {} as FieldErrorOptions, +}); +export const RestrictedKeyNotSupportedError = FieldError.subclass( + "RestrictedKeyNotSupportedError", + { + props: { fieldName: "secretKey" } as FieldErrorOptions, + }, +); +export const InvalidSecretKeyError = FieldError.subclass("InvalidSecretKeyError", { + props: { fieldName: "secretKey" } as FieldErrorOptions, +}); +export const UnexpectedSecretKeyError = FieldError.subclass("UnexpectedSecretKeyError", { + props: { fieldName: "secretKey" } as FieldErrorOptions, +}); +export const InvalidPublishableKeyError = FieldError.subclass("InvalidPublishableKeyError", { + props: { fieldName: "publishableKey" } as FieldErrorOptions, +}); +export const UnexpectedPublishableKeyError = FieldError.subclass("UnexpectedPublishableKeyError", { + props: { fieldName: "publishableKey" } as FieldErrorOptions, +}); + +export const FileReaderError = BaseError.subclass("FileReaderError"); diff --git a/src/lib/api-response.ts b/src/lib/api-response.ts new file mode 100644 index 0000000..a2b250f --- /dev/null +++ b/src/lib/api-response.ts @@ -0,0 +1,71 @@ +import { type JSONValue } from "../types"; + +export const getResponse = + (status: number) => + (data: JSONValue, headers: Headers = new Headers()) => { + if (data) { + headers.append("Content-Type", "application/json"); + } + return new Response(JSON.stringify(data), { + status, + headers, + }); + }; + +export const HttpStatus = { + OK: 200, + Created: 201, + Accepted: 202, + NonAuthoritativeInformation: 203, + NoContent: 204, + ResetContent: 205, + PartialContent: 206, + BadRequest: 400, + Unauthorized: 401, + PaymentRequired: 402, + Forbidden: 403, + NotFound: 404, + MethodNotAllowed: 405, + NotAcceptable: 406, + ProxyAuthenticationRequired: 407, + RequestTimeout: 408, + Conflict: 409, + Gone: 410, + LengthRequired: 411, + PreconditionFailed: 412, + PayloadTooLarge: 413, + URITooLong: 414, + UnsupportedMediaType: 415, + RangeNotSatisfiable: 416, + ExpectationFailed: 417, + ImaTeapot: 418, + MisdirectedRequest: 421, + UnprocessableEntity: 422, + Locked: 423, + FailedDependency: 424, + TooEarly: 425, + UpgradeRequired: 426, + PreconditionRequired: 428, + TooManyRequests: 429, + RequestHeaderFieldsTooLarge: 431, + UnavailableForLegalReasons: 451, + InternalServerError: 500, +} as const; +export type HttpStatus = (typeof HttpStatus)[keyof typeof HttpStatus]; + +export type HttpMethod = "GET" | "POST" | "PATCH" | "PUT" | "DELETE" | "HEAD"; + +export const ok = getResponse(HttpStatus.OK); +export const created = getResponse(HttpStatus.Created); +export const noContent = getResponse(HttpStatus.NoContent); + +export const badRequest = getResponse(HttpStatus.BadRequest); +export const unauthorized = getResponse(HttpStatus.Unauthorized); +export const forbidden = getResponse(HttpStatus.Forbidden); +export const notFound = getResponse(HttpStatus.NotFound); +export const methodNotAllowed = (methods: string[]) => + getResponse(HttpStatus.MethodNotAllowed)( + "Method not allowed", + new Headers({ Allow: methods.join(", ") }), + ); +export const conflict = getResponse(HttpStatus.Conflict); diff --git a/src/lib/create-graphq-client.ts b/src/lib/create-graphq-client.ts new file mode 100644 index 0000000..6c03085 --- /dev/null +++ b/src/lib/create-graphq-client.ts @@ -0,0 +1,52 @@ +import { type AuthConfig, authExchange } from "@urql/exchange-auth"; +import { + cacheExchange, + createClient as urqlCreateClient, + dedupExchange, + fetchExchange, +} from "urql"; + +interface IAuthState { + token: string; +} + +export const createClient = (url: string, getAuth: AuthConfig["getAuth"]) => + urqlCreateClient({ + url, + exchanges: [ + dedupExchange, + cacheExchange, + authExchange({ + addAuthToOperation: ({ authState, operation }) => { + if (!authState || !authState?.token) { + return operation; + } + + const fetchOptions = + typeof operation.context.fetchOptions === "function" + ? operation.context.fetchOptions() + : operation.context.fetchOptions || {}; + + return { + ...operation, + context: { + ...operation.context, + fetchOptions: { + ...fetchOptions, + headers: { + ...fetchOptions.headers, + "Authorization-Bearer": authState.token, + }, + }, + }, + }; + }, + getAuth, + }), + fetchExchange, + ], + }); + +export function createServerClient(saleorApiUrl: string, token: string) { + return createClient(saleorApiUrl, async () => Promise.resolve({ token })); +} diff --git a/src/lib/env.mjs b/src/lib/env.mjs new file mode 100644 index 0000000..5836240 --- /dev/null +++ b/src/lib/env.mjs @@ -0,0 +1,62 @@ +// @ts-check +import { createEnv } from "@t3-oss/env-nextjs"; +import { z } from "zod"; + +export const env = createEnv({ + isServer: typeof window === "undefined" || process.env.NODE_ENV === "test", + /* + * Serverside Environment variables, not available on the client. + * Will throw if you access these variables on the client. + */ + server: { + ENV: z.enum(["development", "test", "staging", "production"]).default("development"), + SECRET_KEY: z.string().min(8, { message: "Cannot be too short" }), + SENTRY_DSN: z.string().min(1).optional(), + APL: z.enum(["saleor-cloud", "upstash", "file"]).optional().default("file"), + CI: z.coerce.boolean().optional().default(false), + APP_DEBUG: z + .enum(["fatal", "error", "warn", "info", "debug", "trace", "silent"]) + .optional() + .default("error"), + VERCEL_URL: z.string().optional(), + PORT: z.coerce.number().optional(), + UPSTASH_URL: z.string().optional(), + UPSTASH_TOKEN: z.string().optional(), + REST_APL_ENDPOINT: z.string().optional(), + REST_APL_TOKEN: z.string().optional(), + ALLOWED_DOMAIN_PATTERN: z.string().optional(), + }, + + /* + * Environment variables available on the client (and server). + * + * 💡 You'll get type errors if these are not prefixed with NEXT_PUBLIC_. + */ + client: { + NEXT_PUBLIC_SENTRY_DSN: z.optional(z.string().min(1)), + }, + + /* + * Due to how Next.js bundles environment variables on Edge and Client, + * we need to manually destructure them to make sure all are included in bundle. + * + * 💡 You'll get type errors if not all variables from `server` & `client` are included here. + */ + runtimeEnv: { + ENV: process.env.ENV, + NEXT_PUBLIC_SENTRY_DSN: process.env.NEXT_PUBLIC_SENTRY_DSN, + + SECRET_KEY: process.env.SECRET_KEY, + SENTRY_DSN: process.env.SENTRY_DSN, + APL: process.env.APL, + CI: process.env.CI, + APP_DEBUG: process.env.APP_DEBUG, + VERCEL_URL: process.env.VERCEL_URL, + PORT: process.env.PORT, + UPSTASH_URL: process.env.UPSTASH_URL, + UPSTASH_TOKEN: process.env.UPSTASH_TOKEN, + REST_APL_ENDPOINT: process.env.REST_APL_ENDPOINT, + REST_APL_TOKEN: process.env.REST_APL_TOKEN, + ALLOWED_DOMAIN_PATTERN: process.env.ALLOWED_DOMAIN_PATTERN, + }, +}); diff --git a/src/lib/gql-ast-to-string.ts b/src/lib/gql-ast-to-string.ts new file mode 100644 index 0000000..648aad7 --- /dev/null +++ b/src/lib/gql-ast-to-string.ts @@ -0,0 +1,8 @@ +// Copied from @saleor/app-sdk/gql-ast-to-string.ts +import { type ASTNode, print } from "graphql"; + +export const gqlAstToString = (ast: ASTNode) => + print(ast) // convert AST to string + .replaceAll(/\n+/g, " ") // remove new lines + .replaceAll(/\s{2,}/g, " ") // remove unnecessary multiple spaces + .trim(); // remove whitespace from beginning and end diff --git a/src/lib/invariant.test.ts b/src/lib/invariant.test.ts new file mode 100644 index 0000000..ce6b729 --- /dev/null +++ b/src/lib/invariant.test.ts @@ -0,0 +1,13 @@ +import { describe, expect, it } from "vitest"; +import { invariant } from "./invariant"; + +describe("invariant", () => { + it.each([0, "", null, undefined, 0n])("should throw for %p", (value) => { + expect(() => invariant(value)).toThrowError("Invariant failed: "); + expect(() => invariant(value, "some message")).toThrowError("Invariant failed: some message"); + }); + + it.each([true, 1, "some str", {}, [], 123n])("should not throw for %p", (value) => { + expect(() => invariant(value)).not.toThrowError(); + }); +}); diff --git a/src/lib/invariant.ts b/src/lib/invariant.ts new file mode 100644 index 0000000..10b7525 --- /dev/null +++ b/src/lib/invariant.ts @@ -0,0 +1,20 @@ +import ModernError from "modern-errors"; + +export const InvariantError = ModernError.subclass("InvariantError"); + +export function invariant(condition: unknown, message?: string): asserts condition { + if (!condition) { + const err = new InvariantError(`Invariant failed: ${message || ""}`); + // remove utils.js from stack trace for better error messages + const stack = (err.stack ?? "").split("\n"); + stack.splice(1, 1); + err.stack = stack.join("\n"); + throw err; + } +} + +/* c8 ignore start */ +export function assertUnreachableButNotThrow(_: never) { + return null as never; +} +/* c8 ignore stop */ diff --git a/src/lib/isEnv.ts b/src/lib/isEnv.ts new file mode 100644 index 0000000..e2a3377 --- /dev/null +++ b/src/lib/isEnv.ts @@ -0,0 +1,4 @@ +/* eslint-disable node/no-process-env */ +export const isTest = () => process.env.NODE_ENV === "test"; +export const isDevelopment = () => process.env.NODE_ENV === "development"; +export const isProduction = () => process.env.NODE_ENV === "production"; diff --git a/src/lib/logger.ts b/src/lib/logger.ts new file mode 100644 index 0000000..b7f9dc3 --- /dev/null +++ b/src/lib/logger.ts @@ -0,0 +1,103 @@ +// We have to use process.env, otherwise pino doesn't work +/* eslint-disable node/no-process-env */ +import pino from "pino"; +// import pinoPretty from "pino-pretty"; +// import { isDevelopment, isTest } from "./isEnv"; +import { isObject } from "./utils"; +import { obfuscateValue } from "@/modules/app-configuration/utils"; +import { BaseError, BaseTrpcError } from "@/errors"; + +/* c8 ignore start */ +export const logger = pino({ + level: process.env.APP_DEBUG ?? "info", + redact: { + paths: ["secretKey", "*[*].secretKey"], + censor: (value) => redactLogValue(value), + }, + // transport: + // process.env.CI || isDevelopment() || isTest() + // ? { + // target: "pino-pretty", + // options: { + // colorize: true, + // }, + // } + // : undefined, +}); +/* c8 ignore stop */ + +export const createLogger = logger.child.bind(logger); + +export const redactLogValue = (value: unknown) => { + if (typeof value !== "string") { + // non-string values are fully redacted to prevent leaks + return "[REDACTED]"; + } + + return obfuscateValue(value); +}; + +export const redactError = (error: unknown) => { + if (error instanceof BaseTrpcError) { + const { message, name, errorCode, statusCode, trpcCode } = error; + return { + message, + name, + errorCode, + statusCode, + trpcCode, + }; + } + if (error instanceof BaseError) { + const { message, name, errorCode, statusCode } = error; + return { + message, + name, + errorCode, + statusCode, + }; + } + if (error instanceof Error) { + const { message, name } = error; + return { + message, + name, + }; + } +}; + +export const redactLogObject = (obj: T, callCount = 1): T => { + if (callCount > 10) { + logger.warn("Exceeded max call count for redactLogObject"); + return { _message: "[REDACTED - MAX CALL COUNT EXCEEDED]" } as unknown as T; + } + + const entries = Object.entries(obj).map(([key, value]) => { + if (isObject(value)) { + return [key, redactLogObject(value, callCount + 1)]; + } + if (Array.isArray(value)) { + return [key, redactLogArray(value)]; + } + return [key, redactLogValue(value)]; + }); + return Object.fromEntries(entries) as T; +}; + +export const redactLogArray = (array: T | undefined, callCount = 1): T => { + if (!array) return [] as unknown as T; + if (callCount > 10) { + logger.warn("Exceeded max call count for redactLogArray"); + return [] as unknown as T; + } + + return array.map((item) => { + if (isObject(item)) { + return redactLogObject(item, callCount + 1); + } + if (Array.isArray(item)) { + return redactLogArray(item, callCount + 1); + } + return redactLogValue(item); + }) as T; +}; diff --git a/src/lib/use-fetch.ts b/src/lib/use-fetch.ts new file mode 100644 index 0000000..e86fca7 --- /dev/null +++ b/src/lib/use-fetch.ts @@ -0,0 +1,119 @@ +import { useAppBridge } from "@saleor/app-sdk/app-bridge"; +import ModernError from "modern-errors"; +import { useCallback, useEffect, useRef } from "react"; +import { type z } from "zod"; +import { type JSONValue } from "../types"; +import { tryJsonParse } from "./utils"; + +export const FetchError = ModernError.subclass("FetchError", { + props: { + body: "", + code: 500, + }, +}); +export const FetchParseError = ModernError.subclass("FetchParseError"); + +type FetchConfig = { + schema: z.ZodType; + onSuccess?: (data: z.infer>) => void | Promise; + onError?: ( + err: InstanceType | InstanceType, + ) => void | Promise; + onFinished?: () => void | Promise; +}; + +export const useFetchFn = () => { + const { appBridgeState } = useAppBridge(); + const { saleorApiUrl, token } = appBridgeState ?? {}; + + const customFetch = useCallback( + (info: RequestInfo | URL, init?: RequestInit | undefined) => { + return fetch(info, { + ...init, + body: JSON.stringify(init?.body), + headers: { + ...init?.headers, + "content-type": "application/json", + "saleor-api-url": saleorApiUrl ?? "", + "authorization-bearer": token ?? "", + }, + }); + }, + [saleorApiUrl, token], + ); + + return { + fetch: customFetch, + isReady: saleorApiUrl && token, + }; +}; + +async function handleResponse(res: Response, config: FetchConfig | undefined): Promise { + if (!res.ok) { + void config?.onError?.( + new FetchError(res.statusText, { + props: { + body: await res.text(), + code: res.status, + }, + }), + ); + void config?.onFinished?.(); + return; + } + + if (config) { + try { + const json = tryJsonParse(await res.text()); + const data = config.schema.parse(json); + void config?.onSuccess?.(data); + } catch (err) { + void config?.onError?.(FetchParseError.normalize(err)); + } + } + void config?.onFinished?.(); +} + +/** Fetch function, can be replaced to any fetching library, e.g. React Query, useSWR */ +export const useFetch = (endpoint: string, config?: FetchConfig) => { + const { fetch, isReady } = useFetchFn(); + const configRef = useRef(config); + + // We don't want changes in config to trigger re-fetch + useEffect(() => { + configRef.current = config; + }, [config]); + + useEffect(() => { + if (!isReady) { + return; + } + + void (async () => { + const res = await fetch(endpoint); + await handleResponse(res, configRef.current); + })(); + }, [endpoint, fetch, isReady]); +}; + +export const usePost = (endpoint: string, config?: FetchConfig) => { + const { fetch, isReady } = useFetchFn(); + + const submit = useCallback( + async (data: JSONValue, options?: RequestInit | undefined) => { + if (!isReady) { + return; + } + + const res = await fetch(endpoint, { + method: "POST", + body: JSON.stringify(data), + ...options, + }); + await handleResponse(res, config); + }, + [config, endpoint, fetch, isReady], + ); + + return submit; +}; diff --git a/src/lib/utils.test.ts b/src/lib/utils.test.ts new file mode 100644 index 0000000..2743231 --- /dev/null +++ b/src/lib/utils.test.ts @@ -0,0 +1,98 @@ +import { describe, expect, it, vi } from "vitest"; +import { tryIgnore, tryJsonParse, toStringOrEmpty, unpackPromise, unpackThrowable } from "./utils"; +import { BaseError } from "@/errors"; + +describe("api-route-utils", () => { + describe("tryIgnore", () => { + it("should run the function", () => { + const fn = vi.fn(); + expect(() => tryIgnore(fn)).not.toThrow(); + expect(fn).toHaveBeenCalledOnce(); + }); + + it("should ignore errors", () => { + expect(() => + tryIgnore(() => { + throw new Error("Error!"); + }), + ).not.toThrow(); + }); + }); + + describe("tryJsonParse", () => { + it("should ignore empty input", () => { + expect(tryJsonParse("")).toBeUndefined(); + expect(tryJsonParse(undefined)).toBeUndefined(); + }); + + it("should try parsing to JSON", () => { + expect(tryJsonParse('{"a": 123, "b": {"c": "aaa"}}')).toEqual({ a: 123, b: { c: "aaa" } }); + }); + + it("should return original input in case of error", () => { + expect(tryJsonParse('{"a": 123, "b" {"c": "aaa"}}')).toBe('{"a": 123, "b" {"c": "aaa"}}'); + }); + }); + + describe("toStringOrEmpty", () => { + it("should return value if it's a string", () => { + expect(toStringOrEmpty("")).toBe(""); + expect(toStringOrEmpty("some string")).toBe("some string"); + }); + + it.each([0, 1, 1n, {}, [], undefined, null, false, true])( + "should return empty string if value is not a string: %p", + (value) => { + expect(toStringOrEmpty(value)).toBe(""); + }, + ); + }); + + describe("unpackPromise", () => { + it("returns value if promise resolves", async () => { + const [error, value] = await unpackPromise(Promise.resolve("some value")); + expect(error).toBeNull(); + expect(value).toBe("some value"); + }); + + it("returns error if promise rejects", async () => { + const [error, value] = await unpackPromise(Promise.reject("some error")); + expect(error).toMatchInlineSnapshot("[UnknownError: some error]"); + expect(value).toBeNull(); + }); + + it("preserves error if it's BaseError or descendants", async () => { + const SomeError = BaseError.subclass("SomeError"); + const [error, value] = await unpackPromise(Promise.reject(new SomeError("some error"))); + expect(error).toMatchInlineSnapshot("[SomeError: some error]"); + expect(value).toBeNull(); + }); + }); + + describe("unpackThrowable", () => { + it("returns value if promise resolves", async () => { + const [error, value] = unpackThrowable(() => { + return "some value"; + }); + expect(error).toBeNull(); + expect(value).toBe("some value"); + }); + + it("returns error if promise rejects", async () => { + const [error, value] = unpackThrowable(() => { + throw new Error("some error"); + }); + expect(error).toMatchInlineSnapshot("[Error: some error]"); + expect(value).toBeNull(); + }); + + it("preserves error if it's BaseError or descendants", async () => { + const SomeError = BaseError.subclass("SomeError"); + const [error, value] = unpackThrowable(() => { + throw new SomeError("some error"); + }); + expect(error).toMatchInlineSnapshot("[SomeError: some error]"); + expect(value).toBeNull(); + }); + }); +}); diff --git a/src/lib/utils.ts b/src/lib/utils.ts new file mode 100644 index 0000000..8f20644 --- /dev/null +++ b/src/lib/utils.ts @@ -0,0 +1,62 @@ +import type { JSONValue } from "../types"; +import { BaseError, UnknownError } from "@/errors"; + +export const tryJsonParse = (text: string | undefined) => { + if (!text) { + return undefined; + } + try { + return JSON.parse(text) as JSONValue; + } catch (e) { + return text; + } +}; + +export const tryIgnore = (fn: () => void) => { + try { + fn(); + } catch { + // noop + } +}; + +export const toStringOrEmpty = (value: unknown) => { + if (typeof value === "string") return value; + return ""; +}; + +type PromiseToTupleResult = [Error, null] | [null, Awaited]; +export const unpackPromise = async >( + promise: T, +): Promise> => { + try { + const result = await promise; + return [null, result]; + } catch (maybeError) { + if (maybeError instanceof Error) { + return [maybeError, null]; + } + return [BaseError.normalize(maybeError, UnknownError), null]; + } +}; + +type ThrowableToTupleResult = [Error, null] | [null, T]; +export const unpackThrowable = (throwable: () => T): ThrowableToTupleResult => { + try { + const result = throwable(); + return [null, result]; + } catch (maybeError) { + if (maybeError instanceof Error) { + return [maybeError, null]; + } + return [BaseError.normalize(maybeError, UnknownError), null]; + } +}; + +export const isNotNullish = (val: T | null | undefined): val is T => + val !== undefined && val !== null; + +export const isObject = (val: unknown): val is Record => + typeof val === "object" && val !== null && !Array.isArray(val); + +export const __do = (fn: () => T): T => fn(); diff --git a/src/load-env.ts b/src/load-env.ts new file mode 100644 index 0000000..39bc85f --- /dev/null +++ b/src/load-env.ts @@ -0,0 +1,2 @@ +import nextEnv from "@next/env"; +nextEnv.loadEnvConfig("."); diff --git a/src/migrations/1-add-issuing-pricinpal/FetchWebhookId.graphql b/src/migrations/1-add-issuing-pricinpal/FetchWebhookId.graphql new file mode 100644 index 0000000..ece9f64 --- /dev/null +++ b/src/migrations/1-add-issuing-pricinpal/FetchWebhookId.graphql @@ -0,0 +1,10 @@ +query Migration_01_FetchWebhookIds { + app { + webhooks { + id + syncEvents { + eventType + } + } + } +} diff --git a/src/migrations/1-add-issuing-pricinpal/UpdateWebhook.graphql b/src/migrations/1-add-issuing-pricinpal/UpdateWebhook.graphql new file mode 100644 index 0000000..a82fac1 --- /dev/null +++ b/src/migrations/1-add-issuing-pricinpal/UpdateWebhook.graphql @@ -0,0 +1,12 @@ +mutation Migration_01_UpdateWebhook($webhookId: ID!, $newQuery: String!) { + webhookUpdate(id: $webhookId, input: { query: $newQuery }) { + webhook { + id + } + errors { + code + field + message + } + } +} diff --git a/src/migrations/1-add-issuing-pricinpal/index.ts b/src/migrations/1-add-issuing-pricinpal/index.ts new file mode 100644 index 0000000..f516046 --- /dev/null +++ b/src/migrations/1-add-issuing-pricinpal/index.ts @@ -0,0 +1,42 @@ +import { type AuthData } from "@saleor/app-sdk/APL"; +import { createServerClient } from "@/lib/create-graphq-client"; +import { + Migration_01_FetchWebhookIdsDocument, + Migration_01_UpdateWebhookDocument, + UntypedTransactionInitializeSessionDocument, + WebhookEventTypeSyncEnum, +} from "generated/graphql"; +import { gqlAstToString } from "@/lib/gql-ast-to-string"; +import { type PaymentAppConfigurator } from "@/modules/payment-app-configuration/payment-app-configuration"; + +export const requiredSaleorVersion = "3.13"; + +export async function migrate(authData: AuthData, _configurator: PaymentAppConfigurator) { + const client = createServerClient(authData.saleorApiUrl, authData.token); + const { data: fetchWebhookData } = await client + .query(Migration_01_FetchWebhookIdsDocument, {}) + .toPromise(); + + const webhook = fetchWebhookData?.app?.webhooks?.find((webhook) => + webhook.syncEvents.find( + (syncEvent) => syncEvent.eventType === WebhookEventTypeSyncEnum.TransactionInitializeSession, + ), + ); + + if (!webhook) { + throw new Error("No webhook to update"); + } + + const webhookId = webhook.id; + + const { data: updateWebhookData, error } = await client + .mutation(Migration_01_UpdateWebhookDocument, { + newQuery: gqlAstToString(UntypedTransactionInitializeSessionDocument), + webhookId, + }) + .toPromise(); + + if (error || !updateWebhookData?.webhookUpdate?.webhook?.id) { + throw new Error("Error while updating webhook"); + } +} diff --git a/src/modules/app-configuration/app-configuration.test.ts b/src/modules/app-configuration/app-configuration.test.ts new file mode 100644 index 0000000..87c2b1e --- /dev/null +++ b/src/modules/app-configuration/app-configuration.test.ts @@ -0,0 +1,159 @@ +import { type MetadataEntry } from "@saleor/app-sdk/settings-manager"; +import { describe, it, expect, vi, beforeEach } from "vitest"; +import { + PrivateMetadataAppConfigurator, + PublicMetadataAppConfiguration, + serializeSettingsToMetadata, +} from "./app-configuration"; +import { + createWebhookPrivateSettingsManager, + createWebhookPublicSettingsManager, +} from "./metadata-manager"; +import { obfuscateValue, filterConfigValues, OBFUSCATION_DOTS } from "./utils"; +import { testEnv } from "@/__tests__/test-env.mjs"; + +describe("obfuscateValue", () => { + it("obfuscates fully short values", () => { + expect(obfuscateValue("123")).toEqual(OBFUSCATION_DOTS); + expect(obfuscateValue("")).toEqual(OBFUSCATION_DOTS); + expect(obfuscateValue("1234")).toEqual(OBFUSCATION_DOTS); + }); + + it("leaves 4 charts of obfuscated value visible", () => { + expect(obfuscateValue("12345")).toBe(`${OBFUSCATION_DOTS}5`); + expect(obfuscateValue("123456")).toBe(`${OBFUSCATION_DOTS}56`); + expect(obfuscateValue("1234567")).toBe(`${OBFUSCATION_DOTS}567`); + expect(obfuscateValue("12345678")).toBe(`${OBFUSCATION_DOTS}5678`); + expect(obfuscateValue("123456789")).toBe(`${OBFUSCATION_DOTS}6789`); + }); +}); + +describe("filterConfigValues", () => { + it("filters out null and undefined values", () => { + expect(filterConfigValues({ a: 1, b: null, c: undefined })).toEqual({ a: 1 }); + }); +}); + +describe("PublicMetadataAppConfigurator", () => { + const onUpdate = vi.fn((update: MetadataEntry[]) => Promise.resolve(update)); + + beforeEach(() => { + onUpdate.mockClear(); + }); + + const KEY = "some-metadata"; + + const getMetadata = (value?: unknown) => { + return serializeSettingsToMetadata({ + key: KEY, + domain: testEnv.TEST_SALEOR_API_URL, + value: value ? JSON.stringify(value) : "", + }); + }; + const defaultMetadata = { a: "a" }; + + const managerEmpty = new PublicMetadataAppConfiguration( + createWebhookPublicSettingsManager([], onUpdate), + testEnv.TEST_SALEOR_API_URL, + KEY, + ); + + // make tests easier + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let manager: PublicMetadataAppConfiguration; + beforeEach(() => { + manager = new PublicMetadataAppConfiguration( + createWebhookPublicSettingsManager([getMetadata(defaultMetadata)], onUpdate), + testEnv.TEST_SALEOR_API_URL, + "some-metadata", + ); + }); + + it("gets metadata from metadataManager and parses it", async () => { + await expect(manager.getConfig()).resolves.toEqual(defaultMetadata); + await expect(managerEmpty.getConfig()).resolves.toBeUndefined(); + }); + + it("gets metadata in raw config form", async () => { + await expect(manager.getRawConfig()).resolves.toEqual([getMetadata(defaultMetadata)]); + await expect(managerEmpty.getRawConfig()).resolves.toEqual([getMetadata()]); + }); + + describe("setConfig", () => { + it("skips saving metadata if there is nothing new", async () => { + await manager.setConfig({}); + expect(onUpdate).not.toHaveBeenCalled(); + }); + + it("replaces metadata if param is passed", async () => { + await manager.setConfig({}, true); + expect(onUpdate).toHaveBeenCalledWith([ + serializeSettingsToMetadata({ + key: "some-metadata", + value: JSON.stringify({}), + domain: testEnv.TEST_SALEOR_API_URL, + }), + ]); + + await manager.setConfig({ b: "b" }, true); + expect(onUpdate).toHaveBeenCalledWith([getMetadata({ b: "b" })]); + }); + + it("saves only settings that have values", async () => { + await managerEmpty.setConfig({ a: null, b: "b", c: undefined }); + expect(onUpdate).toHaveBeenCalledWith([getMetadata({ b: "b" })]); + }); + + it("merges new settings with existing ones", async () => { + await manager.setConfig({ b: "b" }); + expect(onUpdate).toHaveBeenCalledWith([getMetadata({ a: "a", b: "b" })]); + }); + }); + + it("clears metadata", async () => { + await manager.clearConfig(); + expect(onUpdate).toHaveBeenCalledWith([ + serializeSettingsToMetadata({ + key: "some-metadata", + value: "", + domain: testEnv.TEST_SALEOR_API_URL, + }), + ]); + }); +}); + +describe("PrivateMetadataAppConfigurator", () => { + const metadataConfigurator = new PrivateMetadataAppConfigurator( + createWebhookPublicSettingsManager([ + serializeSettingsToMetadata({ + key: "some-metadata", + value: JSON.stringify({ a: "123456", b: "1234" }), + domain: testEnv.TEST_SALEOR_API_URL, + }), + ]), + testEnv.TEST_SALEOR_API_URL, + "some-metadata", + ); + + it("can obfuscate provided config object", () => { + expect(metadataConfigurator.obfuscateConfig({ a: "12345" })).toEqual({ + a: `${OBFUSCATION_DOTS}5`, + }); + }); + + it("returns empty config when none is set", async () => { + const emptyMetadataConfigurator = new PrivateMetadataAppConfigurator( + createWebhookPrivateSettingsManager([]), + testEnv.TEST_SALEOR_API_URL, + "some-metadata", + ); + await expect(emptyMetadataConfigurator.getConfigObfuscated()).resolves.toBeUndefined(); + }); + + it("can obfuscate its own config", async () => { + await expect(metadataConfigurator.getConfigObfuscated()).resolves.toEqual({ + a: `${OBFUSCATION_DOTS}56`, + b: OBFUSCATION_DOTS, + }); + }); +}); diff --git a/src/modules/app-configuration/app-configuration.ts b/src/modules/app-configuration/app-configuration.ts new file mode 100644 index 0000000..e3f1488 --- /dev/null +++ b/src/modules/app-configuration/app-configuration.ts @@ -0,0 +1,126 @@ +import { + type SettingsValue, + type MetadataEntry, + type SettingsManager, +} from "@saleor/app-sdk/settings-manager"; +import merge from "lodash-es/merge"; +import { toStringOrEmpty } from "../../lib/utils"; +import { filterConfigValues, obfuscateValue } from "./utils"; +import { logger as pinoLogger } from "@/lib/logger"; + +export interface GenericAppConfigurator> { + setConfig(config: TConfig): Promise; + getConfig(): Promise; +} + +// Taken from @saleor/app-sdk/src/settings-manager +export const serializeSettingsToMetadata = ({ + key, + value, + domain, +}: SettingsValue): MetadataEntry => { + // domain specific metadata use convention key__domain, e.g. `secret_key__example.com` + if (!domain) { + return { key, value }; + } + + return { + key: [key, domain].join("__"), + value, + }; +}; + +export abstract class MetadataConfigurator> + implements GenericAppConfigurator +{ + constructor( + protected metadataManager: SettingsManager, + protected saleorApiUrl: string, + protected metadataKey: string, + ) {} + + async getConfig(): Promise { + const data = await this.metadataManager.get(this.metadataKey, this.saleorApiUrl); + if (!data) { + return undefined; + } + + try { + return JSON.parse(data) as TConfig; + } catch (e) { + throw new Error("Invalid metadata value, cant be parsed"); + } + } + + async getRawConfig( + prepareValue: (val: string) => string = (data) => data, + ): Promise { + const data = await this.metadataManager.get(this.metadataKey, this.saleorApiUrl); + + return [ + // metadataManager strips out domain from key, we need to add it back + serializeSettingsToMetadata({ + key: this.metadataKey, + value: prepareValue(data ?? ""), + domain: this.saleorApiUrl, + }), + ]; + } + + async setConfig(newConfig: Partial, replace = false) { + const logger = pinoLogger.child({ + saleorApiUrl: this.saleorApiUrl, + metadataKey: this.metadataKey, + }); + const filteredNewConfig = filterConfigValues(newConfig); + if (Object.keys(filteredNewConfig).length === 0 && !replace) { + logger.debug("No config to safe in metadata"); + return; + } + + const existingConfig = replace ? {} : await this.getConfig(); + + return this.metadataManager.set({ + key: this.metadataKey, + value: JSON.stringify(merge(existingConfig, filteredNewConfig)), + domain: this.saleorApiUrl, + }); + } + + async clearConfig() { + return this.metadataManager.set({ + key: this.metadataKey, + value: "", + domain: this.saleorApiUrl, + }); + } +} + +export class PublicMetadataAppConfiguration< + TConfig extends Record, +> extends MetadataConfigurator {} + +export class PrivateMetadataAppConfigurator< + TConfig extends Record, +> extends MetadataConfigurator { + constructor(metadataManager: SettingsManager, saleorApiUrl: string, metadataKey: string) { + super(metadataManager, saleorApiUrl, metadataKey); + } + + obfuscateConfig(config: TConfig): TConfig { + const entries = Object.entries(config).map(([key, value]) => [ + key, + obfuscateValue(toStringOrEmpty(value)), + ]); + + return Object.fromEntries(entries) as TConfig; + } + + async getConfigObfuscated(): Promise { + const config = await this.getConfig(); + if (!config) { + return undefined; + } + return this.obfuscateConfig(config); + } +} diff --git a/src/modules/app-configuration/metadata-manager.ts b/src/modules/app-configuration/metadata-manager.ts new file mode 100644 index 0000000..8254c48 --- /dev/null +++ b/src/modules/app-configuration/metadata-manager.ts @@ -0,0 +1,142 @@ +import { + EncryptedMetadataManager, + type MetadataEntry, + MetadataManager, + type MutateMetadataCallback, +} from "@saleor/app-sdk/settings-manager"; +import { type Client } from "urql"; +import { + FetchAppDetailsDocument, + type FetchAppDetailsQuery, + UpdateAppMetadataDocument, + UpdatePublicMetadataDocument, +} from "../../../generated/graphql"; +import { env } from "@/lib/env.mjs"; + +export async function fetchAllMetadata(client: Client): Promise { + const { error, data } = await client + .query(FetchAppDetailsDocument, {}) + .toPromise(); + + if (error) { + return []; + } + + const combinedMetadata = [...(data?.app?.metadata || []), ...(data?.app?.privateMetadata || [])]; + + return combinedMetadata.map((md) => ({ key: md.key, value: md.value })); +} + +async function getAppId(client: Client) { + const { error: idQueryError, data: idQueryData } = await client + .query(FetchAppDetailsDocument, {}) + .toPromise(); + + if (idQueryError) { + throw new Error( + "Could not fetch the app id. Please check if auth data for the client are valid.", + ); + } + + const appId = idQueryData?.app?.id; + + if (!appId) { + throw new Error("Could not fetch the app ID"); + } + + return appId; +} + +export async function mutatePrivateMetadata(client: Client, metadata: MetadataEntry[]) { + // to update the metadata, ID is required + const appId = await getAppId(client); + + const { error: mutationError, data: mutationData } = await client + .mutation(UpdateAppMetadataDocument, { + id: appId, + input: metadata, + }) + .toPromise(); + + if (mutationError) { + throw new Error(`Mutation error: ${mutationError.message}`); + } + + return ( + mutationData?.updatePrivateMetadata?.item?.privateMetadata.map((md) => ({ + key: md.key, + value: md.value, + })) || [] + ); +} + +export async function mutatePublicMetadata(client: Client, metadata: MetadataEntry[]) { + // to update the metadata, ID is required + const appId = await getAppId(client); + + const { error: mutationError, data: mutationData } = await client + .mutation(UpdatePublicMetadataDocument, { + id: appId, + input: metadata, + }) + .toPromise(); + + if (mutationError) { + throw new Error(`Mutation error: ${mutationError.message}`); + } + + return ( + mutationData?.updateMetadata?.item?.metadata.map((md) => ({ + key: md.key, + value: md.value, + })) || [] + ); +} + +// branded types are used to prevent using wrong manager for wrong metadata +type Brand = K & { __brand: T }; +export type BrandedEncryptedMetadataManager = Brand< + EncryptedMetadataManager, + "EncryptedMetadataManager" +>; +export type BrandedMetadataManager = Brand; + +export const createPrivateSettingsManager = (client: Client) => { + // EncryptedMetadataManager gives you interface to manipulate metadata and cache values in memory. + // We recommend it for production, because all values are encrypted. + // If your use case require plain text values, you can use MetadataManager. + return new EncryptedMetadataManager({ + // Secret key should be randomly created for production and set as environment variable + encryptionKey: env.SECRET_KEY, + fetchMetadata: () => fetchAllMetadata(client), + mutateMetadata: (metadata) => mutatePrivateMetadata(client, metadata), + }) as BrandedEncryptedMetadataManager; +}; + +export const createPublicSettingsManager = (client: Client) => { + return new MetadataManager({ + fetchMetadata: () => fetchAllMetadata(client), + mutateMetadata: (metadata) => mutatePublicMetadata(client, metadata), + }) as BrandedMetadataManager; +}; + +export const createWebhookPrivateSettingsManager = ( + data: MetadataEntry[], + onUpdate?: MutateMetadataCallback, +) => { + return new EncryptedMetadataManager({ + encryptionKey: env.SECRET_KEY, + fetchMetadata: () => Promise.resolve(data), + mutateMetadata: onUpdate ?? (() => Promise.resolve([])), + }) as BrandedEncryptedMetadataManager; +}; + +export const createWebhookPublicSettingsManager = ( + data: MetadataEntry[], + onUpdate?: MutateMetadataCallback, +) => { + return new MetadataManager({ + fetchMetadata: () => Promise.resolve(data), + mutateMetadata: onUpdate ?? (() => Promise.resolve([])), + }) as BrandedMetadataManager; +}; diff --git a/src/modules/app-configuration/utils.ts b/src/modules/app-configuration/utils.ts new file mode 100644 index 0000000..22293d7 --- /dev/null +++ b/src/modules/app-configuration/utils.ts @@ -0,0 +1,38 @@ +import { isNotNullish, toStringOrEmpty } from "../../lib/utils"; + +export const OBFUSCATION_DOTS = "••••"; + +export const obfuscateValue = (value: string) => { + const unbofuscatedLength = Math.min(4, value.length - 4); + + if (unbofuscatedLength <= 0) { + return OBFUSCATION_DOTS; + } + + const visibleValue = value.slice(-unbofuscatedLength); + return `${OBFUSCATION_DOTS}${visibleValue}`; +}; + +export const deobfuscateValues = (values: Record) => { + const entries = Object.entries(values).map( + ([key, value]) => + [key, toStringOrEmpty(value).includes(OBFUSCATION_DOTS) ? null : value] as [string, unknown], + ); + return Object.fromEntries(entries); +}; + +export const filterConfigValues = >(values: T) => { + const entries = Object.entries(values).filter( + ([_, value]) => value !== null && value !== undefined, + ); + return Object.fromEntries(entries); +}; + +export const obfuscateConfig = (config: T): T => { + const entries = Object.entries(config).map(([key, value]) => [ + key, + isNotNullish(value) ? obfuscateValue(toStringOrEmpty(value)) : value, + ]); + + return Object.fromEntries(entries) as T; +}; diff --git a/src/modules/jwt/check-token-expiration.test.ts b/src/modules/jwt/check-token-expiration.test.ts new file mode 100644 index 0000000..1c15ade --- /dev/null +++ b/src/modules/jwt/check-token-expiration.test.ts @@ -0,0 +1,43 @@ +import { describe, it, expect, vi } from "vitest"; +import { SignJWT } from "jose"; +import { checkTokenExpiration } from "./check-token-expiration"; + +describe("checkTokenExpiration", () => { + const secretKey = new TextEncoder().encode("test"); + + it("returns false if token is undefined", () => { + expect(checkTokenExpiration(undefined)).toBe(false); + }); + + it("returns false if token doesn't have expire date", async () => { + // create JWT token without exp claim + const jwt = await new SignJWT({ id: "12345" }) + .setProtectedHeader({ alg: "HS256" }) + .sign(new Uint8Array(secretKey)); + expect(checkTokenExpiration(jwt)).toBe(false); + }); + + it("returns false if token is not expired", async () => { + const jwt = await new SignJWT({ id: "12345" }) + .setProtectedHeader({ alg: "HS256" }) + .setExpirationTime("5s") + .sign(secretKey); + expect(checkTokenExpiration(jwt)).toBe(false); + }); + + it("returns true if token is expired", async () => { + vi.useFakeTimers(); + vi.setSystemTime(new Date(2000, 1, 1, 13, 1, 1)); + + const jwt = await new SignJWT({ id: "12345" }) + .setProtectedHeader({ alg: "HS256" }) + .setExpirationTime("1s") + .sign(secretKey); + + vi.setSystemTime(new Date(2000, 1, 1, 13, 1, 11)); // 10 seconds later + + expect(checkTokenExpiration(jwt)).toBe(true); + + vi.useRealTimers(); + }); +}); diff --git a/src/modules/jwt/check-token-expiration.ts b/src/modules/jwt/check-token-expiration.ts new file mode 100644 index 0000000..ab8eb4c --- /dev/null +++ b/src/modules/jwt/check-token-expiration.ts @@ -0,0 +1,22 @@ +import { decodeJwt } from "jose"; +import { logger } from "@/lib/logger"; + +/** Checks if JWT token expired. + * Returns false if token is still valid (note: there could be other issues) + * or true if it expired */ +export const checkTokenExpiration = (token: string | undefined): boolean => { + if (!token) { + return false; + } + + const claims = decodeJwt(token); + if (claims.exp) { + const now = new Date().getTime(); + const expireDate = claims.exp * 1000; + + logger.trace({ claimsExp: claims.exp, now, expireDate }, "JWT token expiration time"); + return now >= expireDate; + } + + return false; +}; diff --git a/src/modules/jwt/check-token-offline.ts b/src/modules/jwt/check-token-offline.ts new file mode 100644 index 0000000..eb501f4 --- /dev/null +++ b/src/modules/jwt/check-token-offline.ts @@ -0,0 +1,23 @@ +import { type Permission } from "@saleor/app-sdk/types"; +import { decodeJwt } from "jose"; + +const isPermissionsArray = (permissions: unknown): permissions is Permission[] => { + return Array.isArray(permissions); +}; + +export const checkTokenPermissions = ( + token: string | undefined, + permissions: Permission[], +): boolean => { + if (!token) { + return false; + } + + const claims = decodeJwt(token); + if (isPermissionsArray(claims.user_permissions)) { + const userPermissions = new Set(claims.user_permissions); + return permissions.every((requiredPermission) => userPermissions.has(requiredPermission)); + } + + return false; +}; diff --git a/src/modules/jwt/consts.ts b/src/modules/jwt/consts.ts new file mode 100644 index 0000000..9e663c7 --- /dev/null +++ b/src/modules/jwt/consts.ts @@ -0,0 +1,3 @@ +import { type Permission } from "@saleor/app-sdk/types"; + +export const REQUIRED_SALEOR_PERMISSIONS: Permission[] = ["MANAGE_APPS", "MANAGE_SETTINGS"]; diff --git a/src/modules/payment-app-configuration/__tests__/mocks.ts b/src/modules/payment-app-configuration/__tests__/mocks.ts new file mode 100644 index 0000000..962aaa6 --- /dev/null +++ b/src/modules/payment-app-configuration/__tests__/mocks.ts @@ -0,0 +1,10 @@ +import { type PaymentAppConfigEntryFullyConfigured } from "../config-entry"; + +export const configEntryAll: PaymentAppConfigEntryFullyConfigured = { + configurationName: "test", + secretKey: "sk_secret-key", + publishableKey: "pk_that-secret-key", + configurationId: "mock-id", + webhookSecret: "whsec_test", + webhookId: "webhook-id", +}; diff --git a/src/modules/payment-app-configuration/__tests__/payment-app-configuration-factory.ts b/src/modules/payment-app-configuration/__tests__/payment-app-configuration-factory.ts new file mode 100644 index 0000000..f520702 --- /dev/null +++ b/src/modules/payment-app-configuration/__tests__/payment-app-configuration-factory.ts @@ -0,0 +1,38 @@ +import { encrypt, type MetadataEntry } from "@saleor/app-sdk/settings-manager"; +import { + type BrandedEncryptedMetadataManager, + type BrandedMetadataManager, + createWebhookPrivateSettingsManager, +} from "../../app-configuration/metadata-manager"; +import { serializeSettingsToMetadata } from "../../app-configuration/app-configuration"; +import { PaymentAppConfigurator, privateMetadataKey } from "../payment-app-configuration"; +import { type PaymentAppConfig } from "../app-config"; +import { env } from "@/lib/env.mjs"; + +export type MetadataManagerOverride = { + private?: (metadata: MetadataEntry[]) => BrandedEncryptedMetadataManager; + public?: (metadata: MetadataEntry[]) => BrandedMetadataManager; +}; + +export const getFakePaymentAppConfigurator = ( + config: PaymentAppConfig, + saleorApiUrl: string, + metadataManager?: MetadataManagerOverride, +) => { + const privateConfigEntries: MetadataEntry[] = [ + serializeSettingsToMetadata({ + key: privateMetadataKey, + value: encrypt(JSON.stringify(config), env.SECRET_KEY), + domain: saleorApiUrl, + }), + ]; + + const getPrivateSettingsManager = () => { + if (metadataManager?.private) { + return metadataManager.private(privateConfigEntries); + } + return createWebhookPrivateSettingsManager(privateConfigEntries); + }; + + return new PaymentAppConfigurator(getPrivateSettingsManager(), saleorApiUrl); +}; diff --git a/src/modules/payment-app-configuration/__tests__/payment-app-configuration.test.ts b/src/modules/payment-app-configuration/__tests__/payment-app-configuration.test.ts new file mode 100644 index 0000000..c2eab7c --- /dev/null +++ b/src/modules/payment-app-configuration/__tests__/payment-app-configuration.test.ts @@ -0,0 +1,225 @@ +import { vi, describe, it, expect } from "vitest"; +import { PaymentAppConfigurator } from "../payment-app-configuration"; +import { + type ChannelMapping, + paymentAppConfigSchema, + type PaymentAppConfig, + type PaymentAppConfigUserVisible, +} from "../app-config"; +import { type PaymentAppConfigEntry } from "../config-entry"; +import { configEntryAll } from "./mocks"; +import { testEnv } from "@/__tests__/test-env.mjs"; +import { type BrandedEncryptedMetadataManager } from "@/modules/app-configuration/metadata-manager"; +import { type PrivateMetadataAppConfigurator } from "@/modules/app-configuration/app-configuration"; +import { OBFUSCATION_DOTS } from "@/modules/app-configuration/utils"; + +describe("PaymentAppConfigurator", () => { + const metadataManagerMock = {} as BrandedEncryptedMetadataManager; + const saleorApiUrlMock = testEnv.TEST_SALEOR_API_URL; + const configuratorMock = { + setConfig: vi.fn(async () => {}), + getConfig: vi.fn(async () => undefined), + } as unknown as PrivateMetadataAppConfigurator; + const appConfigurator = new PaymentAppConfigurator(metadataManagerMock, saleorApiUrlMock); + appConfigurator["configurator"] = configuratorMock; + + describe("getConfig", () => { + const defaultConfig = { configurations: [], channelToConfigurationId: {}, lastMigration: null }; + it("should call the configurator and return value that matches schema", async () => { + const getConfig = vi.spyOn(configuratorMock, "getConfig").mockResolvedValue(defaultConfig); + + const config = await appConfigurator.getConfig(); + expect(getConfig).toHaveBeenCalled(); + expect(config).toEqual(defaultConfig); + }); + + it("if configurator returns undefined it should provide a default config", async () => { + const getConfig = vi.spyOn(configuratorMock, "getConfig").mockResolvedValue(undefined); + + const config = await appConfigurator.getConfig(); + expect(getConfig).toHaveBeenCalled(); + expect(config).toEqual(defaultConfig); + }); + }); + + describe("getConfigObfuscated", () => { + it("should obfuscate configurations and keep channelToConfigurationId as is", async () => { + const mockConfig = { + configurations: [configEntryAll], + channelToConfigurationId: { "channel-1": "mock-id" }, + } satisfies PaymentAppConfig; + const getConfig = vi.spyOn(appConfigurator, "getConfig").mockResolvedValue(mockConfig); + + const obfuscatedConfig = await appConfigurator.getConfigObfuscated(); + + expect(getConfig).toHaveBeenCalled(); + expect(obfuscatedConfig).toEqual({ + configurations: [ + { + configurationId: "mock-id", + secretKey: `${OBFUSCATION_DOTS}-key`, // from super-secret-key + publishableKey: "pk_that-secret-key", + configurationName: "test", + webhookId: "webhook-id", + }, + ], + channelToConfigurationId: mockConfig.channelToConfigurationId, + } satisfies PaymentAppConfigUserVisible); + }); + }); + + describe("setConfigEntry", () => { + it("should update app config with new config entry added to list of config entries", async () => { + const newConfigEntry: PaymentAppConfigEntry = { + ...configEntryAll, + configurationId: "new-mock-id", + }; + const existingConfig: PaymentAppConfig = { + configurations: [configEntryAll], + channelToConfigurationId: {}, + }; + + const getConfig = vi.spyOn(appConfigurator, "getConfig").mockResolvedValue(existingConfig); + const setConfig = vi.spyOn(appConfigurator, "setConfig"); + + await appConfigurator.setConfigEntry(newConfigEntry); + + expect(getConfig).toHaveBeenCalled(); + expect(setConfig).toHaveBeenCalledWith({ + configurations: [configEntryAll, newConfigEntry], + }); + }); + + it("should update app config with update config entry changed in list of config entries", async () => { + const updateConfigEntry: PaymentAppConfigEntry = { + ...configEntryAll, + configurationId: "new-mock-id", + }; + const existingConfig: PaymentAppConfig = { + configurations: [configEntryAll, { ...configEntryAll, configurationId: "new-mock-id" }], + channelToConfigurationId: {}, + }; + + const getConfig = vi.spyOn(appConfigurator, "getConfig").mockResolvedValue(existingConfig); + const setConfig = vi.spyOn(appConfigurator, "setConfig"); + + await appConfigurator.setConfigEntry(updateConfigEntry); + + expect(getConfig).toHaveBeenCalled(); + expect(setConfig).toHaveBeenCalledWith({ + configurations: [configEntryAll, updateConfigEntry], + }); + }); + }); + + describe("deleteConfigEntry", () => { + it("should call setConfig without the deleted configurationId", async () => { + const existingConfig: PaymentAppConfig = { + configurations: [configEntryAll], + channelToConfigurationId: {}, + }; + + const getConfig = vi.spyOn(appConfigurator, "getConfig").mockResolvedValue(existingConfig); + const setConfig = vi.spyOn(appConfigurator, "setConfig"); + + await appConfigurator.deleteConfigEntry(configEntryAll.configurationId); + + expect(getConfig).toHaveBeenCalled(); + expect(setConfig).toHaveBeenCalledWith( + { channelToConfigurationId: {}, configurations: [] }, + true, + ); + }); + }); + + describe("setMapping", () => { + it("should call setConfig with new mapping", async () => { + const newMapping: ChannelMapping = { "channel-2": "new-mock-id" }; + const existingConfig: PaymentAppConfig = { configurations: [], channelToConfigurationId: {} }; + + const getConfig = vi.spyOn(appConfigurator, "getConfig").mockResolvedValue(existingConfig); + const setConfig = vi.spyOn(appConfigurator, "setConfig"); + + await appConfigurator.setMapping(newMapping); + + expect(getConfig).toHaveBeenCalled(); + expect(setConfig).toHaveBeenCalledWith({ + channelToConfigurationId: newMapping, + }); + }); + + it("should call setConfig with merged mappings", async () => { + const existingMapping: ChannelMapping = { "channel-1": "old-mock-id" }; + const newMapping: ChannelMapping = { "channel-2": "new-mock-id" }; + const existingConfig: PaymentAppConfig = { + configurations: [], + channelToConfigurationId: { ...existingMapping }, + }; + + const getConfig = vi.spyOn(appConfigurator, "getConfig").mockResolvedValue(existingConfig); + const setConfig = vi.spyOn(appConfigurator, "setConfig"); + + await appConfigurator.setMapping(newMapping); + + expect(getConfig).toHaveBeenCalled(); + expect(setConfig).toHaveBeenCalledWith({ + channelToConfigurationId: { ...existingMapping, ...newMapping }, + }); + }); + }); + + describe("deleteMapping", () => { + it("should call setConfig without the deleted channelId", async () => { + const existingMapping: ChannelMapping = { "channel-1": "existing-mock-id" }; + const existingConfig: PaymentAppConfig = { + configurations: [], + channelToConfigurationId: existingMapping, + }; + + const getConfig = vi.spyOn(appConfigurator, "getConfig").mockResolvedValue(existingConfig); + const setConfig = vi.spyOn(appConfigurator, "setConfig"); + + await appConfigurator.deleteMapping("channel-1"); + + expect(getConfig).toHaveBeenCalled(); + expect(setConfig).toHaveBeenCalledWith({ channelToConfigurationId: {} }); + }); + }); + + describe("setConfig", () => { + it("should call setConfig on configurator", async () => { + const newConfig: Partial = { + configurations: [], + channelToConfigurationId: {}, + }; + const setConfig = vi.spyOn(configuratorMock, "setConfig"); + + await appConfigurator.setConfig(newConfig); + + expect(setConfig).toHaveBeenCalledWith(newConfig, false); + }); + + it("should call setConfig with replace = true", async () => { + const newConfig: Partial = { + configurations: [], + channelToConfigurationId: {}, + }; + const setConfig = vi.spyOn(configuratorMock, "setConfig"); + + await appConfigurator.setConfig(newConfig, true); + + expect(setConfig).toHaveBeenCalledWith(newConfig, true); + }); + }); + + describe("clearConfig", () => { + it("should call setConfig on configurator with replace parameter set to true", async () => { + const defaultConfig = paymentAppConfigSchema.parse(undefined); + const setConfig = vi.spyOn(configuratorMock, "setConfig"); + + await appConfigurator.clearConfig(); + + expect(setConfig).toHaveBeenCalledWith(defaultConfig, true); + }); + }); +}); diff --git a/src/modules/payment-app-configuration/__tests__/utils.ts b/src/modules/payment-app-configuration/__tests__/utils.ts new file mode 100644 index 0000000..496735a --- /dev/null +++ b/src/modules/payment-app-configuration/__tests__/utils.ts @@ -0,0 +1,35 @@ +import { type PaymentAppConfig } from "../app-config"; +import { + getFakePaymentAppConfigurator, + type MetadataManagerOverride, +} from "./payment-app-configuration-factory"; +import { testEnv } from "@/__tests__/test-env.mjs"; + +export const filledFakeMatadataConfig = { + configurations: [ + { + secretKey: testEnv.TEST_PAYMENT_APP_SECRET_KEY, + publishableKey: testEnv.TEST_PAYMENT_APP_PUBLISHABLE_KEY, + configurationId: "mock-id", + configurationName: "test", + webhookId: testEnv.TEST_PAYMENT_APP_WEBHOOK_ID, + webhookSecret: testEnv.TEST_PAYMENT_APP_WEBHOOK_SECRET, + }, + ], + channelToConfigurationId: { + "1": "mock-id", + }, +} satisfies PaymentAppConfig; + +export const getFilledFakeMetadataConfigurator = (override?: MetadataManagerOverride) => { + return getFakePaymentAppConfigurator( + filledFakeMatadataConfig, + testEnv.TEST_SALEOR_API_URL, + override, + ); +}; + +export const getFilledMetadata = () => { + const configurator = getFilledFakeMetadataConfigurator(); + return configurator.getRawConfig(); +}; diff --git a/src/modules/payment-app-configuration/app-config.ts b/src/modules/payment-app-configuration/app-config.ts new file mode 100644 index 0000000..d962733 --- /dev/null +++ b/src/modules/payment-app-configuration/app-config.ts @@ -0,0 +1,48 @@ +import { z } from "zod"; +import { + paymentAppConfigEntrySchema, + paymentAppUserVisibleConfigEntrySchema, +} from "./config-entry"; + +export const paymentAppConfigEntriesSchema = paymentAppConfigEntrySchema.array(); +export const paymentAppUserVisibleConfigEntriesSchema = + paymentAppUserVisibleConfigEntrySchema.array(); + +// Record +export const channelMappingSchema = z + .record(z.string().min(1), z.string().min(1).nullable()) + .default({}); + +export type ChannelMapping = z.infer; + +export const paymentAppConfigSchema = z + .object({ + configurations: paymentAppConfigEntriesSchema, + channelToConfigurationId: channelMappingSchema, + lastMigration: z.number().nullish(), + }) + .default({ + configurations: [], + channelToConfigurationId: {}, + lastMigration: null, + }); + +export const paymentAppUserVisibleConfigSchema = z + .object({ + configurations: paymentAppUserVisibleConfigEntriesSchema, + channelToConfigurationId: channelMappingSchema, + }) + .default({ + configurations: [], + channelToConfigurationId: {}, + }); + +export const defaultPaymentAppConfig: PaymentAppConfig = { + configurations: [], + channelToConfigurationId: {}, +}; + +export type PaymentAppConfigEntries = z.infer; +export type PaymentAppUserVisibleEntries = z.infer; +export type PaymentAppConfig = z.infer; +export type PaymentAppConfigUserVisible = z.infer; diff --git a/src/modules/payment-app-configuration/config-entry.ts b/src/modules/payment-app-configuration/config-entry.ts new file mode 100644 index 0000000..ff0a898 --- /dev/null +++ b/src/modules/payment-app-configuration/config-entry.ts @@ -0,0 +1,99 @@ +import { z } from "zod"; +import { deobfuscateValues } from "../app-configuration/utils"; + +export const DANGEROUS_paymentAppConfigHiddenSchema = z.object({ + webhookSecret: z.string().min(1), +}); + +export const paymentAppConfigEntryInternalSchema = z.object({ + configurationId: z.string().min(1), + webhookId: z.string().min(1), +}); + +export const paymentAppConfigEntryEncryptedSchema = z.object({ + secretKey: z + .string({ required_error: "Secret Key is required" }) + .min(1, { message: "Secret Key is required" }), +}); + +export const paymentAppConfigEntryPublicSchema = z.object({ + publishableKey: z + .string({ required_error: "Publishable Key is required" }) + .min(1, { message: "Publishable Key is required" }), + configurationName: z + .string({ required_error: "Configuration name is required" }) + .min(1, { message: "Configuration name is required" }), +}); + +export const paymentAppConfigEntrySchema = DANGEROUS_paymentAppConfigHiddenSchema.merge( + paymentAppConfigEntryEncryptedSchema, +) + .merge(paymentAppConfigEntryPublicSchema) + .merge(paymentAppConfigEntryInternalSchema); + +// Entire config available to user +export const paymentAppUserVisibleConfigEntrySchema = paymentAppConfigEntryPublicSchema + .merge(paymentAppConfigEntryEncryptedSchema) + .merge(paymentAppConfigEntryInternalSchema) + .strict(); + +// Fully configured app - all fields are required +// Zod doesn't have a utility for marking fields as non-nullable, we need to use unwrap +export const paymentAppFullyConfiguredEntrySchema = z + .object({ + configurationName: paymentAppConfigEntryPublicSchema.shape.configurationName, + configurationId: paymentAppConfigEntryInternalSchema.shape.configurationId, + secretKey: paymentAppConfigEntryEncryptedSchema.shape.secretKey, + publishableKey: paymentAppConfigEntryPublicSchema.shape.publishableKey, + webhookSecret: DANGEROUS_paymentAppConfigHiddenSchema.shape.webhookSecret, + webhookId: paymentAppConfigEntryInternalSchema.shape.webhookId, + }) + .required(); + +// Schema used as input validation for saving config entires +export const paymentAppFormConfigEntrySchema = z + .object({ + configurationName: paymentAppConfigEntryPublicSchema.shape.configurationName, + secretKey: paymentAppConfigEntryEncryptedSchema.shape.secretKey.startsWith( + "sk_", + "This isn't a Stripe secret key, it must start with sk_", + ), + publishableKey: paymentAppConfigEntryPublicSchema.shape.publishableKey.startsWith( + "pk_", + "This isn't a Stripe publishable key, it must start with pk_", + ), + }) + .strict() + .default({ + secretKey: "", + publishableKey: "", + configurationName: "", + }); + +/** Schema used in front-end forms + * Replaces obfuscated values with null */ +export const paymentAppEncryptedFormSchema = paymentAppConfigEntryEncryptedSchema.transform( + (values) => deobfuscateValues(values), +); + +// Schema used for front-end forms +export const paymentAppCombinedFormSchema = z.intersection( + paymentAppEncryptedFormSchema, + paymentAppConfigEntryPublicSchema, +); + +export type PaymentAppInternalConfig = z.infer; +export type PaymentAppEncryptedConfig = z.infer; +export type PaymentAppPublicConfig = z.infer; + +export type PaymentAppConfigEntry = z.infer; +export type PaymentAppConfigEntryFullyConfigured = z.infer< + typeof paymentAppFullyConfiguredEntrySchema +>; +export type PaymentAppUserVisibleConfigEntry = z.infer< + typeof paymentAppUserVisibleConfigEntrySchema +>; +export type PaymentAppFormConfigEntry = z.infer; +export type PaymentAppConfigEntryUpdate = Partial & { + configurationId: PaymentAppConfigEntry["configurationId"]; +}; diff --git a/src/modules/payment-app-configuration/config-manager.test.ts b/src/modules/payment-app-configuration/config-manager.test.ts new file mode 100644 index 0000000..356e29e --- /dev/null +++ b/src/modules/payment-app-configuration/config-manager.test.ts @@ -0,0 +1,167 @@ +/* eslint-disable @typescript-eslint/unbound-method */ +import { describe, it, expect, vi } from "vitest"; +import { OBFUSCATION_DOTS } from "../app-configuration/utils"; +import { + addConfigEntry, + updateConfigEntry, + EntryNotFoundError, + deleteConfigEntry, + getConfigEntryObfuscated, + getAllConfigEntriesObfuscated, +} from "./config-manager"; +import { configEntryAll } from "./__tests__/mocks"; +import { obfuscateConfigEntry } from "./utils"; +import { type ConfigEntryUpdate } from "./input-schemas"; +import { type PaymentAppConfigurator } from "./payment-app-configuration"; +import { + type PaymentAppConfigEntryFullyConfigured, + type PaymentAppFormConfigEntry, +} from "./config-entry"; +import { deleteStripeWebhook } from "./webhook-manager"; +import { testEnv } from "@/__tests__/test-env.mjs"; + +vi.mock("@/modules/stripe/stripe-api", async () => { + return { + validateStripeKeys: () => {}, + }; +}); + +vi.mock("@/modules/payment-app-configuration/webhook-manager", () => { + return { + createStripeWebhook: async () => ({ + webhookSecret: "ws_secret", + webhookId: "12345", + }), + deleteStripeWebhook: vi.fn(async () => {}), + }; +}); + +const mockConfigurator = { + getConfig: vi.fn(async () => ({ configurations: [configEntryAll] })), + getConfigObfuscated: vi.fn(async () => ({ + configurations: [obfuscateConfigEntry(configEntryAll)], + })), + setConfigEntry: vi.fn(async () => {}), + saleorApiUrl: testEnv.TEST_SALEOR_API_URL, + deleteConfigEntry: vi.fn(async () => {}), +} as unknown as PaymentAppConfigurator; + +describe("getAllConfigEntriesObfuscated", () => { + it("calls configurator and returns data", async () => { + const entries = await getAllConfigEntriesObfuscated(mockConfigurator); + + expect(entries).toEqual([obfuscateConfigEntry(configEntryAll)]); + expect(mockConfigurator.getConfigObfuscated).toHaveBeenCalledTimes(1); + }); +}); + +describe("findConfigEntry", () => { + it("calls getAllConfigEntriesObfuscated and finds entry with provided ID", async () => { + const entry = await getConfigEntryObfuscated(configEntryAll.configurationId, mockConfigurator); + + expect(entry).toEqual(obfuscateConfigEntry(configEntryAll)); + expect(mockConfigurator.getConfigObfuscated).toHaveBeenCalledTimes(1); + }); +}); + +describe("addConfigEntry", () => { + it("generates random id for new config entry, creates webhook in Stripe, saves config entry in configurator, returns new config entry which has obfuscated fields", async () => { + const input: PaymentAppFormConfigEntry = { + configurationName: "new-config", + secretKey: "new-key", + publishableKey: "client-key", + }; + const result = await addConfigEntry(input, mockConfigurator, "http://stripe.saleor.io"); + + expect(result).toStrictEqual({ + configurationId: expect.any(String), + configurationName: input.configurationName, + secretKey: `${OBFUSCATION_DOTS}key`, + publishableKey: "client-key", + webhookId: "12345", + }); + expect(mockConfigurator.setConfigEntry).toHaveBeenCalledTimes(1); + expect(mockConfigurator.setConfigEntry).toHaveBeenCalledWith({ + configurationId: expect.any(String), + configurationName: input.configurationName, + secretKey: "new-key", + publishableKey: "client-key", + webhookId: "12345", + webhookSecret: "ws_secret", + }); + }); +}); + +describe("updateConfigEntry", () => { + it("checks if entry exists, updates entry in configurator", async () => { + const input = { + configurationId: configEntryAll.configurationId, + entry: { + configurationName: "new-name", + secretKey: "updated-key", + publishableKey: configEntryAll.publishableKey, + }, + } satisfies ConfigEntryUpdate; + + const result = await updateConfigEntry(input, mockConfigurator); + + expect(result).toEqual( + obfuscateConfigEntry({ + ...configEntryAll, + configurationName: "new-name", + }), + ); + expect(mockConfigurator.setConfigEntry).toHaveBeenCalledWith({ + ...input.entry, + configurationId: input.configurationId, + }); + }); + + it("throws an error if config entry is not found", async () => { + const input = { + configurationId: "non-existing-id", + entry: { + configurationName: configEntryAll.configurationName, + secretKey: "updated-key", + publishableKey: configEntryAll.publishableKey, + }, + } satisfies ConfigEntryUpdate; + + await expect(updateConfigEntry(input, mockConfigurator)).rejects.toThrow(EntryNotFoundError); + }); +}); + +describe("deleteConfigEntry", () => { + it("checks if entry exists, deletes entry in configurator, deletes Stripe webhook", async () => { + const result = await deleteConfigEntry(configEntryAll.configurationId, mockConfigurator); + + expect(result).toBeUndefined(); + expect(mockConfigurator.getConfig).toHaveBeenCalledOnce(); + expect(mockConfigurator.deleteConfigEntry).toHaveBeenCalledWith(configEntryAll.configurationId); + expect(deleteStripeWebhook).toHaveBeenCalledOnce(); + }); + + it("checks if entry exists, skips deleting Stripe webhook if it exists in other config", async () => { + const additionalEntry = { + ...configEntryAll, + configurationId: "other-config-id", + } satisfies PaymentAppConfigEntryFullyConfigured; + + const testMockConfigurator = { + ...mockConfigurator, + getConfig: vi.fn(async () => ({ configurations: [configEntryAll, additionalEntry] })), + } as unknown as PaymentAppConfigurator; + + const result = await deleteConfigEntry(configEntryAll.configurationId, testMockConfigurator); + expect(result).toBeUndefined(); + expect(testMockConfigurator.getConfig).toHaveBeenCalledOnce(); + expect(mockConfigurator.deleteConfigEntry).toHaveBeenCalledWith(configEntryAll.configurationId); + expect(deleteStripeWebhook).not.toHaveBeenCalled(); + }); + + it("throws an error if config entry is not found", async () => { + await expect(deleteConfigEntry("non-existing-id", mockConfigurator)).rejects.toThrow( + EntryNotFoundError, + ); + }); +}); diff --git a/src/modules/payment-app-configuration/config-manager.ts b/src/modules/payment-app-configuration/config-manager.ts new file mode 100644 index 0000000..8802647 --- /dev/null +++ b/src/modules/payment-app-configuration/config-manager.ts @@ -0,0 +1,188 @@ +import { uuidv7 } from "uuidv7"; +import { validateStripeKeys } from "../stripe/stripe-api"; +import { type ConfigEntryUpdate } from "./input-schemas"; +import { obfuscateConfigEntry } from "./utils"; +import { type PaymentAppConfigurator } from "./payment-app-configuration"; +import { + type PaymentAppConfigEntryFullyConfigured, + type PaymentAppFormConfigEntry, +} from "./config-entry"; +import { createStripeWebhook, deleteStripeWebhook } from "./webhook-manager"; +import { createLogger, redactError, redactLogObject } from "@/lib/logger"; +import { BaseError } from "@/errors"; + +export const EntryNotFoundError = BaseError.subclass("EntryNotFoundError"); + +export const getAllConfigEntriesObfuscated = async (configurator: PaymentAppConfigurator) => { + const logger = createLogger( + { saleorApiUrl: configurator.saleorApiUrl }, + { msgPrefix: "[getAllConfigEntriesObfuscated] " }, + ); + + const config = await configurator.getConfigObfuscated(); + logger.debug("Got obfuscated config"); + + return config.configurations; +}; + +export const getAllConfigEntriesDecrypted = async (configurator: PaymentAppConfigurator) => { + const logger = createLogger( + { saleorApiUrl: configurator.saleorApiUrl }, + { msgPrefix: "[getAllConfigEntriesDecrypted] " }, + ); + + const config = await configurator.getConfig(); + logger.debug("Got config"); + + return config.configurations; +}; + +export const getConfigEntryObfuscated = async ( + configurationId: string, + configurator: PaymentAppConfigurator, +) => { + const logger = createLogger( + { configurationId, saleorApiUrl: configurator.saleorApiUrl }, + { msgPrefix: "[getConfigEntryObfuscated] " }, + ); + logger.debug("Fetching all config entries"); + const entries = await getAllConfigEntriesObfuscated(configurator); + const entry = entries.find((entry) => entry.configurationId === configurationId); + if (!entry) { + logger.warn("Entry was not found"); + throw new EntryNotFoundError(`Entry with id ${configurationId} was not found`); + } + logger.debug({ entryName: entry.configurationName }, "Found entry"); + return entry; +}; + +export const getConfigEntryDecrypted = async ( + configurationId: string, + configurator: PaymentAppConfigurator, +) => { + const logger = createLogger( + { configurationId, saleorApiUrl: configurator.saleorApiUrl }, + { msgPrefix: "[getConfigEntryDecrypted] " }, + ); + + logger.debug("Fetching all config entries"); + const entries = await getAllConfigEntriesDecrypted(configurator); + const entry = entries.find((entry) => entry.configurationId === configurationId); + if (!entry) { + logger.warn("Entry was not found"); + throw new EntryNotFoundError(`Entry with id ${configurationId} was not found`); + } + logger.debug({ entryName: entry.configurationName }, "Found entry"); + return entry; +}; + +export const addConfigEntry = async ( + newConfigEntry: PaymentAppFormConfigEntry, + configurator: PaymentAppConfigurator, + appUrl: string, +) => { + const logger = createLogger( + { saleorApiUrl: configurator.saleorApiUrl }, + { msgPrefix: "[addConfigEntry] " }, + ); + + await validateStripeKeys(newConfigEntry.secretKey, newConfigEntry.publishableKey); + + logger.debug("Creating new webhook for config entry"); + const { webhookSecret, webhookId } = await createStripeWebhook({ + appUrl, + secretKey: newConfigEntry.secretKey, + saleorApiUrl: configurator.saleorApiUrl, + configurator, + }); + + const uuid = uuidv7(); + const config = { + ...newConfigEntry, + webhookSecret, + webhookId, + configurationId: uuid, + } satisfies PaymentAppConfigEntryFullyConfigured; + + logger.debug({ config: redactLogObject(config) }, "Adding new config entry"); + await configurator.setConfigEntry(config); + logger.info({ configurationId: config.configurationId }, "Config entry added"); + + return obfuscateConfigEntry(config); +}; + +export const updateConfigEntry = async ( + input: ConfigEntryUpdate, + configurator: PaymentAppConfigurator, +) => { + const logger = createLogger( + { saleorApiUrl: configurator.saleorApiUrl }, + { msgPrefix: "[updateConfigEntry] " }, + ); + + const { entry, configurationId } = input; + logger.debug("Checking if config entry with provided ID exists"); + const existingEntry = await getConfigEntryDecrypted(configurationId, configurator); + logger.debug({ existingEntry: redactLogObject(existingEntry) }, "Found entry"); + + await configurator.setConfigEntry({ + ...entry, + configurationId, + }); + logger.info({ configurationId }, "Config entry updated"); + + return obfuscateConfigEntry({ + ...existingEntry, + ...entry, + }); +}; + +export const deleteConfigEntry = async ( + configurationId: string, + configurator: PaymentAppConfigurator, +) => { + const logger = createLogger( + { configurationId, saleorApiUrl: configurator.saleorApiUrl }, + { msgPrefix: "[deleteConfigEntry] " }, + ); + + logger.debug("Checking if config entry with provided ID exists"); + const entries = await getAllConfigEntriesDecrypted(configurator); + const existingEntry = entries.find((entry) => entry.configurationId === configurationId); + + if (!existingEntry) { + logger.error({ configurationId }, "Entry was not found"); + throw new EntryNotFoundError(`Entry with id ${configurationId} was not found`); + } + + logger.debug({ existingEntry: redactLogObject(existingEntry) }, "Found entry"); + + logger.debug( + { webhookId: existingEntry.webhookId }, + "Checking if other config is using assosiated webhook", + ); + + const otherEntries = entries.filter((entry) => entry.configurationId !== configurationId); + const isWebhookUsed = otherEntries.some((entry) => entry.webhookId === existingEntry.webhookId); + + if (!isWebhookUsed) { + logger.debug("Deleting webhook linked with config entry"); + try { + await deleteStripeWebhook({ + webhookId: existingEntry.webhookId, + secretKey: existingEntry.secretKey, + }); + } catch (e) { + // Ignore error + logger.warn( + { error: redactError(e), webhookId: existingEntry.webhookId }, + "Webhook couldn't be deleted with the config", + ); + } + } else { + logger.debug("Webhook linked with deleted config entry is used by other config entries"); + } + + await configurator.deleteConfigEntry(configurationId); + logger.info({ configurationId }, "Config entry deleted"); +}; diff --git a/src/modules/payment-app-configuration/input-schemas.ts b/src/modules/payment-app-configuration/input-schemas.ts new file mode 100644 index 0000000..d70ce12 --- /dev/null +++ b/src/modules/payment-app-configuration/input-schemas.ts @@ -0,0 +1,18 @@ +import { z } from "zod"; +import { paymentAppFormConfigEntrySchema } from "./config-entry"; + +export const mappingUpdate = z.object({ + channelId: z.string().min(1), + configurationId: z.string().nullable(), +}); + +export const paymentConfigEntryUpdate = z.object({ + configurationId: z.string().min(1), + entry: paymentAppFormConfigEntrySchema, +}); + +export const paymentConfigEntryDelete = z.object({ configurationId: z.string().min(1) }); + +export type MappingUpdate = z.infer; +export type ConfigEntryUpdate = z.infer; +export type ConfigEntryDelete = z.infer; diff --git a/src/modules/payment-app-configuration/mapping-manager.test.ts b/src/modules/payment-app-configuration/mapping-manager.test.ts new file mode 100644 index 0000000..e76fc7e --- /dev/null +++ b/src/modules/payment-app-configuration/mapping-manager.test.ts @@ -0,0 +1,71 @@ +/* eslint-disable @typescript-eslint/unbound-method */ +import { describe, it, expect, vi } from "vitest"; +import { type Client } from "urql"; +import { + fetchChannels, + getMappingFromAppConfig, + setMappingInAppConfig, + EntryDoesntExistError, +} from "./mapping-manager"; +import { type PaymentAppConfigurator } from "./payment-app-configuration"; +import { FetchChannelsDocument } from "generated/graphql"; + +describe("fetchChannels", () => { + it("should make a query to Saleor GraphQL endpoint and return channels", async () => { + const mockClient = { + query: vi.fn().mockReturnValue({ + toPromise: () => Promise.resolve({ error: null, data: { channels: [] } }), + }), + } as unknown as Client; + + await fetchChannels(mockClient); + + expect(mockClient.query).toBeCalledWith(FetchChannelsDocument, {}); + }); +}); + +describe("getMappingFromAppConfig", () => { + it("should return correct mapping from app config", async () => { + const mockClient = { + query: vi.fn().mockReturnValue({ + toPromise: () => Promise.resolve({ error: null, data: { channels: [{ id: "123" }] } }), + }), + } as unknown as Client; + + const mockConfigurator = { + getConfigObfuscated: vi + .fn() + .mockResolvedValue({ channelToConfigurationId: { "123": "config1" } }), + } as unknown as PaymentAppConfigurator; + + const result = await getMappingFromAppConfig(mockClient, mockConfigurator); + + expect(result).toEqual({ "123": "config1" }); + }); +}); + +describe("setMappingInAppConfig", () => { + it("should throw error if configurationId does not exist", async () => { + const mockConfigurator = { + getConfig: vi.fn().mockResolvedValue({ configurations: [] }), + } as unknown as PaymentAppConfigurator; + + await expect( + setMappingInAppConfig({ channelId: "123", configurationId: "nonexistent" }, mockConfigurator), + ).rejects.toThrow(EntryDoesntExistError); + }); + + it("should call setMapping if configurationId exists", async () => { + const mockConfigurator = { + getConfig: vi.fn().mockResolvedValue({ configurations: [{ configurationId: "exist" }] }), + setMapping: vi.fn(), + getConfigObfuscated: vi + .fn() + .mockResolvedValue({ channelToConfigurationId: { "123": "exist" } }), + } as unknown as PaymentAppConfigurator; + + await setMappingInAppConfig({ channelId: "123", configurationId: "exist" }, mockConfigurator); + + expect(mockConfigurator.setMapping).toBeCalledWith({ "123": "exist" }); + }); +}); diff --git a/src/modules/payment-app-configuration/mapping-manager.ts b/src/modules/payment-app-configuration/mapping-manager.ts new file mode 100644 index 0000000..42fca9e --- /dev/null +++ b/src/modules/payment-app-configuration/mapping-manager.ts @@ -0,0 +1,90 @@ +import { type Client } from "urql"; +import { type MappingUpdate } from "./input-schemas"; +import { type PaymentAppConfigurator } from "./payment-app-configuration"; +import { createLogger } from "@/lib/logger"; +import { BaseError, FieldError } from "@/errors"; +import { FetchChannelsDocument, type FetchChannelsQuery } from "generated/graphql"; + +export const EntryDoesntExistError = FieldError.subclass("EntryDoesntExistError", { + props: { fieldName: "configurationId" }, +}); + +export const FetchChannelsError = BaseError.subclass("FetchChannelsError"); + +export const fetchChannels = async (client: Client) => { + const { error, data } = await client + .query(FetchChannelsDocument, {}) + .toPromise(); + + if (error) { + throw new FetchChannelsError("Error while fetching channels", { cause: error }); + } + + return data?.channels ?? []; +}; + +export const getMappingFromAppConfig = async ( + client: Client, + configurator: PaymentAppConfigurator, +) => { + const logger = createLogger( + { saleorApiUrl: configurator.saleorApiUrl }, + { msgPrefix: "[getMappingFromAppConfig] " }, + ); + logger.debug("Fetching channels from Saleor and config"); + + const [channels, config] = await Promise.all([ + fetchChannels(client), + configurator.getConfigObfuscated(), + ]); + logger.debug({ channels: channels, config: config.channelToConfigurationId }, "Received data"); + + const emptyMapping = Object.fromEntries(channels.map((channel) => [channel.id, null])); + logger.debug({ emptyMapping: emptyMapping }, "Prepared empty mapping"); + + return { + ...emptyMapping, + ...config.channelToConfigurationId, + }; +}; + +export const setMappingInAppConfig = async ( + input: MappingUpdate, + configurator: PaymentAppConfigurator, +) => { + const { configurationId, channelId } = input; + const logger = createLogger( + { input: { configurationId, channelId }, saleorApiUrl: configurator.saleorApiUrl }, + { msgPrefix: "[setMappingInAppConfig] " }, + ); + const config = await configurator.getConfig(); + logger.debug("Got app config"); + + const entry = config.configurations.find( + (entry) => entry.configurationId === input.configurationId, + ); + + if (!input.configurationId) { + logger.info("Removing entry"); + + await configurator.setMapping({ + [input.channelId]: null, + }); + } else if (entry) { + logger.info("Entry with configurationId exists, updating app config"); + + await configurator.setMapping({ + [input.channelId]: input.configurationId, + }); + } else { + logger.error("Entry with configurationId doesn't exist"); + throw new EntryDoesntExistError( + `Entry with configurationId ${input.configurationId} doesn't exist`, + ); + } + + logger.debug("Updated app config"); + + const updatedConfig = await configurator.getConfigObfuscated(); + return updatedConfig.channelToConfigurationId; +}; diff --git a/src/modules/payment-app-configuration/payment-app-configuration-factory.ts b/src/modules/payment-app-configuration/payment-app-configuration-factory.ts new file mode 100644 index 0000000..244c1ce --- /dev/null +++ b/src/modules/payment-app-configuration/payment-app-configuration-factory.ts @@ -0,0 +1,21 @@ +import { type Client } from "urql"; +import { type MetadataEntry } from "@saleor/app-sdk/settings-manager"; +import { + createPrivateSettingsManager, + createWebhookPrivateSettingsManager, +} from "../app-configuration/metadata-manager"; +import { PaymentAppConfigurator } from "./payment-app-configuration"; + +export const getPaymentAppConfigurator = (client: Client, saleorApiUrl: string) => { + return new PaymentAppConfigurator(createPrivateSettingsManager(client), saleorApiUrl); +}; + +export const getWebhookPaymentAppConfigurator = ( + data: { privateMetadata: readonly Readonly[] }, + saleorApiUrl: string, +) => { + return new PaymentAppConfigurator( + createWebhookPrivateSettingsManager(data.privateMetadata as MetadataEntry[]), + saleorApiUrl, + ); +}; diff --git a/src/modules/payment-app-configuration/payment-app-configuration.router.ts b/src/modules/payment-app-configuration/payment-app-configuration.router.ts new file mode 100644 index 0000000..d7433ae --- /dev/null +++ b/src/modules/payment-app-configuration/payment-app-configuration.router.ts @@ -0,0 +1,107 @@ +import { z } from "zod"; +import { protectedClientProcedure } from "../trpc/protected-client-procedure"; +import { router } from "../trpc/trpc-server"; +import { channelMappingSchema, paymentAppUserVisibleConfigEntriesSchema } from "./app-config"; +import { mappingUpdate, paymentConfigEntryDelete, paymentConfigEntryUpdate } from "./input-schemas"; +import { getMappingFromAppConfig, setMappingInAppConfig } from "./mapping-manager"; +import { getPaymentAppConfigurator } from "./payment-app-configuration-factory"; +import { + paymentAppFormConfigEntrySchema, + paymentAppUserVisibleConfigEntrySchema, +} from "./config-entry"; +import { + addConfigEntry, + deleteConfigEntry, + getAllConfigEntriesObfuscated, + getConfigEntryObfuscated, + updateConfigEntry, +} from "./config-manager"; +import { redactLogValue } from "@/lib/logger"; +import { invariant } from "@/lib/invariant"; + +export const paymentAppConfigurationRouter = router({ + mapping: router({ + getAll: protectedClientProcedure.output(channelMappingSchema).query(async ({ ctx }) => { + ctx.logger.info("appConfigurationRouter.mapping.getAll called"); + const configurator = getPaymentAppConfigurator(ctx.apiClient, ctx.saleorApiUrl); + return getMappingFromAppConfig(ctx.apiClient, configurator); + }), + update: protectedClientProcedure + .input(mappingUpdate) + .output(channelMappingSchema) + .mutation(async ({ input, ctx }) => { + const { configurationId, channelId } = input; + ctx.logger.info( + { configurationId, channelId }, + "appConfigurationRouter.mapping.update called", + ); + + const configurator = getPaymentAppConfigurator(ctx.apiClient, ctx.saleorApiUrl); + return setMappingInAppConfig(input, configurator); + }), + }), + paymentConfig: router({ + get: protectedClientProcedure + .input(z.object({ configurationId: z.string() })) + .output(paymentAppUserVisibleConfigEntrySchema) + .query(async ({ input, ctx }) => { + const { configurationId } = input; + ctx.logger.info({ configurationId }, "appConfigurationRouter.paymentConfig.getAll called"); + + const configurator = getPaymentAppConfigurator(ctx.apiClient, ctx.saleorApiUrl); + return getConfigEntryObfuscated(input.configurationId, configurator); + }), + getAll: protectedClientProcedure + .output(paymentAppUserVisibleConfigEntriesSchema) + .query(async ({ ctx }) => { + ctx.logger.info("appConfigurationRouter.paymentConfig.getAll called"); + const configurator = getPaymentAppConfigurator(ctx.apiClient, ctx.saleorApiUrl); + return getAllConfigEntriesObfuscated(configurator); + }), + add: protectedClientProcedure + .input(paymentAppFormConfigEntrySchema) + .mutation(async ({ input, ctx }) => { + const { configurationName, secretKey } = input; + ctx.logger.info("appConfigurationRouter.paymentConfig.add called"); + ctx.logger.debug( + { configurationName, secretKey: redactLogValue(secretKey) }, + "appConfigurationRouter.paymentConfig.add input", + ); + invariant(ctx.appUrl, "Missing app url"); + + const configurator = getPaymentAppConfigurator(ctx.apiClient, ctx.saleorApiUrl); + return addConfigEntry(input, configurator, ctx.appUrl); + }), + update: protectedClientProcedure + .input(paymentConfigEntryUpdate) + .output(paymentAppUserVisibleConfigEntrySchema) + .mutation(async ({ input, ctx }) => { + const { configurationId, entry } = input; + const { configurationName, publishableKey } = entry; + ctx.logger.info("appConfigurationRouter.paymentConfig.update called"); + ctx.logger.debug( + { + configurationId, + entry: { + publishableKey, + configurationName, + }, + }, + "appConfigurationRouter.paymentConfig.update input", + ); + invariant(ctx.appUrl, "Missing app URL"); + + const configurator = getPaymentAppConfigurator(ctx.apiClient, ctx.saleorApiUrl); + return updateConfigEntry(input, configurator); + }), + delete: protectedClientProcedure + .input(paymentConfigEntryDelete) + .mutation(async ({ input, ctx }) => { + const { configurationId } = input; + ctx.logger.info({ configurationId }, "appConfigurationRouter.paymentConfig.delete called"); + + const configurator = getPaymentAppConfigurator(ctx.apiClient, ctx.saleorApiUrl); + return deleteConfigEntry(configurationId, configurator); + }), + }), +}); diff --git a/src/modules/payment-app-configuration/payment-app-configuration.ts b/src/modules/payment-app-configuration/payment-app-configuration.ts new file mode 100644 index 0000000..b53a05f --- /dev/null +++ b/src/modules/payment-app-configuration/payment-app-configuration.ts @@ -0,0 +1,158 @@ +import { encrypt, type MetadataEntry } from "@saleor/app-sdk/settings-manager"; +import { + type GenericAppConfigurator, + PrivateMetadataAppConfigurator, +} from "../app-configuration/app-configuration"; +import { type BrandedEncryptedMetadataManager } from "../app-configuration/metadata-manager"; +import { type PaymentAppConfig, paymentAppConfigSchema, type ChannelMapping } from "./app-config"; +import { + type PaymentAppConfigEntryUpdate, + type PaymentAppConfigEntry, + paymentAppConfigEntrySchema, +} from "./config-entry"; +import { obfuscateConfigEntry } from "./utils"; +import { env } from "@/lib/env.mjs"; +import { BaseError } from "@/errors"; +import { createLogger } from "@/lib/logger"; + +export const privateMetadataKey = "payment-app-config-private"; +export const hiddenMetadataKey = "payment-app-config-hidden"; +export const publicMetadataKey = "payment-app-config-public"; + +export const AppNotConfiguredError = BaseError.subclass("AppNotConfiguredError"); + +export class PaymentAppConfigurator implements GenericAppConfigurator { + private configurator: PrivateMetadataAppConfigurator; + public saleorApiUrl: string; + + constructor(privateMetadataManager: BrandedEncryptedMetadataManager, saleorApiUrl: string) { + this.configurator = new PrivateMetadataAppConfigurator( + privateMetadataManager, + saleorApiUrl, + privateMetadataKey, + ); + this.saleorApiUrl = saleorApiUrl; + } + + async getConfig(): Promise { + const config = await this.configurator.getConfig(); + return paymentAppConfigSchema.parse(config); + } + + async getConfigObfuscated() { + const { configurations, channelToConfigurationId } = await this.getConfig(); + + return { + configurations: configurations.map((entry) => obfuscateConfigEntry(entry)), + channelToConfigurationId, + }; + } + + async getRawConfig(): Promise { + const encryptFn = (data: string) => encrypt(data, env.SECRET_KEY); + + return this.configurator.getRawConfig(encryptFn); + } + + async getConfigEntry(configurationId: string): Promise { + const config = await this.configurator.getConfig(); + return config?.configurations.find((entry) => entry.configurationId === configurationId); + } + + /** Adds new config entry or updates existing one */ + async setConfigEntry(newConfiguration: PaymentAppConfigEntryUpdate) { + const { configurations } = await this.getConfig(); + + const existingEntryIndex = configurations.findIndex( + (entry) => entry.configurationId === newConfiguration.configurationId, + ); + + // Old entry = allow missing fields (they are already saved) + if (existingEntryIndex !== -1) { + const existingEntry = configurations[existingEntryIndex]; + const mergedEntry = { + ...existingEntry, + ...newConfiguration, + }; + + const newConfigurations = configurations.slice(0); + newConfigurations[existingEntryIndex] = mergedEntry; + return this.setConfig({ configurations: newConfigurations }); + } + + // New entry = check if valid + const parsedConfig = paymentAppConfigEntrySchema.parse(newConfiguration); + + return this.setConfig({ + configurations: [...configurations, parsedConfig], + }); + } + + async deleteConfigEntry(configurationId: string) { + const oldConfig = await this.getConfig(); + const newConfigurations = oldConfig.configurations.filter( + (entry) => entry.configurationId !== configurationId, + ); + const newMappings = Object.fromEntries( + Object.entries(oldConfig.channelToConfigurationId).filter( + ([, configId]) => configId !== configurationId, + ), + ); + await this.setConfig( + { ...oldConfig, configurations: newConfigurations, channelToConfigurationId: newMappings }, + true, + ); + } + + /** Adds new mappings or updates exsting ones */ + async setMapping(newMapping: ChannelMapping) { + const { channelToConfigurationId } = await this.getConfig(); + return this.setConfig({ + channelToConfigurationId: { ...channelToConfigurationId, ...newMapping }, + }); + } + + async deleteMapping(channelId: string) { + const { channelToConfigurationId } = await this.getConfig(); + const newMapping = { ...channelToConfigurationId }; + delete newMapping[channelId]; + return this.setConfig({ channelToConfigurationId: newMapping }); + } + + /** Method that directly updates the config in MetadataConfigurator. + * You should probably use setConfigEntry or setMapping instead */ + async setConfig(newConfig: Partial, replace = false) { + return this.configurator.setConfig(newConfig, replace); + } + + async clearConfig() { + const defaultConfig = paymentAppConfigSchema.parse(undefined); + return this.setConfig(defaultConfig, true); + } +} + +export const getConfigurationForChannel = ( + appConfig: PaymentAppConfig, + channelId?: string | undefined | null, +) => { + const logger = createLogger({ channelId }, { msgPrefix: "[getConfigurationForChannel] " }); + if (!channelId) { + logger.warn("Missing channelId"); + return null; + } + + const configurationId = appConfig.channelToConfigurationId[channelId]; + if (!configurationId) { + logger.warn(`Missing mapping for channelId ${channelId}`); + return null; + } + + const perChannelConfig = appConfig.configurations.find( + (config) => config.configurationId === configurationId, + ); + if (!perChannelConfig) { + logger.warn({ configurationId }, "Missing configuration for configurationId"); + return null; + } + return perChannelConfig; +}; diff --git a/src/modules/payment-app-configuration/utils.ts b/src/modules/payment-app-configuration/utils.ts new file mode 100644 index 0000000..ae430e3 --- /dev/null +++ b/src/modules/payment-app-configuration/utils.ts @@ -0,0 +1,25 @@ +import { obfuscateConfig } from "../app-configuration/utils"; +import { + type PaymentAppConfigEntry, + type PaymentAppEncryptedConfig, + type PaymentAppUserVisibleConfigEntry, + paymentAppUserVisibleConfigEntrySchema, +} from "./config-entry"; + +export const obfuscateConfigEntry = ( + entry: PaymentAppConfigEntry | PaymentAppUserVisibleConfigEntry, +): PaymentAppUserVisibleConfigEntry => { + const { secretKey, publishableKey, configurationName, configurationId, webhookId } = entry; + + const configValuesToObfuscate = { + secretKey, + } satisfies PaymentAppEncryptedConfig; + + return paymentAppUserVisibleConfigEntrySchema.parse({ + publishableKey, + configurationId, + configurationName, + webhookId, + ...obfuscateConfig(configValuesToObfuscate), + } satisfies PaymentAppUserVisibleConfigEntry); +}; diff --git a/src/modules/payment-app-configuration/webhook-manager.ts b/src/modules/payment-app-configuration/webhook-manager.ts new file mode 100644 index 0000000..0a8c8ff --- /dev/null +++ b/src/modules/payment-app-configuration/webhook-manager.ts @@ -0,0 +1,154 @@ +import { type Stripe } from "stripe"; +import { getStripeApiClient } from "../stripe/stripe-api"; +import { type PaymentAppConfigurator } from "./payment-app-configuration"; +import { invariant } from "@/lib/invariant"; +import { createLogger, redactLogObject } from "@/lib/logger"; + +const stripeWebhookEndpointRoute = "/api/webhooks/stripe"; + +const enabledEvents: Array = [ + "payment_intent.created", + "payment_intent.canceled", + "payment_intent.succeeded", + "payment_intent.processing", + "payment_intent.payment_failed", + "payment_intent.requires_action", + "payment_intent.partially_funded", + "payment_intent.amount_capturable_updated", + "charge.refund.updated", + "charge.refunded", +]; + +const getWebhookUrl = (appUrl: string, saleorApiUrl: string): string => { + const url = new URL(appUrl); + url.pathname = stripeWebhookEndpointRoute; + url.searchParams.set("saleorApiUrl", saleorApiUrl); + return url.toString(); +}; + +interface StripeWebhookResult { + webhookSecret: string; + webhookId: string; +} + +export const createStripeWebhook = async ({ + appUrl, + saleorApiUrl, + secretKey, + configurator, +}: { + appUrl: string; + saleorApiUrl: string; + secretKey: string; + configurator: PaymentAppConfigurator; +}): Promise => { + const logger = createLogger({ saleorApiUrl, appUrl }, { msgPrefix: "[createStripeWebhook] " }); + const stripe = getStripeApiClient(secretKey); + + const url = getWebhookUrl(appUrl, saleorApiUrl); + + const existingStripeWebhook = await findExistingWebhook({ appUrl, saleorApiUrl, secretKey }); + if (existingStripeWebhook) { + const existingAppWebhook = await checkWebhookUsage({ + webhookId: existingStripeWebhook.id, + configurator, + }); + + if (existingAppWebhook) { + // There's already a webhook for this app, so we can just + return existingAppWebhook; + } + + // We cannot retrieve webhook secret after it was created, so we need to delete it and create a new one + await deleteStripeWebhook({ webhookId: existingStripeWebhook.id, secretKey }); + } + + logger.debug({ url }, "Creating stripe webhook"); + const stripeWebhook = await stripe.webhookEndpoints.create({ + url, + enabled_events: enabledEvents, + description: "Saleor Stripe App", + }); + + logger.debug({ webhook: redactLogObject(stripeWebhook) }, "Webhook created"); + const { secret, id } = stripeWebhook; + invariant(secret, "Missing webhook secret"); + + return { + webhookSecret: secret, + webhookId: id, + }; +}; + +export const findExistingWebhook = async ({ + appUrl, + saleorApiUrl, + secretKey, +}: { + appUrl: string; + saleorApiUrl: string; + secretKey: string; +}) => { + const logger = createLogger({ saleorApiUrl, appUrl }, { msgPrefix: "[findExistingWebhook] " }); + const stripe = getStripeApiClient(secretKey); + + const url = getWebhookUrl(appUrl, saleorApiUrl); + logger.debug({ url }, "Finding existing stripe webhook"); + + const webhooks = await stripe.webhookEndpoints.list(); + logger.debug({ webhooksLength: webhooks.data.length }, "Found webhooks"); + + const existingWebhook = webhooks.data.find((webhook) => webhook.url === url); + if (existingWebhook) { + logger.debug({ webhook: redactLogObject(existingWebhook) }, "Found existing webhook"); + } + + return existingWebhook; +}; + +export const deleteStripeWebhook = async ({ + webhookId, + secretKey, +}: { + webhookId: string; + secretKey: string; +}) => { + const logger = createLogger({ webhookId }, { msgPrefix: "[deleteStripeWebhook] " }); + const stripe = getStripeApiClient(secretKey); + + logger.debug("Deleting stripe webhook"); + await stripe.webhookEndpoints.del(webhookId); + logger.debug("Webhook was deleted"); +}; + +export const checkWebhookUsage = async ({ + webhookId, + configurator, +}: { + webhookId: string; + configurator: PaymentAppConfigurator; +}) => { + const logger = createLogger( + { webhookId, saleorApiUrl: configurator.saleorApiUrl }, + { msgPrefix: "[checkWebhookUsage] " }, + ); + + logger.debug("Fetching all config entries"); + + const config = await configurator.getConfig(); + const entries = config.configurations; + + logger.debug("Got all entries"); + const entry = entries.find((entry) => entry.webhookId === webhookId); + + if (entry) { + logger.debug("Found entry with matching webhook id"); + return { + webhookId: entry.webhookId, + webhookSecret: entry.webhookSecret, + }; + } + + logger.debug("Entry with matching webhook id was not found"); + return null; +}; diff --git a/src/modules/stripe/__recordings__/stripe-api_748119249/validateStripeKeys_2838756478/not-throw-error-if-both-keys-are-correct_4216631210/recording.har b/src/modules/stripe/__recordings__/stripe-api_748119249/validateStripeKeys_2838756478/not-throw-error-if-both-keys-are-correct_4216631210/recording.har new file mode 100644 index 0000000..86672ec --- /dev/null +++ b/src/modules/stripe/__recordings__/stripe-api_748119249/validateStripeKeys_2838756478/not-throw-error-if-both-keys-are-correct_4216631210/recording.har @@ -0,0 +1,388 @@ +{ + "log": { + "_recordingName": "stripe-api/validateStripeKeys/not throw error if both keys are correct", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "740cb060792366c95c70efe3e6fefb52", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 0, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 727, + "httpVersion": "HTTP/1.1", + "method": "GET", + "queryString": [ + { + "name": "limit", + "value": "1" + } + ], + "url": "https://api.stripe.com/v1/payment_intents?limit=1" + }, + "response": { + "bodySize": 2160, + "content": { + "mimeType": "application/json", + "size": 2160, + "text": { + "data": [ + { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "always", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_3OMtDMEosEcNBN5m1qOegbpT_secret_qhCRYBSNepMmBNyqaPAg14y5R", + "confirmation_method": "automatic", + "created": 1702476908, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtDMEosEcNBN5m1qOegbpT", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "klarna": { + "preferred_locale": null + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "klarna", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + ], + "has_more": true, + "object": "list", + "url": "/v1/payment_intents" + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "2160" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:15:08 GMT" + }, + { + "name": "request-id", + "value": "req_0R5WBWYzQ2M6Jx" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 956, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:15:07.789Z", + "time": 354, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 354 + } + }, + { + "_id": "b402ed8a49dac7e2becb92999f179d8b", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 19, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "19" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-2444489d-914d-414c-844c-ff45f9c06213" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 804, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "pii[id_number]=test" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/tokens" + }, + "response": { + "bodySize": 175, + "content": { + "mimeType": "application/json", + "size": 175, + "text": { + "client_ip": "31.61.175.128", + "created": 1702476908, + "id": "pii_1OMtDMEosEcNBN5mbeBnLtHv", + "livemode": false, + "object": "token", + "type": "pii", + "used": false + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "175" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Ftokens; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:15:08 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-2444489d-914d-414c-844c-ff45f9c06213" + }, + { + "name": "original-request", + "value": "req_o4EjTS3oNbs3Vt" + }, + { + "name": "request-id", + "value": "req_o4EjTS3oNbs3Vt" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1085, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:15:08.145Z", + "time": 390, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 390 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/stripe/__recordings__/stripe-api_748119249/validateStripeKeys_2838756478/should-throw-error-if-both-keys-are-invalid_2549431215/recording.har b/src/modules/stripe/__recordings__/stripe-api_748119249/validateStripeKeys_2838756478/should-throw-error-if-both-keys-are-invalid_2549431215/recording.har new file mode 100644 index 0000000..1a20953 --- /dev/null +++ b/src/modules/stripe/__recordings__/stripe-api_748119249/validateStripeKeys_2838756478/should-throw-error-if-both-keys-are-invalid_2549431215/recording.har @@ -0,0 +1,139 @@ +{ + "log": { + "_recordingName": "stripe-api/validateStripeKeys/should throw error if both keys are invalid", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "90920035c265c2be49ed00c29eb902c0", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 0, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 626, + "httpVersion": "HTTP/1.1", + "method": "GET", + "queryString": [ + { + "name": "limit", + "value": "1" + } + ], + "url": "https://api.stripe.com/v1/payment_intents?limit=1" + }, + "response": { + "bodySize": 108, + "content": { + "mimeType": "application/json", + "size": 108, + "text": { + "error": { + "message": "Invalid API Key provided: blabla", + "type": "invalid_request_error" + } + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "108" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:15:07 GMT" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "www-authenticate", + "value": "Bearer realm=\"Stripe\"" + } + ], + "headersSize": 615, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 401, + "statusText": "Unauthorized" + }, + "startedDateTime": "2023-12-13T14:15:07.688Z", + "time": 97, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 97 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/stripe/__recordings__/stripe-api_748119249/validateStripeKeys_2838756478/should-throw-error-if-publishable-key-is-invalid_3942585802/recording.har b/src/modules/stripe/__recordings__/stripe-api_748119249/validateStripeKeys_2838756478/should-throw-error-if-publishable-key-is-invalid_3942585802/recording.har new file mode 100644 index 0000000..91c0365 --- /dev/null +++ b/src/modules/stripe/__recordings__/stripe-api_748119249/validateStripeKeys_2838756478/should-throw-error-if-publishable-key-is-invalid_3942585802/recording.har @@ -0,0 +1,361 @@ +{ + "log": { + "_recordingName": "stripe-api/validateStripeKeys/should throw error if publishable key is invalid", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "740cb060792366c95c70efe3e6fefb52", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 0, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 727, + "httpVersion": "HTTP/1.1", + "method": "GET", + "queryString": [ + { + "name": "limit", + "value": "1" + } + ], + "url": "https://api.stripe.com/v1/payment_intents?limit=1" + }, + "response": { + "bodySize": 2160, + "content": { + "mimeType": "application/json", + "size": 2160, + "text": { + "data": [ + { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "always", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_3OMtDLEosEcNBN5m11wpQjbx_secret_cUiIxYoObEAywmhr0vL1Tz9Vj", + "confirmation_method": "automatic", + "created": 1702476907, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtDLEosEcNBN5m11wpQjbx", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "klarna": { + "preferred_locale": null + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "klarna", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + ], + "has_more": true, + "object": "list", + "url": "/v1/payment_intents" + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "2160" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:15:07 GMT" + }, + { + "name": "request-id", + "value": "req_lQkucXGjdauYJA" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 956, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:15:07.056Z", + "time": 530, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 530 + } + }, + { + "_id": "990365e93b996a79997b70fe3ca6c55e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 19, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "19" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-de7e2360-cf92-42c3-b03f-65c74d1f65bd" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 703, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "pii[id_number]=test" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/tokens" + }, + "response": { + "bodySize": 108, + "content": { + "mimeType": "application/json", + "size": 108, + "text": { + "error": { + "message": "Invalid API Key provided: blabla", + "type": "invalid_request_error" + } + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "108" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:15:07 GMT" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "www-authenticate", + "value": "Bearer realm=\"Stripe\"" + } + ], + "headersSize": 615, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 401, + "statusText": "Unauthorized" + }, + "startedDateTime": "2023-12-13T14:15:07.589Z", + "time": 91, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 91 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/stripe/__recordings__/stripe-api_748119249/validateStripeKeys_2838756478/should-throw-error-if-secret-key-is-invalid_476878657/recording.har b/src/modules/stripe/__recordings__/stripe-api_748119249/validateStripeKeys_2838756478/should-throw-error-if-secret-key-is-invalid_476878657/recording.har new file mode 100644 index 0000000..1e1cda8 --- /dev/null +++ b/src/modules/stripe/__recordings__/stripe-api_748119249/validateStripeKeys_2838756478/should-throw-error-if-secret-key-is-invalid_476878657/recording.har @@ -0,0 +1,139 @@ +{ + "log": { + "_recordingName": "stripe-api/validateStripeKeys/should throw error if secret key is invalid", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "90920035c265c2be49ed00c29eb902c0", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 0, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 626, + "httpVersion": "HTTP/1.1", + "method": "GET", + "queryString": [ + { + "name": "limit", + "value": "1" + } + ], + "url": "https://api.stripe.com/v1/payment_intents?limit=1" + }, + "response": { + "bodySize": 108, + "content": { + "mimeType": "application/json", + "size": 108, + "text": { + "error": { + "message": "Invalid API Key provided: blabla", + "type": "invalid_request_error" + } + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "108" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:15:07 GMT" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "www-authenticate", + "value": "Bearer realm=\"Stripe\"" + } + ], + "headersSize": 615, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 401, + "statusText": "Unauthorized" + }, + "startedDateTime": "2023-12-13T14:15:06.754Z", + "time": 292, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 292 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/stripe/currencies.test.ts b/src/modules/stripe/currencies.test.ts new file mode 100644 index 0000000..6ea8638 --- /dev/null +++ b/src/modules/stripe/currencies.test.ts @@ -0,0 +1,68 @@ +import { describe, it, expect } from "vitest"; +import { getStripeAmountFromSaleorMoney, getSaleorAmountFromStripeAmount } from "./currencies"; + +describe("currencies", () => { + const testCases = [ + { major: 10, currency: "PLN", minor: 1000 }, + { major: 21.37, currency: "PLN", minor: 2137 }, + { major: 21.37, currency: "EUR", minor: 2137 }, + { major: 21.37, currency: "USD", minor: 2137 }, + { major: 1231231231.23, currency: "PLN", minor: 123123123123 }, + + // https://stripe.com/docs/currencies?presentment-currency=US#zero-decimal + { major: 500, currency: "BIF", minor: 500 }, + { major: 500, currency: "CLP", minor: 500 }, + { major: 500, currency: "DJF", minor: 500 }, + { major: 500, currency: "GNF", minor: 500 }, + { major: 500, currency: "JPY", minor: 500 }, + { major: 500, currency: "KMF", minor: 500 }, + { major: 500, currency: "KRW", minor: 500 }, + { major: 500, currency: "MGA", minor: 500 }, + { major: 500, currency: "PYG", minor: 500 }, + { major: 500, currency: "RWF", minor: 500 }, + { major: 500, currency: "UGX", minor: 500 }, + { major: 500, currency: "VND", minor: 500 }, + { major: 500, currency: "VUV", minor: 500 }, + { major: 500, currency: "XAF", minor: 500 }, + { major: 500, currency: "XOF", minor: 500 }, + { major: 500, currency: "XPF", minor: 500 }, + + // https://stripe.com/docs/currencies?presentment-currency=US#three-decimal + { major: 5.12, currency: "BHD", minor: 5120 }, + { major: 5.12, currency: "JOD", minor: 5120 }, + { major: 5.12, currency: "KWD", minor: 5120 }, + { major: 5.12, currency: "OMR", minor: 5120 }, + { major: 5.12, currency: "TND", minor: 5120 }, + + // @todo + // {major: 5.124, currency: 'BHD', minor: 5120 OR 5130}, + // {major: 5.124, currency: 'JOD', minor: 5120 OR 5130}, + // {major: 5.124, currency: 'KWD', minor: 5120 OR 5130}, + // {major: 5.124, currency: 'OMR', minor: 5120 OR 5130}, + // {major: 5.124, currency: 'TND', minor: 5120 OR 5130}, + + { major: 21.37, currency: "XBT", minor: 2137 }, + ]; + + it.each(testCases)("getStripeAmountFromSaleorMoney %p", ({ major, minor, currency }) => { + expect(getStripeAmountFromSaleorMoney({ amount: major, currency })).toEqual(minor); + }); + it.each(testCases)("getSaleorAmountFromStripeAmount %p", ({ major, minor, currency }) => { + expect(getSaleorAmountFromStripeAmount({ amount: minor, currency })).toEqual(major); + }); + + it.each(testCases)("identity %p", ({ major, minor, currency }) => { + expect( + getStripeAmountFromSaleorMoney({ + amount: getSaleorAmountFromStripeAmount({ amount: minor, currency }), + currency, + }), + ).toEqual(minor); + expect( + getSaleorAmountFromStripeAmount({ + amount: getStripeAmountFromSaleorMoney({ amount: major, currency }), + currency, + }), + ).toEqual(major); + }); +}); diff --git a/src/modules/stripe/currencies.ts b/src/modules/stripe/currencies.ts new file mode 100644 index 0000000..9c39ee2 --- /dev/null +++ b/src/modules/stripe/currencies.ts @@ -0,0 +1,52 @@ +import { type Money } from "generated/graphql"; +import { invariant } from "@/lib/invariant"; + +const getDecimalsForStripe = (currency: string) => { + invariant(currency.length === 3, "currency needs to be a 3-letter code"); + + const stripeDecimals = stripeCurrencies[currency.toUpperCase()]; + const decimals = stripeDecimals ?? 2; + return decimals; +}; + +// Some payment methods expect the amount to be in cents (integers) +// Saleor provides and expects the amount to be in dollars (decimal format / floats) +export const getStripeAmountFromSaleorMoney = ({ amount: major, currency }: Money) => { + const decimals = getDecimalsForStripe(currency); + const multiplier = 10 ** decimals; + return Number.parseInt((major * multiplier).toFixed(0), 10); +}; + +// Some payment methods expect the amount to be in cents (integers) +// Saleor provides and expects the amount to be in dollars (decimal format / floats) +export const getSaleorAmountFromStripeAmount = ({ amount: minor, currency }: Money) => { + const decimals = getDecimalsForStripe(currency); + const multiplier = 10 ** decimals; + return Number.parseFloat((minor / multiplier).toFixed(decimals)); +}; + +// https://docs.stripe.com/development-resources/currency-codes +const stripeCurrencies: Record = { + BIF: 0, + CLP: 0, + DJF: 0, + GNF: 0, + JPY: 0, + KMF: 0, + KRW: 0, + MGA: 0, + PYG: 0, + RWF: 0, + UGX: 0, + VND: 0, + VUV: 0, + XAF: 0, + XOF: 0, + XPF: 0, + + BHD: 3, + JOD: 3, + KWD: 3, + OMR: 3, + TND: 3, +}; diff --git a/src/modules/stripe/stripe-api.test.ts b/src/modules/stripe/stripe-api.test.ts new file mode 100644 index 0000000..6456dea --- /dev/null +++ b/src/modules/stripe/stripe-api.test.ts @@ -0,0 +1,94 @@ +import { describe, it, expect } from "vitest"; +import type Stripe from "stripe"; +import { + getStripeExternalUrlForIntentId, + stripePaymentIntentToTransactionResult, + validateStripeKeys, +} from "./stripe-api"; +import { TransactionFlowStrategyEnum } from "generated/graphql"; +import { type TransactionInitializeSessionResponse } from "@/schemas/TransactionInitializeSession/TransactionInitializeSessionResponse.mjs"; +import { setupRecording } from "@/__tests__/polly"; +import { testEnv } from "@/__tests__/test-env.mjs"; + +describe("stripe-api", () => { + describe("stripeResultCodeToTransactionResult", () => { + type ResultWithoutPrefix = + TransactionInitializeSessionResponse["result"] extends `${infer _Prefix}_${infer Result}` + ? Result + : never; + + // exhaustiveCheck is used to ensure that all Stripe.PaymentIntent.Status are covered + const exhaustiveCheck = { + canceled: "FAILURE", + processing: "REQUEST", + requires_action: "ACTION_REQUIRED", + requires_capture: "SUCCESS", + requires_confirmation: "ACTION_REQUIRED", + requires_payment_method: "ACTION_REQUIRED", + succeeded: "SUCCESS", + } satisfies Record; + + describe.each(Object.entries(exhaustiveCheck))("%p", (stripeResult, expectedResult) => { + it.each([ + { + strategy: TransactionFlowStrategyEnum.Authorization, + expectedAction: "AUTHORIZATION", + }, + { + strategy: TransactionFlowStrategyEnum.Charge, + expectedAction: "CHARGE", + }, + ])("%p", async ({ strategy, expectedAction }) => { + const returned = stripePaymentIntentToTransactionResult(strategy, { + status: stripeResult, + } as Stripe.PaymentIntent); + + if (stripeResult === "requires_capture") { + // special case + expect(returned).toBe("AUTHORIZATION_SUCCESS"); + } else { + expect(returned).toBe(`${expectedAction}_${expectedResult}`); + } + }); + }); + }); + + describe("getStripeExternalUrlForIntentId", () => { + it("should get external url for intentId", () => { + expect(getStripeExternalUrlForIntentId("pi_3MmHAnLE6YuwiJ1e0lqUR2OC")).toMatchInlineSnapshot( + '"https://dashboard.stripe.com/payments/pi_3MmHAnLE6YuwiJ1e0lqUR2OC"', + ); + }); + }); + + describe("validateStripeKeys", () => { + setupRecording(); + + it("should throw error if secret key is invalid", async () => { + return expect( + validateStripeKeys("blabla", testEnv.TEST_PAYMENT_APP_PUBLISHABLE_KEY), + ).rejects.toThrowErrorMatchingInlineSnapshot('"Provided secret key is invalid"'); + }); + + it("should throw error if publishable key is invalid", async () => { + return expect( + validateStripeKeys(testEnv.TEST_PAYMENT_APP_SECRET_KEY, "blabla"), + ).rejects.toThrowErrorMatchingInlineSnapshot('"Provided publishable key is invalid"'); + }); + + it("should throw error if both keys are invalid", async () => { + return expect( + validateStripeKeys("blabla", "blabla"), + ).rejects.toThrowErrorMatchingInlineSnapshot('"Provided secret key is invalid"'); + }); + + it("not throw error if both keys are correct", async () => { + return expect( + validateStripeKeys( + testEnv.TEST_PAYMENT_APP_SECRET_KEY, + testEnv.TEST_PAYMENT_APP_PUBLISHABLE_KEY, + ), + ).resolves.toMatchInlineSnapshot("undefined"); + }); + }); +}); diff --git a/src/modules/stripe/stripe-api.ts b/src/modules/stripe/stripe-api.ts new file mode 100644 index 0000000..a01189a --- /dev/null +++ b/src/modules/stripe/stripe-api.ts @@ -0,0 +1,230 @@ +import { Stripe } from "stripe"; +import { getStripeAmountFromSaleorMoney } from "./currencies"; +import { + TransactionFlowStrategyEnum, + type TransactionProcessSessionEventFragment, + type TransactionInitializeSessionEventFragment, +} from "generated/graphql"; +import { invariant } from "@/lib/invariant"; +import type { TransactionInitializeSessionResponse } from "@/schemas/TransactionInitializeSession/TransactionInitializeSessionResponse.mjs"; +import { InvalidSecretKeyError, RestrictedKeyNotSupportedError } from "@/errors"; +import { unpackPromise } from "@/lib/utils"; +import { createLogger, redactError } from "@/lib/logger"; + +export const getStripeApiClient = (secretKey: string) => { + const stripe = new Stripe(secretKey, { + apiVersion: "2023-10-16", + typescript: true, + httpClient: Stripe.createFetchHttpClient(fetch), + }); + return stripe; +}; + +export const validateStripeKeys = async (secretKey: string, publishableKey: string) => { + const logger = createLogger({}, { msgPrefix: "[validateStripeKeys] " }); + + if (secretKey.startsWith("rk_")) { + // @todo remove this once restricted keys are supported + // validate that restricted keys have required permissions + throw new RestrictedKeyNotSupportedError("Restricted keys are not supported"); + } + + { + const stripe = getStripeApiClient(secretKey); + const [intentsError] = await unpackPromise(stripe.paymentIntents.list({ limit: 1 })); + + if (intentsError) { + logger.error({ error: redactError(intentsError) }, "Invalid secret key"); + if (intentsError instanceof Stripe.errors.StripeError) { + throw new InvalidSecretKeyError("Provided secret key is invalid"); + } + throw new InvalidSecretKeyError("There was an error while checking secret key"); + } + } + + { + // https://stackoverflow.com/a/61001462/704894 + const stripe = getStripeApiClient(publishableKey); + const [tokenError] = await unpackPromise( + stripe.tokens.create({ + pii: { id_number: "test" }, + }), + ); + if (tokenError) { + logger.error({ error: redactError(tokenError) }, "Invalid publishable key"); + if (tokenError instanceof Stripe.errors.StripeError) { + throw new InvalidSecretKeyError("Provided publishable key is invalid"); + } + throw new InvalidSecretKeyError("There was an error while checking publishable key"); + } + } +}; + +export const getEnvironmentFromKey = (secretKeyOrPublishableKey: string) => { + return secretKeyOrPublishableKey.startsWith("sk_live_") || + secretKeyOrPublishableKey.startsWith("pk_live_") || + secretKeyOrPublishableKey.startsWith("rk_live_") + ? "live" + : "test"; +}; + +export const getStripeWebhookDashboardLink = ( + webhookId: string, + environment: "live" | "test", +): string => { + if (environment === "live") { + return `https://dashboard.stripe.com/webhooks/${webhookId}`; + } else { + return `https://dashboard.stripe.com/test/webhooks/${webhookId}`; + } +}; + +export const transactionSessionInitializeEventToStripeCreate = ( + event: TransactionInitializeSessionEventFragment, +): Stripe.PaymentIntentCreateParams => { + const data = event.data as Partial; + + return { + ...data, + amount: getStripeAmountFromSaleorMoney({ + amount: event.sourceObject.total.gross.amount, + currency: event.sourceObject.total.gross.currency, + }), + currency: event.sourceObject.total.gross.currency, + capture_method: + event.action.actionType === TransactionFlowStrategyEnum.Charge ? "automatic" : "manual", + metadata: { + ...data.metadata, + transactionId: event.transaction.id, + channelId: event.sourceObject.channel.id, + ...(event.sourceObject.__typename === "Checkout" && { checkoutId: event.sourceObject.id }), + ...(event.sourceObject.__typename === "Order" && { orderId: event.sourceObject.id }), + }, + }; +}; + +export const transactionSessionProcessEventToStripeUpdate = ( + event: TransactionInitializeSessionEventFragment | TransactionProcessSessionEventFragment, +): Stripe.PaymentIntentUpdateParams => { + const data = event.data as Partial; + + return { + ...data, + amount: getStripeAmountFromSaleorMoney({ + amount: event.sourceObject.total.gross.amount, + currency: event.sourceObject.total.gross.currency, + }), + currency: event.sourceObject.total.gross.currency, + capture_method: + event.action.actionType === TransactionFlowStrategyEnum.Charge ? "automatic" : "manual", + metadata: { + ...data.metadata, + transactionId: event.transaction.id, + channelId: event.sourceObject.channel.id, + ...(event.sourceObject.__typename === "Checkout" && { checkoutId: event.sourceObject.id }), + ...(event.sourceObject.__typename === "Order" && { orderId: event.sourceObject.id }), + }, + }; +}; + +export const stripePaymentIntentToTransactionResult = ( + transactionFlowStrategy: TransactionFlowStrategyEnum, + stripePaymentIntent: Stripe.PaymentIntent, +): TransactionInitializeSessionResponse["result"] => { + const stripeResult = stripePaymentIntent.status; + const prefix = + transactionFlowStrategy === TransactionFlowStrategyEnum.Authorization + ? "AUTHORIZATION" + : transactionFlowStrategy === TransactionFlowStrategyEnum.Charge + ? "CHARGE" + : /* c8 ignore next */ + null; + invariant(prefix, `Unsupported transactionFlowStrategy: ${transactionFlowStrategy}`); + + switch (stripeResult) { + case "processing": + return `${prefix}_REQUEST`; + case "requires_payment_method": + case "requires_action": + case "requires_confirmation": + return `${prefix}_ACTION_REQUIRED`; + case "canceled": + return `${prefix}_FAILURE`; + case "succeeded": + return `${prefix}_SUCCESS`; + case "requires_capture": + return "AUTHORIZATION_SUCCESS"; + } +}; + +export const initializeStripePaymentIntent = ({ + paymentIntentCreateParams, + secretKey, +}: { + paymentIntentCreateParams: Stripe.PaymentIntentCreateParams; + secretKey: string; +}) => { + const stripe = getStripeApiClient(secretKey); + return stripe.paymentIntents.create(paymentIntentCreateParams); +}; + +export const updateStripePaymentIntent = ({ + intentId, + paymentIntentUpdateParams, + secretKey, +}: { + intentId: string; + paymentIntentUpdateParams: Stripe.PaymentIntentUpdateParams; + secretKey: string; +}) => { + const stripe = getStripeApiClient(secretKey); + return stripe.paymentIntents.update(intentId, paymentIntentUpdateParams); +}; + +export const getStripeExternalUrlForIntentId = (intentId: string) => { + const externalUrl = `https://dashboard.stripe.com/payments/${encodeURIComponent(intentId)}`; + return externalUrl; +}; + +export async function processStripePaymentIntentRefundRequest({ + paymentIntentId, + stripeAmount, + secretKey, +}: { + paymentIntentId: string; + stripeAmount: number | null | undefined; + secretKey: string; +}) { + const stripeClient = getStripeApiClient(secretKey); + return stripeClient.refunds.create({ + payment_intent: paymentIntentId, + amount: stripeAmount ?? undefined, + }); +} + +export async function processStripePaymentIntentCancelRequest({ + paymentIntentId, + secretKey, +}: { + paymentIntentId: string; + secretKey: string; +}) { + const stripeClient = getStripeApiClient(secretKey); + + return stripeClient.paymentIntents.cancel(paymentIntentId); +} + +export async function processStripePaymentIntentCaptureRequest({ + paymentIntentId, + stripeAmount, + secretKey, +}: { + paymentIntentId: string; + stripeAmount: number | null | undefined; + secretKey: string; +}) { + const stripeClient = getStripeApiClient(secretKey); + return stripeClient.paymentIntents.capture(paymentIntentId, { + amount_to_capture: stripeAmount ?? undefined, + }); +} diff --git a/src/modules/trpc/protected-client-procedure.ts b/src/modules/trpc/protected-client-procedure.ts new file mode 100644 index 0000000..ed3a21b --- /dev/null +++ b/src/modules/trpc/protected-client-procedure.ts @@ -0,0 +1,122 @@ +import { verifyJWT } from "@saleor/app-sdk/verify-jwt"; +import { logger, redactLogValue } from "../../lib/logger"; +import { REQUIRED_SALEOR_PERMISSIONS } from "../jwt/consts"; +import { middleware, procedure } from "./trpc-server"; +import { checkTokenExpiration } from "@/modules/jwt/check-token-expiration"; +import { saleorApp } from "@/saleor-app"; +import { createClient } from "@/lib/create-graphq-client"; +import { + JwtInvalidError, + JwtTokenExpiredError, + ReqMissingAppIdError, + ReqMissingAuthDataError, + ReqMissingSaleorApiUrlError, + ReqMissingTokenError, +} from "@/errors"; + +const attachAppToken = middleware(async ({ ctx, next }) => { + logger.debug("attachAppToken middleware"); + + if (!ctx.saleorApiUrl) { + logger.debug("ctx.saleorApiUrl not found, throwing"); + + throw new ReqMissingSaleorApiUrlError("Missing saleorApiUrl in request"); + } + + const authData = await saleorApp.apl.get(ctx.saleorApiUrl); + + if (!authData) { + logger.debug("authData not found, throwing 401"); + + throw new ReqMissingAuthDataError("Missing authData in request"); + } + + return next({ + ctx: { + appToken: authData.token, + saleorApiUrl: authData.saleorApiUrl, + appId: authData.appId, + }, + }); +}); + +const validateClientToken = middleware(async ({ ctx, next }) => { + logger.debug("validateClientToken middleware"); + + if (!ctx.token) { + throw new ReqMissingTokenError( + "Missing token in request. This middleware can be used only in frontend", + ); + } + + if (!ctx.appId) { + throw new ReqMissingAppIdError( + "Missing appId in request. This middleware can be used after auth is attached", + ); + } + + if (!ctx.saleorApiUrl) { + throw new ReqMissingSaleorApiUrlError( + "Missing saleorApiUrl in request. This middleware can be used after auth is attached", + ); + } + + logger.debug({ token: redactLogValue(ctx.token) }, "check if JWT token didn't expire"); + + const expired = checkTokenExpiration(ctx.token); + logger.debug({ expired }, "JWT token expiration check result"); + if (expired) { + throw new JwtTokenExpiredError("Token expired"); + } + + try { + logger.debug({ token: redactLogValue(ctx.token) }, "trying to verify JWT token from frontend"); + + await verifyJWT({ + appId: ctx.appId, + token: ctx.token, + saleorApiUrl: ctx.saleorApiUrl, + requiredPermissions: REQUIRED_SALEOR_PERMISSIONS, + }); + } catch (e) { + logger.debug("JWT verification failed, throwing"); + throw new JwtInvalidError("Invalid token", { cause: e }); + } + + return next({ + ctx: { + ...ctx, + saleorApiUrl: ctx.saleorApiUrl, + }, + }); +}); + +/** + * Construct common graphQL client and attach it to the context + * + * Can be used only if called from the frontend (react-query), + * otherwise jwks validation will fail (if createCaller used) + * + * TODO Rethink middleware composition to enable safe server-side router calls + */ +export const protectedClientProcedure = procedure + .use(attachAppToken) + .use(validateClientToken) + .use(async ({ ctx, next }) => { + const client = createClient(ctx.saleorApiUrl, async () => + Promise.resolve({ token: ctx.appToken }), + ); + + const pinoLoggerInstance = logger.child({ + saleorApiUrl: ctx.saleorApiUrl, + }); + + return next({ + ctx: { + apiClient: client, + appToken: ctx.appToken, + saleorApiUrl: ctx.saleorApiUrl, + logger: pinoLoggerInstance, + }, + }); + }); diff --git a/src/modules/trpc/trpc-app-router.ts b/src/modules/trpc/trpc-app-router.ts new file mode 100644 index 0000000..d748cdb --- /dev/null +++ b/src/modules/trpc/trpc-app-router.ts @@ -0,0 +1,9 @@ +import { paymentAppConfigurationRouter } from "../payment-app-configuration/payment-app-configuration.router"; +import { router } from "./trpc-server"; + +export const appRouter = router({ + paymentAppConfigurationRouter, + // CHANGEME: Add additioal routers here +}); + +export type AppRouter = typeof appRouter; diff --git a/src/modules/trpc/trpc-client.ts b/src/modules/trpc/trpc-client.ts new file mode 100644 index 0000000..2e282c9 --- /dev/null +++ b/src/modules/trpc/trpc-client.ts @@ -0,0 +1,87 @@ +import { TRPCClientError, httpBatchLink, loggerLink, type TRPCClientErrorLike } from "@trpc/client"; +import { createTRPCNext } from "@trpc/next"; + +import { SALEOR_API_URL_HEADER, SALEOR_AUTHORIZATION_BEARER_HEADER } from "@saleor/app-sdk/const"; +import { useErrorModalStore } from "../ui/organisms/GlobalErrorModal/state"; +import { type AppRouter } from "./trpc-app-router"; +import { getErrorHandler } from "./utils"; +import { logger } from "@/lib/logger"; +import { appBridgeInstance } from "@/app-bridge-instance"; +import { BaseTrpcError, JwtInvalidError, JwtTokenExpiredError } from "@/errors"; +import { isDevelopment } from "@/lib/isEnv"; + +const genericErrorHandler = (err: unknown) => { + getErrorHandler({ + actionId: "generic-error", + appBridge: appBridgeInstance, + })(err as TRPCClientErrorLike); +}; + +export const trpcClient = createTRPCNext({ + config() { + return { + abortOnUnmount: true, + links: [ + loggerLink({ + // enable client and server logs for development + // enable client logs for production + enabled: (opts) => + (isDevelopment() && typeof window !== "undefined") || + (opts.direction === "down" && opts.result instanceof Error), + // use logger for production, console.log for development + logger: !isDevelopment() ? (data) => logger.error(data, "TRPC client error") : undefined, + }), + loggerLink({ + logger: (data) => { + if (data.direction === "down" && data.result instanceof TRPCClientError) { + const serialized = data.result.data?.serialized; + const error = BaseTrpcError.parse(serialized); + + if (error instanceof JwtTokenExpiredError) { + useErrorModalStore.setState({ + isOpen: true, + message: "JWT Token expired. Please refresh the page.", + }); + } + + if (error instanceof JwtInvalidError) { + useErrorModalStore.setState({ + isOpen: true, + message: "JWT Token is invalid. Please refresh the page.", + }); + } + } + }, + }), + httpBatchLink({ + url: "/api/trpc", + headers() { + return { + /** + * Attach headers from app to client requests, so tRPC can add them to context + */ + [SALEOR_AUTHORIZATION_BEARER_HEADER]: appBridgeInstance?.getState().token, + [SALEOR_API_URL_HEADER]: appBridgeInstance?.getState().saleorApiUrl, + }; + }, + }), + ], + queryClientConfig: { + defaultOptions: { + mutations: { + onError: genericErrorHandler, + retry: false, + }, + queries: { + refetchOnMount: false, + refetchOnWindowFocus: false, + refetchOnReconnect: false, + onError: genericErrorHandler, + retry: false, + }, + }, + }, + }; + }, + ssr: false, +}); diff --git a/src/modules/trpc/trpc-context.ts b/src/modules/trpc/trpc-context.ts new file mode 100644 index 0000000..a8c9d04 --- /dev/null +++ b/src/modules/trpc/trpc-context.ts @@ -0,0 +1,17 @@ +import type * as trpcNext from "@trpc/server/adapters/next"; +import { SALEOR_AUTHORIZATION_BEARER_HEADER, SALEOR_API_URL_HEADER } from "@saleor/app-sdk/const"; +import { type inferAsyncReturnType } from "@trpc/server"; + +export const createTrpcContext = async ({ req }: trpcNext.CreateNextContextOptions) => { + const token = req.headers[SALEOR_AUTHORIZATION_BEARER_HEADER]; + const saleorApiUrl = req.headers[SALEOR_API_URL_HEADER]; + + return { + token: Array.isArray(token) ? token[0] : token, + saleorApiUrl: Array.isArray(saleorApiUrl) ? saleorApiUrl[0] : saleorApiUrl, + appId: undefined as undefined | string, + appUrl: req.headers["origin"], + }; +}; + +export type TrpcContext = inferAsyncReturnType; diff --git a/src/modules/trpc/trpc-server.ts b/src/modules/trpc/trpc-server.ts new file mode 100644 index 0000000..a279dd7 --- /dev/null +++ b/src/modules/trpc/trpc-server.ts @@ -0,0 +1,43 @@ +import { type TRPCError, initTRPC } from "@trpc/server"; +import { TRPC_ERROR_CODES_BY_KEY, type TRPC_ERROR_CODE_KEY } from "@trpc/server/rpc"; +import { type TrpcContext } from "./trpc-context"; +import { BaseTrpcError } from "@/errors"; +import { isProduction } from "@/lib/isEnv"; + +const getErrorCode = (error: TRPCError): TRPC_ERROR_CODE_KEY => { + const cause = error.cause; + if (cause && cause instanceof BaseTrpcError) { + return cause.trpcCode || "INTERNAL_SERVER_ERROR"; + } + return error.code; +}; + +const getSerialized = (error: TRPCError) => { + const cause = error.cause; + if (cause && cause instanceof BaseTrpcError) { + const serializedError = BaseTrpcError.serialize(cause); + if (isProduction()) { + serializedError.stack = "[HIDDEN]"; + } + return serializedError; + } +}; + +const t = initTRPC.context().create({ + errorFormatter({ shape, error }) { + return { + ...shape, + code: TRPC_ERROR_CODES_BY_KEY[getErrorCode(error)], + data: { + ...shape.data, + code: getErrorCode(error), + serialized: getSerialized(error), + stack: isProduction() ? null : error.stack, + }, + }; + }, +}); + +export const router = t.router; +export const procedure = t.procedure; +export const middleware = t.middleware; diff --git a/src/modules/trpc/utils.ts b/src/modules/trpc/utils.ts new file mode 100644 index 0000000..3e4c55d --- /dev/null +++ b/src/modules/trpc/utils.ts @@ -0,0 +1,82 @@ +import { type TRPCClientErrorLike } from "@trpc/client"; +import { + type DeepPartial, + type FieldPath, + type FieldValues, + type UseFormSetError, +} from "react-hook-form"; +import { type AppBridge } from "@saleor/app-sdk/app-bridge"; +import { type AppRouter } from "./trpc-app-router"; +import { BaseTrpcError, FieldError } from "@/errors"; + +interface HandlerInput { + message?: string; + title?: string; + actionId: string; + appBridge: AppBridge | undefined; +} + +const getParsedError = >(error: T) => { + if (error.data?.serialized) { + return BaseTrpcError.parse(error.data.serialized); + } + return null; +}; + +export const getErrorHandler = + (input: HandlerInput) => + >(error: T) => { + if (input.appBridge) { + const parsedError = getParsedError(error); + void input.appBridge.dispatch({ + type: "notification", + payload: { + title: input.title || "Request failed", + text: input.message || parsedError?.message || error.message, + apiMessage: error.shape ? JSON.stringify(error.shape ?? {}, null, 2) : undefined, + actionId: input.actionId, + status: "error", + }, + }); + } + }; + +interface FieldHandlerInput extends HandlerInput { + fieldName: FieldPath | `root.${string}` | "root"; + formFields: FieldPath[]; + setError: UseFormSetError; +} + +export const getFormFields = ( + defaultValues: Readonly> | undefined, +): FieldPath[] => { + if (!defaultValues) { + return []; + } + return Object.keys(defaultValues) as FieldPath[]; +}; + +const isMatchingField = ( + fieldName: string, + formFields: FieldPath[], +): fieldName is FieldPath => { + return formFields.some((field) => field === fieldName); +}; + +export const getFieldErrorHandler = + (input: FieldHandlerInput) => + >(error: T) => { + getErrorHandler(input)(error); + const parsedError = FieldError.parse(error.data?.serialized); + + if ( + parsedError instanceof FieldError && + isMatchingField(parsedError.fieldName, input.formFields) + ) { + input.setError(parsedError.fieldName, { message: parsedError.message }); + } else { + input.setError(input.fieldName, { + message: input.message, + }); + } + }; diff --git a/src/modules/ui/atoms/Chip/Chip.tsx b/src/modules/ui/atoms/Chip/Chip.tsx new file mode 100644 index 0000000..7b4f417 --- /dev/null +++ b/src/modules/ui/atoms/Chip/Chip.tsx @@ -0,0 +1,38 @@ +import { Chip, Text } from "@saleor/macaw-ui/next"; +import { type ReactNode } from "react"; + +export const ChipNeutral = ({ children }: { children: ReactNode }) => ( + + + {children} + + +); +export const ChipDanger = ({ children }: { children: ReactNode }) => ( + + + {children} + + +); +export const ChipStripeOrange = ({ children }: { children: ReactNode }) => ( + + + {children} + + +); +export const ChipSuccess = ({ children }: { children: ReactNode }) => ( + + + {children} + + +); +export const ChipInfo = ({ children }: { children: ReactNode }) => ( + + + {children} + + +); diff --git a/src/modules/ui/atoms/FileUploadInput/FileUploadInput.tsx b/src/modules/ui/atoms/FileUploadInput/FileUploadInput.tsx new file mode 100644 index 0000000..4ae2195 --- /dev/null +++ b/src/modules/ui/atoms/FileUploadInput/FileUploadInput.tsx @@ -0,0 +1,56 @@ +import { ArrowLeftIcon, Box, Button, Text } from "@saleor/macaw-ui/next"; +import { forwardRef } from "react"; +import { fileUploadInput } from "./fileUploadInput.css"; + +export type FileUploadInputProps = { + label: string; + disabled?: boolean; +} & JSX.IntrinsicElements["input"]; + +export const FileUploadInput = forwardRef( + ({ label, disabled = false, ...props }, ref) => { + return ( + + + + {label} + + + + + + ); + }, +); +FileUploadInput.displayName = "FileUploadInput"; diff --git a/src/modules/ui/atoms/FileUploadInput/fileUploadInput.css.ts b/src/modules/ui/atoms/FileUploadInput/fileUploadInput.css.ts new file mode 100644 index 0000000..7c68d49 --- /dev/null +++ b/src/modules/ui/atoms/FileUploadInput/fileUploadInput.css.ts @@ -0,0 +1,25 @@ +import { sprinkles } from "@saleor/macaw-ui/next"; +import { style } from "@vanilla-extract/css"; + +export const fileUploadInput = style([ + sprinkles({ + color: "textNeutralSubdued", + backgroundColor: { + default: "surfaceNeutralHighlight", + hover: "surfaceNeutralPlain", + }, + borderRadius: 3, + borderWidth: 1, + borderStyle: "solid", + borderColor: { + default: "transparent", + hover: "neutralHighlight", + }, + paddingX: 2, + cursor: "pointer", + flexGrow: "1", + display: "flex", + alignItems: "center", + }), + { height: 56 }, +]); diff --git a/src/modules/ui/atoms/RoundedActionBox/RoundedActionBox.tsx b/src/modules/ui/atoms/RoundedActionBox/RoundedActionBox.tsx new file mode 100644 index 0000000..84baf32 --- /dev/null +++ b/src/modules/ui/atoms/RoundedActionBox/RoundedActionBox.tsx @@ -0,0 +1,83 @@ +import { Box, type BoxProps } from "@saleor/macaw-ui/next"; +import { type ReactNode } from "react"; +import { roundedActionBoxRecipe } from "./roundedActionBox.css"; + +export const RoundedBox = ({ + children, + disabled = false, + error = false, + ...boxProps +}: BoxProps & { + disabled?: boolean; + error?: boolean; +}) => { + return ( + + {children} + + ); +}; + +export const RoundedBoxWithFooter = ({ + children, + footer, + error = false, + disabled = false, + ...boxProps +}: BoxProps & { + footer: ReactNode; + error?: boolean; + disabled?: boolean; +}) => { + return ( + + + {children} + + + {footer} + + + ); +}; + +export const RoundedActionBox = ({ + children, + disabled, +}: { + children: ReactNode; + disabled?: boolean; +}) => { + return ( + + + {children} + + + ); +}; diff --git a/src/modules/ui/atoms/RoundedActionBox/roundedActionBox.css.ts b/src/modules/ui/atoms/RoundedActionBox/roundedActionBox.css.ts new file mode 100644 index 0000000..19bb75b --- /dev/null +++ b/src/modules/ui/atoms/RoundedActionBox/roundedActionBox.css.ts @@ -0,0 +1,52 @@ +import { sprinkles } from "@saleor/macaw-ui/next"; +import { recipe } from "@vanilla-extract/recipes"; + +export const roundedActionBoxRecipe = recipe({ + variants: { + error: { + true: {}, + false: {}, + }, + disabled: { true: {}, false: {} }, + }, + compoundVariants: [ + { + variants: { + disabled: false, + error: false, + }, + style: sprinkles({ + borderColor: "neutralPlain", + }), + }, + { + variants: { + disabled: true, + error: false, + }, + style: sprinkles({ + borderColor: "neutralHighlight", + }), + }, + { + variants: { + disabled: false, + error: true, + }, + style: sprinkles({ + backgroundColor: "surfaceCriticalHighlight", + borderColor: "criticalDefault", + }), + }, + { + variants: { + disabled: true, + error: true, + }, + style: sprinkles({ + backgroundColor: "surfaceCriticalSubdued", + borderColor: "criticalHighlight", + }), + }, + ], +}); diff --git a/src/modules/ui/atoms/Skeleton/Skeleton.css.ts b/src/modules/ui/atoms/Skeleton/Skeleton.css.ts new file mode 100644 index 0000000..de8ca70 --- /dev/null +++ b/src/modules/ui/atoms/Skeleton/Skeleton.css.ts @@ -0,0 +1,11 @@ +import { keyframes, style } from "@vanilla-extract/css"; + +const pulse = keyframes({ + "50%": { + opacity: "0.5", + }, +}); + +export const skeleton = style({ + animation: `${pulse} 2s cubic-bezier(.4,0,.6,1) infinite`, +}); diff --git a/src/modules/ui/atoms/Skeleton/Skeleton.tsx b/src/modules/ui/atoms/Skeleton/Skeleton.tsx new file mode 100644 index 0000000..1247fe9 --- /dev/null +++ b/src/modules/ui/atoms/Skeleton/Skeleton.tsx @@ -0,0 +1,16 @@ +import { Box, type BoxProps } from "@saleor/macaw-ui/next"; +import classNames from "classnames"; +import { skeleton } from "./Skeleton.css"; + +export const Skeleton = ({ className, ...props }: BoxProps) => { + return ( + + ); +}; diff --git a/src/modules/ui/atoms/Table/Table.tsx b/src/modules/ui/atoms/Table/Table.tsx new file mode 100644 index 0000000..ac166f4 --- /dev/null +++ b/src/modules/ui/atoms/Table/Table.tsx @@ -0,0 +1,22 @@ +import classNames from "classnames"; +import { type ReactNode } from "react"; +import * as tableStyles from "./table.css"; + +export const Table = ({ children, className }: { children: ReactNode; className?: string }) => ( + {children}
+); +export const Thead = ({ children, className }: { children: ReactNode; className?: string }) => ( + {children} +); +export const Tr = ({ children, className }: { children: ReactNode; className?: string }) => ( + {children} +); +export const Th = ({ children, className }: { children: ReactNode; className?: string }) => ( + {children} +); +export const Tbody = ({ children, className }: { children: ReactNode; className?: string }) => ( + {children} +); +export const Td = ({ children, className }: { children?: ReactNode; className?: string }) => ( + {children} +); diff --git a/src/modules/ui/atoms/Table/table.css.ts b/src/modules/ui/atoms/Table/table.css.ts new file mode 100644 index 0000000..8b4f787 --- /dev/null +++ b/src/modules/ui/atoms/Table/table.css.ts @@ -0,0 +1,74 @@ +import { sprinkles } from "@saleor/macaw-ui/next"; +import { style } from "@vanilla-extract/css"; + +export const table = style( + [ + sprinkles({ width: "100%" }), + { + borderCollapse: "collapse", + }, + ], + "table", +); +export const thead = style([sprinkles({})], "thead"); +export const tbody = style([sprinkles({})], "tbody"); + +export const tr = style([sprinkles({})], "tr"); +// --mu-space-0: 0px; +// --mu-space-1: 1px; +// --mu-space-2: 2px; +// --mu-space-3: 4px; +// --mu-space-4: 6px; +// --mu-space-5: 8px; +// --mu-space-6: 12px; +// --mu-space-7: 16px; +// --mu-space-8: 20px; +// --mu-space-9: 24px; +// --mu-space-10: 30px; +// --mu-space-11: 32px; +// --mu-space-12: 38px; +// --mu-space-13: 40px; + +export const th = style( + [ + sprinkles({ + color: "textNeutralSubdued", + fontSize: "captionMedium", + fontWeight: "captionMedium", + paddingTop: 0.5, + paddingBottom: 3, + paddingLeft: 8, + }), + { + textAlign: "left", + selectors: { + "&:first-child": { + paddingLeft: 0, + }, + }, + }, + ], + "th", +); + +export const td = style( + [ + sprinkles({ + paddingTop: 2, + paddingBottom: 3, + borderTopWidth: 1, + borderTopStyle: "solid", + borderColor: "neutralPlain", + paddingLeft: 8, + }), + { + verticalAlign: "top", + selectors: { + "&:first-child": { + paddingLeft: 0, + }, + }, + }, + ], + "td", +); diff --git a/src/modules/ui/atoms/macaw-ui/FormFileUploadInput.tsx b/src/modules/ui/atoms/macaw-ui/FormFileUploadInput.tsx new file mode 100644 index 0000000..bff7366 --- /dev/null +++ b/src/modules/ui/atoms/macaw-ui/FormFileUploadInput.tsx @@ -0,0 +1,24 @@ +import { + type UseControllerProps, + type FieldPath, + type FieldValues, + useController, +} from "react-hook-form"; +import { + FileUploadInput as $FileUploadInput, + type FileUploadInputProps as $FileUploadInputProps, +} from "../FileUploadInput/FileUploadInput"; + +export type FormFileUploadInputProps< + TFieldValues extends FieldValues, + TName extends FieldPath = FieldPath, +> = UseControllerProps & $FileUploadInputProps; + +export function FormFileUploadInput< + TFieldValues extends FieldValues, + TName extends FieldPath = FieldPath, +>(props: FormFileUploadInputProps) { + const { field } = useController(props); + + return <$FileUploadInput {...props} {...field} />; +} diff --git a/src/modules/ui/atoms/macaw-ui/FormInput.tsx b/src/modules/ui/atoms/macaw-ui/FormInput.tsx new file mode 100644 index 0000000..d1788ac --- /dev/null +++ b/src/modules/ui/atoms/macaw-ui/FormInput.tsx @@ -0,0 +1,39 @@ +import { Input as $Input, type InputProps as $InputProps } from "@saleor/macaw-ui/next"; +import { + type UseControllerProps, + type FieldPath, + type FieldValues, + useController, +} from "react-hook-form"; + +export type FormInputProps< + TFieldValues extends FieldValues, + TName extends FieldPath = FieldPath, +> = UseControllerProps & $InputProps; + +export function FormInput< + TFieldValues extends FieldValues, + TName extends FieldPath = FieldPath, +>(props: FormInputProps) { + const { field, fieldState } = useController(props); + + return ( + <$Input + error={!!fieldState.error?.message} + {...props} + {...field} + helperText={fieldState.error?.message || props.helperText} + onChange={(e) => { + field.onChange(e); + props.onChange?.(e); + }} + onFocus={(e) => { + props.onFocus?.(e); + }} + onBlur={(e) => { + field.onBlur(); + props.onBlur?.(e); + }} + /> + ); +} diff --git a/src/modules/ui/atoms/macaw-ui/FormSelect.tsx b/src/modules/ui/atoms/macaw-ui/FormSelect.tsx new file mode 100644 index 0000000..d517789 --- /dev/null +++ b/src/modules/ui/atoms/macaw-ui/FormSelect.tsx @@ -0,0 +1,42 @@ +import { Select as $Select } from "@saleor/macaw-ui/next"; +import { type ComponentProps } from "react"; +import { + type UseControllerProps, + type FieldPath, + type FieldValues, + useController, + type PathValue, +} from "react-hook-form"; + +type $FormSelectProps = ComponentProps; + +export type FormSelectProps< + TFieldValues extends FieldValues, + TName extends FieldPath = FieldPath, +> = UseControllerProps & Omit<$FormSelectProps, "value">; + +export function FormSelect< + TFieldValues extends FieldValues, + TName extends FieldPath = FieldPath, +>(props: FormSelectProps) { + const { field, fieldState } = useController(props); + + return ( + <$Select + error={!!fieldState.error?.message} + {...props} + {...field} + onChange={(e) => { + field.onChange(e as PathValue); + props.onChange?.(e); + }} + onFocus={(e) => { + props.onFocus?.(e); + }} + onBlur={(e) => { + field.onBlur(); + props.onBlur?.(e); + }} + /> + ); +} diff --git a/src/modules/ui/atoms/macaw-ui/RadioGroup.tsx b/src/modules/ui/atoms/macaw-ui/RadioGroup.tsx new file mode 100644 index 0000000..7ce82ad --- /dev/null +++ b/src/modules/ui/atoms/macaw-ui/RadioGroup.tsx @@ -0,0 +1,42 @@ +import { RadioGroup as $RadioGroup } from "@saleor/macaw-ui/next"; +import { type ComponentProps } from "react"; +import { + type UseControllerProps, + type FieldPath, + type FieldValues, + useController, + type PathValue, +} from "react-hook-form"; + +type $RadioGroupProps = ComponentProps; + +export type FormRadioGroupProps< + TFieldValues extends FieldValues, + TName extends FieldPath = FieldPath, +> = UseControllerProps & $RadioGroupProps; + +export function FormRadioGroup< + TFieldValues extends FieldValues, + TName extends FieldPath = FieldPath, +>(props: FormRadioGroupProps) { + const { field, fieldState } = useController(props); + + return ( + <$RadioGroup + error={!!fieldState.error?.message} + {...props} + {...field} + onChange={(e) => { + field.onChange(e as PathValue); + props.onChange?.(e); + }} + onFocus={(e) => { + props.onFocus?.(e); + }} + onBlur={(e) => { + field.onBlur(); + props.onBlur?.(e); + }} + /> + ); +} diff --git a/src/modules/ui/atoms/modal.css.ts b/src/modules/ui/atoms/modal.css.ts new file mode 100644 index 0000000..801b6d6 --- /dev/null +++ b/src/modules/ui/atoms/modal.css.ts @@ -0,0 +1,35 @@ +import { sprinkles } from "@saleor/macaw-ui/next"; +import { style } from "@vanilla-extract/css"; + +export const modal = style( + [ + sprinkles({ + backgroundColor: "surfaceNeutralPlain", + borderRadius: 4, + position: "fixed", + padding: 5, + boxShadow: "modal", + }), + { + top: "50%", + left: "50%", + transform: "translate(-50%, -50%)", + maxWidth: "30rem", + }, + ], + "modal", +); + +export const modalOverlay = style( + [ + sprinkles({ + backgroundColor: "surfaceNeutralSubdued", + position: "fixed", + inset: 0, + }), + { + opacity: 0.6, + }, + ], + "modalOverlay", +); diff --git a/src/modules/ui/molecules/ConfigurationSummary/ConfigurationSummary.tsx b/src/modules/ui/molecules/ConfigurationSummary/ConfigurationSummary.tsx new file mode 100644 index 0000000..8c79b60 --- /dev/null +++ b/src/modules/ui/molecules/ConfigurationSummary/ConfigurationSummary.tsx @@ -0,0 +1,57 @@ +import { Box } from "@saleor/macaw-ui/next"; +import { ChipSuccess, ChipStripeOrange, ChipInfo } from "@/modules/ui/atoms/Chip/Chip"; +import { type PaymentAppUserVisibleConfigEntry } from "@/modules/payment-app-configuration/config-entry"; +import { getEnvironmentFromKey, getStripeWebhookDashboardLink } from "@/modules/stripe/stripe-api"; +import { appBridgeInstance } from "@/app-bridge-instance"; + +export const ConfigurationSummary = ({ config }: { config: PaymentAppUserVisibleConfigEntry }) => { + return ( + + + Environment + + + {getEnvironmentFromKey(config.publishableKey) === "live" ? ( + LIVE + ) : ( + TESTING + )} + + + Webhook ID + + + + void appBridgeInstance?.dispatch({ + type: "redirect", + payload: { + actionId: "getStripeWebhookDashboardLink", + to: getStripeWebhookDashboardLink( + config.webhookId, + getEnvironmentFromKey(config.publishableKey), + ), + newContext: true, + }, + }) + } + target="_blank" + > + {config.webhookId} + + + + ); +}; diff --git a/src/modules/ui/molecules/ConfigurationsTable/ChannelToConfigurationTable/ChannelToConfigurationTable.tsx b/src/modules/ui/molecules/ConfigurationsTable/ChannelToConfigurationTable/ChannelToConfigurationTable.tsx new file mode 100644 index 0000000..1af28c1 --- /dev/null +++ b/src/modules/ui/molecules/ConfigurationsTable/ChannelToConfigurationTable/ChannelToConfigurationTable.tsx @@ -0,0 +1,153 @@ +import { Combobox, Text } from "@saleor/macaw-ui/next"; +import classNames from "classnames"; +import { useAppBridge } from "@saleor/app-sdk/app-bridge"; +import * as tableStyles from "./channelToConfigurationTable.css"; +import { Table, Thead, Tr, Th, Tbody, Td } from "@/modules/ui/atoms/Table/Table"; +import { ChipStripeOrange, ChipNeutral, ChipSuccess } from "@/modules/ui/atoms/Chip/Chip"; +import { trpcClient } from "@/modules/trpc/trpc-client"; +import { type Channel } from "@/types"; +import { getErrorHandler } from "@/modules/trpc/utils"; +import { + type PaymentAppUserVisibleEntries, + type ChannelMapping, +} from "@/modules/payment-app-configuration/app-config"; +import { type PaymentAppConfigEntry } from "@/modules/payment-app-configuration/config-entry"; +import { getEnvironmentFromKey } from "@/modules/stripe/stripe-api"; + +const ChannelToConfigurationTableRow = ({ + channel, + configurations, + selectedConfigurationId, + disabled, +}: { + channel: Channel; + configurations: PaymentAppUserVisibleEntries; + selectedConfigurationId?: PaymentAppConfigEntry["configurationId"] | null; + disabled?: boolean; +}) => { + const { appBridge } = useAppBridge(); + const selectedConfiguration = configurations.find( + (config) => config.configurationId === selectedConfigurationId, + ); + + const context = trpcClient.useContext(); + const { mutate: saveMapping } = + trpcClient.paymentAppConfigurationRouter.mapping.update.useMutation({ + onSettled: () => { + return context.paymentAppConfigurationRouter.mapping.getAll.invalidate(); + }, + onSuccess: () => { + void appBridge?.dispatch({ + type: "notification", + payload: { + title: "Saved", + status: "success", + actionId: "ChannelToConfigurationTableRow", + }, + }); + }, + onError: (err) => { + getErrorHandler({ + appBridge, + actionId: "ChannelToConfigurationTableRow", + message: "Error while saving mappings", + title: "Mapping error", + })(err); + }, + }); + + return ( + + + + {channel.name} + + + + ({ + value: c.configurationId, + label: c.configurationName, + })), + ]} + onChange={(e: string | { value: string | null } | null) => { + const newMapping = { + channelId: channel.id, + configurationId: e === null || typeof e === "string" ? e : e.value, + }; + context.paymentAppConfigurationRouter.mapping.getAll.setData(undefined, (mappings) => { + return { + ...mappings, + [newMapping.channelId]: newMapping.configurationId, + }; + }); + saveMapping(newMapping); + }} + /> + + + {!selectedConfiguration ? ( + Disabled + ) : getEnvironmentFromKey(selectedConfiguration.publishableKey) === "live" ? ( + LIVE + ) : ( + TESTING + )} + + + ); +}; + +export const ChannelToConfigurationTable = ({ + channelMappings, + channels, + configurations, + disabled, +}: { + channelMappings: ChannelMapping; + channels: readonly Channel[]; + configurations: PaymentAppUserVisibleEntries; + disabled?: boolean; +}) => { + return ( + + + + + + + + + + {Object.entries(channelMappings).map(([channelId, configurationId]) => { + const channel = channels.find((c) => c.id === channelId); + if (!channel) { + return null; + } + + return ( + + ); + })} + +
Saleor ChannelConfiguration + Status +
+ ); +}; diff --git a/src/modules/ui/molecules/ConfigurationsTable/ChannelToConfigurationTable/channelToConfigurationTable.css.ts b/src/modules/ui/molecules/ConfigurationsTable/ChannelToConfigurationTable/channelToConfigurationTable.css.ts new file mode 100644 index 0000000..ac16ab4 --- /dev/null +++ b/src/modules/ui/molecules/ConfigurationsTable/ChannelToConfigurationTable/channelToConfigurationTable.css.ts @@ -0,0 +1,24 @@ +import { sprinkles } from "@saleor/macaw-ui/next"; +import { style } from "@vanilla-extract/css"; + +export const dropdownColumnTd = style( + [ + sprinkles({ + paddingLeft: 10, + }), + { + width: "50%", + }, + ], + "summaryColumnTd", +); +export const statusColumnTd = style( + [ + sprinkles({ + textAlign: "right", + paddingLeft: 10, + }), + ], + "actionsColumnTd", +); +export const td = style([{ verticalAlign: "middle" }], "td"); diff --git a/src/modules/ui/molecules/ConfigurationsTable/ConfigurationsTable.tsx b/src/modules/ui/molecules/ConfigurationsTable/ConfigurationsTable.tsx new file mode 100644 index 0000000..74290e5 --- /dev/null +++ b/src/modules/ui/molecules/ConfigurationsTable/ConfigurationsTable.tsx @@ -0,0 +1,62 @@ +import { Text, EditIcon } from "@saleor/macaw-ui/next"; +import Link from "next/link"; +import { ConfigurationSummary } from "../ConfigurationSummary/ConfigurationSummary"; +import * as tableStyles from "./configurationsTable.css"; +import { Tr, Td, Table, Tbody, Th, Thead } from "@/modules/ui/atoms/Table/Table"; +import { type PaymentAppUserVisibleConfigEntry } from "@/modules/payment-app-configuration/config-entry"; +import { type PaymentAppUserVisibleEntries } from "@/modules/payment-app-configuration/app-config"; + +const ConfigurationsTableRow = ({ item }: { item: PaymentAppUserVisibleConfigEntry }) => { + return ( + + + + {item.configurationName} + + + + + + + + + + Edit + + + + + ); +}; + +export const ConfigurationsTable = ({ + configurations, +}: { + configurations: PaymentAppUserVisibleEntries; +}) => { + return ( + + + + + + + + + + {configurations.map((item) => ( + + ))} + +
Configuration nameStripe Configuration + Actions +
+ ); +}; diff --git a/src/modules/ui/molecules/ConfigurationsTable/configurationsTable.css.ts b/src/modules/ui/molecules/ConfigurationsTable/configurationsTable.css.ts new file mode 100644 index 0000000..406f1a4 --- /dev/null +++ b/src/modules/ui/molecules/ConfigurationsTable/configurationsTable.css.ts @@ -0,0 +1,22 @@ +import { sprinkles } from "@saleor/macaw-ui/next"; +import { style } from "@vanilla-extract/css"; + +export const summaryColumnTd = style( + [ + sprinkles({ + paddingLeft: 8, + }), + { + width: "50%", + }, + ], + "summaryColumnTd", +); +export const actionsColumnTd = style( + [ + sprinkles({ + textAlign: "right", + }), + ], + "actionsColumnTd", +); diff --git a/src/modules/ui/molecules/ConfirmationButton/ConfirmationButton.tsx b/src/modules/ui/molecules/ConfirmationButton/ConfirmationButton.tsx new file mode 100644 index 0000000..ce1d34b --- /dev/null +++ b/src/modules/ui/molecules/ConfirmationButton/ConfirmationButton.tsx @@ -0,0 +1,118 @@ +import * as AlertDialog from "@radix-ui/react-alert-dialog"; +import { Box, Button, TrashBinIcon, type ButtonProps, Text, Input } from "@saleor/macaw-ui/next"; +import { type MouseEventHandler, useCallback, useState } from "react"; +import { modalOverlay, modal } from "../../atoms/modal.css"; + +type ConfirmationButtonProps = Omit & { + onClick: () => void | Promise; + configurationName: string; +}; + +type State = "idle" | "prompt" | "inProgress"; + +export const ConfirmationButton = ({ + onClick, + configurationName, + ...props +}: ConfirmationButtonProps) => { + const [state, setState] = useState("idle"); + const [inputConfiguratioName, setInputConfiguratioName] = useState(""); + + const handleDeleteClick = useCallback>((e) => { + e.preventDefault(); + setState("prompt"); + }, []); + + const handleConfirmationClick = useCallback>( + async (e) => { + e.preventDefault(); + setState("inProgress"); + await onClick(); + setState("idle"); + }, + [onClick], + ); + + const handleOpenChange = useCallback((open: boolean) => { + setState(open ? "prompt" : "idle"); + }, []); + + return ( + <> + + + + + +
+ + + + + ); +}; diff --git a/src/modules/ui/molecules/FullPageError/FullPageError.tsx b/src/modules/ui/molecules/FullPageError/FullPageError.tsx new file mode 100644 index 0000000..a686ee3 --- /dev/null +++ b/src/modules/ui/molecules/FullPageError/FullPageError.tsx @@ -0,0 +1,7 @@ +import { Box } from "@saleor/macaw-ui/next"; +import { type ReactNode } from "react"; + +export const FullPageError = ({ children }: { children: ReactNode }) => { + // @todo + return {children}; +}; diff --git a/src/modules/ui/no-ssr-wrapper.tsx b/src/modules/ui/no-ssr-wrapper.tsx new file mode 100644 index 0000000..1997b25 --- /dev/null +++ b/src/modules/ui/no-ssr-wrapper.tsx @@ -0,0 +1,19 @@ +import React, { type PropsWithChildren } from "react"; +import dynamic from "next/dynamic"; + +const Wrapper = (props: PropsWithChildren<{}>) => {props.children}; + +/** + * Saleor App can be rendered only as a Saleor Dashboard iframe. + * All content is rendered after Dashboard exchanges auth with the app. + * Hence, there is no reason to render app server side. + * + * This component forces app to work in SPA-mode. It simplifies browser-only code and reduces need + * of using dynamic() calls + * + * You can use this wrapper selectively for some pages or remove it completely. + * It doesn't affect Saleor communication, but may cause problems with some client-only code. + */ +export const NoSSRWrapper = dynamic(() => Promise.resolve(Wrapper), { + ssr: false, +}); diff --git a/src/modules/ui/organisms/AddStripeConfigurationForm/AddStripeConfigurationForm.tsx b/src/modules/ui/organisms/AddStripeConfigurationForm/AddStripeConfigurationForm.tsx new file mode 100644 index 0000000..b87bb4e --- /dev/null +++ b/src/modules/ui/organisms/AddStripeConfigurationForm/AddStripeConfigurationForm.tsx @@ -0,0 +1,65 @@ +import { Text } from "@saleor/macaw-ui/next"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { useAppBridge } from "@saleor/app-sdk/app-bridge"; +import { useForm, FormProvider } from "react-hook-form"; +import { AppLayoutRow } from "../../templates/AppLayout"; +import { FullPageError } from "../../molecules/FullPageError/FullPageError"; +import { AddStripeCredentialsForm } from "./AddStripeCredentialsForm"; +import { DeleteStripeConfigurationForm } from "./DeleteStripeConfigurationForm"; +import { checkTokenPermissions } from "@/modules/jwt/check-token-offline"; +import { REQUIRED_SALEOR_PERMISSIONS } from "@/modules/jwt/consts"; +import { trpcClient } from "@/modules/trpc/trpc-client"; +import { + type PaymentAppFormConfigEntry, + paymentAppFormConfigEntrySchema, +} from "@/modules/payment-app-configuration/config-entry"; + +export const StripeConfigurationForm = ({ + configurationId, +}: { + configurationId: string | undefined | null; +}) => { + const { appBridgeState } = useAppBridge(); + const { token } = appBridgeState ?? {}; + + const hasPermissions = true || checkTokenPermissions(token, REQUIRED_SALEOR_PERMISSIONS); + + const formMethods = useForm({ + resolver: zodResolver(paymentAppFormConfigEntrySchema), + defaultValues: { + configurationName: "", + publishableKey: "", + secretKey: "", + }, + }); + + const { data } = trpcClient.paymentAppConfigurationRouter.paymentConfig.get.useQuery( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- query is not enabled if configurationId is missing + { configurationId: configurationId! }, + { enabled: !!configurationId }, + ); + + if (!hasPermissions) { + return ( + + {"You don't have permissions to configure this app."} + + ); + } + + return ( + + + + + {data && configurationId && ( + + + + )} + + ); +}; diff --git a/src/modules/ui/organisms/AddStripeConfigurationForm/AddStripeCredentialsForm.tsx b/src/modules/ui/organisms/AddStripeConfigurationForm/AddStripeCredentialsForm.tsx new file mode 100644 index 0000000..75fd688 --- /dev/null +++ b/src/modules/ui/organisms/AddStripeConfigurationForm/AddStripeCredentialsForm.tsx @@ -0,0 +1,157 @@ +import { Button, Box } from "@saleor/macaw-ui/next"; +import { type SubmitHandler, useFormContext } from "react-hook-form"; +import { useCallback, useEffect } from "react"; +import { useAppBridge } from "@saleor/app-sdk/app-bridge"; +import { useRouter } from "next/router"; +import { RoundedBoxWithFooter } from "../../atoms/RoundedActionBox/RoundedActionBox"; +import { FormInput } from "@/modules/ui/atoms/macaw-ui/FormInput"; +import { trpcClient } from "@/modules/trpc/trpc-client"; +import { getErrorHandler, getFieldErrorHandler, getFormFields } from "@/modules/trpc/utils"; +import { invariant } from "@/lib/invariant"; +import { type PaymentAppFormConfigEntry } from "@/modules/payment-app-configuration/config-entry"; + +const actionId = "payment-form"; + +export const AddStripeCredentialsForm = ({ + configurationId, +}: { + configurationId?: string | undefined | null; +}) => { + const formMethods = useFormContext(); + const { appBridge } = useAppBridge(); + const router = useRouter(); + + const context = trpcClient.useContext(); + + const { + handleSubmit, + reset, + setError, + control, + formState: { defaultValues }, + } = formMethods; + const { data: stripeConfigurationData } = + trpcClient.paymentAppConfigurationRouter.paymentConfig.get.useQuery( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- query is not enabled if configurationId is missing + { configurationId: configurationId! }, + { + enabled: !!configurationId, + onError: (err) => { + getErrorHandler({ + appBridge, + actionId, + message: "Error while fetching initial form data", + title: "Form error", + })(err); + }, + }, + ); + + useEffect(() => { + if (stripeConfigurationData) { + reset(stripeConfigurationData); + } + }, [stripeConfigurationData, reset]); + + const getOnSuccess = useCallback( + (message: string) => { + return () => { + void appBridge?.dispatch({ + type: "notification", + payload: { + title: "Form saved", + text: message, + status: "success", + actionId, + }, + }); + void context.paymentAppConfigurationRouter.paymentConfig.invalidate(); + }; + }, + [appBridge, context.paymentAppConfigurationRouter.paymentConfig], + ); + + const onError = getFieldErrorHandler({ + appBridge, + setError, + actionId, + fieldName: "root", + formFields: getFormFields(defaultValues), + }); + + const { mutate: updateConfig } = + trpcClient.paymentAppConfigurationRouter.paymentConfig.update.useMutation({ + onSuccess: (data) => { + invariant(data.configurationId); + getOnSuccess("App configuration was updated successfully")(); + return router.replace(`/configurations/edit/${data.configurationId}`); + }, + onError, + }); + const { mutate: addNewConfig } = + trpcClient.paymentAppConfigurationRouter.paymentConfig.add.useMutation({ + onSuccess: async (data) => { + invariant(data.configurationId); + context.paymentAppConfigurationRouter.paymentConfig.get.setData( + { configurationId: data.configurationId }, + data, + ); + if (!configurationId) { + await router.replace(`/configurations/edit/${data.configurationId}`); + } + }, + onError, + }); + + const handleConfigSave: SubmitHandler = (data) => { + configurationId + ? updateConfig({ + configurationId, + entry: data, + }) + : addNewConfig(data); + }; + + return ( + + + + } + > + + + + + + + ); +}; diff --git a/src/modules/ui/organisms/AddStripeConfigurationForm/DeleteStripeConfigurationForm.tsx b/src/modules/ui/organisms/AddStripeConfigurationForm/DeleteStripeConfigurationForm.tsx new file mode 100644 index 0000000..9aa2eff --- /dev/null +++ b/src/modules/ui/organisms/AddStripeConfigurationForm/DeleteStripeConfigurationForm.tsx @@ -0,0 +1,82 @@ +import { Box, Text } from "@saleor/macaw-ui/next"; +import { useRouter } from "next/router"; +import { useAppBridge } from "@saleor/app-sdk/app-bridge"; +import { RoundedBoxWithFooter } from "../../atoms/RoundedActionBox/RoundedActionBox"; +import { ConfirmationButton } from "../../molecules/ConfirmationButton/ConfirmationButton"; +import { trpcClient } from "@/modules/trpc/trpc-client"; +import { getErrorHandler } from "@/modules/trpc/utils"; + +export const DeleteStripeConfigurationForm = ({ + configurationId, + configurationName, +}: { + configurationId: string | null | undefined; + configurationName: string; +}) => { + const context = trpcClient.useContext(); + const router = useRouter(); + const { appBridge } = useAppBridge(); + + const { mutateAsync: deleteConfig } = + trpcClient.paymentAppConfigurationRouter.paymentConfig.delete.useMutation({ + onError: (err) => { + getErrorHandler({ + appBridge, + actionId: "DeleteStripeConfigurationForm", + message: "Error while deleting configuration", + title: "Error", + })(err); + }, + }); + + const handleConfigDelete = async () => { + if (!configurationId) { + return; + } + await deleteConfig({ configurationId }); + await router.replace("/configurations/list"); + await context.paymentAppConfigurationRouter.invalidate(); + }; + + return ( + + + Delete configuration + + + } + > +
+ + + Remove configuration + + + + You can remove the configuration{" "} + + {configurationName} + + + + This operation will permanently remove all settings related to this configuration and + disable Stripe in all assigned channels. + + + This operation cannot be undone.{" "} + + + +
+
+ ); +}; diff --git a/src/modules/ui/organisms/ChannelToConfigurationList/ChannelToConfigurationList.tsx b/src/modules/ui/organisms/ChannelToConfigurationList/ChannelToConfigurationList.tsx new file mode 100644 index 0000000..f9eb4df --- /dev/null +++ b/src/modules/ui/organisms/ChannelToConfigurationList/ChannelToConfigurationList.tsx @@ -0,0 +1,89 @@ +import { Box, Button, Text } from "@saleor/macaw-ui/next"; +import { useAppBridge } from "@saleor/app-sdk/app-bridge"; +import { RoundedActionBox, RoundedBox } from "../../atoms/RoundedActionBox/RoundedActionBox"; +import { ChannelToConfigurationTable } from "../../molecules/ConfigurationsTable/ChannelToConfigurationTable/ChannelToConfigurationTable"; +import { type Channel } from "@/types"; +import { + type PaymentAppUserVisibleEntries, + type ChannelMapping, +} from "@/modules/payment-app-configuration/app-config"; + +export const ChannelToConfigurationList = ({ + channelMappings, + configurations, + channels, + disabled, +}: { + channelMappings: ChannelMapping; + configurations: PaymentAppUserVisibleEntries; + channels: readonly Channel[]; + disabled?: boolean; +}) => { + return Object.keys(channelMappings).length > 0 ? ( + + ) : ( + + ); +}; + +const NotEmpty = ({ + channelMappings, + configurations, + channels, + disabled, +}: { + channelMappings: ChannelMapping; + configurations: PaymentAppUserVisibleEntries; + channels: readonly Channel[]; + disabled?: boolean; +}) => { + return ( + + + + + + ); +}; + +const Empty = ({ disabled }: { disabled?: boolean }) => { + const { appBridge } = useAppBridge(); + + return ( + + + + It appears you have 0 channels. + + + You need to add at least one channel to proceed. + + + + + ); +}; diff --git a/src/modules/ui/organisms/GlobalErrorModal/modal.tsx b/src/modules/ui/organisms/GlobalErrorModal/modal.tsx new file mode 100644 index 0000000..8faf421 --- /dev/null +++ b/src/modules/ui/organisms/GlobalErrorModal/modal.tsx @@ -0,0 +1,42 @@ +import * as AlertDialog from "@radix-ui/react-alert-dialog"; +import { Box, Button, Text } from "@saleor/macaw-ui/next"; +import { modalOverlay, modal } from "../../atoms/modal.css"; +import { + useErrorModalActions, + useErrorModalMessage, + useErrorModalOpen, + useErrorModalTitle, +} from "./state"; + +export const ErrorModal = () => { + const isOpen = useErrorModalOpen(); + const title = useErrorModalTitle(); + const message = useErrorModalMessage(); + const { closeModal } = useErrorModalActions(); + + return ( + + + + + {title && ( + + Confirm delete + + )} + + {message} + + + + + + + + + + + ); +}; diff --git a/src/modules/ui/organisms/GlobalErrorModal/state.ts b/src/modules/ui/organisms/GlobalErrorModal/state.ts new file mode 100644 index 0000000..a596393 --- /dev/null +++ b/src/modules/ui/organisms/GlobalErrorModal/state.ts @@ -0,0 +1,29 @@ +import { create } from "zustand"; + +export interface ErrorModalState { + isOpen: boolean; + title?: string; + message: string | null; + + actions: { + openModal: ({ message, title }: { message: string; title?: string }) => void; + closeModal: () => void; + }; +} + +export const useErrorModalStore = create((set) => ({ + isOpen: false, + message: null, + title: undefined, + + actions: { + openModal: ({ message, title }: { message: string; title?: string }) => + set(() => ({ isOpen: true, message, title })), + closeModal: () => set(() => ({ isOpen: false, message: null, title: undefined })), + }, +})); + +export const useErrorModalOpen = () => useErrorModalStore((state) => state.isOpen); +export const useErrorModalMessage = () => useErrorModalStore((state) => state.message); +export const useErrorModalTitle = () => useErrorModalStore((state) => state.title); +export const useErrorModalActions = () => useErrorModalStore((state) => state.actions); diff --git a/src/modules/ui/organisms/StripeConfigurationList/StripeConfigurationList.tsx b/src/modules/ui/organisms/StripeConfigurationList/StripeConfigurationList.tsx new file mode 100644 index 0000000..97bb8bf --- /dev/null +++ b/src/modules/ui/organisms/StripeConfigurationList/StripeConfigurationList.tsx @@ -0,0 +1,52 @@ +import { Box, Button, Text } from "@saleor/macaw-ui/next"; +import Link from "next/link"; +import { + RoundedActionBox, + RoundedBoxWithFooter, +} from "@/modules/ui/atoms/RoundedActionBox/RoundedActionBox"; +import { ConfigurationsTable } from "@/modules/ui/molecules/ConfigurationsTable/ConfigurationsTable"; +import { type PaymentAppUserVisibleEntries } from "@/modules/payment-app-configuration/app-config"; + +export const StripeConfigurationsList = ({ + configurations, +}: { + configurations: PaymentAppUserVisibleEntries; +}) => { + return configurations.length > 0 ? : ; +}; + +const NotEmpty = ({ configurations }: { configurations: PaymentAppUserVisibleEntries }) => { + return ( + + + + } + > + + + ); +}; + +const Empty = () => { + return ( + + + + No Stripe configurations added. + + + This means payments are not processed by Stripe. + + + + + + + ); +}; diff --git a/src/modules/ui/templates/AppLayout.tsx b/src/modules/ui/templates/AppLayout.tsx new file mode 100644 index 0000000..09a0bef --- /dev/null +++ b/src/modules/ui/templates/AppLayout.tsx @@ -0,0 +1,92 @@ +import { Box, Text } from "@saleor/macaw-ui/next"; +import { type ReactNode, isValidElement } from "react"; +import Head from "next/head"; +import { appLayoutBoxRecipe, appLayoutTextRecipe } from "./appLayout.css"; + +export const AppLayout = ({ + title, + description, + children, +}: { + title: string; + description?: ReactNode; + children: ReactNode; +}) => { + return ( + <> + + Saleor App Payment {title} + + + + + + {title} + + {isValidElement(description) ? ( + description + ) : ( + + {description} + + )} + + {children} + + + ); +}; + +export const AppLayoutRow = ({ + title, + description, + children, + disabled = false, + error = false, +}: { + title: string; + description?: ReactNode; + disabled?: boolean; + error?: boolean; + children: ReactNode; +}) => { + return ( + + + + {title} + + {isValidElement(description) ? ( + + {description} + + ) : ( + + {description} + + )} + + + {children} + + + ); +}; diff --git a/src/modules/ui/templates/appLayout.css.ts b/src/modules/ui/templates/appLayout.css.ts new file mode 100644 index 0000000..eae9de9 --- /dev/null +++ b/src/modules/ui/templates/appLayout.css.ts @@ -0,0 +1,66 @@ +import { sprinkles } from "@saleor/macaw-ui/next"; +import { recipe } from "@vanilla-extract/recipes"; + +export const appLayoutBoxRecipe = recipe({ + base: { + gridTemplateColumns: "5fr 9fr", + columnGap: "7%", + }, + variants: { + disabled: { + true: { + opacity: 0.6, + cursor: "not-allowed", + }, + false: { + opacity: 1, + }, + }, + error: { true: {}, false: {} }, + }, +}); + +export const appLayoutTextRecipe = recipe({ + variants: { + disabled: { true: {}, false: {} }, + error: { true: {}, false: {} }, + }, + compoundVariants: [ + { + variants: { + disabled: false, + error: false, + }, + style: sprinkles({ + color: "textNeutralDefault", + }), + }, + { + variants: { + disabled: true, + error: false, + }, + style: sprinkles({ + color: "textNeutralDisabled", + }), + }, + { + variants: { + disabled: false, + error: true, + }, + style: sprinkles({ + color: "textCriticalSubdued", + }), + }, + { + variants: { + disabled: true, + error: true, + }, + style: sprinkles({ + color: "textCriticalDisabled", + }), + }, + ], +}); diff --git a/src/modules/ui/theme-synchronizer.test.tsx b/src/modules/ui/theme-synchronizer.test.tsx new file mode 100644 index 0000000..39e6d23 --- /dev/null +++ b/src/modules/ui/theme-synchronizer.test.tsx @@ -0,0 +1,50 @@ +import { describe, expect, it, vi } from "vitest"; +import { type AppBridgeState } from "@saleor/app-sdk/app-bridge"; +import { render, waitFor } from "@testing-library/react"; +import { type ThemeTokensValues, type DefaultTheme } from "@saleor/macaw-ui/next"; +import { ThemeSynchronizer } from "./theme-synchronizer"; + +const appBridgeState: AppBridgeState = { + ready: true, + token: "token", + domain: "some-domain.saleor.cloud", + theme: "dark", + path: "/", + locale: "en", + id: "app-id", + saleorApiUrl: "https://some-domain.saleor.cloud/graphql/", +}; + +const mockThemeChange = vi.fn(); + +vi.mock("@saleor/app-sdk/app-bridge", () => { + return { + useAppBridge() { + return { + appBridgeState: appBridgeState, + }; + }, + }; +}); + +vi.mock("@saleor/macaw-ui/next", () => { + return { + useTheme() { + return { + setTheme: mockThemeChange, + theme: "defaultLight", + themeValues: {} as ThemeTokensValues, + } satisfies ReturnType; + }, + } satisfies Pick; +}); + +describe("ThemeSynchronizer", () => { + it("Updates MacawUI theme when AppBridgeState theme changes", () => { + render(); + + return waitFor(() => { + expect(mockThemeChange).toHaveBeenCalledWith<[DefaultTheme]>("defaultDark"); + }); + }); +}); diff --git a/src/modules/ui/theme-synchronizer.tsx b/src/modules/ui/theme-synchronizer.tsx new file mode 100644 index 0000000..9f0f138 --- /dev/null +++ b/src/modules/ui/theme-synchronizer.tsx @@ -0,0 +1,33 @@ +import { type ThemeType, useAppBridge } from "@saleor/app-sdk/app-bridge"; +import { type DefaultTheme, useTheme } from "@saleor/macaw-ui/next"; +import { memo, useEffect } from "react"; + +const mapAppBridgeToMacawTheme: Record = { + light: "defaultLight", + dark: "defaultDark", +}; + +/** + * Macaw-ui stores its theme mode in memory and local storage. To synchronize App with Dashboard, + * Macaw must be informed about this change from AppBridge. + * + * If you are not using Macaw, you can remove this. + */ +export const ThemeSynchronizer = memo(function ThemeSynchronizer() { + const { appBridgeState } = useAppBridge(); + const { setTheme, theme } = useTheme(); + + useEffect(() => { + if (!setTheme || !appBridgeState?.theme) { + return; + } + + const mappedAppBridgeTheme = mapAppBridgeToMacawTheme[appBridgeState?.theme]; + + if (theme !== mappedAppBridgeTheme) { + setTheme(mappedAppBridgeTheme); + } + }, [appBridgeState?.theme, setTheme, theme]); + + return null; +}); diff --git a/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/American-Express-pm_card_amex_1702901941/should-cancel-pre-authorized-card_3641244857/recording.har b/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/American-Express-pm_card_amex_1702901941/should-cancel-pre-authorized-card_3641244857/recording.har new file mode 100644 index 0000000..a1e3d48 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/American-Express-pm_card_amex_1702901941/should-cancel-pre-authorized-card_3641244857/recording.har @@ -0,0 +1,470 @@ +{ + "log": { + "_recordingName": "TransactionCancelationRequestedWebhookHandler/'American Express' 'pm_card_amex'/should cancel pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-54ebe21d-d3f9-40ef-b389-8fee72ba37fe" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477365, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKjEosEcNBN5m0IMpKdZI", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:45 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-54ebe21d-d3f9-40ef-b389-8fee72ba37fe" + }, + { + "name": "original-request", + "value": "req_wQMsaRdx3ch0Wm" + }, + { + "name": "request-id", + "value": "req_wQMsaRdx3ch0Wm" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:34.853Z", + "time": 10970, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 10970 + } + }, + { + "_id": "09961e1cd5abe26724f68f52a532d4a9", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 27, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "27" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b7b7ace3-e56c-4d0e-96f2-a4658918ded1" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_amex" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtKjEosEcNBN5m0IMpKdZI/confirm" + }, + "response": { + "bodySize": 2642, + "content": { + "mimeType": "application/json", + "size": 2642, + "text": { + "error": { + "code": "payment_intent_unexpected_state", + "doc_url": "https://stripe.com/docs/error-codes/payment-intent-unexpected-state", + "message": "This PaymentIntent's payment_method could not be updated because it has a status of canceled. You may only update the payment_method of a PaymentIntent with one of the following statuses: requires_payment_method, requires_confirmation, requires_action.", + "param": "payment_method", + "payment_intent": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": 1702477367, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_3OMtKjEosEcNBN5m0IMpKdZI_secret_yQKx08JxltBGb5fiLraqa2tXA", + "confirmation_method": "automatic", + "created": 1702477365, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKjEosEcNBN5m0IMpKdZI", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtKjEosEcNBN5m0JHUOrqY", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtKkEosEcNBN5mSqNhoa5a", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "canceled", + "transfer_data": null, + "transfer_group": null + }, + "request_log_url": "https://dashboard.stripe.com/test/logs/req_opm0NuqwQYrWqW?t=1702477938", + "type": "invalid_request_error" + } + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "2642" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:18 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b7b7ace3-e56c-4d0e-96f2-a4658918ded1" + }, + { + "name": "original-request", + "value": "req_opm0NuqwQYrWqW" + }, + { + "name": "request-id", + "value": "req_opm0NuqwQYrWqW" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 400, + "statusText": "Bad Request" + }, + "startedDateTime": "2023-12-13T14:32:18.339Z", + "time": 502, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 502 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Diners-Club-pm_card_diners_3136405054/should-cancel-pre-authorized-card_3641244857/recording.har b/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Diners-Club-pm_card_diners_3136405054/should-cancel-pre-authorized-card_3641244857/recording.har new file mode 100644 index 0000000..25c4d03 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Diners-Club-pm_card_diners_3136405054/should-cancel-pre-authorized-card_3641244857/recording.har @@ -0,0 +1,678 @@ +{ + "log": { + "_recordingName": "TransactionCancelationRequestedWebhookHandler/'Diners Club' 'pm_card_diners'/should cancel pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-93964a81-ef10-40a0-8f01-f68fe808a910" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477368, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKmEosEcNBN5m1mmpnxTV", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:49 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-93964a81-ef10-40a0-8f01-f68fe808a910" + }, + { + "name": "original-request", + "value": "req_jKnKkwSyVeFiLk" + }, + { + "name": "request-id", + "value": "req_jKnKkwSyVeFiLk" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:48.501Z", + "time": 460, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 460 + } + }, + { + "_id": "132eca35f40d77389f2749d4d0fed7dd", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 29, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "29" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-8b87b28d-8707-4364-8ce7-5af147a6e72f" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_diners" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtKmEosEcNBN5m1mmpnxTV/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477368, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKmEosEcNBN5m1mmpnxTV", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtKmEosEcNBN5m1yHmroRF", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtKnEosEcNBN5m4w8rFMPJ", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:50 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-8b87b28d-8707-4364-8ce7-5af147a6e72f" + }, + { + "name": "original-request", + "value": "req_aWoz3EifwjIon3" + }, + { + "name": "request-id", + "value": "req_aWoz3EifwjIon3" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:48.963Z", + "time": 1103, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1103 + } + }, + { + "_id": "bc9872fe36bbd10b29aad31e6b458124", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 0, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "0" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-32523be4-2ede-4ca7-9a79-edcc08f30ddd" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 847, + "httpVersion": "HTTP/1.1", + "method": "POST", + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtKmEosEcNBN5m1mmpnxTV/cancel" + }, + "response": { + "bodySize": 1736, + "content": { + "mimeType": "application/json", + "size": 1736, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": 1702477370, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477368, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKmEosEcNBN5m1mmpnxTV", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtKmEosEcNBN5m1yHmroRF", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtKnEosEcNBN5m4w8rFMPJ", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "canceled", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1736" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcancel; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:50 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-32523be4-2ede-4ca7-9a79-edcc08f30ddd" + }, + { + "name": "original-request", + "value": "req_XP88lcemezJh5t" + }, + { + "name": "request-id", + "value": "req_XP88lcemezJh5t" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1116, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:50.069Z", + "time": 665, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 665 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Discover-pm_card_discover_3985489676/should-cancel-pre-authorized-card_3641244857/recording.har b/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Discover-pm_card_discover_3985489676/should-cancel-pre-authorized-card_3641244857/recording.har new file mode 100644 index 0000000..8896f26 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Discover-pm_card_discover_3985489676/should-cancel-pre-authorized-card_3641244857/recording.har @@ -0,0 +1,896 @@ +{ + "log": { + "_recordingName": "TransactionCancelationRequestedWebhookHandler/'Discover' 'pm_card_discover'/should cancel pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-35ed3a71-22bd-48ad-bd49-05594aff0737" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477366, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKkEosEcNBN5m08NksTmO", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:46 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-35ed3a71-22bd-48ad-bd49-05594aff0737" + }, + { + "name": "original-request", + "value": "req_hvPjj2AfbcgagD" + }, + { + "name": "request-id", + "value": "req_hvPjj2AfbcgagD" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:45.832Z", + "time": 877, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 877 + } + }, + { + "_id": "8c75c844b74ed6c3188416158e88dc8f", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 31, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "31" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-1f0221dc-e61a-44b0-ab87-ea8a4c786a84" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_discover" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtKkEosEcNBN5m08NksTmO/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477366, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKkEosEcNBN5m08NksTmO", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtKkEosEcNBN5m0NHZf7BJ", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtKlEosEcNBN5mPXstSBX8", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:47 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-1f0221dc-e61a-44b0-ab87-ea8a4c786a84" + }, + { + "name": "original-request", + "value": "req_eRZpZNvZqJN9L0" + }, + { + "name": "request-id", + "value": "req_eRZpZNvZqJN9L0" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:46.711Z", + "time": 1107, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1107 + } + }, + { + "_id": "84dbf2cb146ac5b4138902928d22b488", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 0, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "0" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-bb510413-59a0-45e4-98d0-d7ac00a02b53" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 847, + "httpVersion": "HTTP/1.1", + "method": "POST", + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtKjEosEcNBN5m0IMpKdZI/cancel" + }, + "response": { + "bodySize": 1736, + "content": { + "mimeType": "application/json", + "size": 1736, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": 1702477367, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477365, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKjEosEcNBN5m0IMpKdZI", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtKjEosEcNBN5m0JHUOrqY", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtKkEosEcNBN5mSqNhoa5a", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "canceled", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1736" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcancel; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:48 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-bb510413-59a0-45e4-98d0-d7ac00a02b53" + }, + { + "name": "original-request", + "value": "req_ds3W276l8ATpQF" + }, + { + "name": "request-id", + "value": "req_ds3W276l8ATpQF" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1116, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:47.213Z", + "time": 706, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 706 + } + }, + { + "_id": "4b15b4e92e937ac7ac8458b03131eb41", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 0, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "0" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-f52c36d2-3d7b-4483-b205-8439d1d4cfb2" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 847, + "httpVersion": "HTTP/1.1", + "method": "POST", + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtKkEosEcNBN5m08NksTmO/cancel" + }, + "response": { + "bodySize": 1736, + "content": { + "mimeType": "application/json", + "size": 1736, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": 1702477368, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477366, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKkEosEcNBN5m08NksTmO", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtKkEosEcNBN5m0NHZf7BJ", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtKlEosEcNBN5mPXstSBX8", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "canceled", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1736" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcancel; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:48 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-f52c36d2-3d7b-4483-b205-8439d1d4cfb2" + }, + { + "name": "original-request", + "value": "req_IRm4JG2mvONwvn" + }, + { + "name": "request-id", + "value": "req_IRm4JG2mvONwvn" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1116, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:47.821Z", + "time": 673, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 673 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-cancel-pre-authorized-card_3641244857/recording.har b/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-cancel-pre-authorized-card_3641244857/recording.har new file mode 100644 index 0000000..dd7e494 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-cancel-pre-authorized-card_3641244857/recording.har @@ -0,0 +1,678 @@ +{ + "log": { + "_recordingName": "TransactionCancelationRequestedWebhookHandler/'Mastercard (debit)' 'pm_card_mastercard_debit'/should cancel pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b1d1912b-1d36-4d72-a9f8-bf94eadf6db0" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477934, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTuEosEcNBN5m0R6NgfQL", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:14 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b1d1912b-1d36-4d72-a9f8-bf94eadf6db0" + }, + { + "name": "original-request", + "value": "req_32vul3I68NVzWe" + }, + { + "name": "request-id", + "value": "req_32vul3I68NVzWe" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:13.625Z", + "time": 508, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 508 + } + }, + { + "_id": "283610a10f2a990fabc6dce8f0bd6ba2", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 39, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "39" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b9c216c3-7122-4cad-afac-425d8dbe14ec" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_mastercard_debit" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtTuEosEcNBN5m0R6NgfQL/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477934, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTuEosEcNBN5m0R6NgfQL", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtTuEosEcNBN5m0jKs570F", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtTuEosEcNBN5mmko3ToGt", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:15 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b9c216c3-7122-4cad-afac-425d8dbe14ec" + }, + { + "name": "original-request", + "value": "req_22VFjJ6X1sX6R8" + }, + { + "name": "request-id", + "value": "req_22VFjJ6X1sX6R8" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:14.135Z", + "time": 1139, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1139 + } + }, + { + "_id": "c0a977b51c9b970b10a572d94fccc743", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 0, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "0" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-2868a258-4e2e-48d5-9ade-10c8b49bc471" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 847, + "httpVersion": "HTTP/1.1", + "method": "POST", + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtTuEosEcNBN5m0R6NgfQL/cancel" + }, + "response": { + "bodySize": 1736, + "content": { + "mimeType": "application/json", + "size": 1736, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": 1702477935, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477934, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTuEosEcNBN5m0R6NgfQL", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtTuEosEcNBN5m0jKs570F", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtTuEosEcNBN5mmko3ToGt", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "canceled", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1736" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcancel; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:16 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-2868a258-4e2e-48d5-9ade-10c8b49bc471" + }, + { + "name": "original-request", + "value": "req_lpoQ0xy1S1D66y" + }, + { + "name": "request-id", + "value": "req_lpoQ0xy1S1D66y" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1116, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:15.276Z", + "time": 756, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 756 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Mastercard-pm_card_mastercard_3189003338/should-cancel-pre-authorized-card_3641244857/recording.har b/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Mastercard-pm_card_mastercard_3189003338/should-cancel-pre-authorized-card_3641244857/recording.har new file mode 100644 index 0000000..5efb10a --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Mastercard-pm_card_mastercard_3189003338/should-cancel-pre-authorized-card_3641244857/recording.har @@ -0,0 +1,678 @@ +{ + "log": { + "_recordingName": "TransactionCancelationRequestedWebhookHandler/'Mastercard' 'pm_card_mastercard'/should cancel pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-875ccb6a-9e7b-4ba7-8a07-b62126945ca9" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477931, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTrEosEcNBN5m0cuEONHL", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:11 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-875ccb6a-9e7b-4ba7-8a07-b62126945ca9" + }, + { + "name": "original-request", + "value": "req_TaTuPtsZfZUkdP" + }, + { + "name": "request-id", + "value": "req_TaTuPtsZfZUkdP" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:11.047Z", + "time": 447, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 447 + } + }, + { + "_id": "2622da507e44620a52336a459a02541a", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 33, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "33" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-7724e595-bafe-4ac7-adbf-cf69ca83a21a" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_mastercard" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtTrEosEcNBN5m0cuEONHL/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477931, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTrEosEcNBN5m0cuEONHL", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtTrEosEcNBN5m0XmlRgsS", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtTrEosEcNBN5mpAEgoWoN", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:12 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-7724e595-bafe-4ac7-adbf-cf69ca83a21a" + }, + { + "name": "original-request", + "value": "req_HNNBtNuGyi9iHX" + }, + { + "name": "request-id", + "value": "req_HNNBtNuGyi9iHX" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:11.496Z", + "time": 1272, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1272 + } + }, + { + "_id": "568819e3ec4bede1297d00e127685a20", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 0, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "0" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-c5c9cb06-eb13-489a-9dc0-65b032f1d03a" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 847, + "httpVersion": "HTTP/1.1", + "method": "POST", + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtTrEosEcNBN5m0cuEONHL/cancel" + }, + "response": { + "bodySize": 1736, + "content": { + "mimeType": "application/json", + "size": 1736, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": 1702477933, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477931, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTrEosEcNBN5m0cuEONHL", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtTrEosEcNBN5m0XmlRgsS", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtTrEosEcNBN5mpAEgoWoN", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "canceled", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1736" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcancel; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:13 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-c5c9cb06-eb13-489a-9dc0-65b032f1d03a" + }, + { + "name": "original-request", + "value": "req_sX9aIvgUphoo2H" + }, + { + "name": "request-id", + "value": "req_sX9aIvgUphoo2H" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1116, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:12.772Z", + "time": 846, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 846 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-cancel-pre-authorized-card_3641244857/recording.har b/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-cancel-pre-authorized-card_3641244857/recording.har new file mode 100644 index 0000000..e3f93f3 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-cancel-pre-authorized-card_3641244857/recording.har @@ -0,0 +1,678 @@ +{ + "log": { + "_recordingName": "TransactionCancelationRequestedWebhookHandler/'Mastercard (prepaid)' 'pm_card_mastercard_prepaid'/should cancel pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-116e1794-d3b2-45d0-b072-ac162f82654b" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477936, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTwEosEcNBN5m1A2tGn1j", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:16 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-116e1794-d3b2-45d0-b072-ac162f82654b" + }, + { + "name": "original-request", + "value": "req_XYun4Lm6hbKu0e" + }, + { + "name": "request-id", + "value": "req_XYun4Lm6hbKu0e" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:16.037Z", + "time": 425, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 425 + } + }, + { + "_id": "4bebfa82ae49286dc536eff55fda0d6f", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 41, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "41" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-25be77f1-f5a3-4e89-88b3-cb8a8afbc4f3" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_mastercard_prepaid" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtTwEosEcNBN5m1A2tGn1j/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477936, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTwEosEcNBN5m1A2tGn1j", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtTwEosEcNBN5m1KS335Cj", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtTwEosEcNBN5mFxJAm2xQ", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:17 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-25be77f1-f5a3-4e89-88b3-cb8a8afbc4f3" + }, + { + "name": "original-request", + "value": "req_1lnHQBgCPNCpkn" + }, + { + "name": "request-id", + "value": "req_1lnHQBgCPNCpkn" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:16.465Z", + "time": 1135, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1135 + } + }, + { + "_id": "bd507dae7bc8db62c3913148eb1f61b2", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 0, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "0" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-16fed5ea-8249-40a6-bb17-bba164a9e494" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 847, + "httpVersion": "HTTP/1.1", + "method": "POST", + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtTwEosEcNBN5m1A2tGn1j/cancel" + }, + "response": { + "bodySize": 1736, + "content": { + "mimeType": "application/json", + "size": 1736, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": 1702477938, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477936, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTwEosEcNBN5m1A2tGn1j", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtTwEosEcNBN5m1KS335Cj", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtTwEosEcNBN5mFxJAm2xQ", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "canceled", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1736" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcancel; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:18 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-16fed5ea-8249-40a6-bb17-bba164a9e494" + }, + { + "name": "original-request", + "value": "req_VNtmYZEylhS38h" + }, + { + "name": "request-id", + "value": "req_VNtmYZEylhS38h" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1116, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:17.604Z", + "time": 726, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 726 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/UnionPay-pm_card_unionpay_3165217716/should-cancel-pre-authorized-card_3641244857/recording.har b/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/UnionPay-pm_card_unionpay_3165217716/should-cancel-pre-authorized-card_3641244857/recording.har new file mode 100644 index 0000000..7ca65ac --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/UnionPay-pm_card_unionpay_3165217716/should-cancel-pre-authorized-card_3641244857/recording.har @@ -0,0 +1,678 @@ +{ + "log": { + "_recordingName": "TransactionCancelationRequestedWebhookHandler/'UnionPay' 'pm_card_unionpay'/should cancel pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-33ffb279-3ceb-48bb-9442-ae931fe94bc0" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477371, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKpEosEcNBN5m1qIYcMUV", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:51 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-33ffb279-3ceb-48bb-9442-ae931fe94bc0" + }, + { + "name": "original-request", + "value": "req_d9aInU4SPLgNNY" + }, + { + "name": "request-id", + "value": "req_d9aInU4SPLgNNY" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:50.740Z", + "time": 456, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 456 + } + }, + { + "_id": "316abd48fc184cc6026de30d91bb776a", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 31, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "31" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-ea47e6ec-c138-40ee-9399-4b1c66a3b2c6" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_unionpay" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtKpEosEcNBN5m1qIYcMUV/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477371, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKpEosEcNBN5m1qIYcMUV", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtKpEosEcNBN5m1mw2CGkW", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtKpEosEcNBN5mMdZ0jTK4", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:52 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-ea47e6ec-c138-40ee-9399-4b1c66a3b2c6" + }, + { + "name": "original-request", + "value": "req_sL53Komu7LbmRp" + }, + { + "name": "request-id", + "value": "req_sL53Komu7LbmRp" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:51.197Z", + "time": 1089, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1089 + } + }, + { + "_id": "f24fe5add1b6ee79b3fe387cbfa80780", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 0, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "0" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-e5906b13-e7b5-416f-a381-951b911c1632" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 847, + "httpVersion": "HTTP/1.1", + "method": "POST", + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtKpEosEcNBN5m1qIYcMUV/cancel" + }, + "response": { + "bodySize": 1736, + "content": { + "mimeType": "application/json", + "size": 1736, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": 1702477372, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477371, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKpEosEcNBN5m1qIYcMUV", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtKpEosEcNBN5m1mw2CGkW", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtKpEosEcNBN5mMdZ0jTK4", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "canceled", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1736" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcancel; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:53 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-e5906b13-e7b5-416f-a381-951b911c1632" + }, + { + "name": "original-request", + "value": "req_WLzfF5g6bkA3se" + }, + { + "name": "request-id", + "value": "req_WLzfF5g6bkA3se" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1116, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:52.288Z", + "time": 680, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 680 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Visa-debit-pm_card_visa_debit_2311568982/should-cancel-pre-authorized-card_3641244857/recording.har b/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Visa-debit-pm_card_visa_debit_2311568982/should-cancel-pre-authorized-card_3641244857/recording.har new file mode 100644 index 0000000..bd3e54b --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Visa-debit-pm_card_visa_debit_2311568982/should-cancel-pre-authorized-card_3641244857/recording.har @@ -0,0 +1,678 @@ +{ + "log": { + "_recordingName": "TransactionCancelationRequestedWebhookHandler/'Visa (debit)' 'pm_card_visa_debit'/should cancel pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-aa9251f7-e400-4593-a9c5-83ebfcdb42fa" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477928, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtToEosEcNBN5m1Ve1c5su", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:08 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-aa9251f7-e400-4593-a9c5-83ebfcdb42fa" + }, + { + "name": "original-request", + "value": "req_FDHnvnAlyaFFmM" + }, + { + "name": "request-id", + "value": "req_FDHnvnAlyaFFmM" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:08.262Z", + "time": 588, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 588 + } + }, + { + "_id": "103fd0f9c014e355deb553c8353c9dfa", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 33, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "33" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-fae21558-c1a9-4171-892f-6db5ea8270c1" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_visa_debit" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtToEosEcNBN5m1Ve1c5su/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477928, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtToEosEcNBN5m1Ve1c5su", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtToEosEcNBN5m1ly6D5Ar", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtTpEosEcNBN5m0AcXUNyc", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:10 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-fae21558-c1a9-4171-892f-6db5ea8270c1" + }, + { + "name": "original-request", + "value": "req_R5IZUfNKlJooyC" + }, + { + "name": "request-id", + "value": "req_R5IZUfNKlJooyC" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:08.853Z", + "time": 1439, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1439 + } + }, + { + "_id": "0d977dbafc600997f7ded4599e5c378e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 0, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "0" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-ab5fbad1-a95d-42c7-b486-b41192f06a67" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 847, + "httpVersion": "HTTP/1.1", + "method": "POST", + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtToEosEcNBN5m1Ve1c5su/cancel" + }, + "response": { + "bodySize": 1736, + "content": { + "mimeType": "application/json", + "size": 1736, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": 1702477930, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477928, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtToEosEcNBN5m1Ve1c5su", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtToEosEcNBN5m1ly6D5Ar", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtTpEosEcNBN5m0AcXUNyc", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "canceled", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1736" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcancel; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:11 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-ab5fbad1-a95d-42c7-b486-b41192f06a67" + }, + { + "name": "original-request", + "value": "req_x5fLtwLVtwtScf" + }, + { + "name": "request-id", + "value": "req_x5fLtwLVtwtScf" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1116, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:10.295Z", + "time": 745, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 745 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Visa-pm_card_visa_1355345048/should-cancel-pre-authorized-card_3641244857/recording.har b/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Visa-pm_card_visa_1355345048/should-cancel-pre-authorized-card_3641244857/recording.har new file mode 100644 index 0000000..36920bb --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionCancelationRequestedWebhookHandler_2898564197/Visa-pm_card_visa_1355345048/should-cancel-pre-authorized-card_3641244857/recording.har @@ -0,0 +1,678 @@ +{ + "log": { + "_recordingName": "TransactionCancelationRequestedWebhookHandler/'Visa' 'pm_card_visa'/should cancel pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-0d77975c-c6a5-4cf5-bbbc-30d3c87c9bb6" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477431, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtLnEosEcNBN5m0jcOwRj0", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:51 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-0d77975c-c6a5-4cf5-bbbc-30d3c87c9bb6" + }, + { + "name": "original-request", + "value": "req_uJa6JNUmarDuhB" + }, + { + "name": "request-id", + "value": "req_uJa6JNUmarDuhB" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:50.865Z", + "time": 874, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 874 + } + }, + { + "_id": "e3aea640d6ec068834443814f2b9b09a", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 27, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "27" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-514f2fda-9557-4bae-92e9-b53f98929eeb" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_visa" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtLnEosEcNBN5m0jcOwRj0/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477431, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtLnEosEcNBN5m0jcOwRj0", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtLnEosEcNBN5m0osag7jP", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtLoEosEcNBN5msdU5lroA", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:53 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-514f2fda-9557-4bae-92e9-b53f98929eeb" + }, + { + "name": "original-request", + "value": "req_OI1RCfwdoIMpH2" + }, + { + "name": "request-id", + "value": "req_OI1RCfwdoIMpH2" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:51.742Z", + "time": 1302, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1302 + } + }, + { + "_id": "c3544755a1383ee4208c897f8f037614", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 0, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "0" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-33f53a5d-c173-4128-902a-af03dd99dfa5" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 847, + "httpVersion": "HTTP/1.1", + "method": "POST", + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtLnEosEcNBN5m0jcOwRj0/cancel" + }, + "response": { + "bodySize": 1736, + "content": { + "mimeType": "application/json", + "size": 1736, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": 1702477433, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477431, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtLnEosEcNBN5m0jcOwRj0", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtLnEosEcNBN5m0osag7jP", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtLoEosEcNBN5msdU5lroA", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "canceled", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1736" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcancel; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:53 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-33f53a5d-c173-4128-902a-af03dd99dfa5" + }, + { + "name": "original-request", + "value": "req_veGhtRm0m4kQwC" + }, + { + "name": "request-id", + "value": "req_veGhtRm0m4kQwC" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1116, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:53.047Z", + "time": 747, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 747 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/American-Express-pm_card_amex_1702901941/should-charge-pre-authorized-card_3197581963/recording.har b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/American-Express-pm_card_amex_1702901941/should-charge-pre-authorized-card_3197581963/recording.har new file mode 100644 index 0000000..64599da --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/American-Express-pm_card_amex_1702901941/should-charge-pre-authorized-card_3197581963/recording.har @@ -0,0 +1,683 @@ +{ + "log": { + "_recordingName": "TransactionChargeRequestedWebhookHandler/'American Express' 'pm_card_amex'/should charge pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-adb329c1-5269-4269-8c4d-473e76979287" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477379, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKxEosEcNBN5m0QI03EJm", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:59 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-adb329c1-5269-4269-8c4d-473e76979287" + }, + { + "name": "original-request", + "value": "req_79nOUiH5i50XZL" + }, + { + "name": "request-id", + "value": "req_79nOUiH5i50XZL" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:58.906Z", + "time": 464, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 464 + } + }, + { + "_id": "a29b34c09ab728ba2a5d705cd0ab4ff9", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 27, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "27" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-7fe2c2f8-18f2-4722-a64a-9d488a87b685" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_amex" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtKxEosEcNBN5m0QI03EJm/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477379, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKxEosEcNBN5m0QI03EJm", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtKxEosEcNBN5m0nwyNwMN", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtKxEosEcNBN5mnri3Ecek", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:00 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-7fe2c2f8-18f2-4722-a64a-9d488a87b685" + }, + { + "name": "original-request", + "value": "req_wGb7MXREn0FetX" + }, + { + "name": "request-id", + "value": "req_wGb7MXREn0FetX" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:59.371Z", + "time": 1366, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1366 + } + }, + { + "_id": "90fd2e1175fde6ce0527a1009344a013", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-ccb7902c-6b45-4e48-a3d8-932cbcc014f6" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtKxEosEcNBN5m0QI03EJm/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477379, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKxEosEcNBN5m0QI03EJm", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtKxEosEcNBN5m0nwyNwMN", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtKxEosEcNBN5mnri3Ecek", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:01 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-ccb7902c-6b45-4e48-a3d8-932cbcc014f6" + }, + { + "name": "original-request", + "value": "req_tsC77GXnSXFpHC" + }, + { + "name": "request-id", + "value": "req_tsC77GXnSXFpHC" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:00.739Z", + "time": 903, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 903 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/American-Express-pm_card_amex_1702901941/should-partially-charge-pre-authorized-card_330064185/recording.har b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/American-Express-pm_card_amex_1702901941/should-partially-charge-pre-authorized-card_330064185/recording.har new file mode 100644 index 0000000..dab2d73 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/American-Express-pm_card_amex_1702901941/should-partially-charge-pre-authorized-card_330064185/recording.har @@ -0,0 +1,683 @@ +{ + "log": { + "_recordingName": "TransactionChargeRequestedWebhookHandler/'American Express' 'pm_card_amex'/should partially charge pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-ada4d265-473c-4802-ad50-77cbc1f01454" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477382, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtL0EosEcNBN5m0v84r3MA", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:02 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-ada4d265-473c-4802-ad50-77cbc1f01454" + }, + { + "name": "original-request", + "value": "req_2NhLa9lwsp9uJT" + }, + { + "name": "request-id", + "value": "req_2NhLa9lwsp9uJT" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:01.647Z", + "time": 443, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 443 + } + }, + { + "_id": "b62a6dc09403df906f14f8420e2cc347", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 27, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "27" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-8f0dee21-f88d-4246-8c1d-727af1d92371" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_amex" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtL0EosEcNBN5m0v84r3MA/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477382, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtL0EosEcNBN5m0v84r3MA", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtL0EosEcNBN5m0LTlWkvX", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtL0EosEcNBN5m6YRWuweL", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:03 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-8f0dee21-f88d-4246-8c1d-727af1d92371" + }, + { + "name": "original-request", + "value": "req_gyT5eK37F1vpwM" + }, + { + "name": "request-id", + "value": "req_gyT5eK37F1vpwM" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:02.091Z", + "time": 1252, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1252 + } + }, + { + "_id": "1468ab6c21c9d2b5be4f0f1f950c2e86", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 22, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "22" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-eddc9883-dd92-41e1-89ca-1b301f489ef0" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtL0EosEcNBN5m0v84r3MA/capture" + }, + "response": { + "bodySize": 1734, + "content": { + "mimeType": "application/json", + "size": 1734, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 4999, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477382, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtL0EosEcNBN5m0v84r3MA", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtL0EosEcNBN5m0LTlWkvX", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtL0EosEcNBN5m6YRWuweL", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1734" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:04 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-eddc9883-dd92-41e1-89ca-1b301f489ef0" + }, + { + "name": "original-request", + "value": "req_khlAP7xhSTQhMh" + }, + { + "name": "request-id", + "value": "req_khlAP7xhSTQhMh" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:03.345Z", + "time": 1303, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1303 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Diners-Club-pm_card_diners_3136405054/should-charge-pre-authorized-card_3197581963/recording.har b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Diners-Club-pm_card_diners_3136405054/should-charge-pre-authorized-card_3197581963/recording.har new file mode 100644 index 0000000..a1f3645 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Diners-Club-pm_card_diners_3136405054/should-charge-pre-authorized-card_3197581963/recording.har @@ -0,0 +1,683 @@ +{ + "log": { + "_recordingName": "TransactionChargeRequestedWebhookHandler/'Diners Club' 'pm_card_diners'/should charge pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-053cb4f9-a110-465c-9c9d-f14383aea6e8" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477390, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtL8EosEcNBN5m06cgYv0l", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:10 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-053cb4f9-a110-465c-9c9d-f14383aea6e8" + }, + { + "name": "original-request", + "value": "req_o0SAblHRShxesf" + }, + { + "name": "request-id", + "value": "req_o0SAblHRShxesf" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:09.919Z", + "time": 429, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 429 + } + }, + { + "_id": "8dbeb03ad972ecf172b755192a511489", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 29, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "29" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-2dfb83f9-e62d-45d5-b7ef-8ac3db7221fd" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_diners" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtL8EosEcNBN5m06cgYv0l/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477390, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtL8EosEcNBN5m06cgYv0l", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtL8EosEcNBN5m0q68LupO", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtL8EosEcNBN5mME7cubCx", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:11 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-2dfb83f9-e62d-45d5-b7ef-8ac3db7221fd" + }, + { + "name": "original-request", + "value": "req_yEaYX5A4zKhcFC" + }, + { + "name": "request-id", + "value": "req_yEaYX5A4zKhcFC" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:10.349Z", + "time": 1123, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1123 + } + }, + { + "_id": "4a7134168ac43f923931cf649f51e4cc", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-6496c8ed-6983-4a1d-a708-bfc87f2df296" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtL8EosEcNBN5m06cgYv0l/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477390, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtL8EosEcNBN5m06cgYv0l", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtL8EosEcNBN5m0q68LupO", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtL8EosEcNBN5mME7cubCx", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:12 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-6496c8ed-6983-4a1d-a708-bfc87f2df296" + }, + { + "name": "original-request", + "value": "req_30VGwHNzz94xZ3" + }, + { + "name": "request-id", + "value": "req_30VGwHNzz94xZ3" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:11.474Z", + "time": 810, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 810 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Diners-Club-pm_card_diners_3136405054/should-partially-charge-pre-authorized-card_330064185/recording.har b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Diners-Club-pm_card_diners_3136405054/should-partially-charge-pre-authorized-card_330064185/recording.har new file mode 100644 index 0000000..167daf2 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Diners-Club-pm_card_diners_3136405054/should-partially-charge-pre-authorized-card_330064185/recording.har @@ -0,0 +1,683 @@ +{ + "log": { + "_recordingName": "TransactionChargeRequestedWebhookHandler/'Diners Club' 'pm_card_diners'/should partially charge pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-85f9a961-be41-416f-9000-16664535960b" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477392, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtLAEosEcNBN5m0UPB5nSf", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:12 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-85f9a961-be41-416f-9000-16664535960b" + }, + { + "name": "original-request", + "value": "req_zy5Iv8aD36Rr6F" + }, + { + "name": "request-id", + "value": "req_zy5Iv8aD36Rr6F" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:12.287Z", + "time": 434, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 434 + } + }, + { + "_id": "2cd3f923409d30f6622f13b65a0afd28", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 29, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "29" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-f449871b-e6f8-4647-b481-581b0cf6855e" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_diners" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtLAEosEcNBN5m0UPB5nSf/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477392, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtLAEosEcNBN5m0UPB5nSf", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtLAEosEcNBN5m0THVEHaX", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtLBEosEcNBN5mQsV5lHeA", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:13 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-f449871b-e6f8-4647-b481-581b0cf6855e" + }, + { + "name": "original-request", + "value": "req_YHv19ImMcALsSI" + }, + { + "name": "request-id", + "value": "req_YHv19ImMcALsSI" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:12.722Z", + "time": 1040, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1040 + } + }, + { + "_id": "4c7729d8e28084a578e9eea47ce502dd", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 22, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "22" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-4c9f3b1f-759c-46f8-a8ba-4e28c88b84e7" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtLAEosEcNBN5m0UPB5nSf/capture" + }, + "response": { + "bodySize": 1734, + "content": { + "mimeType": "application/json", + "size": 1734, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 4999, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477392, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtLAEosEcNBN5m0UPB5nSf", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtLAEosEcNBN5m0THVEHaX", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtLBEosEcNBN5mQsV5lHeA", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1734" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:15 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-4c9f3b1f-759c-46f8-a8ba-4e28c88b84e7" + }, + { + "name": "original-request", + "value": "req_IVHYhvIvi4BAVO" + }, + { + "name": "request-id", + "value": "req_IVHYhvIvi4BAVO" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:13.764Z", + "time": 1325, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1325 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Discover-pm_card_discover_3985489676/should-charge-pre-authorized-card_3197581963/recording.har b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Discover-pm_card_discover_3985489676/should-charge-pre-authorized-card_3197581963/recording.har new file mode 100644 index 0000000..c55c465 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Discover-pm_card_discover_3985489676/should-charge-pre-authorized-card_3197581963/recording.har @@ -0,0 +1,683 @@ +{ + "log": { + "_recordingName": "TransactionChargeRequestedWebhookHandler/'Discover' 'pm_card_discover'/should charge pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-1fc9059f-a5c9-43b7-86a4-4dff96733ad0" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477385, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtL3EosEcNBN5m0520GfeC", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:05 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-1fc9059f-a5c9-43b7-86a4-4dff96733ad0" + }, + { + "name": "original-request", + "value": "req_Bor3LOa73kVgaj" + }, + { + "name": "request-id", + "value": "req_Bor3LOa73kVgaj" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:04.652Z", + "time": 408, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 408 + } + }, + { + "_id": "de6cf5b346f0a1b4a4f276078f2ee5db", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 31, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "31" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-5ac2636c-861a-48a1-8189-c4c7b9cf14b4" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_discover" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtL3EosEcNBN5m0520GfeC/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477385, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtL3EosEcNBN5m0520GfeC", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtL3EosEcNBN5m0uz5eD8E", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtL3EosEcNBN5mVC3IvgSF", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:06 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-5ac2636c-861a-48a1-8189-c4c7b9cf14b4" + }, + { + "name": "original-request", + "value": "req_9l8ou0dnw17ehb" + }, + { + "name": "request-id", + "value": "req_9l8ou0dnw17ehb" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:05.062Z", + "time": 1077, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1077 + } + }, + { + "_id": "2c2f58d255edadd1f9db1890a3b8a7c7", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-10a13e20-b0f1-4632-881b-816300b13f02" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtL3EosEcNBN5m0520GfeC/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477385, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtL3EosEcNBN5m0520GfeC", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtL3EosEcNBN5m0uz5eD8E", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtL3EosEcNBN5mVC3IvgSF", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:07 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-10a13e20-b0f1-4632-881b-816300b13f02" + }, + { + "name": "original-request", + "value": "req_mq422dnZVmDN63" + }, + { + "name": "request-id", + "value": "req_mq422dnZVmDN63" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:06.141Z", + "time": 969, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 969 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Discover-pm_card_discover_3985489676/should-partially-charge-pre-authorized-card_330064185/recording.har b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Discover-pm_card_discover_3985489676/should-partially-charge-pre-authorized-card_330064185/recording.har new file mode 100644 index 0000000..25a1e9f --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Discover-pm_card_discover_3985489676/should-partially-charge-pre-authorized-card_330064185/recording.har @@ -0,0 +1,683 @@ +{ + "log": { + "_recordingName": "TransactionChargeRequestedWebhookHandler/'Discover' 'pm_card_discover'/should partially charge pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-2e99fdb1-8286-437f-a1b9-0a92f9455932" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477387, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtL5EosEcNBN5m1KerXnMm", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:07 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-2e99fdb1-8286-437f-a1b9-0a92f9455932" + }, + { + "name": "original-request", + "value": "req_5LB9CXGr1G1L5P" + }, + { + "name": "request-id", + "value": "req_5LB9CXGr1G1L5P" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:07.114Z", + "time": 433, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 433 + } + }, + { + "_id": "2ea774bc954f131af36f7268569e4941", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 31, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "31" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-6fcff2ab-e465-4e0b-b6be-98700841a04f" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_discover" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtL5EosEcNBN5m1KerXnMm/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477387, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtL5EosEcNBN5m1KerXnMm", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtL5EosEcNBN5m1KxCPvmi", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtL5EosEcNBN5mKXJOnfra", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:08 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-6fcff2ab-e465-4e0b-b6be-98700841a04f" + }, + { + "name": "original-request", + "value": "req_fQpYooWwg3ZqJe" + }, + { + "name": "request-id", + "value": "req_fQpYooWwg3ZqJe" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:07.548Z", + "time": 1062, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1062 + } + }, + { + "_id": "91ffef6eb4405c349e416d0178da7908", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 22, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "22" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-d6ca3479-2d25-4421-8381-985291a84801" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtL5EosEcNBN5m1KerXnMm/capture" + }, + "response": { + "bodySize": 1734, + "content": { + "mimeType": "application/json", + "size": 1734, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 4999, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477387, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtL5EosEcNBN5m1KerXnMm", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtL5EosEcNBN5m1KxCPvmi", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtL5EosEcNBN5mKXJOnfra", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1734" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:10 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-d6ca3479-2d25-4421-8381-985291a84801" + }, + { + "name": "original-request", + "value": "req_SmP48QNFBiM5Cq" + }, + { + "name": "request-id", + "value": "req_SmP48QNFBiM5Cq" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:08.612Z", + "time": 1303, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1303 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-charge-pre-authorized-card_3197581963/recording.har b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-charge-pre-authorized-card_3197581963/recording.har new file mode 100644 index 0000000..c38c10b --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-charge-pre-authorized-card_3197581963/recording.har @@ -0,0 +1,906 @@ +{ + "log": { + "_recordingName": "TransactionChargeRequestedWebhookHandler/'Mastercard (debit)' 'pm_card_mastercard_debit'/should charge pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-1b919e75-a6fc-42d4-ab61-b9cc6d0199be" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477368, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKmEosEcNBN5m0FuzB06g", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:48 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-1b919e75-a6fc-42d4-ab61-b9cc6d0199be" + }, + { + "name": "original-request", + "value": "req_WKbKKQtaKZjE5d" + }, + { + "name": "request-id", + "value": "req_WKbKKQtaKZjE5d" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:47.965Z", + "time": 894, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 894 + } + }, + { + "_id": "adbf8e85883daceddcc41e15449059c9", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 39, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "39" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-07044c7d-b830-4eb8-ab5d-ba0ed867e0ee" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_mastercard_debit" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtKmEosEcNBN5m0FuzB06g/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477368, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKmEosEcNBN5m0FuzB06g", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtKmEosEcNBN5m0ogbVKiA", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtKnEosEcNBN5mK6qhSyzq", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:50 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-07044c7d-b830-4eb8-ab5d-ba0ed867e0ee" + }, + { + "name": "original-request", + "value": "req_2rGAqc1SpjIjcq" + }, + { + "name": "request-id", + "value": "req_2rGAqc1SpjIjcq" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:48.861Z", + "time": 1137, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1137 + } + }, + { + "_id": "f6b62b70a4be4bee8f679cb7e7b7c695", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 22, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "22" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-775db4c9-ea25-41c6-b5b9-a443515a5ad4" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtKlEosEcNBN5m1VFevvzS/capture" + }, + "response": { + "bodySize": 1734, + "content": { + "mimeType": "application/json", + "size": 1734, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 4999, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477367, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKlEosEcNBN5m1VFevvzS", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtKlEosEcNBN5m1LLfvJiR", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtKmEosEcNBN5mSEfE0qLi", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1734" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:50 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-775db4c9-ea25-41c6-b5b9-a443515a5ad4" + }, + { + "name": "original-request", + "value": "req_aGmWGpmosDg97v" + }, + { + "name": "request-id", + "value": "req_aGmWGpmosDg97v" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:49.174Z", + "time": 1385, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1385 + } + }, + { + "_id": "bc46a4f8f735e119e492439b5704c2d3", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-1987e899-7566-4c6d-b9a6-ec4c5814afb4" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtKmEosEcNBN5m0FuzB06g/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477368, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKmEosEcNBN5m0FuzB06g", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtKmEosEcNBN5m0ogbVKiA", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtKnEosEcNBN5mK6qhSyzq", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:51 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-1987e899-7566-4c6d-b9a6-ec4c5814afb4" + }, + { + "name": "original-request", + "value": "req_zPaJgBl8xohLrt" + }, + { + "name": "request-id", + "value": "req_zPaJgBl8xohLrt" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:50.000Z", + "time": 887, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 887 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-partially-charge-pre-authorized-card_330064185/recording.har b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-partially-charge-pre-authorized-card_330064185/recording.har new file mode 100644 index 0000000..6e969f3 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-partially-charge-pre-authorized-card_330064185/recording.har @@ -0,0 +1,683 @@ +{ + "log": { + "_recordingName": "TransactionChargeRequestedWebhookHandler/'Mastercard (debit)' 'pm_card_mastercard_debit'/should partially charge pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-a96cc0b2-3f2c-451f-a9c8-f3ef10970e48" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477371, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKpEosEcNBN5m0hQjAOao", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:51 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-a96cc0b2-3f2c-451f-a9c8-f3ef10970e48" + }, + { + "name": "original-request", + "value": "req_MPEW2GrVAbUCv6" + }, + { + "name": "request-id", + "value": "req_MPEW2GrVAbUCv6" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:50.893Z", + "time": 407, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 407 + } + }, + { + "_id": "e2042c7e42d4b084da2676231a700a1b", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 39, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "39" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-00eb2065-4c3e-4311-8864-d11a4244f188" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_mastercard_debit" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtKpEosEcNBN5m0hQjAOao/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477371, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKpEosEcNBN5m0hQjAOao", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtKpEosEcNBN5m05Q4t6H8", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtKpEosEcNBN5mGZc3cCNA", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:52 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-00eb2065-4c3e-4311-8864-d11a4244f188" + }, + { + "name": "original-request", + "value": "req_r0etJaPmhF6KQm" + }, + { + "name": "request-id", + "value": "req_r0etJaPmhF6KQm" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:51.301Z", + "time": 1079, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1079 + } + }, + { + "_id": "4a3c0239f41ab23a64845fb2193971f3", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 22, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "22" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-0a390b4d-bf44-4c36-a622-e892a428c088" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtKpEosEcNBN5m0hQjAOao/capture" + }, + "response": { + "bodySize": 1734, + "content": { + "mimeType": "application/json", + "size": 1734, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 4999, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477371, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKpEosEcNBN5m0hQjAOao", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtKpEosEcNBN5m05Q4t6H8", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtKpEosEcNBN5mGZc3cCNA", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1734" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:53 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-0a390b4d-bf44-4c36-a622-e892a428c088" + }, + { + "name": "original-request", + "value": "req_IZXWU42hI8ybnD" + }, + { + "name": "request-id", + "value": "req_IZXWU42hI8ybnD" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:52.382Z", + "time": 1325, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1325 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Mastercard-pm_card_mastercard_3189003338/should-charge-pre-authorized-card_3197581963/recording.har b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Mastercard-pm_card_mastercard_3189003338/should-charge-pre-authorized-card_3197581963/recording.har new file mode 100644 index 0000000..b3bc31b --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Mastercard-pm_card_mastercard_3189003338/should-charge-pre-authorized-card_3197581963/recording.har @@ -0,0 +1,683 @@ +{ + "log": { + "_recordingName": "TransactionChargeRequestedWebhookHandler/'Mastercard' 'pm_card_mastercard'/should charge pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-d9687093-0338-471c-af6e-dcdcd8c3efe5" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477936, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTwEosEcNBN5m0gdhB6Bi", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:16 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-d9687093-0338-471c-af6e-dcdcd8c3efe5" + }, + { + "name": "original-request", + "value": "req_XkJrpmVs9zy7vf" + }, + { + "name": "request-id", + "value": "req_XkJrpmVs9zy7vf" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:16.406Z", + "time": 448, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 448 + } + }, + { + "_id": "da68c297f7d361aab9c7fc4d7083be33", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 33, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "33" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-95c5374c-090d-4ec1-a3f9-94e1b6f1a316" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_mastercard" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtTwEosEcNBN5m0gdhB6Bi/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477936, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTwEosEcNBN5m0gdhB6Bi", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtTwEosEcNBN5m0SSlLQIC", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtTxEosEcNBN5mnNQjSIfp", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:18 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-95c5374c-090d-4ec1-a3f9-94e1b6f1a316" + }, + { + "name": "original-request", + "value": "req_JRvi7faIHRJr3g" + }, + { + "name": "request-id", + "value": "req_JRvi7faIHRJr3g" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:16.856Z", + "time": 1091, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1091 + } + }, + { + "_id": "5d31326afd6a9edde7f97273b9ce9e26", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-c99796f0-699a-44c2-ae00-248970d23bc4" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtTwEosEcNBN5m0gdhB6Bi/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477936, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTwEosEcNBN5m0gdhB6Bi", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtTwEosEcNBN5m0SSlLQIC", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtTxEosEcNBN5mnNQjSIfp", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:18 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-c99796f0-699a-44c2-ae00-248970d23bc4" + }, + { + "name": "original-request", + "value": "req_xt2bz4ClOwwuLx" + }, + { + "name": "request-id", + "value": "req_xt2bz4ClOwwuLx" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:17.949Z", + "time": 851, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 851 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Mastercard-pm_card_mastercard_3189003338/should-partially-charge-pre-authorized-card_330064185/recording.har b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Mastercard-pm_card_mastercard_3189003338/should-partially-charge-pre-authorized-card_330064185/recording.har new file mode 100644 index 0000000..6268628 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Mastercard-pm_card_mastercard_3189003338/should-partially-charge-pre-authorized-card_330064185/recording.har @@ -0,0 +1,465 @@ +{ + "log": { + "_recordingName": "TransactionChargeRequestedWebhookHandler/'Mastercard' 'pm_card_mastercard'/should partially charge pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-d0aee91b-5c13-4608-b7cc-03fc4e7da215" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477367, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKlEosEcNBN5m1VFevvzS", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:48 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-d0aee91b-5c13-4608-b7cc-03fc4e7da215" + }, + { + "name": "original-request", + "value": "req_71THGp6RZL52GV" + }, + { + "name": "request-id", + "value": "req_71THGp6RZL52GV" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:33.646Z", + "time": 14309, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 14309 + } + }, + { + "_id": "b50b341e67634bf256093a6f3f69b84b", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 33, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "33" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-283f06b4-b4ff-4ae6-9541-0a8073cb2004" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_mastercard" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtKlEosEcNBN5m1VFevvzS/confirm" + }, + "response": { + "bodySize": 2461, + "content": { + "mimeType": "application/json", + "size": 2461, + "text": { + "error": { + "code": "payment_intent_unexpected_state", + "doc_url": "https://stripe.com/docs/error-codes/payment-intent-unexpected-state", + "message": "You cannot confirm this PaymentIntent because it has already succeeded after being previously confirmed.", + "payment_intent": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 4999, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_3OMtKlEosEcNBN5m1VFevvzS_secret_QVGTwOriF751jodkpZWusPIQj", + "confirmation_method": "automatic", + "created": 1702477367, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKlEosEcNBN5m1VFevvzS", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtKlEosEcNBN5m1LLfvJiR", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtKmEosEcNBN5mSEfE0qLi", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + }, + "request_log_url": "https://dashboard.stripe.com/test/logs/req_pYEDZ3P9tXSfGy?t=1702477939", + "type": "invalid_request_error" + } + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "2461" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:19 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-283f06b4-b4ff-4ae6-9541-0a8073cb2004" + }, + { + "name": "original-request", + "value": "req_pYEDZ3P9tXSfGy" + }, + { + "name": "request-id", + "value": "req_pYEDZ3P9tXSfGy" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1089, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 400, + "statusText": "Bad Request" + }, + "startedDateTime": "2023-12-13T14:32:18.811Z", + "time": 506, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 506 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-charge-pre-authorized-card_3197581963/recording.har b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-charge-pre-authorized-card_3197581963/recording.har new file mode 100644 index 0000000..f5fd614 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-charge-pre-authorized-card_3197581963/recording.har @@ -0,0 +1,683 @@ +{ + "log": { + "_recordingName": "TransactionChargeRequestedWebhookHandler/'Mastercard (prepaid)' 'pm_card_mastercard_prepaid'/should charge pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-099f9deb-fca7-442f-b4e5-94f7a0a9ecb2" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477374, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKsEosEcNBN5m13HTExjB", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:54 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-099f9deb-fca7-442f-b4e5-94f7a0a9ecb2" + }, + { + "name": "original-request", + "value": "req_Ol0JYj1s9NqvK3" + }, + { + "name": "request-id", + "value": "req_Ol0JYj1s9NqvK3" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:53.713Z", + "time": 440, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 440 + } + }, + { + "_id": "887d17f9e04f98a3cd34a97de8f991f8", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 41, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "41" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-d7fdf04f-6a29-49ce-97d7-1c31baba22a4" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_mastercard_prepaid" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtKsEosEcNBN5m13HTExjB/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477374, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKsEosEcNBN5m13HTExjB", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtKsEosEcNBN5m1QavS1s8", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtKsEosEcNBN5mUHPyx9iE", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:55 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-d7fdf04f-6a29-49ce-97d7-1c31baba22a4" + }, + { + "name": "original-request", + "value": "req_O3rTyFvVvHZka9" + }, + { + "name": "request-id", + "value": "req_O3rTyFvVvHZka9" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:54.154Z", + "time": 1056, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1056 + } + }, + { + "_id": "e15bae9fbb173b24b2543ceb5dbd3dd3", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-590cd253-fadb-4656-9fa4-9a1907345414" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtKsEosEcNBN5m13HTExjB/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477374, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKsEosEcNBN5m13HTExjB", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtKsEosEcNBN5m1QavS1s8", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtKsEosEcNBN5mUHPyx9iE", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:56 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-590cd253-fadb-4656-9fa4-9a1907345414" + }, + { + "name": "original-request", + "value": "req_aI1k93f64VsvDg" + }, + { + "name": "request-id", + "value": "req_aI1k93f64VsvDg" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:55.212Z", + "time": 903, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 903 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-partially-charge-pre-authorized-card_330064185/recording.har b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-partially-charge-pre-authorized-card_330064185/recording.har new file mode 100644 index 0000000..8fbeef5 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-partially-charge-pre-authorized-card_330064185/recording.har @@ -0,0 +1,683 @@ +{ + "log": { + "_recordingName": "TransactionChargeRequestedWebhookHandler/'Mastercard (prepaid)' 'pm_card_mastercard_prepaid'/should partially charge pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-c59e8968-a580-4897-a9a5-d398c0e63cfb" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477376, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKuEosEcNBN5m1mvb62fV", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:56 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-c59e8968-a580-4897-a9a5-d398c0e63cfb" + }, + { + "name": "original-request", + "value": "req_AGNIaBJLPAP13T" + }, + { + "name": "request-id", + "value": "req_AGNIaBJLPAP13T" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:56.121Z", + "time": 439, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 439 + } + }, + { + "_id": "6a48124e7494057281675456292c7174", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 41, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "41" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b5c9e733-d76d-4014-8b40-7652638ec42a" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_mastercard_prepaid" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtKuEosEcNBN5m1mvb62fV/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477376, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKuEosEcNBN5m1mvb62fV", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtKuEosEcNBN5m1kNoKRZu", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtKuEosEcNBN5m7Mkz2vP9", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:57 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b5c9e733-d76d-4014-8b40-7652638ec42a" + }, + { + "name": "original-request", + "value": "req_BEVZYXhE0XHUG8" + }, + { + "name": "request-id", + "value": "req_BEVZYXhE0XHUG8" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:56.562Z", + "time": 1016, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1016 + } + }, + { + "_id": "f52d1b9b090c30b70fc91e0d26b85863", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 22, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "22" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-e2a20dad-61b3-4222-b487-5cdc58f6d29b" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtKuEosEcNBN5m1mvb62fV/capture" + }, + "response": { + "bodySize": 1734, + "content": { + "mimeType": "application/json", + "size": 1734, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 4999, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477376, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKuEosEcNBN5m1mvb62fV", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtKuEosEcNBN5m1kNoKRZu", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtKuEosEcNBN5m7Mkz2vP9", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1734" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:59 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-e2a20dad-61b3-4222-b487-5cdc58f6d29b" + }, + { + "name": "original-request", + "value": "req_gyLag1bMTwarn9" + }, + { + "name": "request-id", + "value": "req_gyLag1bMTwarn9" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:57.580Z", + "time": 1321, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1321 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/UnionPay-pm_card_unionpay_3165217716/should-charge-pre-authorized-card_3197581963/recording.har b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/UnionPay-pm_card_unionpay_3165217716/should-charge-pre-authorized-card_3197581963/recording.har new file mode 100644 index 0000000..d6a14b8 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/UnionPay-pm_card_unionpay_3165217716/should-charge-pre-authorized-card_3197581963/recording.har @@ -0,0 +1,683 @@ +{ + "log": { + "_recordingName": "TransactionChargeRequestedWebhookHandler/'UnionPay' 'pm_card_unionpay'/should charge pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-07fc0c3b-37d1-4427-8853-4c8123624895" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477395, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtLDEosEcNBN5m0IjzLOaL", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:15 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-07fc0c3b-37d1-4427-8853-4c8123624895" + }, + { + "name": "original-request", + "value": "req_i2F6V4mJNth3bl" + }, + { + "name": "request-id", + "value": "req_i2F6V4mJNth3bl" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:15.094Z", + "time": 433, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 433 + } + }, + { + "_id": "07ead1447d577a7bcdaf6ee26e3415b3", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 31, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "31" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-662cc626-f810-412a-9dc2-62c1e437ad7b" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_unionpay" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtLDEosEcNBN5m0IjzLOaL/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477395, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtLDEosEcNBN5m0IjzLOaL", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtLDEosEcNBN5m0se40W2b", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtLDEosEcNBN5mVkJFTJ6t", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:16 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-662cc626-f810-412a-9dc2-62c1e437ad7b" + }, + { + "name": "original-request", + "value": "req_dDD2ZouS1oh2T0" + }, + { + "name": "request-id", + "value": "req_dDD2ZouS1oh2T0" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:15.529Z", + "time": 1152, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1152 + } + }, + { + "_id": "bc2b0b06fc31ed5974ace6d268ac9486", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-793257e6-fe01-4181-b57a-03ebe3cb676e" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtLDEosEcNBN5m0IjzLOaL/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477395, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtLDEosEcNBN5m0IjzLOaL", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtLDEosEcNBN5m0se40W2b", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtLDEosEcNBN5mVkJFTJ6t", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:17 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-793257e6-fe01-4181-b57a-03ebe3cb676e" + }, + { + "name": "original-request", + "value": "req_VD013dpyQuJh1d" + }, + { + "name": "request-id", + "value": "req_VD013dpyQuJh1d" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:16.683Z", + "time": 898, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 898 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/UnionPay-pm_card_unionpay_3165217716/should-partially-charge-pre-authorized-card_330064185/recording.har b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/UnionPay-pm_card_unionpay_3165217716/should-partially-charge-pre-authorized-card_330064185/recording.har new file mode 100644 index 0000000..0410fbe --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/UnionPay-pm_card_unionpay_3165217716/should-partially-charge-pre-authorized-card_330064185/recording.har @@ -0,0 +1,683 @@ +{ + "log": { + "_recordingName": "TransactionChargeRequestedWebhookHandler/'UnionPay' 'pm_card_unionpay'/should partially charge pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-7d4b6450-d9dc-4799-a33d-8b17f3d8385e" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477397, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtLFEosEcNBN5m0SkGe2BR", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:18 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-7d4b6450-d9dc-4799-a33d-8b17f3d8385e" + }, + { + "name": "original-request", + "value": "req_33oCTjjNdSqDx1" + }, + { + "name": "request-id", + "value": "req_33oCTjjNdSqDx1" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:17.586Z", + "time": 438, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 438 + } + }, + { + "_id": "d239a8d22e8c053c275214e2afe4a1fd", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 31, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "31" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-07ad8fa3-875f-4db0-b5eb-0014c1386d8d" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_unionpay" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtLFEosEcNBN5m0SkGe2BR/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477397, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtLFEosEcNBN5m0SkGe2BR", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtLFEosEcNBN5m0vY2nrHL", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtLGEosEcNBN5mULbmjQGp", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:19 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-07ad8fa3-875f-4db0-b5eb-0014c1386d8d" + }, + { + "name": "original-request", + "value": "req_bAvUuOyq2jRWvx" + }, + { + "name": "request-id", + "value": "req_bAvUuOyq2jRWvx" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:18.026Z", + "time": 1122, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1122 + } + }, + { + "_id": "3d8d4ebd32e92bec4a78b579fcd9c195", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 22, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "22" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-0b8bb3c9-08a6-44b6-9a82-ef3084bdccf3" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtLFEosEcNBN5m0SkGe2BR/capture" + }, + "response": { + "bodySize": 1734, + "content": { + "mimeType": "application/json", + "size": 1734, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 4999, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477397, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtLFEosEcNBN5m0SkGe2BR", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtLFEosEcNBN5m0vY2nrHL", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtLGEosEcNBN5mULbmjQGp", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1734" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:20 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-0b8bb3c9-08a6-44b6-9a82-ef3084bdccf3" + }, + { + "name": "original-request", + "value": "req_4h9PPnIXZzmcr9" + }, + { + "name": "request-id", + "value": "req_4h9PPnIXZzmcr9" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:19.150Z", + "time": 1307, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1307 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Visa-debit-pm_card_visa_debit_2311568982/should-charge-pre-authorized-card_3197581963/recording.har b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Visa-debit-pm_card_visa_debit_2311568982/should-charge-pre-authorized-card_3197581963/recording.har new file mode 100644 index 0000000..94c45c7 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Visa-debit-pm_card_visa_debit_2311568982/should-charge-pre-authorized-card_3197581963/recording.har @@ -0,0 +1,683 @@ +{ + "log": { + "_recordingName": "TransactionChargeRequestedWebhookHandler/'Visa (debit)' 'pm_card_visa_debit'/should charge pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-e068e594-44ea-4792-a19d-c5a9082305f6" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477930, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTqEosEcNBN5m1fTekOcm", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:11 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-e068e594-44ea-4792-a19d-c5a9082305f6" + }, + { + "name": "original-request", + "value": "req_fp7fyu8pp95ZJM" + }, + { + "name": "request-id", + "value": "req_fp7fyu8pp95ZJM" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:10.529Z", + "time": 441, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 441 + } + }, + { + "_id": "21c898e6af2111d32b096d435ac56ce4", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 33, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "33" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-71f58fd2-3a53-4364-88ce-9cfee4fd24e5" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_visa_debit" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtTqEosEcNBN5m1fTekOcm/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477930, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTqEosEcNBN5m1fTekOcm", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtTqEosEcNBN5m1MQReXTO", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtTrEosEcNBN5mo8AzWXdR", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:12 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-71f58fd2-3a53-4364-88ce-9cfee4fd24e5" + }, + { + "name": "original-request", + "value": "req_mVLF9sJuqWt5gA" + }, + { + "name": "request-id", + "value": "req_mVLF9sJuqWt5gA" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:10.972Z", + "time": 1096, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1096 + } + }, + { + "_id": "7d2de4e73e03fc788708a59893605794", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-be0ac563-4d40-4c93-b583-9da876c4694d" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtTqEosEcNBN5m1fTekOcm/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477930, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTqEosEcNBN5m1fTekOcm", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtTqEosEcNBN5m1MQReXTO", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtTrEosEcNBN5mo8AzWXdR", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:13 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-be0ac563-4d40-4c93-b583-9da876c4694d" + }, + { + "name": "original-request", + "value": "req_brrzQp4byjib0Q" + }, + { + "name": "request-id", + "value": "req_brrzQp4byjib0Q" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:12.071Z", + "time": 987, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 987 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Visa-debit-pm_card_visa_debit_2311568982/should-partially-charge-pre-authorized-card_330064185/recording.har b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Visa-debit-pm_card_visa_debit_2311568982/should-partially-charge-pre-authorized-card_330064185/recording.har new file mode 100644 index 0000000..bce09d5 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Visa-debit-pm_card_visa_debit_2311568982/should-partially-charge-pre-authorized-card_330064185/recording.har @@ -0,0 +1,683 @@ +{ + "log": { + "_recordingName": "TransactionChargeRequestedWebhookHandler/'Visa (debit)' 'pm_card_visa_debit'/should partially charge pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-47478ae5-bfce-4aa3-ac09-0992da80a416" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477933, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTtEosEcNBN5m1V2TMbn2", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:13 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-47478ae5-bfce-4aa3-ac09-0992da80a416" + }, + { + "name": "original-request", + "value": "req_RbbDMFGkGAjzls" + }, + { + "name": "request-id", + "value": "req_RbbDMFGkGAjzls" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:13.064Z", + "time": 572, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 572 + } + }, + { + "_id": "2980bab23b0ad2a80dfee56776ae7659", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 33, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "33" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-2ae9723c-b85f-4466-ae7a-5cf69b82829b" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_visa_debit" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtTtEosEcNBN5m1V2TMbn2/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477933, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTtEosEcNBN5m1V2TMbn2", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtTtEosEcNBN5m1e6by6j7", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtTuEosEcNBN5mZwGDT5fq", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:15 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-2ae9723c-b85f-4466-ae7a-5cf69b82829b" + }, + { + "name": "original-request", + "value": "req_NE0KSrNsGAkrSE" + }, + { + "name": "request-id", + "value": "req_NE0KSrNsGAkrSE" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:13.641Z", + "time": 1350, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1350 + } + }, + { + "_id": "e40d9e05bf55c52684340c4c127283d3", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 22, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "22" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-2ddf8b70-9a6e-426e-a504-14065f96959d" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtTtEosEcNBN5m1V2TMbn2/capture" + }, + "response": { + "bodySize": 1734, + "content": { + "mimeType": "application/json", + "size": 1734, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 4999, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477933, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTtEosEcNBN5m1V2TMbn2", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtTtEosEcNBN5m1e6by6j7", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtTuEosEcNBN5mZwGDT5fq", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1734" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:16 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-2ddf8b70-9a6e-426e-a504-14065f96959d" + }, + { + "name": "original-request", + "value": "req_6Q6UMguiEDbJ0X" + }, + { + "name": "request-id", + "value": "req_6Q6UMguiEDbJ0X" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:14.993Z", + "time": 1406, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1406 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Visa-pm_card_visa_1355345048/should-charge-pre-authorized-card_3197581963/recording.har b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Visa-pm_card_visa_1355345048/should-charge-pre-authorized-card_3197581963/recording.har new file mode 100644 index 0000000..780e458 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Visa-pm_card_visa_1355345048/should-charge-pre-authorized-card_3197581963/recording.har @@ -0,0 +1,683 @@ +{ + "log": { + "_recordingName": "TransactionChargeRequestedWebhookHandler/'Visa' 'pm_card_visa'/should charge pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-2c4deb92-5f59-44ed-adab-d6f929a5d195" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477430, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtLmEosEcNBN5m1i98vPr1", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:50 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-2c4deb92-5f59-44ed-adab-d6f929a5d195" + }, + { + "name": "original-request", + "value": "req_JXYejFHkQIs7Ao" + }, + { + "name": "request-id", + "value": "req_JXYejFHkQIs7Ao" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:49.600Z", + "time": 810, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 810 + } + }, + { + "_id": "05c968102157f05df1b483f67da8bf72", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 27, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "27" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-9dfa91e2-bd7d-4e64-9392-80f3c823cc5e" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_visa" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtLmEosEcNBN5m1i98vPr1/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477430, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtLmEosEcNBN5m1i98vPr1", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtLmEosEcNBN5m1djI77aE", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtLmEosEcNBN5mGWxYCqjP", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:51 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-9dfa91e2-bd7d-4e64-9392-80f3c823cc5e" + }, + { + "name": "original-request", + "value": "req_N4OL10ZolaYNVa" + }, + { + "name": "request-id", + "value": "req_N4OL10ZolaYNVa" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:50.415Z", + "time": 1249, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1249 + } + }, + { + "_id": "ba758e83058c8029358532169905996d", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-585f0889-2475-4783-a946-a83f750f85c9" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtLmEosEcNBN5m1i98vPr1/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477430, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtLmEosEcNBN5m1i98vPr1", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtLmEosEcNBN5m1djI77aE", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtLmEosEcNBN5mGWxYCqjP", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:52 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-585f0889-2475-4783-a946-a83f750f85c9" + }, + { + "name": "original-request", + "value": "req_TihQ7HhC6dKlQz" + }, + { + "name": "request-id", + "value": "req_TihQ7HhC6dKlQz" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:51.668Z", + "time": 917, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 917 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Visa-pm_card_visa_1355345048/should-partially-charge-pre-authorized-card_330064185/recording.har b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Visa-pm_card_visa_1355345048/should-partially-charge-pre-authorized-card_330064185/recording.har new file mode 100644 index 0000000..09cc709 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionChargeRequestedWebhookHandler_1851550814/Visa-pm_card_visa_1355345048/should-partially-charge-pre-authorized-card_330064185/recording.har @@ -0,0 +1,683 @@ +{ + "log": { + "_recordingName": "TransactionChargeRequestedWebhookHandler/'Visa' 'pm_card_visa'/should partially charge pre-authorized card", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-7abce5f0-be05-4363-aba6-d21ef89e3029" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477927, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTnEosEcNBN5m1lpU59SK", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:07 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-7abce5f0-be05-4363-aba6-d21ef89e3029" + }, + { + "name": "original-request", + "value": "req_6QX00VH6aomFwU" + }, + { + "name": "request-id", + "value": "req_6QX00VH6aomFwU" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:06.888Z", + "time": 732, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 732 + } + }, + { + "_id": "8a2ee66fcfe9b582edf993d0a8c433f0", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 27, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "27" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b061ab2e-b615-4fbe-8791-7d6dd1c964a0" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_visa" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtTnEosEcNBN5m1lpU59SK/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477927, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTnEosEcNBN5m1lpU59SK", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtTnEosEcNBN5m1MO6kmNw", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtToEosEcNBN5m9DE3pCWT", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:09 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b061ab2e-b615-4fbe-8791-7d6dd1c964a0" + }, + { + "name": "original-request", + "value": "req_SU3L4Tv02dreJM" + }, + { + "name": "request-id", + "value": "req_SU3L4Tv02dreJM" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:07.624Z", + "time": 1570, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1570 + } + }, + { + "_id": "0c76e5f15cb5630703106be10f0fcdfd", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 22, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "22" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-871cbba0-a25c-4794-b1b0-68bec6ac07d9" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtTnEosEcNBN5m1lpU59SK/capture" + }, + "response": { + "bodySize": 1734, + "content": { + "mimeType": "application/json", + "size": 1734, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 4999, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477927, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTnEosEcNBN5m1lpU59SK", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtTnEosEcNBN5m1MO6kmNw", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtToEosEcNBN5m9DE3pCWT", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1734" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:10 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-871cbba0-a25c-4794-b1b0-68bec6ac07d9" + }, + { + "name": "original-request", + "value": "req_WBzAAyH8xjjfKo" + }, + { + "name": "request-id", + "value": "req_WBzAAyH8xjjfKo" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:09.198Z", + "time": 1323, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1323 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionInitializeSessionWebhookHandler_3934145280/Checkout_2840636407/should-work-authorization_889917716/recording.har b/src/modules/webhooks/__recordings__/TransactionInitializeSessionWebhookHandler_3934145280/Checkout_2840636407/should-work-authorization_889917716/recording.har new file mode 100644 index 0000000..98b2739 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionInitializeSessionWebhookHandler_3934145280/Checkout_2840636407/should-work-authorization_889917716/recording.har @@ -0,0 +1,237 @@ +{ + "log": { + "_recordingName": "TransactionInitializeSessionWebhookHandler/'Checkout'/'should work authorization'", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-0cc2cb1f-9c61-4ae0-b1ed-96eb4ffeb3bb" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477936, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTwEosEcNBN5m1thrINip", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:16 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-0cc2cb1f-9c61-4ae0-b1ed-96eb4ffeb3bb" + }, + { + "name": "original-request", + "value": "req_0C68rRb0hNRPhG" + }, + { + "name": "request-id", + "value": "req_0C68rRb0hNRPhG" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:15.637Z", + "time": 765, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 765 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionInitializeSessionWebhookHandler_3934145280/Checkout_2840636407/should-work-charge_2556039247/recording.har b/src/modules/webhooks/__recordings__/TransactionInitializeSessionWebhookHandler_3934145280/Checkout_2840636407/should-work-charge_2556039247/recording.har new file mode 100644 index 0000000..53db48e --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionInitializeSessionWebhookHandler_3934145280/Checkout_2840636407/should-work-charge_2556039247/recording.har @@ -0,0 +1,239 @@ +{ + "log": { + "_recordingName": "TransactionInitializeSessionWebhookHandler/'Checkout'/'should work charge'", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "ea24209e006db5387b22524c87199d2e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 242, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "242" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-10a7f95a-0d68-4031-902e-b7f5bb992087" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=automatic&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1726, + "content": { + "mimeType": "application/json", + "size": 1726, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477362, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKgEosEcNBN5m0AXKZnAl", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1726" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:43 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-10a7f95a-0d68-4031-902e-b7f5bb992087" + }, + { + "name": "original-request", + "value": "req_VqDg0JK0odJf8g" + }, + { + "name": "request-id", + "value": "req_VqDg0JK0odJf8g" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:38.801Z", + "time": 4228, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 4228 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionInitializeSessionWebhookHandler_3934145280/Order_2373458299/should-work-authorization_889917716/recording.har b/src/modules/webhooks/__recordings__/TransactionInitializeSessionWebhookHandler_3934145280/Order_2373458299/should-work-authorization_889917716/recording.har new file mode 100644 index 0000000..37af267 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionInitializeSessionWebhookHandler_3934145280/Order_2373458299/should-work-authorization_889917716/recording.har @@ -0,0 +1,237 @@ +{ + "log": { + "_recordingName": "TransactionInitializeSessionWebhookHandler/'Order'/'should work authorization'", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "67918559ef1ec636cc345882a4bfb879", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 236, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "236" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-568f2173-068e-4940-aed5-30313fe04dbe" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[orderId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1692, + "content": { + "mimeType": "application/json", + "size": 1692, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477363, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKhEosEcNBN5m0azoRql7", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "orderId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1692" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:44 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-568f2173-068e-4940-aed5-30313fe04dbe" + }, + { + "name": "original-request", + "value": "req_a12aPn6M36br5G" + }, + { + "name": "request-id", + "value": "req_a12aPn6M36br5G" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:43.041Z", + "time": 839, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 839 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionInitializeSessionWebhookHandler_3934145280/Order_2373458299/should-work-charge_2556039247/recording.har b/src/modules/webhooks/__recordings__/TransactionInitializeSessionWebhookHandler_3934145280/Order_2373458299/should-work-charge_2556039247/recording.har new file mode 100644 index 0000000..6441f1d --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionInitializeSessionWebhookHandler_3934145280/Order_2373458299/should-work-charge_2556039247/recording.har @@ -0,0 +1,239 @@ +{ + "log": { + "_recordingName": "TransactionInitializeSessionWebhookHandler/'Order'/'should work charge'", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "bb497bd5def96386e277ed45cc818347", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-40c1f4ab-848a-4bb8-9d52-c0687d5e3850" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=automatic&metadata[transactionId]=555555&metadata[channelId]=1&metadata[orderId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1723, + "content": { + "mimeType": "application/json", + "size": 1723, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477364, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtKiEosEcNBN5m0BWDtnvo", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "orderId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1723" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:22:44 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-40c1f4ab-848a-4bb8-9d52-c0687d5e3850" + }, + { + "name": "original-request", + "value": "req_BPVkwJAHgAgCV4" + }, + { + "name": "request-id", + "value": "req_BPVkwJAHgAgCV4" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:22:43.888Z", + "time": 413, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 413 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionProcessSessionWebhookHandler_1802350267/Checkout_2840636407/should-work-authorization_889917716/recording.har b/src/modules/webhooks/__recordings__/TransactionProcessSessionWebhookHandler_1802350267/Checkout_2840636407/should-work-authorization_889917716/recording.har new file mode 100644 index 0000000..720a398 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionProcessSessionWebhookHandler_1802350267/Checkout_2840636407/should-work-authorization_889917716/recording.har @@ -0,0 +1,460 @@ +{ + "log": { + "_recordingName": "TransactionProcessSessionWebhookHandler/'Checkout'/'should work authorization'", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-4aaf29a3-8680-4cad-be8c-9b73dac9f932" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477432, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtLoEosEcNBN5m03gE6sKO", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:52 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-4aaf29a3-8680-4cad-be8c-9b73dac9f932" + }, + { + "name": "original-request", + "value": "req_Q0hgMtsLSpstqd" + }, + { + "name": "request-id", + "value": "req_Q0hgMtsLSpstqd" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:51.576Z", + "time": 879, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 879 + } + }, + { + "_id": "e834f25d173be089c0a36c73e969b8d7", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 150, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "150" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-a014d2aa-5c26-4566-a5f3-194cb75dddb6" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 842, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtLoEosEcNBN5m03gE6sKO" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477432, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtLoEosEcNBN5m03gE6sKO", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:39:34 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-a014d2aa-5c26-4566-a5f3-194cb75dddb6" + }, + { + "name": "original-request", + "value": "req_0WmAPJBXBCvlDZ" + }, + { + "name": "request-id", + "value": "req_0WmAPJBXBCvlDZ" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1107, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:39:33.806Z", + "time": 884, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 884 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionProcessSessionWebhookHandler_1802350267/Checkout_2840636407/should-work-charge_2556039247/recording.har b/src/modules/webhooks/__recordings__/TransactionProcessSessionWebhookHandler_1802350267/Checkout_2840636407/should-work-charge_2556039247/recording.har new file mode 100644 index 0000000..fd1ae28 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionProcessSessionWebhookHandler_1802350267/Checkout_2840636407/should-work-charge_2556039247/recording.har @@ -0,0 +1,464 @@ +{ + "log": { + "_recordingName": "TransactionProcessSessionWebhookHandler/'Checkout'/'should work charge'", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "ea24209e006db5387b22524c87199d2e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 242, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "242" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-5726a9f8-e450-48ee-a4ba-9cf5dc333083" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=automatic&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1726, + "content": { + "mimeType": "application/json", + "size": 1726, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477930, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTqEosEcNBN5m0cCQupT5", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1726" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:10 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-5726a9f8-e450-48ee-a4ba-9cf5dc333083" + }, + { + "name": "original-request", + "value": "req_i64Cndc3ULOsrk" + }, + { + "name": "request-id", + "value": "req_i64Cndc3ULOsrk" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:09.535Z", + "time": 694, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 694 + } + }, + { + "_id": "5b5c00f5f16d2cf60f1a5af9150a10cf", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 153, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "153" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-0ad52497-efc2-4112-9f0b-ed704959cda4" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 842, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount=22299¤cy=PLN&capture_method=automatic&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtTqEosEcNBN5m0cCQupT5" + }, + "response": { + "bodySize": 1726, + "content": { + "mimeType": "application/json", + "size": 1726, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477930, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTqEosEcNBN5m0cCQupT5", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1726" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:39:35 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-0ad52497-efc2-4112-9f0b-ed704959cda4" + }, + { + "name": "original-request", + "value": "req_NDQPDlaFNLfIrn" + }, + { + "name": "request-id", + "value": "req_NDQPDlaFNLfIrn" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1107, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:39:34.729Z", + "time": 652, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 652 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionProcessSessionWebhookHandler_1802350267/Order_2373458299/should-work-authorization_889917716/recording.har b/src/modules/webhooks/__recordings__/TransactionProcessSessionWebhookHandler_1802350267/Order_2373458299/should-work-authorization_889917716/recording.har new file mode 100644 index 0000000..ec10378 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionProcessSessionWebhookHandler_1802350267/Order_2373458299/should-work-authorization_889917716/recording.har @@ -0,0 +1,460 @@ +{ + "log": { + "_recordingName": "TransactionProcessSessionWebhookHandler/'Order'/'should work authorization'", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "67918559ef1ec636cc345882a4bfb879", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 236, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "236" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-6b7b7ada-436b-4124-a82e-d9f16579dc67" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[orderId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1692, + "content": { + "mimeType": "application/json", + "size": 1692, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477931, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTrEosEcNBN5m0OJVvvKc", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "orderId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1692" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:11 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-6b7b7ada-436b-4124-a82e-d9f16579dc67" + }, + { + "name": "original-request", + "value": "req_1qvyqJhz8sMlO6" + }, + { + "name": "request-id", + "value": "req_1qvyqJhz8sMlO6" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:10.844Z", + "time": 467, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 467 + } + }, + { + "_id": "a538223377b166dc5509d6cc494f7bc4", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 147, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "147" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-1aef54e1-2700-4bea-b359-583fcbef3b8f" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 842, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[orderId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtTrEosEcNBN5m0OJVvvKc" + }, + "response": { + "bodySize": 1692, + "content": { + "mimeType": "application/json", + "size": 1692, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477931, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTrEosEcNBN5m0OJVvvKc", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "orderId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1692" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:39:35 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-1aef54e1-2700-4bea-b359-583fcbef3b8f" + }, + { + "name": "original-request", + "value": "req_DfA4oXaQ81a7Bj" + }, + { + "name": "request-id", + "value": "req_DfA4oXaQ81a7Bj" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1107, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:39:35.391Z", + "time": 417, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 417 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionProcessSessionWebhookHandler_1802350267/Order_2373458299/should-work-charge_2556039247/recording.har b/src/modules/webhooks/__recordings__/TransactionProcessSessionWebhookHandler_1802350267/Order_2373458299/should-work-charge_2556039247/recording.har new file mode 100644 index 0000000..1320de0 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionProcessSessionWebhookHandler_1802350267/Order_2373458299/should-work-charge_2556039247/recording.har @@ -0,0 +1,464 @@ +{ + "log": { + "_recordingName": "TransactionProcessSessionWebhookHandler/'Order'/'should work charge'", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "bb497bd5def96386e277ed45cc818347", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-8f46ae8f-dc8c-4ddf-8af3-67589182e2cc" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=automatic&metadata[transactionId]=555555&metadata[channelId]=1&metadata[orderId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1723, + "content": { + "mimeType": "application/json", + "size": 1723, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477932, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTsEosEcNBN5m0H7sQ5zA", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "orderId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1723" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:12 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-8f46ae8f-dc8c-4ddf-8af3-67589182e2cc" + }, + { + "name": "original-request", + "value": "req_eicnfPp6NJmiFy" + }, + { + "name": "request-id", + "value": "req_eicnfPp6NJmiFy" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:11.685Z", + "time": 423, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 423 + } + }, + { + "_id": "97ba992430db31cd470af291f7078761", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 150, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "150" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-a0ba58bd-3d2c-4612-842d-f0e8973d92cc" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 842, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount=22299¤cy=PLN&capture_method=automatic&metadata[transactionId]=555555&metadata[channelId]=1&metadata[orderId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtTsEosEcNBN5m0H7sQ5zA" + }, + "response": { + "bodySize": 1723, + "content": { + "mimeType": "application/json", + "size": 1723, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477932, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTsEosEcNBN5m0H7sQ5zA", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "orderId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1723" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:39:36 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-a0ba58bd-3d2c-4612-842d-f0e8973d92cc" + }, + { + "name": "original-request", + "value": "req_2x2KEq9mDHZyxd" + }, + { + "name": "request-id", + "value": "req_2x2KEq9mDHZyxd" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1107, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:39:35.816Z", + "time": 422, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 422 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/American-Express-pm_card_amex_1702901941/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/American-Express-pm_card_amex_1702901941/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har new file mode 100644 index 0000000..acfb9f3 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/American-Express-pm_card_amex_1702901941/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har @@ -0,0 +1,639 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'American Express' 'pm_card_amex'/should request a partial refund in Stripe after a charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "ea24209e006db5387b22524c87199d2e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 242, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "242" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-5d315471-57f2-4b0e-9bc2-132750cd8d31" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=automatic&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1726, + "content": { + "mimeType": "application/json", + "size": 1726, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477994, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUsEosEcNBN5m0afvhrrn", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1726" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:14 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-5d315471-57f2-4b0e-9bc2-132750cd8d31" + }, + { + "name": "original-request", + "value": "req_FocPCi4B5PvFZA" + }, + { + "name": "request-id", + "value": "req_FocPCi4B5PvFZA" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:13.991Z", + "time": 406, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 406 + } + }, + { + "_id": "c72bfcce5f8d9566f4ec1166fadb5729", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 27, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "27" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-a1055ee6-1456-4449-82de-ffed2da9a2f9" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_amex" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtUsEosEcNBN5m0afvhrrn/confirm" + }, + "response": { + "bodySize": 1766, + "content": { + "mimeType": "application/json", + "size": 1766, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477994, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUsEosEcNBN5m0afvhrrn", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtUsEosEcNBN5m0To5qAL0", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtUsEosEcNBN5mBJtIVdJU", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1766" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:15 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-a1055ee6-1456-4449-82de-ffed2da9a2f9" + }, + { + "name": "original-request", + "value": "req_GCUSxXzFezLFPy" + }, + { + "name": "request-id", + "value": "req_GCUSxXzFezLFPy" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:14.398Z", + "time": 1401, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1401 + } + }, + { + "_id": "84e2615f87fb556d63e2040712b487f7", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 54, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "54" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-cbf81d73-0cd4-486c-93e7-ad2abbba4249" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtUsEosEcNBN5m0afvhrrn&amount=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 615, + "content": { + "mimeType": "application/json", + "size": 615, + "text": { + "amount": 4999, + "balance_transaction": "txn_3OMtUsEosEcNBN5m07iCuG9u", + "charge": "ch_3OMtUsEosEcNBN5m0To5qAL0", + "created": 1702477996, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtUsEosEcNBN5m0RgxCHdv", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtUsEosEcNBN5m0afvhrrn", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "615" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:16 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-cbf81d73-0cd4-486c-93e7-ad2abbba4249" + }, + { + "name": "original-request", + "value": "req_qjaBw2D3IL5sQa" + }, + { + "name": "request-id", + "value": "req_qjaBw2D3IL5sQa" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:15.800Z", + "time": 1106, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1106 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/American-Express-pm_card_amex_1702901941/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/American-Express-pm_card_amex_1702901941/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har new file mode 100644 index 0000000..2489355 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/American-Express-pm_card_amex_1702901941/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har @@ -0,0 +1,858 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'American Express' 'pm_card_amex'/should request a partial refund in Stripe after authorize and charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-3956c654-30c2-4983-9c50-a1b665cb4856" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477990, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUoEosEcNBN5m1Fgfbmo7", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:11 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-3956c654-30c2-4983-9c50-a1b665cb4856" + }, + { + "name": "original-request", + "value": "req_B82ZqAgtRXbqDF" + }, + { + "name": "request-id", + "value": "req_B82ZqAgtRXbqDF" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:10.480Z", + "time": 416, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 416 + } + }, + { + "_id": "757f8846ae07e17449006bbe1e0d5696", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 27, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "27" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-7555178d-6ee6-4422-a07c-71c33247c6a3" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_amex" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtUoEosEcNBN5m1Fgfbmo7/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477990, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUoEosEcNBN5m1Fgfbmo7", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtUoEosEcNBN5m1a91vv8R", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtUpEosEcNBN5mTIGTK8zj", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:12 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-7555178d-6ee6-4422-a07c-71c33247c6a3" + }, + { + "name": "original-request", + "value": "req_0fLu72F84KjmIW" + }, + { + "name": "request-id", + "value": "req_0fLu72F84KjmIW" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:10.898Z", + "time": 1286, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1286 + } + }, + { + "_id": "bf21021fb33192ea20d84d72d140892d", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-3d5b1b48-5522-4d8c-8ca9-f1f6a9c10133" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtUoEosEcNBN5m1Fgfbmo7/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477990, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUoEosEcNBN5m1Fgfbmo7", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtUoEosEcNBN5m1a91vv8R", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtUpEosEcNBN5mTIGTK8zj", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:13 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-3d5b1b48-5522-4d8c-8ca9-f1f6a9c10133" + }, + { + "name": "original-request", + "value": "req_lK4DWGfKRF0uHD" + }, + { + "name": "request-id", + "value": "req_lK4DWGfKRF0uHD" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:12.186Z", + "time": 851, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 851 + } + }, + { + "_id": "57d39a5111ea39fcf032600c9d74fd81", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 54, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "54" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-65562ec3-79e1-4f10-aa50-3411cbb5e8aa" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtUoEosEcNBN5m1Fgfbmo7&amount=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 615, + "content": { + "mimeType": "application/json", + "size": 615, + "text": { + "amount": 4999, + "balance_transaction": "txn_3OMtUoEosEcNBN5m1YnzpEsA", + "charge": "ch_3OMtUoEosEcNBN5m1a91vv8R", + "created": 1702477993, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtUoEosEcNBN5m11h9amRg", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtUoEosEcNBN5m1Fgfbmo7", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "615" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:14 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-65562ec3-79e1-4f10-aa50-3411cbb5e8aa" + }, + { + "name": "original-request", + "value": "req_rQ1UUqNe4RdyML" + }, + { + "name": "request-id", + "value": "req_rQ1UUqNe4RdyML" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:13.038Z", + "time": 947, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 947 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/American-Express-pm_card_amex_1702901941/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/American-Express-pm_card_amex_1702901941/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har new file mode 100644 index 0000000..f53b6ac --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/American-Express-pm_card_amex_1702901941/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har @@ -0,0 +1,639 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'American Express' 'pm_card_amex'/should request a refund in Stripe after a charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "ea24209e006db5387b22524c87199d2e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 242, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "242" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b3ea49a2-80c4-4479-a858-df56cd73c2b4" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=automatic&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1726, + "content": { + "mimeType": "application/json", + "size": 1726, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477988, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUmEosEcNBN5m1rrndFFI", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1726" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:08 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b3ea49a2-80c4-4479-a858-df56cd73c2b4" + }, + { + "name": "original-request", + "value": "req_mgMQxZxG2KoZ91" + }, + { + "name": "request-id", + "value": "req_mgMQxZxG2KoZ91" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:07.728Z", + "time": 576, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 576 + } + }, + { + "_id": "c4efb409cb321254a37937c8e3f21359", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 27, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "27" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-943b8c2a-0157-4085-a1be-8bc55f2b0a65" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_amex" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtUmEosEcNBN5m1rrndFFI/confirm" + }, + "response": { + "bodySize": 1766, + "content": { + "mimeType": "application/json", + "size": 1766, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477988, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUmEosEcNBN5m1rrndFFI", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtUmEosEcNBN5m1bDMmzRP", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtUmEosEcNBN5mbqvsvxEw", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1766" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:09 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-943b8c2a-0157-4085-a1be-8bc55f2b0a65" + }, + { + "name": "original-request", + "value": "req_A7UbnSw5eBew9b" + }, + { + "name": "request-id", + "value": "req_A7UbnSw5eBew9b" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:08.306Z", + "time": 1253, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1253 + } + }, + { + "_id": "648117c182f20926199ec4a0fffa5dbc", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 55, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "55" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-997353fc-4577-4ca2-a159-5d79c3a7008b" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtUmEosEcNBN5m1rrndFFI&amount=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 616, + "content": { + "mimeType": "application/json", + "size": 616, + "text": { + "amount": 22299, + "balance_transaction": "txn_3OMtUmEosEcNBN5m1yj5xj4D", + "charge": "ch_3OMtUmEosEcNBN5m1bDMmzRP", + "created": 1702477990, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtUmEosEcNBN5m1vYf5koK", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtUmEosEcNBN5m1rrndFFI", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "616" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:10 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-997353fc-4577-4ca2-a159-5d79c3a7008b" + }, + { + "name": "original-request", + "value": "req_BxXi6skigTizbj" + }, + { + "name": "request-id", + "value": "req_BxXi6skigTizbj" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:09.561Z", + "time": 914, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 914 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/American-Express-pm_card_amex_1702901941/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/American-Express-pm_card_amex_1702901941/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har new file mode 100644 index 0000000..a65c15a --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/American-Express-pm_card_amex_1702901941/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har @@ -0,0 +1,858 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'American Express' 'pm_card_amex'/should request a refund in Stripe after authorize and charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-792c6da9-67ba-4d63-a347-7ae421f51481" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477984, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUiEosEcNBN5m1qTwePuz", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:04 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-792c6da9-67ba-4d63-a347-7ae421f51481" + }, + { + "name": "original-request", + "value": "req_qLnWhTes0sGMyo" + }, + { + "name": "request-id", + "value": "req_qLnWhTes0sGMyo" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:04.268Z", + "time": 389, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 389 + } + }, + { + "_id": "5ec45c0716aec524fc5f4c3b52ea2c82", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 27, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "27" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-59fd0a83-45a6-4897-953c-8fabb74b949e" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_amex" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtUiEosEcNBN5m1qTwePuz/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477984, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUiEosEcNBN5m1qTwePuz", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtUiEosEcNBN5m1fD8JGm5", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtUjEosEcNBN5mmJ5P2OC4", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:05 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-59fd0a83-45a6-4897-953c-8fabb74b949e" + }, + { + "name": "original-request", + "value": "req_OKnaizAkP6F4f7" + }, + { + "name": "request-id", + "value": "req_OKnaizAkP6F4f7" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:04.658Z", + "time": 1202, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1202 + } + }, + { + "_id": "bfc641d0524428c811b50d9b831cf9d2", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-5ea97abc-aa97-49d7-be9d-63013faa983b" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtUiEosEcNBN5m1qTwePuz/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477984, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUiEosEcNBN5m1qTwePuz", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtUiEosEcNBN5m1fD8JGm5", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtUjEosEcNBN5mmJ5P2OC4", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:06 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-5ea97abc-aa97-49d7-be9d-63013faa983b" + }, + { + "name": "original-request", + "value": "req_QGiusqtcRkU1I7" + }, + { + "name": "request-id", + "value": "req_QGiusqtcRkU1I7" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:05.862Z", + "time": 907, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 907 + } + }, + { + "_id": "3d32853228cfcb5d574640e27b67219e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 55, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "55" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-8a66fb42-94ee-4b70-9a9c-c99e6373b9d6" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtUiEosEcNBN5m1qTwePuz&amount=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 616, + "content": { + "mimeType": "application/json", + "size": 616, + "text": { + "amount": 22299, + "balance_transaction": "txn_3OMtUiEosEcNBN5m1FPOy9FW", + "charge": "ch_3OMtUiEosEcNBN5m1fD8JGm5", + "created": 1702477987, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtUiEosEcNBN5m1DdZT1cI", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtUiEosEcNBN5m1qTwePuz", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "616" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:07 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-8a66fb42-94ee-4b70-9a9c-c99e6373b9d6" + }, + { + "name": "original-request", + "value": "req_SgU0uD9827Ix1z" + }, + { + "name": "request-id", + "value": "req_SgU0uD9827Ix1z" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:06.771Z", + "time": 952, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 952 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Diners-Club-pm_card_diners_3136405054/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Diners-Club-pm_card_diners_3136405054/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har new file mode 100644 index 0000000..e077512 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Diners-Club-pm_card_diners_3136405054/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har @@ -0,0 +1,639 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Diners Club' 'pm_card_diners'/should request a partial refund in Stripe after a charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "ea24209e006db5387b22524c87199d2e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 242, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "242" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-4e87aac9-0dea-43a3-9620-a0a557fdd81e" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=automatic&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1726, + "content": { + "mimeType": "application/json", + "size": 1726, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478022, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtVKEosEcNBN5m0RY5sht2", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1726" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:43 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-4e87aac9-0dea-43a3-9620-a0a557fdd81e" + }, + { + "name": "original-request", + "value": "req_TPqcKtVyWU0Yf6" + }, + { + "name": "request-id", + "value": "req_TPqcKtVyWU0Yf6" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:42.503Z", + "time": 515, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 515 + } + }, + { + "_id": "04366c71688551a2efcbc722af2cd4d6", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 29, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "29" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-40ba1c11-3d9c-42cc-9e06-1df6da4dacf2" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_diners" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtVKEosEcNBN5m0RY5sht2/confirm" + }, + "response": { + "bodySize": 1766, + "content": { + "mimeType": "application/json", + "size": 1766, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478022, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtVKEosEcNBN5m0RY5sht2", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtVKEosEcNBN5m0YXZj2od", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtVLEosEcNBN5mfv98PNhX", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1766" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:44 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-40ba1c11-3d9c-42cc-9e06-1df6da4dacf2" + }, + { + "name": "original-request", + "value": "req_BBuw3aD3pau3cX" + }, + { + "name": "request-id", + "value": "req_BBuw3aD3pau3cX" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:43.021Z", + "time": 1261, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1261 + } + }, + { + "_id": "ba5dfb170734b2ba0d1070feab46bcf4", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 54, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "54" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-7e82dd39-ea6b-499b-8efc-9b77bb4c64b6" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtVKEosEcNBN5m0RY5sht2&amount=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 615, + "content": { + "mimeType": "application/json", + "size": 615, + "text": { + "amount": 4999, + "balance_transaction": "txn_3OMtVKEosEcNBN5m0FomoFN3", + "charge": "ch_3OMtVKEosEcNBN5m0YXZj2od", + "created": 1702478024, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtVKEosEcNBN5m0MjoLbw6", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtVKEosEcNBN5m0RY5sht2", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "615" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:45 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-7e82dd39-ea6b-499b-8efc-9b77bb4c64b6" + }, + { + "name": "original-request", + "value": "req_lD0s1mfBZC75hy" + }, + { + "name": "request-id", + "value": "req_lD0s1mfBZC75hy" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:44.284Z", + "time": 953, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 953 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Diners-Club-pm_card_diners_3136405054/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Diners-Club-pm_card_diners_3136405054/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har new file mode 100644 index 0000000..e2cc79f --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Diners-Club-pm_card_diners_3136405054/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har @@ -0,0 +1,858 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Diners Club' 'pm_card_diners'/should request a partial refund in Stripe after authorize and charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-fcaa6de6-b2be-4277-a209-2de275233c12" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478019, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtVHEosEcNBN5m1UFoBwJ8", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:39 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-fcaa6de6-b2be-4277-a209-2de275233c12" + }, + { + "name": "original-request", + "value": "req_Y0ELpMZEiWxCgn" + }, + { + "name": "request-id", + "value": "req_Y0ELpMZEiWxCgn" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:38.945Z", + "time": 440, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 440 + } + }, + { + "_id": "eed8d990cba9625bf34efb1ba129363e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 29, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "29" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-35e9478d-eb51-470f-92b8-cdaec49a795a" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_diners" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtVHEosEcNBN5m1UFoBwJ8/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478019, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtVHEosEcNBN5m1UFoBwJ8", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtVHEosEcNBN5m18EftjhL", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtVHEosEcNBN5m7fUFQw3n", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:40 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-35e9478d-eb51-470f-92b8-cdaec49a795a" + }, + { + "name": "original-request", + "value": "req_DQDH8GGjlBDhwR" + }, + { + "name": "request-id", + "value": "req_DQDH8GGjlBDhwR" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:39.386Z", + "time": 1092, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1092 + } + }, + { + "_id": "ab5c92c6ca0a783ebdff76a131b9a571", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-cc05ae4a-e959-42fa-9939-5cce7415dcd5" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtVHEosEcNBN5m1UFoBwJ8/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478019, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtVHEosEcNBN5m1UFoBwJ8", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtVHEosEcNBN5m18EftjhL", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtVHEosEcNBN5m7fUFQw3n", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:41 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-cc05ae4a-e959-42fa-9939-5cce7415dcd5" + }, + { + "name": "original-request", + "value": "req_cUOrfUsawX5VMT" + }, + { + "name": "request-id", + "value": "req_cUOrfUsawX5VMT" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:40.480Z", + "time": 1002, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1002 + } + }, + { + "_id": "133963d13e0c28031c88824aaa4f9c7a", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 54, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "54" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-abee6239-54c0-4671-88ac-3ae6f2ae858f" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtVHEosEcNBN5m1UFoBwJ8&amount=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 615, + "content": { + "mimeType": "application/json", + "size": 615, + "text": { + "amount": 4999, + "balance_transaction": "txn_3OMtVHEosEcNBN5m1pN6ww9L", + "charge": "ch_3OMtVHEosEcNBN5m18EftjhL", + "created": 1702478021, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtVHEosEcNBN5m1Vq4UmP4", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtVHEosEcNBN5m1UFoBwJ8", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "615" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:42 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-abee6239-54c0-4671-88ac-3ae6f2ae858f" + }, + { + "name": "original-request", + "value": "req_QgTygDzXjTF0w7" + }, + { + "name": "request-id", + "value": "req_QgTygDzXjTF0w7" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:41.484Z", + "time": 1013, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1013 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Diners-Club-pm_card_diners_3136405054/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Diners-Club-pm_card_diners_3136405054/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har new file mode 100644 index 0000000..f8f91c8 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Diners-Club-pm_card_diners_3136405054/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har @@ -0,0 +1,639 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Diners Club' 'pm_card_diners'/should request a refund in Stripe after a charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "ea24209e006db5387b22524c87199d2e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 242, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "242" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-0fa6a324-0ff2-4262-ac30-a0b08cea6728" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=automatic&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1726, + "content": { + "mimeType": "application/json", + "size": 1726, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478016, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtVEEosEcNBN5m1B5q9Z79", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1726" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:36 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-0fa6a324-0ff2-4262-ac30-a0b08cea6728" + }, + { + "name": "original-request", + "value": "req_tvLflQMasMNumE" + }, + { + "name": "request-id", + "value": "req_tvLflQMasMNumE" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:35.958Z", + "time": 521, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 521 + } + }, + { + "_id": "8d3539fafc54994ce9a1abbc865dcbac", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 29, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "29" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-ce3900fd-0da5-49a7-bbd3-3f5fa8082e4a" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_diners" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtVEEosEcNBN5m1B5q9Z79/confirm" + }, + "response": { + "bodySize": 1766, + "content": { + "mimeType": "application/json", + "size": 1766, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478016, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtVEEosEcNBN5m1B5q9Z79", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtVEEosEcNBN5m1hNX7fc7", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtVEEosEcNBN5m43urUKqA", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1766" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:37 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-ce3900fd-0da5-49a7-bbd3-3f5fa8082e4a" + }, + { + "name": "original-request", + "value": "req_ID9HNWN03HfLPu" + }, + { + "name": "request-id", + "value": "req_ID9HNWN03HfLPu" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:36.480Z", + "time": 1623, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1623 + } + }, + { + "_id": "b76fa50e0d503710d21a18a224480f22", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 55, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "55" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-c7e0bcf2-483e-4f98-b6a6-a539e934d409" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtVEEosEcNBN5m1B5q9Z79&amount=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 616, + "content": { + "mimeType": "application/json", + "size": 616, + "text": { + "amount": 22299, + "balance_transaction": "txn_3OMtVEEosEcNBN5m1xS95gq1", + "charge": "ch_3OMtVEEosEcNBN5m1hNX7fc7", + "created": 1702478018, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtVEEosEcNBN5m1yX9om0o", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtVEEosEcNBN5m1B5q9Z79", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "616" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:39 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-c7e0bcf2-483e-4f98-b6a6-a539e934d409" + }, + { + "name": "original-request", + "value": "req_tW6DzUgvaxVj0p" + }, + { + "name": "request-id", + "value": "req_tW6DzUgvaxVj0p" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:38.107Z", + "time": 834, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 834 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Diners-Club-pm_card_diners_3136405054/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Diners-Club-pm_card_diners_3136405054/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har new file mode 100644 index 0000000..c01612c --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Diners-Club-pm_card_diners_3136405054/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har @@ -0,0 +1,858 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Diners Club' 'pm_card_diners'/should request a refund in Stripe after authorize and charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-caf1342e-77dc-4307-b66e-5104e73b45d0" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478011, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtV9EosEcNBN5m02LJi31k", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:31 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-caf1342e-77dc-4307-b66e-5104e73b45d0" + }, + { + "name": "original-request", + "value": "req_EYJryP51PVBsjA" + }, + { + "name": "request-id", + "value": "req_EYJryP51PVBsjA" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:30.360Z", + "time": 905, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 905 + } + }, + { + "_id": "86e5bf8595b80a4fc62eb9b3e13db961", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 29, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "29" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-7bdab999-cd7c-42cd-8efb-e57a98128515" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_diners" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtV9EosEcNBN5m02LJi31k/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478011, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtV9EosEcNBN5m02LJi31k", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtV9EosEcNBN5m0mClvUZG", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtV9EosEcNBN5m7Z6avYTX", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:32 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-7bdab999-cd7c-42cd-8efb-e57a98128515" + }, + { + "name": "original-request", + "value": "req_XuSgJMI4yOwKo4" + }, + { + "name": "request-id", + "value": "req_XuSgJMI4yOwKo4" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:31.266Z", + "time": 1036, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1036 + } + }, + { + "_id": "8b8a631d104b7894bdb861d7bfbcbdfe", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-5f4981df-83d3-49dd-b2ea-e01c1e1b71be" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtV9EosEcNBN5m02LJi31k/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478011, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtV9EosEcNBN5m02LJi31k", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtV9EosEcNBN5m0mClvUZG", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtV9EosEcNBN5m7Z6avYTX", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:34 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-5f4981df-83d3-49dd-b2ea-e01c1e1b71be" + }, + { + "name": "original-request", + "value": "req_11EPT0yLmOHdmJ" + }, + { + "name": "request-id", + "value": "req_11EPT0yLmOHdmJ" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:32.304Z", + "time": 2480, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 2480 + } + }, + { + "_id": "069275a3f9d3495fd67aa5b93219d1b2", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 55, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "55" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-53065094-fee0-4757-b049-b42adbc74087" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtV9EosEcNBN5m02LJi31k&amount=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 616, + "content": { + "mimeType": "application/json", + "size": 616, + "text": { + "amount": 22299, + "balance_transaction": "txn_3OMtV9EosEcNBN5m039QwH6I", + "charge": "ch_3OMtV9EosEcNBN5m0mClvUZG", + "created": 1702478015, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtV9EosEcNBN5m0jmPgeAH", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtV9EosEcNBN5m02LJi31k", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "616" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:35 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-53065094-fee0-4757-b049-b42adbc74087" + }, + { + "name": "original-request", + "value": "req_yMtStaTewcg2XR" + }, + { + "name": "request-id", + "value": "req_yMtStaTewcg2XR" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:34.786Z", + "time": 1168, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1168 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Discover-pm_card_discover_3985489676/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Discover-pm_card_discover_3985489676/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har new file mode 100644 index 0000000..6843e29 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Discover-pm_card_discover_3985489676/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har @@ -0,0 +1,639 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Discover' 'pm_card_discover'/should request a partial refund in Stripe after a charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "ea24209e006db5387b22524c87199d2e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 242, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "242" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-9b5c4f45-b8ce-4274-ad53-e10b64ff6a02" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=automatic&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1726, + "content": { + "mimeType": "application/json", + "size": 1726, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478007, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtV5EosEcNBN5m0Qw75V0b", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1726" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:27 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-9b5c4f45-b8ce-4274-ad53-e10b64ff6a02" + }, + { + "name": "original-request", + "value": "req_WzD3TMIJONXSx7" + }, + { + "name": "request-id", + "value": "req_WzD3TMIJONXSx7" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:27.091Z", + "time": 442, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 442 + } + }, + { + "_id": "9e53ecc3ed4cfc17099a984472323dd4", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 31, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "31" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-9ee7b067-a277-4337-b9ba-7d7c1459dcc7" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_discover" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtV5EosEcNBN5m0Qw75V0b/confirm" + }, + "response": { + "bodySize": 1766, + "content": { + "mimeType": "application/json", + "size": 1766, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478007, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtV5EosEcNBN5m0Qw75V0b", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtV5EosEcNBN5m06JyOpAz", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtV5EosEcNBN5mg1rmpcAv", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1766" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:29 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-9ee7b067-a277-4337-b9ba-7d7c1459dcc7" + }, + { + "name": "original-request", + "value": "req_hWVVUtexBGeY74" + }, + { + "name": "request-id", + "value": "req_hWVVUtexBGeY74" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:27.535Z", + "time": 1406, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1406 + } + }, + { + "_id": "cdba550bbe97b0b4e6acbd3155282aaa", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 54, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "54" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-ad90ae4c-f48f-49bb-8da3-90e80b455b1d" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtV5EosEcNBN5m0Qw75V0b&amount=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 615, + "content": { + "mimeType": "application/json", + "size": 615, + "text": { + "amount": 4999, + "balance_transaction": "txn_3OMtV5EosEcNBN5m0mkcJhyS", + "charge": "ch_3OMtV5EosEcNBN5m06JyOpAz", + "created": 1702478009, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtV5EosEcNBN5m0S2c3Ozu", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtV5EosEcNBN5m0Qw75V0b", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "615" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:30 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-ad90ae4c-f48f-49bb-8da3-90e80b455b1d" + }, + { + "name": "original-request", + "value": "req_uLT3iZLHg7rOr4" + }, + { + "name": "request-id", + "value": "req_uLT3iZLHg7rOr4" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:28.942Z", + "time": 1412, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1412 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Discover-pm_card_discover_3985489676/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Discover-pm_card_discover_3985489676/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har new file mode 100644 index 0000000..81e6ec5 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Discover-pm_card_discover_3985489676/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har @@ -0,0 +1,858 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Discover' 'pm_card_discover'/should request a partial refund in Stripe after authorize and charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-122dfbf3-d514-4149-adbd-4322d31d9980" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478003, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtV1EosEcNBN5m10MpZbCu", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:23 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-122dfbf3-d514-4149-adbd-4322d31d9980" + }, + { + "name": "original-request", + "value": "req_Fr8Hk7nLPH28Fv" + }, + { + "name": "request-id", + "value": "req_Fr8Hk7nLPH28Fv" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:23.096Z", + "time": 472, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 472 + } + }, + { + "_id": "24c9d5e44489cff64466685ea03f0964", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 31, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "31" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b0ba4995-e92c-4e75-825b-b1ea525cd009" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_discover" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtV1EosEcNBN5m10MpZbCu/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478003, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtV1EosEcNBN5m10MpZbCu", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtV1EosEcNBN5m1GtwbWHP", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtV1EosEcNBN5mBpH1BuNm", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:24 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b0ba4995-e92c-4e75-825b-b1ea525cd009" + }, + { + "name": "original-request", + "value": "req_A5tkTgOf2aMlQs" + }, + { + "name": "request-id", + "value": "req_A5tkTgOf2aMlQs" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:23.570Z", + "time": 1231, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1231 + } + }, + { + "_id": "174e1a7beebfd458666b8cbc3009bc5b", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-a73a0f45-6634-4e91-a75a-1b2565d3ddea" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtV1EosEcNBN5m10MpZbCu/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478003, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtV1EosEcNBN5m10MpZbCu", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtV1EosEcNBN5m1GtwbWHP", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtV1EosEcNBN5mBpH1BuNm", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:26 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-a73a0f45-6634-4e91-a75a-1b2565d3ddea" + }, + { + "name": "original-request", + "value": "req_hANJq4J5DiWwPr" + }, + { + "name": "request-id", + "value": "req_hANJq4J5DiWwPr" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:24.803Z", + "time": 1125, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1125 + } + }, + { + "_id": "77a32594c0b75b4ddda850a3c8fc69b4", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 54, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "54" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-3ca3f2d8-864d-4ac4-bd42-1f9f0e96bd4e" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtV1EosEcNBN5m10MpZbCu&amount=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 615, + "content": { + "mimeType": "application/json", + "size": 615, + "text": { + "amount": 4999, + "balance_transaction": "txn_3OMtV1EosEcNBN5m1g6GtODg", + "charge": "ch_3OMtV1EosEcNBN5m1GtwbWHP", + "created": 1702478006, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtV1EosEcNBN5m1CnXAyRa", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtV1EosEcNBN5m10MpZbCu", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "615" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:27 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-3ca3f2d8-864d-4ac4-bd42-1f9f0e96bd4e" + }, + { + "name": "original-request", + "value": "req_63E6X07ev9ZQiV" + }, + { + "name": "request-id", + "value": "req_63E6X07ev9ZQiV" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:25.930Z", + "time": 1156, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1156 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Discover-pm_card_discover_3985489676/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Discover-pm_card_discover_3985489676/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har new file mode 100644 index 0000000..1929a6b --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Discover-pm_card_discover_3985489676/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har @@ -0,0 +1,639 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Discover' 'pm_card_discover'/should request a refund in Stripe after a charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "ea24209e006db5387b22524c87199d2e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 242, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "242" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-c6db5f50-b555-4f19-bee0-78fdc7ba5051" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=automatic&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1726, + "content": { + "mimeType": "application/json", + "size": 1726, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478000, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUyEosEcNBN5m072sWUP4", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1726" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:20 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-c6db5f50-b555-4f19-bee0-78fdc7ba5051" + }, + { + "name": "original-request", + "value": "req_730MQJAi0tlmW3" + }, + { + "name": "request-id", + "value": "req_730MQJAi0tlmW3" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:20.291Z", + "time": 437, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 437 + } + }, + { + "_id": "49ef7f8962be185d3800df2527c95118", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 31, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "31" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-c2342f95-7285-47b6-8111-731543f8ea87" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_discover" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtUyEosEcNBN5m072sWUP4/confirm" + }, + "response": { + "bodySize": 1766, + "content": { + "mimeType": "application/json", + "size": 1766, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478000, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUyEosEcNBN5m072sWUP4", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtUyEosEcNBN5m0GkphJd8", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtUzEosEcNBN5mDU4t79bj", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1766" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:22 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-c2342f95-7285-47b6-8111-731543f8ea87" + }, + { + "name": "original-request", + "value": "req_wUIueEA3UidcX5" + }, + { + "name": "request-id", + "value": "req_wUIueEA3UidcX5" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:20.729Z", + "time": 1369, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1369 + } + }, + { + "_id": "3bd6e57634dc7dca70ed5f3059b5afac", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 55, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "55" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-4fbdfdbd-ee47-4389-a73c-c4f741e1d77f" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtUyEosEcNBN5m072sWUP4&amount=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 616, + "content": { + "mimeType": "application/json", + "size": 616, + "text": { + "amount": 22299, + "balance_transaction": "txn_3OMtUyEosEcNBN5m02e4UNVA", + "charge": "ch_3OMtUyEosEcNBN5m0GkphJd8", + "created": 1702478002, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtUyEosEcNBN5m0197OR9M", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtUyEosEcNBN5m072sWUP4", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "616" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:23 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-4fbdfdbd-ee47-4389-a73c-c4f741e1d77f" + }, + { + "name": "original-request", + "value": "req_5CKM6jZpADmkXQ" + }, + { + "name": "request-id", + "value": "req_5CKM6jZpADmkXQ" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:22.099Z", + "time": 993, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 993 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Discover-pm_card_discover_3985489676/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Discover-pm_card_discover_3985489676/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har new file mode 100644 index 0000000..01a2115 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Discover-pm_card_discover_3985489676/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har @@ -0,0 +1,858 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Discover' 'pm_card_discover'/should request a refund in Stripe after authorize and charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-7cdd7aff-975b-43d6-9940-49a06e41924b" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477997, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUvEosEcNBN5m0qDxLLSr", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:17 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-7cdd7aff-975b-43d6-9940-49a06e41924b" + }, + { + "name": "original-request", + "value": "req_XMJRZUaABMkQP7" + }, + { + "name": "request-id", + "value": "req_XMJRZUaABMkQP7" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:16.912Z", + "time": 422, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 422 + } + }, + { + "_id": "48f085bbff76d50f2bd5bf28f77718d5", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 31, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "31" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-ba7ee4bf-f5c1-4be3-bcfc-a6cae33ff307" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_discover" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtUvEosEcNBN5m0qDxLLSr/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477997, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUvEosEcNBN5m0qDxLLSr", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtUvEosEcNBN5m0tKN0BES", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtUvEosEcNBN5mFG0Hvww7", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:18 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-ba7ee4bf-f5c1-4be3-bcfc-a6cae33ff307" + }, + { + "name": "original-request", + "value": "req_pzR4sb0BsuhsVm" + }, + { + "name": "request-id", + "value": "req_pzR4sb0BsuhsVm" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:17.335Z", + "time": 1046, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1046 + } + }, + { + "_id": "dffc2a0427cb2053073d49fcebdc6257", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-e16c6196-c110-4ec8-86de-3f65abfa179c" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtUvEosEcNBN5m0qDxLLSr/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477997, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUvEosEcNBN5m0qDxLLSr", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtUvEosEcNBN5m0tKN0BES", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtUvEosEcNBN5mFG0Hvww7", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:19 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-e16c6196-c110-4ec8-86de-3f65abfa179c" + }, + { + "name": "original-request", + "value": "req_q6nPSGJr0clWKU" + }, + { + "name": "request-id", + "value": "req_q6nPSGJr0clWKU" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:18.383Z", + "time": 831, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 831 + } + }, + { + "_id": "1d77cf8d63b2cdc04f724b6af0b28362", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 55, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "55" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-74788808-7180-47c2-81a2-d4826ee8a8d9" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtUvEosEcNBN5m0qDxLLSr&amount=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 616, + "content": { + "mimeType": "application/json", + "size": 616, + "text": { + "amount": 22299, + "balance_transaction": "txn_3OMtUvEosEcNBN5m0ImB6xcY", + "charge": "ch_3OMtUvEosEcNBN5m0tKN0BES", + "created": 1702477999, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtUvEosEcNBN5m0tx81cV7", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtUvEosEcNBN5m0qDxLLSr", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "616" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:20 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-74788808-7180-47c2-81a2-d4826ee8a8d9" + }, + { + "name": "original-request", + "value": "req_gxp3dv0sOqgh4q" + }, + { + "name": "request-id", + "value": "req_gxp3dv0sOqgh4q" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:19.215Z", + "time": 1071, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1071 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har new file mode 100644 index 0000000..7d79969 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har @@ -0,0 +1,639 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Mastercard (debit)' 'pm_card_mastercard_debit'/should request a partial refund in Stripe after a charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "ea24209e006db5387b22524c87199d2e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 242, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "242" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-d9fdcc06-0a16-450d-882b-98f23cc2bee3" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=automatic&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1726, + "content": { + "mimeType": "application/json", + "size": 1726, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477969, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUTEosEcNBN5m0qGNVhZV", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1726" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:49 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-d9fdcc06-0a16-450d-882b-98f23cc2bee3" + }, + { + "name": "original-request", + "value": "req_W7QNTfmFVCsF24" + }, + { + "name": "request-id", + "value": "req_W7QNTfmFVCsF24" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:49.075Z", + "time": 498, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 498 + } + }, + { + "_id": "851efd1fe4a13991fb68e5f42a7e7faf", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 39, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "39" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-72e649ed-28ec-420d-aac4-df864e6af89d" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_mastercard_debit" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtUTEosEcNBN5m0qGNVhZV/confirm" + }, + "response": { + "bodySize": 1766, + "content": { + "mimeType": "application/json", + "size": 1766, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477969, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUTEosEcNBN5m0qGNVhZV", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtUTEosEcNBN5m0vikBAnt", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtUTEosEcNBN5m7nAeXluR", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1766" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:50 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-72e649ed-28ec-420d-aac4-df864e6af89d" + }, + { + "name": "original-request", + "value": "req_xoR3DEvQ7TYAhq" + }, + { + "name": "request-id", + "value": "req_xoR3DEvQ7TYAhq" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:49.574Z", + "time": 1230, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1230 + } + }, + { + "_id": "e781b2f4db948c9082d51a8f84585e68", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 54, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "54" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-d7fdd6ea-e2de-421d-8962-659e2b569697" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtUTEosEcNBN5m0qGNVhZV&amount=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 615, + "content": { + "mimeType": "application/json", + "size": 615, + "text": { + "amount": 4999, + "balance_transaction": "txn_3OMtUTEosEcNBN5m0orbqL7K", + "charge": "ch_3OMtUTEosEcNBN5m0vikBAnt", + "created": 1702477971, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtUTEosEcNBN5m0fL972wR", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtUTEosEcNBN5m0qGNVhZV", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "615" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:51 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-d7fdd6ea-e2de-421d-8962-659e2b569697" + }, + { + "name": "original-request", + "value": "req_UFxIk8yT8nVNna" + }, + { + "name": "request-id", + "value": "req_UFxIk8yT8nVNna" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:50.806Z", + "time": 1033, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1033 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har new file mode 100644 index 0000000..620dfef --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har @@ -0,0 +1,858 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Mastercard (debit)' 'pm_card_mastercard_debit'/should request a partial refund in Stripe after authorize and charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-bfc13dfd-575c-465a-8400-c04cba57d2f9" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477966, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUQEosEcNBN5m0jyThYnp", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:46 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-bfc13dfd-575c-465a-8400-c04cba57d2f9" + }, + { + "name": "original-request", + "value": "req_PxCWslVBrMDUtP" + }, + { + "name": "request-id", + "value": "req_PxCWslVBrMDUtP" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:45.900Z", + "time": 415, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 415 + } + }, + { + "_id": "b7bb39e2e494b89ffc29c0667182e907", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 39, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "39" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-e38edc36-92ab-4388-b009-58e7efe4d078" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_mastercard_debit" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtUQEosEcNBN5m0jyThYnp/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477966, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUQEosEcNBN5m0jyThYnp", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtUQEosEcNBN5m0r3QrN7r", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtUQEosEcNBN5mS9mQ8W48", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:47 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-e38edc36-92ab-4388-b009-58e7efe4d078" + }, + { + "name": "original-request", + "value": "req_eZo7jhfn6hMvAr" + }, + { + "name": "request-id", + "value": "req_eZo7jhfn6hMvAr" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:46.317Z", + "time": 1015, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1015 + } + }, + { + "_id": "172d0b3789b3f73632aa3b2f15e6d122", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-c312f6de-fc45-487f-86ae-37817a5370e7" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtUQEosEcNBN5m0jyThYnp/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477966, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUQEosEcNBN5m0jyThYnp", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtUQEosEcNBN5m0r3QrN7r", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtUQEosEcNBN5mS9mQ8W48", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:48 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-c312f6de-fc45-487f-86ae-37817a5370e7" + }, + { + "name": "original-request", + "value": "req_jIKK7bu9D6ZxKO" + }, + { + "name": "request-id", + "value": "req_jIKK7bu9D6ZxKO" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:47.334Z", + "time": 822, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 822 + } + }, + { + "_id": "8560de93a4c49691bd2c5869d85793b1", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 54, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "54" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-5754ce83-5053-4c70-9fd7-c6147f99c280" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtUQEosEcNBN5m0jyThYnp&amount=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 615, + "content": { + "mimeType": "application/json", + "size": 615, + "text": { + "amount": 4999, + "balance_transaction": "txn_3OMtUQEosEcNBN5m04VNmHOD", + "charge": "ch_3OMtUQEosEcNBN5m0r3QrN7r", + "created": 1702477968, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtUQEosEcNBN5m06V1nlxU", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtUQEosEcNBN5m0jyThYnp", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "615" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:49 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-5754ce83-5053-4c70-9fd7-c6147f99c280" + }, + { + "name": "original-request", + "value": "req_fuR7y6jJxjVB9v" + }, + { + "name": "request-id", + "value": "req_fuR7y6jJxjVB9v" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:48.157Z", + "time": 912, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 912 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har new file mode 100644 index 0000000..fc3d722 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har @@ -0,0 +1,639 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Mastercard (debit)' 'pm_card_mastercard_debit'/should request a refund in Stripe after a charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "ea24209e006db5387b22524c87199d2e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 242, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "242" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-2319589e-e593-4015-b46e-f5d12f601ba4" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=automatic&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1726, + "content": { + "mimeType": "application/json", + "size": 1726, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477963, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUNEosEcNBN5m0DLkrTn8", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1726" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:43 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-2319589e-e593-4015-b46e-f5d12f601ba4" + }, + { + "name": "original-request", + "value": "req_pdkqRi8At3gOgE" + }, + { + "name": "request-id", + "value": "req_pdkqRi8At3gOgE" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:43.181Z", + "time": 446, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 446 + } + }, + { + "_id": "0edb4aff79e33c915008f31a24171099", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 39, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "39" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b5773281-733e-4705-b8e0-59563ac686ea" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_mastercard_debit" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtUNEosEcNBN5m0DLkrTn8/confirm" + }, + "response": { + "bodySize": 1766, + "content": { + "mimeType": "application/json", + "size": 1766, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477963, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUNEosEcNBN5m0DLkrTn8", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtUNEosEcNBN5m0xg4HClX", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtUOEosEcNBN5mq6uto8dl", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1766" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:45 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b5773281-733e-4705-b8e0-59563ac686ea" + }, + { + "name": "original-request", + "value": "req_6g8dmOyfUEWEDD" + }, + { + "name": "request-id", + "value": "req_6g8dmOyfUEWEDD" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:43.628Z", + "time": 1278, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1278 + } + }, + { + "_id": "8ee00a7f4e77644fdcc0fba919a570a3", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 55, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "55" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-2731c07b-56bc-4242-9c7b-f5e02eb42d42" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtUNEosEcNBN5m0DLkrTn8&amount=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 616, + "content": { + "mimeType": "application/json", + "size": 616, + "text": { + "amount": 22299, + "balance_transaction": "txn_3OMtUNEosEcNBN5m07n5kUWL", + "charge": "ch_3OMtUNEosEcNBN5m0xg4HClX", + "created": 1702477965, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtUNEosEcNBN5m0vJMpKhN", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtUNEosEcNBN5m0DLkrTn8", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "616" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:46 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-2731c07b-56bc-4242-9c7b-f5e02eb42d42" + }, + { + "name": "original-request", + "value": "req_GpDdxl6uMLlg1N" + }, + { + "name": "request-id", + "value": "req_GpDdxl6uMLlg1N" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:44.908Z", + "time": 987, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 987 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har new file mode 100644 index 0000000..0c0664e --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-debit-pm_card_mastercard_debit_1832142636/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har @@ -0,0 +1,858 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Mastercard (debit)' 'pm_card_mastercard_debit'/should request a refund in Stripe after authorize and charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-41ffd425-728b-4248-9dc8-6fc4fa899fc8" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477960, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUKEosEcNBN5m14WdjF3D", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:40 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-41ffd425-728b-4248-9dc8-6fc4fa899fc8" + }, + { + "name": "original-request", + "value": "req_qIsVZFYOvUbfAX" + }, + { + "name": "request-id", + "value": "req_qIsVZFYOvUbfAX" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:39.903Z", + "time": 392, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 392 + } + }, + { + "_id": "7925351b2b1c4f15b8e77daf77580cad", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 39, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "39" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b50437db-b837-48db-a99a-9b64f5001355" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_mastercard_debit" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtUKEosEcNBN5m14WdjF3D/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477960, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUKEosEcNBN5m14WdjF3D", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtUKEosEcNBN5m1fazCRcj", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtUKEosEcNBN5mzkjWYNZv", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:41 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b50437db-b837-48db-a99a-9b64f5001355" + }, + { + "name": "original-request", + "value": "req_CW44jkxkzI8GTQ" + }, + { + "name": "request-id", + "value": "req_CW44jkxkzI8GTQ" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:40.297Z", + "time": 1133, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1133 + } + }, + { + "_id": "137ccf4b6547c0bf2b739ac08c5ac69e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-ae0001c3-e947-40f1-b866-db95ae2cc99a" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtUKEosEcNBN5m14WdjF3D/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477960, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUKEosEcNBN5m14WdjF3D", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtUKEosEcNBN5m1fazCRcj", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtUKEosEcNBN5mzkjWYNZv", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:42 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-ae0001c3-e947-40f1-b866-db95ae2cc99a" + }, + { + "name": "original-request", + "value": "req_jiIDKVVFks4O6g" + }, + { + "name": "request-id", + "value": "req_jiIDKVVFks4O6g" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:41.432Z", + "time": 809, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 809 + } + }, + { + "_id": "41457d92ffb9fd39a614beced1f49fcb", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 55, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "55" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-3b07e459-03e4-429a-ae73-c30846dfa16f" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtUKEosEcNBN5m14WdjF3D&amount=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 616, + "content": { + "mimeType": "application/json", + "size": 616, + "text": { + "amount": 22299, + "balance_transaction": "txn_3OMtUKEosEcNBN5m12DuLFLP", + "charge": "ch_3OMtUKEosEcNBN5m1fazCRcj", + "created": 1702477962, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtUKEosEcNBN5m1MDvDmIP", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtUKEosEcNBN5m14WdjF3D", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "616" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:43 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-3b07e459-03e4-429a-ae73-c30846dfa16f" + }, + { + "name": "original-request", + "value": "req_vDQh9tE5jHmWHN" + }, + { + "name": "request-id", + "value": "req_vDQh9tE5jHmWHN" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:42.247Z", + "time": 928, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 928 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-pm_card_mastercard_3189003338/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-pm_card_mastercard_3189003338/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har new file mode 100644 index 0000000..80b7235 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-pm_card_mastercard_3189003338/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har @@ -0,0 +1,639 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Mastercard' 'pm_card_mastercard'/should request a partial refund in Stripe after a charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "ea24209e006db5387b22524c87199d2e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 242, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "242" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-7ca7c4b4-f0bf-49fb-88b9-4f55c570cc4e" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=automatic&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1726, + "content": { + "mimeType": "application/json", + "size": 1726, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477957, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUHEosEcNBN5m0n5ZF8Ve", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1726" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:37 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-7ca7c4b4-f0bf-49fb-88b9-4f55c570cc4e" + }, + { + "name": "original-request", + "value": "req_bo4S0jTZxyZfxV" + }, + { + "name": "request-id", + "value": "req_bo4S0jTZxyZfxV" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:36.750Z", + "time": 445, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 445 + } + }, + { + "_id": "3dbc4e342010f9f4b8b73fef05c43f6e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 33, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "33" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b0da2add-2569-4e35-8348-111d6b3e289d" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_mastercard" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtUHEosEcNBN5m0n5ZF8Ve/confirm" + }, + "response": { + "bodySize": 1766, + "content": { + "mimeType": "application/json", + "size": 1766, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477957, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUHEosEcNBN5m0n5ZF8Ve", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtUHEosEcNBN5m0pqUC1rZ", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtUHEosEcNBN5mgZHmvBax", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1766" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:38 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b0da2add-2569-4e35-8348-111d6b3e289d" + }, + { + "name": "original-request", + "value": "req_DgrGzMNSS2f88B" + }, + { + "name": "request-id", + "value": "req_DgrGzMNSS2f88B" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:37.197Z", + "time": 1804, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1804 + } + }, + { + "_id": "b22fa026416833c54a2e4031eb2b3552", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 54, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "54" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-40c35395-eec2-4cda-b6e0-4c68c423ca94" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtUHEosEcNBN5m0n5ZF8Ve&amount=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 615, + "content": { + "mimeType": "application/json", + "size": 615, + "text": { + "amount": 4999, + "balance_transaction": "txn_3OMtUHEosEcNBN5m0xG5Giec", + "charge": "ch_3OMtUHEosEcNBN5m0pqUC1rZ", + "created": 1702477959, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtUHEosEcNBN5m0hJh32JL", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtUHEosEcNBN5m0n5ZF8Ve", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "615" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:40 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-40c35395-eec2-4cda-b6e0-4c68c423ca94" + }, + { + "name": "original-request", + "value": "req_nvzHWjCr9viKcE" + }, + { + "name": "request-id", + "value": "req_nvzHWjCr9viKcE" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:39.002Z", + "time": 897, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 897 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-pm_card_mastercard_3189003338/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-pm_card_mastercard_3189003338/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har new file mode 100644 index 0000000..a16b300 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-pm_card_mastercard_3189003338/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har @@ -0,0 +1,858 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Mastercard' 'pm_card_mastercard'/should request a partial refund in Stripe after authorize and charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-53fa52fb-302c-4d5f-83a0-4d88bc8822aa" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477953, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUDEosEcNBN5m0ZtEr5pu", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:33 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-53fa52fb-302c-4d5f-83a0-4d88bc8822aa" + }, + { + "name": "original-request", + "value": "req_ZXxixj5jCHIjpm" + }, + { + "name": "request-id", + "value": "req_ZXxixj5jCHIjpm" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:33.268Z", + "time": 396, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 396 + } + }, + { + "_id": "9ebee0ef8bb443fa88366551a8f62a6e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 33, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "33" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-517d9fe4-7f37-49f4-b510-f55a09ef9d62" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_mastercard" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtUDEosEcNBN5m0ZtEr5pu/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477953, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUDEosEcNBN5m0ZtEr5pu", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtUDEosEcNBN5m0Tme5Tq4", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtUEEosEcNBN5mMcZ5gE5s", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:34 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-517d9fe4-7f37-49f4-b510-f55a09ef9d62" + }, + { + "name": "original-request", + "value": "req_UW6puFlTZCcTYn" + }, + { + "name": "request-id", + "value": "req_UW6puFlTZCcTYn" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:33.665Z", + "time": 1160, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1160 + } + }, + { + "_id": "eefb04b211d5d1d150e075735337ea8c", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-1cde50e0-bb95-46de-b07e-18ea03bb9f56" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtUDEosEcNBN5m0ZtEr5pu/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477953, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUDEosEcNBN5m0ZtEr5pu", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtUDEosEcNBN5m0Tme5Tq4", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtUEEosEcNBN5mMcZ5gE5s", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:35 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-1cde50e0-bb95-46de-b07e-18ea03bb9f56" + }, + { + "name": "original-request", + "value": "req_vtrQQSxvQRh2I8" + }, + { + "name": "request-id", + "value": "req_vtrQQSxvQRh2I8" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:34.827Z", + "time": 842, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 842 + } + }, + { + "_id": "cfe5bb717c27d6ac045466e24965a4ba", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 54, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "54" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-d2e0cb9b-73f6-4ef1-b7bc-a6f359ba008f" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtUDEosEcNBN5m0ZtEr5pu&amount=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 615, + "content": { + "mimeType": "application/json", + "size": 615, + "text": { + "amount": 4999, + "balance_transaction": "txn_3OMtUDEosEcNBN5m0grWekAV", + "charge": "ch_3OMtUDEosEcNBN5m0Tme5Tq4", + "created": 1702477956, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtUDEosEcNBN5m06gLiB6U", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtUDEosEcNBN5m0ZtEr5pu", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "615" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:36 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-d2e0cb9b-73f6-4ef1-b7bc-a6f359ba008f" + }, + { + "name": "original-request", + "value": "req_Bu7mc2OY4QyGHo" + }, + { + "name": "request-id", + "value": "req_Bu7mc2OY4QyGHo" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:35.671Z", + "time": 1075, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1075 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-pm_card_mastercard_3189003338/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-pm_card_mastercard_3189003338/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har new file mode 100644 index 0000000..00e4822 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-pm_card_mastercard_3189003338/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har @@ -0,0 +1,639 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Mastercard' 'pm_card_mastercard'/should request a refund in Stripe after a charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "ea24209e006db5387b22524c87199d2e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 242, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "242" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-d216b9c8-e0a0-4c57-85bc-8028fbcc2b11" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=automatic&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1726, + "content": { + "mimeType": "application/json", + "size": 1726, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477950, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUAEosEcNBN5m1BOtJHzx", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1726" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:30 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-d216b9c8-e0a0-4c57-85bc-8028fbcc2b11" + }, + { + "name": "original-request", + "value": "req_77ywrZCVxZT3VV" + }, + { + "name": "request-id", + "value": "req_77ywrZCVxZT3VV" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:30.371Z", + "time": 438, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 438 + } + }, + { + "_id": "0d7475f412de23783cf9b894470ca0cd", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 33, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "33" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-4ec6c97e-c1eb-426b-8442-ef1477e35b27" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_mastercard" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtUAEosEcNBN5m1BOtJHzx/confirm" + }, + "response": { + "bodySize": 1766, + "content": { + "mimeType": "application/json", + "size": 1766, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477950, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUAEosEcNBN5m1BOtJHzx", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtUAEosEcNBN5m14UAP1Um", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtUBEosEcNBN5mHwO8OoaI", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1766" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:32 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-4ec6c97e-c1eb-426b-8442-ef1477e35b27" + }, + { + "name": "original-request", + "value": "req_IlnUYja1rfHfVA" + }, + { + "name": "request-id", + "value": "req_IlnUYja1rfHfVA" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:30.811Z", + "time": 1530, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1530 + } + }, + { + "_id": "b2053eab48a54a9ea80fc393aa79a4c3", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 55, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "55" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-1edaf4cf-e801-444f-a012-05ffa64b8c7a" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtUAEosEcNBN5m1BOtJHzx&amount=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 616, + "content": { + "mimeType": "application/json", + "size": 616, + "text": { + "amount": 22299, + "balance_transaction": "txn_3OMtUAEosEcNBN5m12JxXHR8", + "charge": "ch_3OMtUAEosEcNBN5m14UAP1Um", + "created": 1702477952, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtUAEosEcNBN5m1T0w6xMy", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtUAEosEcNBN5m1BOtJHzx", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "616" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:33 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-1edaf4cf-e801-444f-a012-05ffa64b8c7a" + }, + { + "name": "original-request", + "value": "req_ESVLhWeb0G0ZEy" + }, + { + "name": "request-id", + "value": "req_ESVLhWeb0G0ZEy" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:32.343Z", + "time": 895, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 895 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-pm_card_mastercard_3189003338/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-pm_card_mastercard_3189003338/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har new file mode 100644 index 0000000..8ac3079 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-pm_card_mastercard_3189003338/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har @@ -0,0 +1,858 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Mastercard' 'pm_card_mastercard'/should request a refund in Stripe after authorize and charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-65a760d7-b405-4b97-8011-41e139f4332a" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477947, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtU7EosEcNBN5m1v1gnGOG", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:27 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-65a760d7-b405-4b97-8011-41e139f4332a" + }, + { + "name": "original-request", + "value": "req_CgUvb2OxjxcpHa" + }, + { + "name": "request-id", + "value": "req_CgUvb2OxjxcpHa" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:27.171Z", + "time": 414, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 414 + } + }, + { + "_id": "5b166508d45a4a02b16f413ec2fe5b68", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 33, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "33" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-a074ad04-e9cd-4bc9-a157-13eedf4d52a4" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_mastercard" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtU7EosEcNBN5m1v1gnGOG/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477947, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtU7EosEcNBN5m1v1gnGOG", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtU7EosEcNBN5m1JxSJGcP", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtU7EosEcNBN5mBS5yQTGl", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:28 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-a074ad04-e9cd-4bc9-a157-13eedf4d52a4" + }, + { + "name": "original-request", + "value": "req_TjkUATfW7CE3ct" + }, + { + "name": "request-id", + "value": "req_TjkUATfW7CE3ct" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:27.587Z", + "time": 1052, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1052 + } + }, + { + "_id": "15d5ef59c38edc72675536ec26089f71", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b6e5f03c-a975-4d7b-b40e-e2032e2319db" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtU7EosEcNBN5m1v1gnGOG/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477947, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtU7EosEcNBN5m1v1gnGOG", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtU7EosEcNBN5m1JxSJGcP", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtU7EosEcNBN5mBS5yQTGl", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:29 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b6e5f03c-a975-4d7b-b40e-e2032e2319db" + }, + { + "name": "original-request", + "value": "req_3QmvD4NiTVTHph" + }, + { + "name": "request-id", + "value": "req_3QmvD4NiTVTHph" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:28.641Z", + "time": 831, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 831 + } + }, + { + "_id": "036879d27545ec0c29e1b0235597f365", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 55, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "55" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-56455f67-67f9-4557-8d2a-d57d066700f4" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtU7EosEcNBN5m1v1gnGOG&amount=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 616, + "content": { + "mimeType": "application/json", + "size": 616, + "text": { + "amount": 22299, + "balance_transaction": "txn_3OMtU7EosEcNBN5m1Azrcr4L", + "charge": "ch_3OMtU7EosEcNBN5m1JxSJGcP", + "created": 1702477949, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtU7EosEcNBN5m1Y3zOoLM", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtU7EosEcNBN5m1v1gnGOG", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "616" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:30 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-56455f67-67f9-4557-8d2a-d57d066700f4" + }, + { + "name": "original-request", + "value": "req_JmYPZKqlDiY7iH" + }, + { + "name": "request-id", + "value": "req_JmYPZKqlDiY7iH" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:29.474Z", + "time": 892, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 892 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har new file mode 100644 index 0000000..5a01a3d --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har @@ -0,0 +1,639 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Mastercard (prepaid)' 'pm_card_mastercard_prepaid'/should request a partial refund in Stripe after a charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "ea24209e006db5387b22524c87199d2e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 242, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "242" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b41a47e6-bd17-45df-ba2e-b32ce21192d8" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=automatic&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1726, + "content": { + "mimeType": "application/json", + "size": 1726, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477982, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUgEosEcNBN5m026wt6aU", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1726" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:02 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b41a47e6-bd17-45df-ba2e-b32ce21192d8" + }, + { + "name": "original-request", + "value": "req_ojSsdjQFHT3JGB" + }, + { + "name": "request-id", + "value": "req_ojSsdjQFHT3JGB" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:01.721Z", + "time": 419, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 419 + } + }, + { + "_id": "a7e328e47c200957f16f23b691b3979c", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 41, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "41" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-8422ffe3-0b6b-4fce-ba7c-8310d1d1636c" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_mastercard_prepaid" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtUgEosEcNBN5m026wt6aU/confirm" + }, + "response": { + "bodySize": 1766, + "content": { + "mimeType": "application/json", + "size": 1766, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477982, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUgEosEcNBN5m026wt6aU", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtUgEosEcNBN5m0AJk794J", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtUgEosEcNBN5m59KYXftG", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1766" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:03 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-8422ffe3-0b6b-4fce-ba7c-8310d1d1636c" + }, + { + "name": "original-request", + "value": "req_CUFiUWsNRs3VCK" + }, + { + "name": "request-id", + "value": "req_CUFiUWsNRs3VCK" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:02.142Z", + "time": 1191, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1191 + } + }, + { + "_id": "40041a62d47abffc21000936a9f44480", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 54, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "54" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-1695a87e-6ef5-4277-aedd-6b4f93634ec5" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtUgEosEcNBN5m026wt6aU&amount=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 615, + "content": { + "mimeType": "application/json", + "size": 615, + "text": { + "amount": 4999, + "balance_transaction": "txn_3OMtUgEosEcNBN5m04RO2mYF", + "charge": "ch_3OMtUgEosEcNBN5m0AJk794J", + "created": 1702477983, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtUgEosEcNBN5m0ptIF4sb", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtUgEosEcNBN5m026wt6aU", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "615" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:04 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-1695a87e-6ef5-4277-aedd-6b4f93634ec5" + }, + { + "name": "original-request", + "value": "req_2aZtDJT1vS6I0U" + }, + { + "name": "request-id", + "value": "req_2aZtDJT1vS6I0U" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:03.334Z", + "time": 931, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 931 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har new file mode 100644 index 0000000..af62fcf --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har @@ -0,0 +1,858 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Mastercard (prepaid)' 'pm_card_mastercard_prepaid'/should request a partial refund in Stripe after authorize and charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-20e54dab-fc45-4269-adc8-c7c8918cfb66" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477978, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUcEosEcNBN5m1hS1SuRC", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:59 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-20e54dab-fc45-4269-adc8-c7c8918cfb66" + }, + { + "name": "original-request", + "value": "req_2SUab6EWEE9MmE" + }, + { + "name": "request-id", + "value": "req_2SUab6EWEE9MmE" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:58.529Z", + "time": 416, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 416 + } + }, + { + "_id": "5c4c7256c58c8d16826701729878730b", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 41, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "41" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-db7f8068-bd0c-4ee2-bcaf-5bd22c40e9b5" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_mastercard_prepaid" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtUcEosEcNBN5m1hS1SuRC/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477978, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUcEosEcNBN5m1hS1SuRC", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtUcEosEcNBN5m1IvWmxQg", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtUdEosEcNBN5mw63nuLYM", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:00 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-db7f8068-bd0c-4ee2-bcaf-5bd22c40e9b5" + }, + { + "name": "original-request", + "value": "req_4eNARksdCJL2ui" + }, + { + "name": "request-id", + "value": "req_4eNARksdCJL2ui" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:58.947Z", + "time": 1047, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1047 + } + }, + { + "_id": "c75b8238134882c19d251b25c49c7210", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-aaebff00-7471-4dcc-9825-833a710dcdb9" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtUcEosEcNBN5m1hS1SuRC/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477978, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUcEosEcNBN5m1hS1SuRC", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtUcEosEcNBN5m1IvWmxQg", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtUdEosEcNBN5mw63nuLYM", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:00 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-aaebff00-7471-4dcc-9825-833a710dcdb9" + }, + { + "name": "original-request", + "value": "req_6o0QxMXE6HYUU4" + }, + { + "name": "request-id", + "value": "req_6o0QxMXE6HYUU4" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:59.996Z", + "time": 779, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 779 + } + }, + { + "_id": "37134a604892387dd8b11c9fd2f13f7c", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 54, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "54" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-cdbbf49e-e43f-4e19-b5c7-ceb032b2c8a5" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtUcEosEcNBN5m1hS1SuRC&amount=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 615, + "content": { + "mimeType": "application/json", + "size": 615, + "text": { + "amount": 4999, + "balance_transaction": "txn_3OMtUcEosEcNBN5m1agZIMrY", + "charge": "ch_3OMtUcEosEcNBN5m1IvWmxQg", + "created": 1702477981, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtUcEosEcNBN5m1VLmm0vZ", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtUcEosEcNBN5m1hS1SuRC", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "615" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:01 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-cdbbf49e-e43f-4e19-b5c7-ceb032b2c8a5" + }, + { + "name": "original-request", + "value": "req_cPWV737h99uySc" + }, + { + "name": "request-id", + "value": "req_cPWV737h99uySc" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:00.777Z", + "time": 939, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 939 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har new file mode 100644 index 0000000..8f05023 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har @@ -0,0 +1,639 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Mastercard (prepaid)' 'pm_card_mastercard_prepaid'/should request a refund in Stripe after a charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "ea24209e006db5387b22524c87199d2e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 242, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "242" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-aa8b19d3-50b1-49f0-8644-13ae99fd4864" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=automatic&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1726, + "content": { + "mimeType": "application/json", + "size": 1726, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477975, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUZEosEcNBN5m1LoB6Q1A", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1726" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:56 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-aa8b19d3-50b1-49f0-8644-13ae99fd4864" + }, + { + "name": "original-request", + "value": "req_Vgg1c1BvYazoKf" + }, + { + "name": "request-id", + "value": "req_Vgg1c1BvYazoKf" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:55.326Z", + "time": 670, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 670 + } + }, + { + "_id": "2dfa5ef2a047845dceb9f1d1052cc394", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 41, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "41" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-c506ac63-5ce3-4f72-8af1-ed332fd336c1" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_mastercard_prepaid" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtUZEosEcNBN5m1LoB6Q1A/confirm" + }, + "response": { + "bodySize": 1766, + "content": { + "mimeType": "application/json", + "size": 1766, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477975, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUZEosEcNBN5m1LoB6Q1A", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtUZEosEcNBN5m1bRwrPO5", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtUaEosEcNBN5maIyQBfRN", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1766" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:57 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-c506ac63-5ce3-4f72-8af1-ed332fd336c1" + }, + { + "name": "original-request", + "value": "req_7hAzq02MbdwsT7" + }, + { + "name": "request-id", + "value": "req_7hAzq02MbdwsT7" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:55.997Z", + "time": 1571, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1571 + } + }, + { + "_id": "261edab331a5e8c3d1cc31e039484689", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 55, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "55" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-a17c3345-bdfa-4332-85a1-47a0aa7f6d9d" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtUZEosEcNBN5m1LoB6Q1A&amount=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 616, + "content": { + "mimeType": "application/json", + "size": 616, + "text": { + "amount": 22299, + "balance_transaction": "txn_3OMtUZEosEcNBN5m1YE0bLV7", + "charge": "ch_3OMtUZEosEcNBN5m1bRwrPO5", + "created": 1702477978, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtUZEosEcNBN5m1Dczhz28", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtUZEosEcNBN5m1LoB6Q1A", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "616" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:58 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-a17c3345-bdfa-4332-85a1-47a0aa7f6d9d" + }, + { + "name": "original-request", + "value": "req_mpT2yCuly3a6vD" + }, + { + "name": "request-id", + "value": "req_mpT2yCuly3a6vD" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:57.570Z", + "time": 952, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 952 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har new file mode 100644 index 0000000..65d9470 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Mastercard-prepaid-pm_card_mastercard_prepaid_3717248556/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har @@ -0,0 +1,858 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Mastercard (prepaid)' 'pm_card_mastercard_prepaid'/should request a refund in Stripe after authorize and charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-0161ee91-4e5a-4099-81e9-f626c5ba48fb" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477972, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUWEosEcNBN5m0FJKwMBW", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:52 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-0161ee91-4e5a-4099-81e9-f626c5ba48fb" + }, + { + "name": "original-request", + "value": "req_adJb6LWWqBE51y" + }, + { + "name": "request-id", + "value": "req_adJb6LWWqBE51y" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:51.843Z", + "time": 534, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 534 + } + }, + { + "_id": "52159b7603bf93c20b655a695cb23626", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 41, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "41" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-4e2ec903-a9b1-4959-910e-4828150fbe36" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_mastercard_prepaid" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtUWEosEcNBN5m0FJKwMBW/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477972, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUWEosEcNBN5m0FJKwMBW", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtUWEosEcNBN5m0QAFxvwZ", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtUWEosEcNBN5mxauaMF5R", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:53 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-4e2ec903-a9b1-4959-910e-4828150fbe36" + }, + { + "name": "original-request", + "value": "req_2fZ8hzHY5nIvWF" + }, + { + "name": "request-id", + "value": "req_2fZ8hzHY5nIvWF" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:52.378Z", + "time": 1097, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1097 + } + }, + { + "_id": "c18adf9175753c0316a67e3d4c2f198e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-39563b27-4dae-4eaf-b5f8-8ba8f0d3ad2e" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtUWEosEcNBN5m0FJKwMBW/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477972, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtUWEosEcNBN5m0FJKwMBW", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtUWEosEcNBN5m0QAFxvwZ", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtUWEosEcNBN5mxauaMF5R", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:54 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-39563b27-4dae-4eaf-b5f8-8ba8f0d3ad2e" + }, + { + "name": "original-request", + "value": "req_wVVjdbVUlMXnDO" + }, + { + "name": "request-id", + "value": "req_wVVjdbVUlMXnDO" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:53.477Z", + "time": 953, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 953 + } + }, + { + "_id": "0ef37ba7d1bff7a22f43a22b315ae62d", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 55, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "55" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-8c7b9cb6-4cd4-4e26-8ffc-dc7c36098262" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtUWEosEcNBN5m0FJKwMBW&amount=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 616, + "content": { + "mimeType": "application/json", + "size": 616, + "text": { + "amount": 22299, + "balance_transaction": "txn_3OMtUWEosEcNBN5m0F1Fjl58", + "charge": "ch_3OMtUWEosEcNBN5m0QAFxvwZ", + "created": 1702477974, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtUWEosEcNBN5m0pe6IT65", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtUWEosEcNBN5m0FJKwMBW", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "616" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:55 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-8c7b9cb6-4cd4-4e26-8ffc-dc7c36098262" + }, + { + "name": "original-request", + "value": "req_oztslV0teL9039" + }, + { + "name": "request-id", + "value": "req_oztslV0teL9039" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:54.431Z", + "time": 889, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 889 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/UnionPay-pm_card_unionpay_3165217716/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/UnionPay-pm_card_unionpay_3165217716/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har new file mode 100644 index 0000000..bc5db35 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/UnionPay-pm_card_unionpay_3165217716/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har @@ -0,0 +1,639 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'UnionPay' 'pm_card_unionpay'/should request a partial refund in Stripe after a charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "ea24209e006db5387b22524c87199d2e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 242, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "242" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-f6bb511b-5143-4c7f-a1d3-e484a7e55ec6" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=automatic&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1726, + "content": { + "mimeType": "application/json", + "size": 1726, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478034, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtVWEosEcNBN5m0UTNqokz", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1726" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:55 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-f6bb511b-5143-4c7f-a1d3-e484a7e55ec6" + }, + { + "name": "original-request", + "value": "req_QKNtXHgIA34KqH" + }, + { + "name": "request-id", + "value": "req_QKNtXHgIA34KqH" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:54.482Z", + "time": 415, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 415 + } + }, + { + "_id": "49c87f4779dcae028cb9db20f979498b", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 31, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "31" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b4191a4a-e8a3-49ee-af63-b181e684c3aa" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_unionpay" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtVWEosEcNBN5m0UTNqokz/confirm" + }, + "response": { + "bodySize": 1766, + "content": { + "mimeType": "application/json", + "size": 1766, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478034, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtVWEosEcNBN5m0UTNqokz", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtVWEosEcNBN5m0xr5Tn3A", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtVXEosEcNBN5mQlc2TlCt", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1766" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:56 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b4191a4a-e8a3-49ee-af63-b181e684c3aa" + }, + { + "name": "original-request", + "value": "req_wnZdi6vsCecRop" + }, + { + "name": "request-id", + "value": "req_wnZdi6vsCecRop" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:54.898Z", + "time": 1636, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1636 + } + }, + { + "_id": "fc6b3ff4961554465a23e4ca3bf04872", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 54, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "54" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-15f011fc-c082-4ea2-8c94-d1ebcd72b286" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtVWEosEcNBN5m0UTNqokz&amount=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 619, + "content": { + "mimeType": "application/json", + "size": 619, + "text": { + "amount": 4999, + "balance_transaction": "txn_3OMtVWEosEcNBN5m0gln8vpB", + "charge": "ch_3OMtVWEosEcNBN5m0xr5Tn3A", + "created": 1702478037, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "unavailable", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtVWEosEcNBN5m0d7ohrgZ", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtVWEosEcNBN5m0UTNqokz", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "619" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:57 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-15f011fc-c082-4ea2-8c94-d1ebcd72b286" + }, + { + "name": "original-request", + "value": "req_YeAbc9OXzxqmm5" + }, + { + "name": "request-id", + "value": "req_YeAbc9OXzxqmm5" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:56.536Z", + "time": 1011, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1011 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/UnionPay-pm_card_unionpay_3165217716/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/UnionPay-pm_card_unionpay_3165217716/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har new file mode 100644 index 0000000..a521b8f --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/UnionPay-pm_card_unionpay_3165217716/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har @@ -0,0 +1,858 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'UnionPay' 'pm_card_unionpay'/should request a partial refund in Stripe after authorize and charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-72ca7ec4-ebfd-4599-a49e-a5dc23382809" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478031, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtVTEosEcNBN5m0WKw70PL", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:51 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-72ca7ec4-ebfd-4599-a49e-a5dc23382809" + }, + { + "name": "original-request", + "value": "req_ow6A4YMf3Vah24" + }, + { + "name": "request-id", + "value": "req_ow6A4YMf3Vah24" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:51.326Z", + "time": 410, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 410 + } + }, + { + "_id": "b8d2d79599acee53caf99aa98b2aaa1e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 31, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "31" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b196545a-2a5e-4ffb-a42d-361f0f334c78" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_unionpay" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtVTEosEcNBN5m0WKw70PL/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478031, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtVTEosEcNBN5m0WKw70PL", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtVTEosEcNBN5m0XkRvZl9", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtVUEosEcNBN5mA92ER6N0", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:52 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b196545a-2a5e-4ffb-a42d-361f0f334c78" + }, + { + "name": "original-request", + "value": "req_0qt7yO6FXNaaDx" + }, + { + "name": "request-id", + "value": "req_0qt7yO6FXNaaDx" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:51.738Z", + "time": 959, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 959 + } + }, + { + "_id": "1718d0f72f6dbbc817099241266edeb3", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-8ba37a59-037f-4131-97e9-a7e9678383f9" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtVTEosEcNBN5m0WKw70PL/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478031, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtVTEosEcNBN5m0WKw70PL", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtVTEosEcNBN5m0XkRvZl9", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtVUEosEcNBN5mA92ER6N0", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:53 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-8ba37a59-037f-4131-97e9-a7e9678383f9" + }, + { + "name": "original-request", + "value": "req_3ZljGbHom4Xq9Y" + }, + { + "name": "request-id", + "value": "req_3ZljGbHom4Xq9Y" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:52.698Z", + "time": 862, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 862 + } + }, + { + "_id": "24af3a541019b0af40726f8322209da1", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 54, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "54" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-c71cee56-1686-408c-8696-8858bc68ee5b" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtVTEosEcNBN5m0WKw70PL&amount=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 619, + "content": { + "mimeType": "application/json", + "size": 619, + "text": { + "amount": 4999, + "balance_transaction": "txn_3OMtVTEosEcNBN5m0ARp1H1J", + "charge": "ch_3OMtVTEosEcNBN5m0XkRvZl9", + "created": 1702478034, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "unavailable", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtVTEosEcNBN5m02MPXL04", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtVTEosEcNBN5m0WKw70PL", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "619" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:54 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-c71cee56-1686-408c-8696-8858bc68ee5b" + }, + { + "name": "original-request", + "value": "req_URkpU9v8lNXY1f" + }, + { + "name": "request-id", + "value": "req_URkpU9v8lNXY1f" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:53.564Z", + "time": 914, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 914 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/UnionPay-pm_card_unionpay_3165217716/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/UnionPay-pm_card_unionpay_3165217716/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har new file mode 100644 index 0000000..5499e46 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/UnionPay-pm_card_unionpay_3165217716/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har @@ -0,0 +1,639 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'UnionPay' 'pm_card_unionpay'/should request a refund in Stripe after a charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "ea24209e006db5387b22524c87199d2e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 242, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "242" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b24b3de3-c53e-4adb-8db1-70c77045f3e9" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=automatic&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1726, + "content": { + "mimeType": "application/json", + "size": 1726, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478028, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtVQEosEcNBN5m0qNRxOvz", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1726" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:49 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b24b3de3-c53e-4adb-8db1-70c77045f3e9" + }, + { + "name": "original-request", + "value": "req_3SkUt6PPRWkweB" + }, + { + "name": "request-id", + "value": "req_3SkUt6PPRWkweB" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:48.573Z", + "time": 586, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 586 + } + }, + { + "_id": "a5633ceca3e1eff6d080d5ce84f76c80", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 31, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "31" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-1558251e-d31d-4df9-88ec-437b90c8d7fa" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_unionpay" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtVQEosEcNBN5m0qNRxOvz/confirm" + }, + "response": { + "bodySize": 1766, + "content": { + "mimeType": "application/json", + "size": 1766, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478028, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtVQEosEcNBN5m0qNRxOvz", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtVQEosEcNBN5m0RSfCQTJ", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtVREosEcNBN5mdVqrPKrT", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1766" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:50 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-1558251e-d31d-4df9-88ec-437b90c8d7fa" + }, + { + "name": "original-request", + "value": "req_AjOymGDxdlEEWz" + }, + { + "name": "request-id", + "value": "req_AjOymGDxdlEEWz" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:49.160Z", + "time": 1186, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1186 + } + }, + { + "_id": "ff7eeb456e10e1b685183852d3448d8b", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 55, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "55" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-1a119a78-c851-4c48-b4e2-83c3fd186530" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtVQEosEcNBN5m0qNRxOvz&amount=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 620, + "content": { + "mimeType": "application/json", + "size": 620, + "text": { + "amount": 22299, + "balance_transaction": "txn_3OMtVQEosEcNBN5m0qUc8L8W", + "charge": "ch_3OMtVQEosEcNBN5m0RSfCQTJ", + "created": 1702478030, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "unavailable", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtVQEosEcNBN5m0yUTjkUe", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtVQEosEcNBN5m0qNRxOvz", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "620" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:51 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-1a119a78-c851-4c48-b4e2-83c3fd186530" + }, + { + "name": "original-request", + "value": "req_RUwFNoUTHED49O" + }, + { + "name": "request-id", + "value": "req_RUwFNoUTHED49O" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:50.348Z", + "time": 975, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 975 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/UnionPay-pm_card_unionpay_3165217716/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/UnionPay-pm_card_unionpay_3165217716/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har new file mode 100644 index 0000000..af75941 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/UnionPay-pm_card_unionpay_3165217716/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har @@ -0,0 +1,858 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'UnionPay' 'pm_card_unionpay'/should request a refund in Stripe after authorize and charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-804e9e3b-d1ff-426f-b233-a213adceec46" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478025, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtVNEosEcNBN5m0hPvy4SY", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:45 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-804e9e3b-d1ff-426f-b233-a213adceec46" + }, + { + "name": "original-request", + "value": "req_ppLCCiqEFJt8Ns" + }, + { + "name": "request-id", + "value": "req_ppLCCiqEFJt8Ns" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:45.241Z", + "time": 419, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 419 + } + }, + { + "_id": "e7edd21f6cc8ffa3b63f43262cc4a609", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 31, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "31" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-37a86981-1642-4f49-9b57-ed78013e2672" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_unionpay" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtVNEosEcNBN5m0hPvy4SY/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478025, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtVNEosEcNBN5m0hPvy4SY", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtVNEosEcNBN5m00FeIWcJ", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtVOEosEcNBN5mO101InEf", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:46 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-37a86981-1642-4f49-9b57-ed78013e2672" + }, + { + "name": "original-request", + "value": "req_1YTH6juqEvIVI7" + }, + { + "name": "request-id", + "value": "req_1YTH6juqEvIVI7" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:45.661Z", + "time": 1074, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1074 + } + }, + { + "_id": "c6f2b587277d7617d2517bac000f9185", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-1bf4b51f-a14e-47d7-863e-281627f3af67" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtVNEosEcNBN5m0hPvy4SY/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702478025, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtVNEosEcNBN5m0hPvy4SY", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtVNEosEcNBN5m00FeIWcJ", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtVOEosEcNBN5mO101InEf", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:47 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-1bf4b51f-a14e-47d7-863e-281627f3af67" + }, + { + "name": "original-request", + "value": "req_J6YVspofC3arF7" + }, + { + "name": "request-id", + "value": "req_J6YVspofC3arF7" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:46.736Z", + "time": 858, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 858 + } + }, + { + "_id": "da7b06ffe0441b417a00b211af1c8e36", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 55, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "55" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-41c62f50-a331-4770-add0-4bd2c267ba10" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtVNEosEcNBN5m0hPvy4SY&amount=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 620, + "content": { + "mimeType": "application/json", + "size": 620, + "text": { + "amount": 22299, + "balance_transaction": "txn_3OMtVNEosEcNBN5m0EGwURMb", + "charge": "ch_3OMtVNEosEcNBN5m00FeIWcJ", + "created": 1702478028, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "unavailable", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtVNEosEcNBN5m06T6DOFy", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtVNEosEcNBN5m0hPvy4SY", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "620" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:33:48 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-41c62f50-a331-4770-add0-4bd2c267ba10" + }, + { + "name": "original-request", + "value": "req_OsDQhjNKDXidzQ" + }, + { + "name": "request-id", + "value": "req_OsDQhjNKDXidzQ" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:33:47.595Z", + "time": 974, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 974 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-debit-pm_card_visa_debit_2311568982/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-debit-pm_card_visa_debit_2311568982/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har new file mode 100644 index 0000000..23fc56d --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-debit-pm_card_visa_debit_2311568982/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har @@ -0,0 +1,639 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Visa (debit)' 'pm_card_visa_debit'/should request a partial refund in Stripe after a charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "ea24209e006db5387b22524c87199d2e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 242, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "242" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-968bb660-a6b3-4289-b12a-3e4a7099bac3" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=automatic&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1726, + "content": { + "mimeType": "application/json", + "size": 1726, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477944, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtU4EosEcNBN5m1J83qNKR", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1726" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:25 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-968bb660-a6b3-4289-b12a-3e4a7099bac3" + }, + { + "name": "original-request", + "value": "req_wOWMaWzCjO40pQ" + }, + { + "name": "request-id", + "value": "req_wOWMaWzCjO40pQ" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:24.472Z", + "time": 458, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 458 + } + }, + { + "_id": "f3fbe41931e8f15d8b9c886de031d6e2", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 33, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "33" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-9b9c2518-3e02-4fe7-a9ec-081761949ab1" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_visa_debit" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtU4EosEcNBN5m1J83qNKR/confirm" + }, + "response": { + "bodySize": 1766, + "content": { + "mimeType": "application/json", + "size": 1766, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477944, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtU4EosEcNBN5m1J83qNKR", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtU4EosEcNBN5m1nOiQvKN", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtU5EosEcNBN5m25Dqef92", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1766" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:26 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-9b9c2518-3e02-4fe7-a9ec-081761949ab1" + }, + { + "name": "original-request", + "value": "req_bzulkiyB521uAa" + }, + { + "name": "request-id", + "value": "req_bzulkiyB521uAa" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:24.932Z", + "time": 1335, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1335 + } + }, + { + "_id": "9efa564f17ffd0d6b887f15b0bb636db", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 54, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "54" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-52a62dcd-dcbc-42fa-ab6a-791db431bfc2" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtU4EosEcNBN5m1J83qNKR&amount=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 615, + "content": { + "mimeType": "application/json", + "size": 615, + "text": { + "amount": 4999, + "balance_transaction": "txn_3OMtU4EosEcNBN5m16Ns0yYx", + "charge": "ch_3OMtU4EosEcNBN5m1nOiQvKN", + "created": 1702477946, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtU4EosEcNBN5m1MgJlNzy", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtU4EosEcNBN5m1J83qNKR", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "615" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:27 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-52a62dcd-dcbc-42fa-ab6a-791db431bfc2" + }, + { + "name": "original-request", + "value": "req_PXHndrC2gRFhlQ" + }, + { + "name": "request-id", + "value": "req_PXHndrC2gRFhlQ" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:26.268Z", + "time": 898, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 898 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-debit-pm_card_visa_debit_2311568982/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-debit-pm_card_visa_debit_2311568982/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har new file mode 100644 index 0000000..ffbcfe7 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-debit-pm_card_visa_debit_2311568982/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har @@ -0,0 +1,858 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Visa (debit)' 'pm_card_visa_debit'/should request a partial refund in Stripe after authorize and charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-747730f3-be3a-499c-8300-9c3819e2af7c" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477941, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtU1EosEcNBN5m1bYb7B7q", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:21 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-747730f3-be3a-499c-8300-9c3819e2af7c" + }, + { + "name": "original-request", + "value": "req_QEapPT2uhjFXh0" + }, + { + "name": "request-id", + "value": "req_QEapPT2uhjFXh0" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:20.996Z", + "time": 456, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 456 + } + }, + { + "_id": "f4ad25450d2be87d911741cb5d822342", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 33, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "33" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-3f531d78-fe6e-4b00-87a7-b979f2103078" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_visa_debit" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtU1EosEcNBN5m1bYb7B7q/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477941, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtU1EosEcNBN5m1bYb7B7q", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtU1EosEcNBN5m1nl3WlE2", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtU1EosEcNBN5mwSn6cOmn", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:22 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-3f531d78-fe6e-4b00-87a7-b979f2103078" + }, + { + "name": "original-request", + "value": "req_NFOnnMxeqFnIVW" + }, + { + "name": "request-id", + "value": "req_NFOnnMxeqFnIVW" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:21.454Z", + "time": 1154, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1154 + } + }, + { + "_id": "7a4a04e19580c2a0ef0f48140a225692", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-d3baec7c-c3d8-4a81-bf94-22604521d7fc" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtU1EosEcNBN5m1bYb7B7q/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477941, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtU1EosEcNBN5m1bYb7B7q", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtU1EosEcNBN5m1nl3WlE2", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtU1EosEcNBN5mwSn6cOmn", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:23 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-d3baec7c-c3d8-4a81-bf94-22604521d7fc" + }, + { + "name": "original-request", + "value": "req_Q6EJLOuq8rou4e" + }, + { + "name": "request-id", + "value": "req_Q6EJLOuq8rou4e" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:22.611Z", + "time": 894, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 894 + } + }, + { + "_id": "5e1918cb74b307f6610cd08f4b8e2aad", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 54, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "54" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-e6223963-dad3-444a-97aa-6b0e0d4f3ee0" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtU1EosEcNBN5m1bYb7B7q&amount=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 615, + "content": { + "mimeType": "application/json", + "size": 615, + "text": { + "amount": 4999, + "balance_transaction": "txn_3OMtU1EosEcNBN5m1tRIbwIt", + "charge": "ch_3OMtU1EosEcNBN5m1nl3WlE2", + "created": 1702477944, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtU1EosEcNBN5m1ymLRKa0", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtU1EosEcNBN5m1bYb7B7q", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "615" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:24 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-e6223963-dad3-444a-97aa-6b0e0d4f3ee0" + }, + { + "name": "original-request", + "value": "req_xchDSfH3LDtXIc" + }, + { + "name": "request-id", + "value": "req_xchDSfH3LDtXIc" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:23.506Z", + "time": 961, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 961 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-debit-pm_card_visa_debit_2311568982/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-debit-pm_card_visa_debit_2311568982/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har new file mode 100644 index 0000000..c7b854f --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-debit-pm_card_visa_debit_2311568982/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har @@ -0,0 +1,639 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Visa (debit)' 'pm_card_visa_debit'/should request a refund in Stripe after a charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "ea24209e006db5387b22524c87199d2e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 242, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "242" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-14a10ccb-92de-466e-b3c6-c23566b4056c" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=automatic&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1726, + "content": { + "mimeType": "application/json", + "size": 1726, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477938, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTyEosEcNBN5m0uPxft2C", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1726" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:19 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-14a10ccb-92de-466e-b3c6-c23566b4056c" + }, + { + "name": "original-request", + "value": "req_qSiDDJQi9Os3J1" + }, + { + "name": "request-id", + "value": "req_qSiDDJQi9Os3J1" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:18.422Z", + "time": 470, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 470 + } + }, + { + "_id": "5761751f89ac29728fd18f089d6cd73e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 33, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "33" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-36635e95-a053-4ca3-be15-f91d80df1bfc" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_visa_debit" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtTyEosEcNBN5m0uPxft2C/confirm" + }, + "response": { + "bodySize": 1766, + "content": { + "mimeType": "application/json", + "size": 1766, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477938, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTyEosEcNBN5m0uPxft2C", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtTyEosEcNBN5m0C76PchO", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtTzEosEcNBN5mdPiigK6a", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1766" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:20 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-36635e95-a053-4ca3-be15-f91d80df1bfc" + }, + { + "name": "original-request", + "value": "req_gT2li8to7sNGXH" + }, + { + "name": "request-id", + "value": "req_gT2li8to7sNGXH" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:18.894Z", + "time": 1198, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1198 + } + }, + { + "_id": "c5eb376423bf053e6748a7b208833378", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 55, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "55" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b94256e2-5d75-4afb-8b70-9becd22fb836" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtTyEosEcNBN5m0uPxft2C&amount=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 616, + "content": { + "mimeType": "application/json", + "size": 616, + "text": { + "amount": 22299, + "balance_transaction": "txn_3OMtTyEosEcNBN5m0mXzBWOb", + "charge": "ch_3OMtTyEosEcNBN5m0C76PchO", + "created": 1702477940, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtTyEosEcNBN5m0dQshEza", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtTyEosEcNBN5m0uPxft2C", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "616" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:21 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-b94256e2-5d75-4afb-8b70-9becd22fb836" + }, + { + "name": "original-request", + "value": "req_e7bZtbKgmmJyso" + }, + { + "name": "request-id", + "value": "req_e7bZtbKgmmJyso" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:20.093Z", + "time": 899, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 899 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-debit-pm_card_visa_debit_2311568982/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-debit-pm_card_visa_debit_2311568982/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har new file mode 100644 index 0000000..e10c618 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-debit-pm_card_visa_debit_2311568982/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har @@ -0,0 +1,858 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Visa (debit)' 'pm_card_visa_debit'/should request a refund in Stripe after authorize and charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-3a4fdb8a-a8e4-427e-8102-56f22a945217" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477935, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTvEosEcNBN5m0uhsKPAo", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:15 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-3a4fdb8a-a8e4-427e-8102-56f22a945217" + }, + { + "name": "original-request", + "value": "req_iIqA2tl9DcsvCk" + }, + { + "name": "request-id", + "value": "req_iIqA2tl9DcsvCk" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:15.121Z", + "time": 421, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 421 + } + }, + { + "_id": "491cc185f7659afc4f916d10e60729c4", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 33, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "33" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-1bcab8ce-8330-4db4-a2d1-7ef2f84c810c" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_visa_debit" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtTvEosEcNBN5m0uhsKPAo/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477935, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTvEosEcNBN5m0uhsKPAo", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtTvEosEcNBN5m01Aw9Tpc", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtTvEosEcNBN5mmiZdW75P", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:16 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-1bcab8ce-8330-4db4-a2d1-7ef2f84c810c" + }, + { + "name": "original-request", + "value": "req_JWThLcCkHpyNw5" + }, + { + "name": "request-id", + "value": "req_JWThLcCkHpyNw5" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:15.544Z", + "time": 999, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 999 + } + }, + { + "_id": "6d19eeef459e0178fe383537d035d356", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-d953b978-3897-4553-a28a-a9af292cf367" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtTvEosEcNBN5m0uhsKPAo/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477935, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTvEosEcNBN5m0uhsKPAo", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtTvEosEcNBN5m01Aw9Tpc", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtTvEosEcNBN5mmiZdW75P", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:17 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-d953b978-3897-4553-a28a-a9af292cf367" + }, + { + "name": "original-request", + "value": "req_53aAC9EYnhrdZ3" + }, + { + "name": "request-id", + "value": "req_53aAC9EYnhrdZ3" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:16.545Z", + "time": 930, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 930 + } + }, + { + "_id": "db4a14179ea72bdda7aaf94aeb69a9f2", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 55, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "55" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-d14135b2-475a-40d8-ab02-023220a2219c" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtTvEosEcNBN5m0uhsKPAo&amount=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 616, + "content": { + "mimeType": "application/json", + "size": 616, + "text": { + "amount": 22299, + "balance_transaction": "txn_3OMtTvEosEcNBN5m03zY5sSp", + "charge": "ch_3OMtTvEosEcNBN5m01Aw9Tpc", + "created": 1702477937, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtTvEosEcNBN5m0udP5GNr", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtTvEosEcNBN5m0uhsKPAo", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "616" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:18 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-d14135b2-475a-40d8-ab02-023220a2219c" + }, + { + "name": "original-request", + "value": "req_yzjXF5fkeP4jti" + }, + { + "name": "request-id", + "value": "req_yzjXF5fkeP4jti" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:17.477Z", + "time": 939, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 939 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-pm_card_visa_1355345048/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-pm_card_visa_1355345048/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har new file mode 100644 index 0000000..26839f7 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-pm_card_visa_1355345048/should-request-a-partial-refund-in-Stripe-after-a-charge_1798832548/recording.har @@ -0,0 +1,639 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Visa' 'pm_card_visa'/should request a partial refund in Stripe after a charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "ea24209e006db5387b22524c87199d2e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 242, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "242" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-0149f3e5-b507-48fd-a494-32f9b34b9577" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=automatic&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1726, + "content": { + "mimeType": "application/json", + "size": 1726, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477932, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTsEosEcNBN5m1uVkt3uj", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1726" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:12 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-0149f3e5-b507-48fd-a494-32f9b34b9577" + }, + { + "name": "original-request", + "value": "req_DeE7YH9CUXb7PH" + }, + { + "name": "request-id", + "value": "req_DeE7YH9CUXb7PH" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:12.113Z", + "time": 655, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 655 + } + }, + { + "_id": "ee2e5321207d0bb90300413d4768d448", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 27, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "27" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-d7a5e604-5f10-4814-bd8c-4797e438b0ef" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_visa" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtTsEosEcNBN5m1uVkt3uj/confirm" + }, + "response": { + "bodySize": 1766, + "content": { + "mimeType": "application/json", + "size": 1766, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477932, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTsEosEcNBN5m1uVkt3uj", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtTsEosEcNBN5m1oQrhdbt", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtTtEosEcNBN5mdKORS1dO", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1766" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:14 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-d7a5e604-5f10-4814-bd8c-4797e438b0ef" + }, + { + "name": "original-request", + "value": "req_BJfAfFdS0f1d5b" + }, + { + "name": "request-id", + "value": "req_BJfAfFdS0f1d5b" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:12.770Z", + "time": 1364, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1364 + } + }, + { + "_id": "0090e3c411fe21105f278ccb2b8d6dad", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 54, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "54" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-7e4293d1-3c73-4a6c-a3c9-bbe174cbc975" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtTsEosEcNBN5m1uVkt3uj&amount=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 615, + "content": { + "mimeType": "application/json", + "size": 615, + "text": { + "amount": 4999, + "balance_transaction": "txn_3OMtTsEosEcNBN5m1iyl2zue", + "charge": "ch_3OMtTsEosEcNBN5m1oQrhdbt", + "created": 1702477934, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtTsEosEcNBN5m1tE1dYxl", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtTsEosEcNBN5m1uVkt3uj", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "615" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:15 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-7e4293d1-3c73-4a6c-a3c9-bbe174cbc975" + }, + { + "name": "original-request", + "value": "req_Z58BqkfDg366TY" + }, + { + "name": "request-id", + "value": "req_Z58BqkfDg366TY" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:14.136Z", + "time": 978, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 978 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-pm_card_visa_1355345048/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-pm_card_visa_1355345048/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har new file mode 100644 index 0000000..e1fb315 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-pm_card_visa_1355345048/should-request-a-partial-refund-in-Stripe-after-authorize-and-charge_590324687/recording.har @@ -0,0 +1,858 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Visa' 'pm_card_visa'/should request a partial refund in Stripe after authorize and charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-ecb9bc23-a871-496e-874c-ef75479c71ea" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477929, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTpEosEcNBN5m1oduDeMU", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:09 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-ecb9bc23-a871-496e-874c-ef75479c71ea" + }, + { + "name": "original-request", + "value": "req_hQyF31pY1xLouM" + }, + { + "name": "request-id", + "value": "req_hQyF31pY1xLouM" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:08.586Z", + "time": 469, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 469 + } + }, + { + "_id": "bd896b2d03bbe651ad23892b163de159", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 27, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "27" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-d21893d7-400a-4f81-b20c-db0bb12b8a72" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_visa" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtTpEosEcNBN5m1oduDeMU/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477929, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTpEosEcNBN5m1oduDeMU", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtTpEosEcNBN5m1NbNfnL8", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtTpEosEcNBN5mdlEkY7dq", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:10 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-d21893d7-400a-4f81-b20c-db0bb12b8a72" + }, + { + "name": "original-request", + "value": "req_cRRX1hZV4jI3Uy" + }, + { + "name": "request-id", + "value": "req_cRRX1hZV4jI3Uy" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:09.057Z", + "time": 1169, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1169 + } + }, + { + "_id": "4bce40dc82d2e7d7c5dfde1e3fbba1f3", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-c67ed087-9e57-4a59-b8d4-de5e193ffed5" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtTpEosEcNBN5m1oduDeMU/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477929, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTpEosEcNBN5m1oduDeMU", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtTpEosEcNBN5m1NbNfnL8", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtTpEosEcNBN5mdlEkY7dq", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:11 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-c67ed087-9e57-4a59-b8d4-de5e193ffed5" + }, + { + "name": "original-request", + "value": "req_yUUS6viQkoe3Fj" + }, + { + "name": "request-id", + "value": "req_yUUS6viQkoe3Fj" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:10.229Z", + "time": 959, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 959 + } + }, + { + "_id": "6f44104dcfd95147fd8ea328e3461929", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 54, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "54" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-a02211fd-701e-4aa6-9610-b32c996847db" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtTpEosEcNBN5m1oduDeMU&amount=4999" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 615, + "content": { + "mimeType": "application/json", + "size": 615, + "text": { + "amount": 4999, + "balance_transaction": "txn_3OMtTpEosEcNBN5m1sz40wVW", + "charge": "ch_3OMtTpEosEcNBN5m1NbNfnL8", + "created": 1702477931, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtTpEosEcNBN5m1oyAUPbc", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtTpEosEcNBN5m1oduDeMU", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "615" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:12 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-a02211fd-701e-4aa6-9610-b32c996847db" + }, + { + "name": "original-request", + "value": "req_21fgZkZrYL1Co2" + }, + { + "name": "request-id", + "value": "req_21fgZkZrYL1Co2" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:11.191Z", + "time": 917, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 917 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-pm_card_visa_1355345048/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-pm_card_visa_1355345048/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har new file mode 100644 index 0000000..8b6ad95 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-pm_card_visa_1355345048/should-request-a-refund-in-Stripe-after-a-charge_2638780977/recording.har @@ -0,0 +1,639 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Visa' 'pm_card_visa'/should request a refund in Stripe after a charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "ea24209e006db5387b22524c87199d2e", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 242, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "242" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-74ad22fa-fc8a-4da5-bb93-d23085ba821e" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=automatic&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1726, + "content": { + "mimeType": "application/json", + "size": 1726, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477925, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTlEosEcNBN5m0JVOkk9c", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1726" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:05 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-74ad22fa-fc8a-4da5-bb93-d23085ba821e" + }, + { + "name": "original-request", + "value": "req_m7MeQNPXGtg2lG" + }, + { + "name": "request-id", + "value": "req_m7MeQNPXGtg2lG" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:04.651Z", + "time": 1289, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1289 + } + }, + { + "_id": "7f940fa265562d08fd5bf5e5d7b64bc2", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 27, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "27" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-39077660-0708-4d52-bcd7-463a16867801" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_visa" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtTlEosEcNBN5m0JVOkk9c/confirm" + }, + "response": { + "bodySize": 1766, + "content": { + "mimeType": "application/json", + "size": 1766, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "automatic", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477925, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtTlEosEcNBN5m0JVOkk9c", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtTlEosEcNBN5m04x8fGpc", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtTmEosEcNBN5mqsAQgFAq", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "blik": {}, + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "blik", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1766" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:07 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-39077660-0708-4d52-bcd7-463a16867801" + }, + { + "name": "original-request", + "value": "req_1SrGSDBemVuYML" + }, + { + "name": "request-id", + "value": "req_1SrGSDBemVuYML" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:05.943Z", + "time": 1510, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1510 + } + }, + { + "_id": "fa3bf81c244e8ed77c2baa073d67d6f4", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 55, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "55" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-3c4c1082-05ae-4b0b-9f97-e049d461721e" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtTlEosEcNBN5m0JVOkk9c&amount=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 616, + "content": { + "mimeType": "application/json", + "size": 616, + "text": { + "amount": 22299, + "balance_transaction": "txn_3OMtTlEosEcNBN5m0qLdsGT4", + "charge": "ch_3OMtTlEosEcNBN5m04x8fGpc", + "created": 1702477928, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtTlEosEcNBN5m0RSCKf95", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtTlEosEcNBN5m0JVOkk9c", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "616" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:32:08 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-3c4c1082-05ae-4b0b-9f97-e049d461721e" + }, + { + "name": "original-request", + "value": "req_JigCfa0qd3Wk39" + }, + { + "name": "request-id", + "value": "req_JigCfa0qd3Wk39" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:32:07.456Z", + "time": 1120, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1120 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-pm_card_visa_1355345048/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-pm_card_visa_1355345048/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har new file mode 100644 index 0000000..8e88662 --- /dev/null +++ b/src/modules/webhooks/__recordings__/TransactionRefundRequestedWebhookHandler_2252282828/Visa-pm_card_visa_1355345048/should-request-a-refund-in-Stripe-after-authorize-and-charge_292217866/recording.har @@ -0,0 +1,858 @@ +{ + "log": { + "_recordingName": "TransactionRefundRequestedWebhookHandler/'Visa' 'pm_card_visa'/should request a refund in Stripe after authorize and charge", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.5" + }, + "entries": [ + { + "_id": "e832e0e9ad4807ac377f5e27c0fd1344", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 239, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "239" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-ee01183f-d325-4019-ace5-41700c67b351" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 814, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "automatic_payment_methods[enabled]=true&automatic_payment_methods[allow_redirects]=never&amount=22299¤cy=PLN&capture_method=manual&metadata[transactionId]=555555&metadata[channelId]=1&metadata[checkoutId]=c29tZS1jaGVja291dC1pZA%3D%3D" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents" + }, + "response": { + "bodySize": 1695, + "content": { + "mimeType": "application/json", + "size": 1695, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477428, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtLkEosEcNBN5m0dWjPgyZ", + "invoice": null, + "last_payment_error": null, + "latest_charge": null, + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": null, + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_payment_method", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1695" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:49 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-ee01183f-d325-4019-ace5-41700c67b351" + }, + { + "name": "original-request", + "value": "req_HSBwo80dYxFhyE" + }, + { + "name": "request-id", + "value": "req_HSBwo80dYxFhyE" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1095, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:47.905Z", + "time": 1020, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1020 + } + }, + { + "_id": "7792ead05b8e9ba3e952c8e4c971d085", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 27, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "27" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-8eb51046-8702-4811-abf5-b03c6959c74b" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_method=pm_card_visa" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtLkEosEcNBN5m0dWjPgyZ/confirm" + }, + "response": { + "bodySize": 1742, + "content": { + "mimeType": "application/json", + "size": 1742, + "text": { + "amount": 22299, + "amount_capturable": 22299, + "amount_details": { + "tip": {} + }, + "amount_received": 0, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477428, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtLkEosEcNBN5m0dWjPgyZ", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtLkEosEcNBN5m0al2ad0u", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtLlEosEcNBN5m2LACPOBG", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "requires_capture", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1742" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fconfirm; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:50 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-8eb51046-8702-4811-abf5-b03c6959c74b" + }, + { + "name": "original-request", + "value": "req_FBIT2oe2TqpOnZ" + }, + { + "name": "request-id", + "value": "req_FBIT2oe2TqpOnZ" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:48.931Z", + "time": 1305, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 1305 + } + }, + { + "_id": "4f0cf6aed92b0b8c29318373abd312c2", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 23, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "23" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-52ab7c3d-49ad-4e47-a999-50258170fff9" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 849, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "amount_to_capture=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/payment_intents/pi_3OMtLkEosEcNBN5m0dWjPgyZ/capture" + }, + "response": { + "bodySize": 1735, + "content": { + "mimeType": "application/json", + "size": 1735, + "text": { + "amount": 22299, + "amount_capturable": 0, + "amount_details": { + "tip": {} + }, + "amount_received": 22299, + "application": null, + "application_fee_amount": null, + "automatic_payment_methods": { + "allow_redirects": "never", + "enabled": true + }, + "canceled_at": null, + "cancellation_reason": null, + "capture_method": "manual", + "client_secret": "pi_FAKE_CLIENT_SECRET", + "confirmation_method": "automatic", + "created": 1702477428, + "currency": "pln", + "customer": null, + "description": null, + "id": "pi_3OMtLkEosEcNBN5m0dWjPgyZ", + "invoice": null, + "last_payment_error": null, + "latest_charge": "ch_3OMtLkEosEcNBN5m0al2ad0u", + "livemode": false, + "metadata": { + "channelId": "1", + "checkoutId": "c29tZS1jaGVja291dC1pZA==", + "transactionId": "555555" + }, + "next_action": null, + "object": "payment_intent", + "on_behalf_of": null, + "payment_method": "pm_1OMtLlEosEcNBN5m2LACPOBG", + "payment_method_configuration_details": { + "id": "pmc_1LVZxMEosEcNBN5manO2iTW7", + "parent": null + }, + "payment_method_options": { + "card": { + "installments": null, + "mandate_options": null, + "network": null, + "request_three_d_secure": "automatic" + }, + "link": { + "persistent_token": null + }, + "paypal": { + "preferred_locale": null, + "reference": null + } + }, + "payment_method_types": [ + "card", + "link", + "paypal" + ], + "processing": null, + "receipt_email": null, + "review": null, + "setup_future_usage": null, + "shipping": null, + "source": null, + "statement_descriptor": null, + "statement_descriptor_suffix": null, + "status": "succeeded", + "transfer_data": null, + "transfer_group": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "1735" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Fpayment_intents%2F%3Aintent%2Fcapture; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:51 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-52ab7c3d-49ad-4e47-a999-50258170fff9" + }, + { + "name": "original-request", + "value": "req_qSMJPi9ww9MM4F" + }, + { + "name": "request-id", + "value": "req_qSMJPi9ww9MM4F" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1117, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:50.240Z", + "time": 862, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 862 + } + }, + { + "_id": "8c1e4d699e16159b8d5220f9375eb9ac", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 55, + "cookies": [], + "headers": [ + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-length", + "value": "55" + }, + { + "name": "content-type", + "value": "application/x-www-form-urlencoded" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-c94d9240-175d-4b10-9391-9f54313adaeb" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "user-agent", + "value": "Stripe/v1 NodeBindings/14.8.0" + } + ], + "headersSize": 805, + "httpVersion": "HTTP/1.1", + "method": "POST", + "postData": { + "mimeType": "application/x-www-form-urlencoded", + "params": [], + "text": "payment_intent=pi_3OMtLkEosEcNBN5m0dWjPgyZ&amount=22299" + }, + "queryString": [], + "url": "https://api.stripe.com/v1/refunds" + }, + "response": { + "bodySize": 616, + "content": { + "mimeType": "application/json", + "size": 616, + "text": { + "amount": 22299, + "balance_transaction": "txn_3OMtLkEosEcNBN5m0wrm9IyC", + "charge": "ch_3OMtLkEosEcNBN5m0al2ad0u", + "created": 1702477431, + "currency": "pln", + "destination_details": { + "card": { + "reference_status": "pending", + "reference_type": "acquirer_reference_number", + "type": "refund" + }, + "type": "card" + }, + "id": "re_3OMtLkEosEcNBN5m0ncHyBsB", + "metadata": {}, + "object": "refund", + "payment_intent": "pi_3OMtLkEosEcNBN5m0dWjPgyZ", + "reason": null, + "receipt_number": null, + "source_transfer_reversal": null, + "status": "succeeded", + "transfer_reversal": null + } + }, + "cookies": [], + "headers": [ + { + "name": "access-control-allow-credentials", + "value": "true" + }, + { + "name": "access-control-allow-methods", + "value": "GET,HEAD,PUT,PATCH,POST,DELETE" + }, + { + "name": "access-control-allow-origin", + "value": "*" + }, + { + "name": "access-control-expose-headers", + "value": "Request-Id, Stripe-Manage-Version, Stripe-Should-Retry, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required" + }, + { + "name": "access-control-max-age", + "value": "300" + }, + { + "name": "cache-control", + "value": "no-cache, no-store" + }, + { + "name": "connection", + "value": "keep-alive" + }, + { + "name": "content-length", + "value": "616" + }, + { + "name": "content-security-policy", + "value": "report-uri https://q.stripe.com/csp-report?p=v1%2Frefunds; block-all-mixed-content; default-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'; img-src 'self'; script-src 'self' 'report-sample'; style-src 'self'" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "date", + "value": "Wed, 13 Dec 2023 14:23:52 GMT" + }, + { + "name": "idempotency-key", + "value": "stripe-node-retry-c94d9240-175d-4b10-9391-9f54313adaeb" + }, + { + "name": "original-request", + "value": "req_Thvqz6HyOosXk2" + }, + { + "name": "request-id", + "value": "req_Thvqz6HyOosXk2" + }, + { + "name": "server", + "value": "nginx" + }, + { + "name": "strict-transport-security", + "value": "max-age=63072000; includeSubDomains; preload" + }, + { + "name": "stripe-should-retry", + "value": "false" + }, + { + "name": "stripe-version", + "value": "2023-10-16" + }, + { + "name": "vary", + "value": "Origin" + }, + { + "name": "x-stripe-routing-context-priority-tier", + "value": "api-testmode" + } + ], + "headersSize": 1086, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2023-12-13T14:23:51.107Z", + "time": 934, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 934 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/src/modules/webhooks/__snapshots__/transaction-initialize-session.test.ts.snap b/src/modules/webhooks/__snapshots__/transaction-initialize-session.test.ts.snap new file mode 100644 index 0000000..6c679dd --- /dev/null +++ b/src/modules/webhooks/__snapshots__/transaction-initialize-session.test.ts.snap @@ -0,0 +1,37 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`TransactionInitializeSessionWebhookHandler > 'Checkout' > 'should work authorization' > should work authorization 1`] = ` +{ + "paymentIntent": { + "client_secret": Any, + }, + "publishableKey": "pk_test_51LVZwxEosEcNBN5mTKD5afBfOzEF1S1T9tMGyfG4sw6vC6adm8VaKph9EGee1Dk1rlSWz9LgOj4nNNLb2CxJS3HT00x3Dx44oB", +} +`; + +exports[`TransactionInitializeSessionWebhookHandler > 'Checkout' > 'should work charge' > should work charge 1`] = ` +{ + "paymentIntent": { + "client_secret": Any, + }, + "publishableKey": "pk_test_51LVZwxEosEcNBN5mTKD5afBfOzEF1S1T9tMGyfG4sw6vC6adm8VaKph9EGee1Dk1rlSWz9LgOj4nNNLb2CxJS3HT00x3Dx44oB", +} +`; + +exports[`TransactionInitializeSessionWebhookHandler > 'Order' > 'should work authorization' > should work authorization 1`] = ` +{ + "paymentIntent": { + "client_secret": Any, + }, + "publishableKey": "pk_test_51LVZwxEosEcNBN5mTKD5afBfOzEF1S1T9tMGyfG4sw6vC6adm8VaKph9EGee1Dk1rlSWz9LgOj4nNNLb2CxJS3HT00x3Dx44oB", +} +`; + +exports[`TransactionInitializeSessionWebhookHandler > 'Order' > 'should work charge' > should work charge 1`] = ` +{ + "paymentIntent": { + "client_secret": Any, + }, + "publishableKey": "pk_test_51LVZwxEosEcNBN5mTKD5afBfOzEF1S1T9tMGyfG4sw6vC6adm8VaKph9EGee1Dk1rlSWz9LgOj4nNNLb2CxJS3HT00x3Dx44oB", +} +`; diff --git a/src/modules/webhooks/__snapshots__/transaction-process-session.test.ts.snap b/src/modules/webhooks/__snapshots__/transaction-process-session.test.ts.snap new file mode 100644 index 0000000..9a585e9 --- /dev/null +++ b/src/modules/webhooks/__snapshots__/transaction-process-session.test.ts.snap @@ -0,0 +1,37 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`TransactionProcessSessionWebhookHandler > 'Checkout' > 'should work authorization' > should work authorization 1`] = ` +{ + "paymentIntent": { + "client_secret": Any, + }, + "publishableKey": "pk_test_51LVZwxEosEcNBN5mTKD5afBfOzEF1S1T9tMGyfG4sw6vC6adm8VaKph9EGee1Dk1rlSWz9LgOj4nNNLb2CxJS3HT00x3Dx44oB", +} +`; + +exports[`TransactionProcessSessionWebhookHandler > 'Checkout' > 'should work charge' > should work charge 1`] = ` +{ + "paymentIntent": { + "client_secret": Any, + }, + "publishableKey": "pk_test_51LVZwxEosEcNBN5mTKD5afBfOzEF1S1T9tMGyfG4sw6vC6adm8VaKph9EGee1Dk1rlSWz9LgOj4nNNLb2CxJS3HT00x3Dx44oB", +} +`; + +exports[`TransactionProcessSessionWebhookHandler > 'Order' > 'should work authorization' > should work authorization 1`] = ` +{ + "paymentIntent": { + "client_secret": Any, + }, + "publishableKey": "pk_test_51LVZwxEosEcNBN5mTKD5afBfOzEF1S1T9tMGyfG4sw6vC6adm8VaKph9EGee1Dk1rlSWz9LgOj4nNNLb2CxJS3HT00x3Dx44oB", +} +`; + +exports[`TransactionProcessSessionWebhookHandler > 'Order' > 'should work charge' > should work charge 1`] = ` +{ + "paymentIntent": { + "client_secret": Any, + }, + "publishableKey": "pk_test_51LVZwxEosEcNBN5mTKD5afBfOzEF1S1T9tMGyfG4sw6vC6adm8VaKph9EGee1Dk1rlSWz9LgOj4nNNLb2CxJS3HT00x3Dx44oB", +} +`; diff --git a/src/modules/webhooks/__tests__/utils.ts b/src/modules/webhooks/__tests__/utils.ts new file mode 100644 index 0000000..1211ed4 --- /dev/null +++ b/src/modules/webhooks/__tests__/utils.ts @@ -0,0 +1,489 @@ +import merge from "lodash-es/merge"; +import { + type CheckoutLine, + LanguageCodeEnum, + type OrderOrCheckoutLines_Checkout_Fragment, + type PaymentGatewayInitializeSessionEventFragment, + type PaymentGatewayRecipientFragment, + TransactionFlowStrategyEnum, + type TransactionInitializeSessionEventFragment, + type TransactionChargeRequestedEventFragment, + TransactionActionEnum, + type OrderOrCheckoutLines_Order_Fragment, + type TransactionRefundRequestedEventFragment, + type TransactionCancelationRequestedEventFragment, + type OrderOrCheckoutSourceObject_Checkout_Fragment, + type OrderOrCheckoutSourceObject_Order_Fragment, + type OrderLine, + type TransactionProcessSessionEventFragment, +} from "generated/graphql"; +import { type JSONValue } from "@/types"; +import { getFilledMetadata } from "@/modules/payment-app-configuration/__tests__/utils"; + +type DeepPartial = T extends object + ? { + [P in keyof T]?: DeepPartial; + } + : T; +type CreateMockFn = (overrides?: DeepPartial | null | undefined) => T; +type CreateMockAsyncFn = (overrides?: DeepPartial | null | undefined) => Promise; + +export const createMockApp: CreateMockAsyncFn = async ( + overrides, +) => { + const privateMetadata = await getFilledMetadata(); + return merge( + { + __typename: "App", + id: "app-id", + privateMetadata, + metadata: {} as PaymentGatewayRecipientFragment["metadata"], + } as const, + overrides, + ); +}; + +export const createMockPaymentGatewayInitializeSessionEvent: CreateMockAsyncFn< + PaymentGatewayInitializeSessionEventFragment +> = async (overrides) => { + return merge( + { + __typename: "PaymentGatewayInitializeSession", + issuingPrincipal: null, + sourceObject: { + __typename: "Checkout", + id: "c29tZS1jaGVja291dC1pZA==", + languageCode: LanguageCodeEnum.PlPl, + channel: { id: "1", slug: "default-channel" }, + total: { + gross: { + amount: 123.45, + currency: "PLN", + }, + }, + billingAddress: { + country: { + code: "PL", + }, + }, + }, + recipient: await createMockApp(overrides?.recipient), + data: undefined, + } as const, + overrides, + ); +}; + +export const createMockTransactionChargeRequestedEvent: CreateMockAsyncFn< + TransactionChargeRequestedEventFragment +> = async (overrides) => { + return merge( + { + __typename: "TransactionChargeRequested", + recipient: await createMockApp(overrides?.recipient), + action: { + __typename: "TransactionAction", + amount: 99.99 + 123.0, // gross delivery cost + actionType: TransactionActionEnum.Charge, + }, + transaction: { + __typename: "TransactionItem", + id: "555555", + pspReference: "", + authorizedAmount: { + __typename: "Money", + currency: "PLN", + amount: 99.99 + 123.0, // gross delivery cost + }, + sourceObject: { + __typename: "Order", + channel: { id: "1", slug: "default-channel" }, + deliveryMethod: { + __typename: "ShippingMethod", + id: "some-shipping-id", + name: "some-shipping-name", + }, + shippingPrice: { + gross: { + currency: "PLN", + amount: 123.0, + }, + net: { + currency: "PLN", + amount: 100.0, + }, + tax: { + currency: "PLN", + amount: 23.0, + }, + }, + total: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + currency: "PLN", + amount: 99.99 + 123.0, + }, + }, + lines: [createMockOrderLine(overrides?.transaction?.sourceObject?.lines?.[0])], + }, + }, + } as const, + overrides, + ); +}; + +export const createMockTransactionRefundRequestedEvent: CreateMockAsyncFn< + TransactionRefundRequestedEventFragment +> = async (overrides) => { + return merge( + { + __typename: "TransactionRefundRequested", + recipient: await createMockApp(overrides?.recipient), + action: { + amount: 99.99 + 123.0, + actionType: TransactionActionEnum.Refund, + }, + issuedAt: new Date().toISOString(), + transaction: { + __typename: "TransactionItem", + id: "55555", + pspReference: "", + sourceObject: { + __typename: "Order", + channel: { id: "1", slug: "default-channel" }, + deliveryMethod: { + __typename: "ShippingMethod", + id: "some-shipping-id", + name: "some-shipping-name", + }, + shippingPrice: { + gross: { + currency: "PLN", + amount: 123.0, + }, + net: { + currency: "PLN", + amount: 100.0, + }, + tax: { + currency: "PLN", + amount: 23.0, + }, + }, + total: { + __typename: "TaxedMoney", + gross: { + __typename: "Money", + currency: "PLN", + amount: 99.99 + 123.0, + }, + }, + lines: [createMockOrderLine(overrides?.transaction?.sourceObject?.lines?.[0])], + }, + }, + } as const, + overrides, + ); +}; + +export const createMockTransactionCancelationRequestedEvent: CreateMockAsyncFn< + TransactionCancelationRequestedEventFragment +> = async (overrides) => { + return merge( + { + __typename: "TransactionCancelationRequested", + recipient: await createMockApp(overrides?.recipient), + action: { + __typename: "TransactionAction", + amount: 99.99 + 123.0, + actionType: TransactionActionEnum.Cancel, + }, + transaction: { + __typename: "TransactionItem", + id: "555555", + pspReference: "", + sourceObject: { + channel: { id: "1", slug: "default-channel" }, + }, + }, + } as const, + overrides, + ); +}; + +export const createMockCheckoutLine: CreateMockFn< + OrderOrCheckoutLines_Checkout_Fragment["lines"][number] +> = (overrides) => { + return merge( + { + __typename: "CheckoutLine", + id: "1", + quantity: 1, + totalPrice: { + gross: { + currency: "PLN", + amount: 99.99, + }, + net: { + currency: "PLN", + amount: 81.29, + }, + tax: { + currency: "PLN", + amount: 18.7, + }, + }, + checkoutVariant: { + name: "product variant", + product: { + name: "product", + }, + }, + }, + overrides, + ); +}; + +export const createMockOrderLine: CreateMockFn< + OrderOrCheckoutLines_Order_Fragment["lines"][number] +> = (overrides) => { + return merge( + { + __typename: "OrderLine", + id: "1", + quantity: 1, + taxRate: 23, + totalPrice: { + gross: { + currency: "PLN", + amount: 99.99, + }, + net: { + currency: "PLN", + amount: 81.29, + }, + tax: { + currency: "PLN", + amount: 18.7, + }, + }, + orderVariant: { + name: "product variant", + product: { + name: "product", + }, + }, + }, + overrides, + ); +}; + +export const createMockTransactionInitializeSessionSourceObjectCheckout: CreateMockFn< + OrderOrCheckoutSourceObject_Checkout_Fragment +> = (overrides) => { + return merge( + { + __typename: "Checkout", + id: "c29tZS1jaGVja291dC1pZA==", + channel: { id: "1", slug: "default-channel" }, + languageCode: LanguageCodeEnum.PlPl, + total: { + gross: { + amount: 99.99 + 123.0, + currency: "PLN", + }, + }, + deliveryMethod: { + __typename: "ShippingMethod", + id: "some-shipping-id", + name: "some-shipping-name", + }, + shippingPrice: { + gross: { + currency: "PLN", + amount: 123.0, + }, + net: { + currency: "PLN", + amount: 100.0, + }, + tax: { + currency: "PLN", + amount: 23.0, + }, + }, + billingAddress: { + firstName: "John", + lastName: "Smith", + phone: "+48123456789", + city: "Washington", + code: "", + streetAddress1: "1600 Ave NW", + streetAddress2: "", + postalCode: "20500", + countryArea: "DC", + country: { + code: "US", + }, + companyName: "", + }, + shippingAddress: { + firstName: "Jan", + lastName: "Kowalski", + phone: "+48123456789", + city: "New York", + code: "", + streetAddress1: "3111 Broadway", + streetAddress2: "", + postalCode: "10027", + countryArea: "NY", + country: { + code: "US", + }, + companyName: "", + }, + userEmail: "test@saleor.io", + lines: [createMockCheckoutLine(overrides?.lines?.[0] as CheckoutLine | undefined)], + }, + overrides, + ); +}; + +export const createMockTransactionInitializeSessionSourceObjectOrder: CreateMockFn< + OrderOrCheckoutSourceObject_Order_Fragment +> = (overrides) => { + return merge( + { + __typename: "Order", + id: "c29tZS1jaGVja291dC1pZA==", + channel: { id: "1", slug: "default-channel" }, + languageCodeEnum: LanguageCodeEnum.PlPl, + total: { + gross: { + amount: 99.99 + 123.0, + currency: "PLN", + }, + }, + deliveryMethod: { + __typename: "ShippingMethod", + id: "some-shipping-id", + name: "some-shipping-name", + }, + shippingPrice: { + gross: { + currency: "PLN", + amount: 123.0, + }, + net: { + currency: "PLN", + amount: 100.0, + }, + tax: { + currency: "PLN", + amount: 23.0, + }, + }, + billingAddress: { + firstName: "John", + lastName: "Smith", + phone: "+48123456789", + city: "Washington", + code: "", + streetAddress1: "1600 Ave NW", + streetAddress2: "", + postalCode: "20500", + countryArea: "DC", + country: { + code: "US", + }, + companyName: "", + }, + shippingAddress: { + firstName: "Jan", + lastName: "Kowalski", + phone: "+48123456789", + city: "New York", + code: "", + streetAddress1: "3111 Broadway", + streetAddress2: "", + postalCode: "10027", + countryArea: "NY", + country: { + code: "US", + }, + companyName: "", + }, + userEmail: "test@saleor.io", + lines: [createMockOrderLine(overrides?.lines?.[0] as OrderLine | undefined)], + }, + overrides, + ); +}; + +export const createMockTransactionInitializeSessionEvent: CreateMockAsyncFn< + TransactionInitializeSessionEventFragment +> = async (overrides) => { + return merge( + { + __typename: "TransactionInitializeSession", + action: { + __typename: "TransactionAction", + amount: 99.99 + 123.0, + currency: "PLN", + actionType: TransactionFlowStrategyEnum.Charge, + }, + merchantReference: "123123123", + sourceObject: createMockTransactionInitializeSessionSourceObjectCheckout(), + recipient: await createMockApp(overrides?.recipient), + transaction: { + __typename: "TransactionItem", + id: "555555", + pspReference: "", + }, + issuingPrincipal: null, + data: { + automatic_payment_methods: { + enabled: true, + allow_redirects: "never", + }, + } as JSONValue, + } as const, + overrides, + ); +}; + +export const createMockTransactionProcessSessionEvent: CreateMockAsyncFn< + TransactionProcessSessionEventFragment +> = async (overrides) => { + return merge( + { + __typename: "TransactionProcessSession", + action: { + __typename: "TransactionAction", + amount: 99.99 + 123.0, + currency: "PLN", + actionType: TransactionFlowStrategyEnum.Charge, + }, + merchantReference: "123123123", + sourceObject: createMockTransactionInitializeSessionSourceObjectCheckout(), + recipient: await createMockApp(overrides?.recipient), + transaction: { + __typename: "TransactionItem", + id: "555555", + pspReference: "AAAAAAAAAAAAAAAA", + }, + data: {} as JSONValue, + } as const, + overrides, + ); +}; + +export const createMockStripeDataActionNotRequired = () => { + return { + automatic_payment_methods: { + enabled: true, + allow_redirects: "never", + }, + }; +}; diff --git a/src/modules/webhooks/payment-gateway-initialize-session.test.ts b/src/modules/webhooks/payment-gateway-initialize-session.test.ts new file mode 100644 index 0000000..2718b14 --- /dev/null +++ b/src/modules/webhooks/payment-gateway-initialize-session.test.ts @@ -0,0 +1,25 @@ +import { describe, it, expect } from "vitest"; +import { PaymentGatewayInitializeSessionWebhookHandler } from "./payment-gateway-initialize-session"; +import { createMockPaymentGatewayInitializeSessionEvent } from "./__tests__/utils"; + +import { setupRecording } from "@/__tests__/polly"; +import { testEnv } from "@/__tests__/test-env.mjs"; + +describe("PaymentGatewayInitializeSessionWebhookHandler", () => { + setupRecording({}); + + it("should work", async () => { + const event = await createMockPaymentGatewayInitializeSessionEvent(); + const result = await PaymentGatewayInitializeSessionWebhookHandler( + event, + testEnv.TEST_SALEOR_API_URL, + ); + expect(result.data).toEqual(expect.any(Object)); + expect(result.data.publishableKey).toEqual(expect.any(String)); + expect(result.data).toMatchInlineSnapshot(` + { + "publishableKey": "pk_test_51LVZwxEosEcNBN5mTKD5afBfOzEF1S1T9tMGyfG4sw6vC6adm8VaKph9EGee1Dk1rlSWz9LgOj4nNNLb2CxJS3HT00x3Dx44oB", + } + `); + }); +}); diff --git a/src/modules/webhooks/payment-gateway-initialize-session.ts b/src/modules/webhooks/payment-gateway-initialize-session.ts new file mode 100644 index 0000000..00f44ae --- /dev/null +++ b/src/modules/webhooks/payment-gateway-initialize-session.ts @@ -0,0 +1,37 @@ +import { getWebhookPaymentAppConfigurator } from "../payment-app-configuration/payment-app-configuration-factory"; +import { paymentAppFullyConfiguredEntrySchema } from "../payment-app-configuration/config-entry"; +import { getConfigurationForChannel } from "../payment-app-configuration/payment-app-configuration"; +import { type PaymentGatewayInitializeSessionResponse } from "@/schemas/PaymentGatewayInitializeSession/PaymentGatewayInitializeSessionResponse.mjs"; +import { type PaymentGatewayInitializeSessionEventFragment } from "generated/graphql"; +import { invariant } from "@/lib/invariant"; +import { createLogger } from "@/lib/logger"; + +export const PaymentGatewayInitializeSessionWebhookHandler = async ( + event: PaymentGatewayInitializeSessionEventFragment, + saleorApiUrl: string, +): Promise => { + const logger = createLogger( + {}, + { msgPrefix: "[PaymentGatewayInitializeSessionWebhookHandler] " }, + ); + + const app = event.recipient; + invariant(app, "Missing event.recipient!"); + + const { privateMetadata } = app; + const configurator = getWebhookPaymentAppConfigurator({ privateMetadata }, saleorApiUrl); + const appConfig = await configurator.getConfig(); + + const stripeConfig = paymentAppFullyConfiguredEntrySchema.parse( + getConfigurationForChannel(appConfig, event.sourceObject.channel.id), + ); + + logger.info({}, "Processing Payment Gateway Initialize request"); + const data = { + publishableKey: stripeConfig.publishableKey, + }; + const paymentGatewayInitializeSessionResponse: PaymentGatewayInitializeSessionResponse = { + data, + }; + return paymentGatewayInitializeSessionResponse; +}; diff --git a/src/modules/webhooks/stripe-webhook.errors.ts b/src/modules/webhooks/stripe-webhook.errors.ts new file mode 100644 index 0000000..77c11c8 --- /dev/null +++ b/src/modules/webhooks/stripe-webhook.errors.ts @@ -0,0 +1,6 @@ +import { BaseError } from "@/errors"; + +export const MissingSignatureError = BaseError.subclass("MissingSignatureError"); +export const UnexpectedTransactionEventReportError = BaseError.subclass( + "UnexpectedTransactionEventReportError", +); diff --git a/src/modules/webhooks/stripe-webhook.test.ts b/src/modules/webhooks/stripe-webhook.test.ts new file mode 100644 index 0000000..248e57d --- /dev/null +++ b/src/modules/webhooks/stripe-webhook.test.ts @@ -0,0 +1,453 @@ +import { Readable } from "node:stream"; +import merge from "lodash-es/merge"; +import { describe, it, vi, expect } from "vitest"; +import { type NextApiRequest } from "next"; +import type Stripe from "stripe"; +import type * as configurationFactoryModule from "../payment-app-configuration/payment-app-configuration-factory"; +import { getFilledFakeMetadataConfigurator } from "../payment-app-configuration/__tests__/utils"; +import { getStripeApiClient } from "../stripe/stripe-api"; +import { stripeWebhookHandler } from "./stripe-webhook"; +import { testEnv } from "@/__tests__/test-env.mjs"; +import { setupRecording } from "@/__tests__/polly"; +import { TransactionActionEnum } from "generated/graphql"; + +vi.mock("../payment-app-configuration/payment-app-configuration-factory", async () => { + const actual = await vi.importActual( + "../payment-app-configuration/payment-app-configuration-factory", + ); + + return { + ...actual, + getPaymentAppConfigurator: vi.fn(() => getFilledFakeMetadataConfigurator()), + }; +}); + +type DeepPartial = T extends object + ? { + [P in keyof T]?: DeepPartial; + } + : T; + +const createMockStripeEvent = ( + overrides: DeepPartial, +) => { + return merge( + { + id: "evt_3NQ63WEosEcNBN5m1g4vSCvI", + object: "event", + api_version: "2022-08-01", + created: Date.now() / 1000, + data: { + object: { + id: "pi_3NQ63WEosEcNBN5m1AB4zgVN", + object: "payment_intent", + amount: 2000, + amount_capturable: 0, + amount_details: { + tip: {}, + }, + amount_received: 2000, + application: null, + application_fee_amount: null, + automatic_payment_methods: null, + canceled_at: null, + cancellation_reason: null, + capture_method: "automatic", + charges: { + object: "list", + data: [ + { + id: "ch_3NQ63WEosEcNBN5m1xPmXlzQ", + object: "charge", + amount: 2000, + amount_captured: 2000, + amount_refunded: 0, + application: null, + application_fee: null, + application_fee_amount: null, + balance_transaction: "txn_3NQ63WEosEcNBN5m1kuFOTeH", + billing_details: { + address: { + city: null, + country: null, + line1: null, + line2: null, + postal_code: null, + state: null, + }, + email: null, + name: null, + phone: null, + }, + calculated_statement_descriptor: "Stripe", + captured: true, + created: Date.now() / 1000, + currency: "usd", + customer: null, + description: "(created by Stripe CLI)", + destination: null, + dispute: null, + disputed: false, + failure_balance_transaction: null, + failure_code: null, + failure_message: null, + fraud_details: {}, + invoice: null, + livemode: false, + metadata: { + channelId: "1", + transactionId: "420", + }, + on_behalf_of: null, + order: null, + outcome: { + network_status: "approved_by_network", + reason: null, + risk_level: "normal", + risk_score: 17, + seller_message: "Payment complete.", + type: "authorized", + }, + paid: true, + payment_intent: "pi_3NQ63WEosEcNBN5m1AB4zgVN", + payment_method: "pm_1NQ63WEosEcNBN5mAQ9JNokZ", + payment_method_details: { + card: { + brand: "visa", + checks: { + address_line1_check: null, + address_postal_code_check: null, + cvc_check: null, + }, + country: "US", + exp_month: 7, + exp_year: 2024, + fingerprint: "7aB2lHdoeemL4wct", + funding: "credit", + installments: null, + last4: "4242", + mandate: null, + network: "visa", + network_token: { + used: false, + }, + three_d_secure: null, + wallet: null, + }, + type: "card", + }, + receipt_email: null, + receipt_number: null, + receipt_url: + "https://pay.stripe.com/receipts/payment/CAcaFwoVYWNjdF8xTFZad3hFb3NFY05CTjVtKJfcj6UGMgZNVOI-RcQ6LBbbB8smhr5AzEmXDebHf65GAxmk_bkMFUCp1ZB_c9cU2w_X8KR0H0Mm5j3u", + refunded: false, + refunds: { + object: "list", + data: [], + has_more: false, + total_count: 0, + url: "/v1/charges/ch_3NQ63WEosEcNBN5m1xPmXlzQ/refunds", + }, + review: null, + shipping: { + address: { + city: "San Francisco", + country: "US", + line1: "510 Townsend St", + line2: null, + postal_code: "94103", + state: "CA", + }, + carrier: null, + name: "Jenny Rosen", + phone: null, + tracking_number: null, + }, + source: null, + source_transfer: null, + statement_descriptor: null, + statement_descriptor_suffix: null, + status: "succeeded", + transfer_data: null, + transfer_group: null, + }, + ], + has_more: false, + total_count: 1, + url: "/v1/charges?payment_intent=pi_3NQ63WEosEcNBN5m1AB4zgVN", + }, + client_secret: "pi_3NQ63WEosEcNBN5m1AB4zgVN_secret_0Pm1FhPHo2j7SVOxd2enckIkb", + confirmation_method: "automatic", + created: 1688464918, + currency: "usd", + customer: null, + description: "(created by Stripe CLI)", + invoice: null, + last_payment_error: null, + latest_charge: "ch_3NQ63WEosEcNBN5m1xPmXlzQ", + livemode: false, + metadata: { + channelId: "1", + transactionId: "420", + }, + next_action: null, + on_behalf_of: null, + payment_method: "pm_1NQ63WEosEcNBN5mAQ9JNokZ", + payment_method_options: { + card: { + installments: null, + mandate_options: null, + network: null, + request_three_d_secure: "automatic", + }, + }, + payment_method_types: ["card"], + processing: null, + receipt_email: null, + review: null, + setup_future_usage: null, + shipping: { + address: { + city: "San Francisco", + country: "US", + line1: "510 Townsend St", + line2: null, + postal_code: "94103", + state: "CA", + }, + carrier: null, + name: "Jenny Rosen", + phone: null, + tracking_number: null, + }, + source: null, + statement_descriptor: null, + statement_descriptor_suffix: null, + status: "succeeded", + transfer_data: null, + transfer_group: null, + }, + }, + livemode: false, + pending_webhooks: 2, + request: { + id: "req_eQqf484VGeHAYm", + idempotency_key: "947cdd9e-03d7-4e8f-b79e-b1fecff78c7f", + }, + type: "payment_intent.succeeded", + }, + overrides, + ); +}; + +const createMockRequest = ({ + body, + query, + headers, +}: { + body: string; + query: Record; + headers: Record; +}) => { + const request = Readable.from([body]) as NextApiRequest; + request.query = query; + request.headers = headers; + return request; +}; + +describe("stripe-webhook", () => { + setupRecording({}); + + describe("stripeWebhookHandler", () => { + it("throw if saleorApiUrl is not provided in query", async () => { + const stripe = getStripeApiClient(testEnv.TEST_PAYMENT_APP_SECRET_KEY); + const body = JSON.stringify(createMockStripeEvent({ type: "payment_intent.succeeded" })); + const signature = stripe.webhooks.generateTestHeaderString({ + payload: body, + secret: testEnv.TEST_PAYMENT_APP_WEBHOOK_SECRET, + }); + + await expect( + stripeWebhookHandler( + createMockRequest({ + body, + query: {}, + headers: { + "stripe-signature": signature, + }, + }), + ), + ).rejects.toMatch(/MissingSaleorApiUrlError/); + }); + + it("throw if Stripe signature header is not provided", async () => { + await expect( + stripeWebhookHandler( + createMockRequest({ + body: JSON.stringify(createMockStripeEvent({ type: "payment_intent.succeeded" })), + query: { + saleorApiUrl: testEnv.TEST_SALEOR_API_URL, + }, + headers: {}, + }), + ), + ).rejects.toMatch(/MissingSignatureError/); + }); + + it("ignores misconfigured requests", async () => { + const stripe = getStripeApiClient(testEnv.TEST_PAYMENT_APP_SECRET_KEY); + const body = JSON.stringify( + createMockStripeEvent({ + type: "payment_intent.succeeded", + data: { object: { metadata: { channelId: "some-channel-420" } } }, + }), + ); + const signature = stripe.webhooks.generateTestHeaderString({ + payload: body, + secret: testEnv.TEST_PAYMENT_APP_WEBHOOK_SECRET, + }); + + await expect( + stripeWebhookHandler( + createMockRequest({ + body, + query: { + saleorApiUrl: testEnv.TEST_SALEOR_API_URL, + }, + headers: { + "stripe-signature": signature, + }, + }), + ), + ).resolves.toBeNull(); + }); + + it("handles payment_intent.succeeded", async (ctx) => { + const localGraphqlUrl = testEnv.TEST_SALEOR_API_URL; + const event = createMockStripeEvent({ type: "payment_intent.succeeded" }); + + ctx.polly?.server.post(localGraphqlUrl).on("request", (req) => { + expect(req.headers["authorization-bearer"]).toEqual(testEnv.TEST_SALEOR_APP_TOKEN); + // @todo maybe we should parse graphql to AST here? + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + expect(req.jsonBody().query).toMatch("transactionEventReport("); + + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + const variables = req.jsonBody().variables; + expect(variables).toEqual({ + transactionId: "420", + amount: 20, + externalUrl: `https://dashboard.stripe.com/payments/${event.data.object.id}`, + message: "(created by Stripe CLI)", + pspReference: event.data.object.id, + time: expect.any(String), + type: "CHARGE_SUCCESS", + availableActions: [TransactionActionEnum.Refund], + }); + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + expect(Date.parse(variables.time)).not.toBeNaN(); + }); + + ctx.polly?.server.post(localGraphqlUrl).intercept((_req, res) => { + res.json({ + data: { transactionEventReport: { alreadyProcessed: false, errors: [] } }, + }); + }); + + const stripe = getStripeApiClient(testEnv.TEST_PAYMENT_APP_SECRET_KEY); + const body = JSON.stringify(event); + const signature = stripe.webhooks.generateTestHeaderString({ + payload: body, + secret: testEnv.TEST_PAYMENT_APP_WEBHOOK_SECRET, + }); + + await expect( + stripeWebhookHandler( + createMockRequest({ + body, + query: { + saleorApiUrl: testEnv.TEST_SALEOR_API_URL, + }, + headers: { + "stripe-signature": signature, + }, + }), + ), + ).resolves.toMatchInlineSnapshot(` + { + "data": { + "transactionEventReport": { + "alreadyProcessed": false, + "errors": [], + }, + }, + "errors": [], + } + `); + }); + + it("handles payment_intent.payment_failed", async (ctx) => { + const localGraphqlUrl = testEnv.TEST_SALEOR_API_URL; + const event = createMockStripeEvent({ type: "payment_intent.payment_failed" }); + + ctx.polly?.server.post(localGraphqlUrl).on("request", (req) => { + expect(req.headers["authorization-bearer"]).toEqual(testEnv.TEST_SALEOR_APP_TOKEN); + // @todo maybe we should parse graphql to AST here? + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + expect(req.jsonBody().query).toMatch("transactionEventReport("); + + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + const variables = req.jsonBody().variables; + expect(variables).toEqual({ + transactionId: "420", + amount: 20, + externalUrl: `https://dashboard.stripe.com/payments/${event.data.object.id}`, + message: "(created by Stripe CLI)", + pspReference: event.data.object.id, + time: expect.any(String), + type: "CHARGE_FAILURE", + availableActions: [], + }); + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + expect(Date.parse(variables.time)).not.toBeNaN(); + }); + + ctx.polly?.server.post(localGraphqlUrl).intercept((_req, res) => { + res.json({ + data: { transactionEventReport: { alreadyProcessed: false, errors: [] } }, + }); + }); + + const stripe = getStripeApiClient(testEnv.TEST_PAYMENT_APP_SECRET_KEY); + const body = JSON.stringify(event); + const signature = stripe.webhooks.generateTestHeaderString({ + payload: body, + secret: testEnv.TEST_PAYMENT_APP_WEBHOOK_SECRET, + }); + + await expect( + stripeWebhookHandler( + createMockRequest({ + body, + query: { + saleorApiUrl: testEnv.TEST_SALEOR_API_URL, + }, + headers: { + "stripe-signature": signature, + }, + }), + ), + ).resolves.toMatchInlineSnapshot(` + { + "data": { + "transactionEventReport": { + "alreadyProcessed": false, + "errors": [], + }, + }, + "errors": [], + } + `); + }); + }); +}); diff --git a/src/modules/webhooks/stripe-webhook.ts b/src/modules/webhooks/stripe-webhook.ts new file mode 100644 index 0000000..bf1617f --- /dev/null +++ b/src/modules/webhooks/stripe-webhook.ts @@ -0,0 +1,525 @@ +/// +import { type Readable } from "node:stream"; + +import * as Sentry from "@sentry/nextjs"; +import { type NextApiRequest } from "next"; +import Stripe from "stripe"; +import { type Client } from "urql"; +import { getStripeApiClient, getStripeExternalUrlForIntentId } from "../stripe/stripe-api"; +import { getPaymentAppConfigurator } from "../payment-app-configuration/payment-app-configuration-factory"; +import { getConfigurationForChannel } from "../payment-app-configuration/payment-app-configuration"; +import { type PaymentAppConfig } from "../payment-app-configuration/app-config"; +import { getSaleorAmountFromStripeAmount } from "../stripe/currencies"; +import { + MissingSignatureError, + UnexpectedTransactionEventReportError, +} from "./stripe-webhook.errors"; +import { createClient } from "@/lib/create-graphq-client"; +import { getAuthDataForRequest } from "@/backend-lib/api-route-utils"; +import { createLogger } from "@/lib/logger"; +import { + type TransactionEventReportMutation, + type TransactionEventReportMutationVariables, + UntypedTransactionEventReportDocument, + TransactionEventTypeEnum, + TransactionActionEnum, +} from "generated/graphql"; +import { assertUnreachableButNotThrow } from "@/lib/invariant"; +import { __do, unpackPromise } from "@/lib/utils"; + +export const stripeWebhookHandler = async (req: NextApiRequest) => { + const logger = createLogger({}, { msgPrefix: "[stripeWebhookHandler] " }); + const authData = await getAuthDataForRequest(req); + const client = createClient(authData.saleorApiUrl, async () => ({ token: authData.token })); + const configurator = getPaymentAppConfigurator(client, authData.saleorApiUrl); + const appConfig = await configurator.getConfig(); + + const stripeEvent = await requestToStripeEvent({ req, appConfig }); + if (!stripeEvent) { + logger.debug("stripeEvent was null"); + return null; + } + + return processStripeEvent({ stripeEvent, appConfig, client }); +}; + +async function processStripeEvent({ + stripeEvent, + appConfig, + client, +}: { + stripeEvent: Stripe.DiscriminatedEvent; + appConfig: PaymentAppConfig; + client: Client; +}) { + const logger = createLogger({}, { msgPrefix: "[processStripeEvent] " }); + logger.debug( + { + id: "id" in stripeEvent && typeof stripeEvent.id === "string" ? stripeEvent.id : "", + type: stripeEvent.type, + }, + "Got Stripe event", + ); + + const transactionEventReport = await stripeEventToTransactionEventReport({ + appConfig, + stripeEvent, + }); + logger.debug({ + transactionEventReport: transactionEventReport && { + transactionId: transactionEventReport.transactionId, + amount: transactionEventReport.amount, + availableActions: transactionEventReport.availableActions, + externalUrl: transactionEventReport.externalUrl, + message: transactionEventReport.message, + pspReference: transactionEventReport.pspReference, + time: transactionEventReport.time, + type: transactionEventReport.type, + }, + }); + + if (!transactionEventReport) { + return; + } + + const transactionEventReportResult = await processTransactionEventReport({ + client, + transactionEventReport, + }); + logger.debug( + { + data: transactionEventReportResult.data, + errors: transactionEventReportResult.errors, + }, + "Received response from event report", + ); + + if (transactionEventReportResult.errors.length > 0) { + const message = transactionEventReportResult.errors.map((err) => err.message).join("\n"); + throw new UnexpectedTransactionEventReportError(message, { + errors: transactionEventReportResult.errors, + }); + } + return transactionEventReportResult; +} + +async function processTransactionEventReport({ + client, + transactionEventReport, +}: { + client: Client; + transactionEventReport: TransactionEventReportMutationVariables; +}) { + const { data, error } = await client + .mutation( + UntypedTransactionEventReportDocument, + transactionEventReport, + ) + .toPromise(); + + const errors = [error, ...(data?.transactionEventReport?.errors || [])].filter(Boolean); + return { data, errors }; +} + +async function requestToStripeEvent({ + req, + appConfig, +}: { + req: NextApiRequest; + appConfig: PaymentAppConfig; +}): Promise { + const logger = createLogger({}, { msgPrefix: "[requestToStripeEvent] " }); + + const signature = req.headers["stripe-signature"]; + + if (!signature) { + throw new MissingSignatureError("Stripe signature is missing"); + } + + const body = await buffer(req); + + const unsafeParsedBody = JSON.parse(body.toString()) as Stripe.DiscriminatedEvent; + const channelId = getChannelIdFromEventData(unsafeParsedBody.data); + + const configEntry = getConfigurationForChannel(appConfig, channelId); + + if (!configEntry || !configEntry.secretKey) { + logger.warn(`Missing configuration for channel ${channelId || ""}`); + return null; + } + + const stripe = getStripeApiClient(configEntry.secretKey); + const [stripeEventError, stripeEvent] = await unpackPromise( + stripe.webhooks.constructEventAsync( + body, + signature, + configEntry.webhookSecret, + ) as Promise, + ); + + if (stripeEventError instanceof Stripe.errors.StripeSignatureVerificationError) { + logger.warn( + { message: stripeEventError.message, name: stripeEventError.name }, + "Invalid signature for event", + ); + return null; + } else if (stripeEventError) { + Sentry.captureException(stripeEventError); + logger.error({ message: stripeEventError.message, name: stripeEventError.name }); + return null; + } + + return stripeEvent; +} + +async function buffer(readable: Readable) { + const chunks = []; + for await (const chunk of readable) { + chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk); + } + return Buffer.concat(chunks); +} + +const getTransactionIdFromEventData = (data?: T) => { + if ( + typeof data === "object" && + data && + "object" in data && + typeof data?.object === "object" && + data?.object && + "metadata" in data.object && + typeof data.object.metadata === "object" && + data.object.metadata && + "transactionId" in data.object.metadata && + typeof data.object.metadata.transactionId === "string" + ) { + return data.object.metadata.transactionId; + } + return null; +}; +const getChannelIdFromEventData = (data?: T) => { + if ( + typeof data === "object" && + data && + "object" in data && + typeof data.object === "object" && + data?.object && + "metadata" in data.object && + typeof data.object.metadata === "object" && + data.object.metadata && + "channelId" in data.object.metadata && + typeof data.object.metadata.channelId === "string" + ) { + return data.object.metadata.channelId; + } + return null; +}; + +async function stripeEventToTransactionEventReport({ + appConfig, + stripeEvent, +}: { + appConfig: PaymentAppConfig; + stripeEvent: Stripe.DiscriminatedEvent; +}): Promise { + const logger = createLogger({}, { msgPrefix: "[stripeEventToTransactionEventReport] " }); + + const transactionId = getTransactionIdFromEventData(stripeEvent.data); + if (!transactionId) { + logger.warn("stripeEvent is missing metadata.transactionId"); + return null; + } + const channelId = getChannelIdFromEventData(stripeEvent.data); + if (!channelId) { + logger.warn("stripeEvent is missing metadata.channelId"); + return null; + } + + const stripeConfig = getConfigurationForChannel(appConfig, channelId); + if (!stripeConfig) { + logger.warn(`Missing configuration for channel: ${channelId}`); + return null; + } + + return stripeEventToTransactionEventReportMutationVariables(transactionId, stripeEvent); +} + +export async function stripeEventToTransactionEventReportMutationVariables( + transactionId: string, + stripeEvent: Stripe.DiscriminatedEvent, +): Promise { + const logger = createLogger( + {}, + { msgPrefix: "[stripeEventToTransactionEventReportMutationVariables] " }, + ); + + const partialVariables = stripeEventToPartialTransactionEventReportMutationVariables(stripeEvent); + if (!partialVariables) { + return null; + } + + const availableActions = getAvailableActionsForType(partialVariables.type); + + const result = { + transactionId, + amount: partialVariables.amount, + externalUrl: partialVariables.externalUrl, + message: partialVariables.message, + pspReference: partialVariables.pspReference, + time: + "created" in stripeEvent && typeof stripeEvent.created === "number" + ? new Date(stripeEvent.created * 1000).toISOString() + : new Date().toISOString(), + type: partialVariables.type, + availableActions, + }; + logger.debug( + { + transactionId: result.transactionId, + amount: result.amount, + externalUrl: result.externalUrl, + message: result.message, + pspReference: result.pspReference, + time: result.time, + type: result.type, + availableActions: result.availableActions, + }, + "Result", + ); + return result; +} + +const getAvailableActionsForType = ( + type: TransactionEventTypeEnum, +): readonly TransactionActionEnum[] => { + switch (type) { + case TransactionEventTypeEnum.AuthorizationAdjustment: + return [TransactionActionEnum.Cancel]; + case TransactionEventTypeEnum.AuthorizationSuccess: + return [TransactionActionEnum.Charge, TransactionActionEnum.Cancel]; + case TransactionEventTypeEnum.ChargeSuccess: + return [TransactionActionEnum.Refund]; + case TransactionEventTypeEnum.RefundReverse: + return [TransactionActionEnum.Refund]; + + // no actions possible + case TransactionEventTypeEnum.AuthorizationActionRequired: + case TransactionEventTypeEnum.AuthorizationFailure: + case TransactionEventTypeEnum.AuthorizationRequest: + case TransactionEventTypeEnum.CancelFailure: + case TransactionEventTypeEnum.CancelRequest: + case TransactionEventTypeEnum.CancelSuccess: + case TransactionEventTypeEnum.ChargeActionRequired: + case TransactionEventTypeEnum.ChargeBack: + case TransactionEventTypeEnum.ChargeFailure: + case TransactionEventTypeEnum.ChargeRequest: + case TransactionEventTypeEnum.Info: + case TransactionEventTypeEnum.RefundFailure: + case TransactionEventTypeEnum.RefundRequest: + case TransactionEventTypeEnum.RefundSuccess: + return []; + default: + assertUnreachableButNotThrow(type); + return []; + } +}; + +function stripeEventToPartialTransactionEventReportMutationVariables( + stripeEvent: Stripe.DiscriminatedEvent, +) { + switch (stripeEvent.type) { + case "payment_intent.succeeded": + case "payment_intent.processing": + case "payment_intent.payment_failed": + case "payment_intent.created": + case "payment_intent.canceled": + case "payment_intent.partially_funded": + case "payment_intent.amount_capturable_updated": + case "payment_intent.requires_action": + return stripePaymentIntentEventToPartialTransactionEventReportMutationVariables(stripeEvent); + case "charge.refunded": + return stripeChargeRefundedEventToPartialTransactionEventReportMutationVariables({ + ...stripeEvent, + // TypeScript incorrectly widens the type of `type` + // This fixes the problem + type: stripeEvent.type, + }); + case "charge.refund.updated": + return stripeChargeRefundUpdatedEventToPartialTransactionEventReportMutationVariables( + stripeEvent, + ); + default: + return null; + } +} + +const getPaymentIntentIdFromObject = ({ payment_intent }: Stripe.Refund | Stripe.Charge) => + typeof payment_intent === "string" ? payment_intent : payment_intent?.id; + +function stripeChargeRefundUpdatedEventToPartialTransactionEventReportMutationVariables( + stripeEvent: Stripe.DiscriminatedEvent.ChargeRefundEvent, +) { + const paymentIntentId = getPaymentIntentIdFromObject(stripeEvent.data.object); + + // we can use chargeID for externalURL - it automatically redirects to the right place + const pspReference = + paymentIntentId || + ("id" in stripeEvent && typeof stripeEvent.id === "string" ? stripeEvent.id : ""); + const externalUrl = getStripeExternalUrlForIntentId(pspReference); + + const amount = getSaleorAmountFromStripeAmount({ + amount: stripeEvent.data.object.amount, + currency: stripeEvent.data.object.currency, + }); + + const typeAndMessage = __do(() => { + switch (stripeEvent.data.object.status) { + case "canceled": + case "failed": + return { + type: TransactionEventTypeEnum.RefundFailure, + message: stripeEvent.data.object.failure_reason, + }; + case "pending": + return { type: TransactionEventTypeEnum.RefundRequest }; + case "succeeded": + return { type: TransactionEventTypeEnum.RefundSuccess }; + case "requires_action": + return { type: TransactionEventTypeEnum.RefundRequest, message: "requires_action" }; + } + }); + + if (!typeAndMessage) { + return; + } + + return { + amount, + message: typeAndMessage.message || stripeEvent.data.object.description, + type: typeAndMessage.type, + pspReference, + externalUrl, + }; +} + +function stripeChargeRefundedEventToPartialTransactionEventReportMutationVariables( + stripeEvent: Stripe.DiscriminatedEvent.ChargeEvent & { type: "charge.refunded" }, +) { + const paymentIntentId = getPaymentIntentIdFromObject(stripeEvent.data.object); + + // we can use chargeID for externalURL - it automatically redirects to the right place + const pspReference = + paymentIntentId || + ("id" in stripeEvent && typeof stripeEvent.id === "string" ? stripeEvent.id : ""); + const externalUrl = getStripeExternalUrlForIntentId(pspReference); + + const amount = getSaleorAmountFromStripeAmount({ + amount: stripeEvent.data.object.amount_refunded, + currency: stripeEvent.data.object.currency, + }); + const type = TransactionEventTypeEnum.RefundSuccess; + return { amount, type, message: stripeEvent.data.object.description, pspReference, externalUrl }; +} + +function stripePaymentIntentEventToPartialTransactionEventReportMutationVariables( + stripeEvent: Stripe.DiscriminatedEvent.PaymentIntentEvent, +) { + const paymentIntent = stripeEvent.data.object; + const message = paymentIntent.cancellation_reason || paymentIntent.description || ""; + const manualCapture = stripeEvent.data.object.capture_method === "manual"; + const externalUrl = getStripeExternalUrlForIntentId(paymentIntent.id); + const pspReference = paymentIntent.id; + + switch (stripeEvent.type) { + // handling these is required + case "payment_intent.succeeded": { + const amount = getSaleorAmountFromStripeAmount({ + amount: manualCapture ? paymentIntent.amount_capturable : paymentIntent.amount_received, + currency: paymentIntent.currency, + }); + const type = manualCapture + ? TransactionEventTypeEnum.AuthorizationSuccess + : TransactionEventTypeEnum.ChargeSuccess; + + return { amount, type, externalUrl, pspReference, message }; + } + + case "payment_intent.processing": { + const amount = getSaleorAmountFromStripeAmount({ + amount: paymentIntent.amount, + currency: paymentIntent.currency, + }); + const type = manualCapture + ? TransactionEventTypeEnum.AuthorizationRequest + : TransactionEventTypeEnum.ChargeRequest; + return { amount, type, externalUrl, pspReference, message }; + } + + case "payment_intent.payment_failed": { + const amount = getSaleorAmountFromStripeAmount({ + amount: paymentIntent.amount, + currency: paymentIntent.currency, + }); + const type = manualCapture + ? TransactionEventTypeEnum.AuthorizationFailure + : TransactionEventTypeEnum.ChargeFailure; + return { amount, type, externalUrl, pspReference, message }; + } + + // additional events + case "payment_intent.created": { + const amount = getSaleorAmountFromStripeAmount({ + amount: paymentIntent.amount, + currency: paymentIntent.currency, + }); + const type = manualCapture + ? TransactionEventTypeEnum.AuthorizationRequest + : TransactionEventTypeEnum.ChargeRequest; + return { amount, type, externalUrl, pspReference, message }; + } + + case "payment_intent.canceled": { + const amount = getSaleorAmountFromStripeAmount({ + amount: paymentIntent.amount, + currency: paymentIntent.currency, + }); + const type = manualCapture + ? TransactionEventTypeEnum.AuthorizationFailure + : TransactionEventTypeEnum.ChargeFailure; + return { amount, type, externalUrl, pspReference, message }; + } + + case "payment_intent.partially_funded": { + const amount = getSaleorAmountFromStripeAmount({ + amount: paymentIntent.amount, + currency: paymentIntent.currency, + }); + const type = TransactionEventTypeEnum.Info; + return { amount, type, externalUrl, pspReference, message }; + } + + case "payment_intent.amount_capturable_updated": { + const amount = getSaleorAmountFromStripeAmount({ + amount: paymentIntent.amount, + currency: paymentIntent.currency, + }); + const type = TransactionEventTypeEnum.AuthorizationAdjustment; + return { amount, type, externalUrl, pspReference, message }; + } + + case "payment_intent.requires_action": { + const amount = getSaleorAmountFromStripeAmount({ + amount: paymentIntent.amount, + currency: paymentIntent.currency, + }); + const type = manualCapture + ? TransactionEventTypeEnum.AuthorizationActionRequired + : TransactionEventTypeEnum.ChargeActionRequired; + return { amount, type, externalUrl, pspReference, message }; + } + + default: + assertUnreachableButNotThrow(stripeEvent.type); + return null; + } +} diff --git a/src/modules/webhooks/transaction-cancelation-requested.test.ts b/src/modules/webhooks/transaction-cancelation-requested.test.ts new file mode 100644 index 0000000..b7baaed --- /dev/null +++ b/src/modules/webhooks/transaction-cancelation-requested.test.ts @@ -0,0 +1,74 @@ +import { describe, it, expect } from "vitest"; + +import { getStripeApiClient } from "../stripe/stripe-api"; +import { TransactionCancelationRequestedWebhookHandler } from "./transaction-cancelation-requested"; +import { + createMockTransactionCancelationRequestedEvent, + createMockTransactionInitializeSessionEvent, +} from "./__tests__/utils"; +import { TransactionInitializeSessionWebhookHandler } from "./transaction-initialize-session"; +import { setupRecording } from "@/__tests__/polly"; +import { testEnv } from "@/__tests__/test-env.mjs"; + +import { TransactionEventTypeEnum, TransactionFlowStrategyEnum } from "generated/graphql"; +import { invariant } from "@/lib/invariant"; + +describe("TransactionCancelationRequestedWebhookHandler", () => { + setupRecording({}); + + // https://stripe.com/docs/testing?testing-method=payment-methods#visa + // ${"JCB"} | ${"pm_card_jcb"} + // ${"American Express"} | ${"pm_card_amex"} + // @todo JCB and amex are omitted because they don't work + describe.each` + brand | paymentMethod + ${"Visa"} | ${"pm_card_visa"} + ${"Visa (debit)"} | ${"pm_card_visa_debit"} + ${"Mastercard"} | ${"pm_card_mastercard"} + ${"Mastercard (debit)"} | ${"pm_card_mastercard_debit"} + ${"Mastercard (prepaid)"} | ${"pm_card_mastercard_prepaid"} + ${"Discover"} | ${"pm_card_discover"} + ${"Diners Club"} | ${"pm_card_diners"} + ${"UnionPay"} | ${"pm_card_unionpay"} + `("$brand $paymentMethod", ({ paymentMethod }) => { + it("should cancel pre-authorized card", async () => { + // preauthorize + const data = {}; + const transactionInitializeEvent = await createMockTransactionInitializeSessionEvent({ + data, + action: { + actionType: TransactionFlowStrategyEnum.Authorization, + }, + }); + const initializeResult = await TransactionInitializeSessionWebhookHandler( + transactionInitializeEvent, + testEnv.TEST_SALEOR_API_URL, + ); + + invariant(initializeResult.pspReference, "Missing initializeResult.pspReference"); + + // mock frontend action – adding payment method details (card) + const stripeClient = getStripeApiClient(testEnv.TEST_PAYMENT_APP_SECRET_KEY); + await stripeClient.paymentIntents.confirm(initializeResult.pspReference, { + payment_method: paymentMethod, + }); + + // cancelation + const transactionCancelationEvent = await createMockTransactionCancelationRequestedEvent({ + transaction: { + pspReference: initializeResult.pspReference, + }, + }); + const cancelationResult = await TransactionCancelationRequestedWebhookHandler( + transactionCancelationEvent, + testEnv.TEST_SALEOR_API_URL, + ); + + expect(cancelationResult.amount).toEqual(222.99); + expect(cancelationResult.result).toEqual(TransactionEventTypeEnum.CancelSuccess); + const pspReference = cancelationResult.pspReference; + expect(pspReference).toEqual(expect.any(String)); + expect(cancelationResult.externalUrl).toContain(pspReference); + }); + }); +}); diff --git a/src/modules/webhooks/transaction-cancelation-requested.ts b/src/modules/webhooks/transaction-cancelation-requested.ts new file mode 100644 index 0000000..4a0806b --- /dev/null +++ b/src/modules/webhooks/transaction-cancelation-requested.ts @@ -0,0 +1,60 @@ +import { getWebhookPaymentAppConfigurator } from "../payment-app-configuration/payment-app-configuration-factory"; +import { paymentAppFullyConfiguredEntrySchema } from "../payment-app-configuration/config-entry"; +import { getConfigurationForChannel } from "../payment-app-configuration/payment-app-configuration"; +import { + getStripeExternalUrlForIntentId, + processStripePaymentIntentCancelRequest, +} from "../stripe/stripe-api"; +import { getSaleorAmountFromStripeAmount } from "../stripe/currencies"; +import { type TransactionCancelationRequestedResponse } from "@/schemas/TransactionCancelationRequested/TransactionCancelationRequestedResponse.mjs"; +import { + TransactionEventTypeEnum, + type TransactionCancelationRequestedEventFragment, + TransactionActionEnum, +} from "generated/graphql"; +import { invariant } from "@/lib/invariant"; + +export const TransactionCancelationRequestedWebhookHandler = async ( + event: TransactionCancelationRequestedEventFragment, + saleorApiUrl: string, +): Promise => { + const app = event.recipient; + invariant(app, "Missing event.recipient!"); + invariant( + event.action.actionType === TransactionActionEnum.Cancel, + `Incorrect action.actionType: ${event.action.actionType}`, + ); + invariant(event.action.amount, "Missing action.amount"); + invariant(event.transaction, "Missing transaction"); + + const { privateMetadata } = app; + const configurator = getWebhookPaymentAppConfigurator({ privateMetadata }, saleorApiUrl); + const appConfig = await configurator.getConfig(); + const stripeConfig = paymentAppFullyConfiguredEntrySchema.parse( + getConfigurationForChannel(appConfig, event.transaction.sourceObject?.channel.id), + ); + + const stripePaymentIntentCancelResponse = await processStripePaymentIntentCancelRequest({ + paymentIntentId: event.transaction.pspReference, + secretKey: stripeConfig.secretKey, + }); + + const transactionCancelationRequestedResponse: TransactionCancelationRequestedResponse = + stripePaymentIntentCancelResponse.status === "canceled" + ? // Sync flow + { + pspReference: stripePaymentIntentCancelResponse.id, + amount: getSaleorAmountFromStripeAmount({ + amount: stripePaymentIntentCancelResponse.amount, + currency: stripePaymentIntentCancelResponse.currency, + }), + result: TransactionEventTypeEnum.CancelSuccess, + externalUrl: getStripeExternalUrlForIntentId(stripePaymentIntentCancelResponse.id), + } + : // Async flow; waiting for confirmation + { + pspReference: stripePaymentIntentCancelResponse.id, + }; + + return transactionCancelationRequestedResponse; +}; diff --git a/src/modules/webhooks/transaction-charge-requested.test.ts b/src/modules/webhooks/transaction-charge-requested.test.ts new file mode 100644 index 0000000..1a9bd79 --- /dev/null +++ b/src/modules/webhooks/transaction-charge-requested.test.ts @@ -0,0 +1,118 @@ +import { describe, it, expect } from "vitest"; + +import { getStripeApiClient } from "../stripe/stripe-api"; +import { TransactionChargeRequestedWebhookHandler } from "./transaction-charge-requested"; +import { + createMockTransactionChargeRequestedEvent, + createMockStripeDataActionNotRequired, + createMockTransactionInitializeSessionEvent, +} from "./__tests__/utils"; +import { TransactionInitializeSessionWebhookHandler } from "./transaction-initialize-session"; +import { setupRecording } from "@/__tests__/polly"; +import { testEnv } from "@/__tests__/test-env.mjs"; + +import { TransactionEventTypeEnum, TransactionFlowStrategyEnum } from "generated/graphql"; +import { invariant } from "@/lib/invariant"; + +describe("TransactionChargeRequestedWebhookHandler", () => { + setupRecording({}); + + // https://stripe.com/docs/testing?testing-method=payment-methods#visa + // ${"JCB"} | ${"pm_card_jcb"} + // ${"Mastercard"} | ${"pm_card_mastercard"} + // @todo JCB and Mastercard are omitted because they don't work + describe.each` + brand | paymentMethod + ${"Visa"} | ${"pm_card_visa"} + ${"Visa (debit)"} | ${"pm_card_visa_debit"} + ${"Mastercard (debit)"} | ${"pm_card_mastercard_debit"} + ${"Mastercard (prepaid)"} | ${"pm_card_mastercard_prepaid"} + ${"American Express"} | ${"pm_card_amex"} + ${"Discover"} | ${"pm_card_discover"} + ${"Diners Club"} | ${"pm_card_diners"} + ${"UnionPay"} | ${"pm_card_unionpay"} + `("$brand $paymentMethod", ({ paymentMethod }) => { + it("should charge pre-authorized card", async () => { + // preauthorize + const data = createMockStripeDataActionNotRequired(); + const transactionInitializeEvent = await createMockTransactionInitializeSessionEvent({ + data, + action: { + actionType: TransactionFlowStrategyEnum.Authorization, + }, + }); + const initializeResult = await TransactionInitializeSessionWebhookHandler( + transactionInitializeEvent, + testEnv.TEST_SALEOR_API_URL, + ); + + invariant(initializeResult.pspReference, "Missing initializeResult.pspReference"); + + // mock frontend action – adding payment method details (card) + const stripeClient = getStripeApiClient(testEnv.TEST_PAYMENT_APP_SECRET_KEY); + await stripeClient.paymentIntents.confirm(initializeResult.pspReference, { + payment_method: paymentMethod, + }); + + // charge + const transactionChargeEvent = await createMockTransactionChargeRequestedEvent({ + transaction: { + pspReference: initializeResult.pspReference, + }, + }); + const chargeResult = await TransactionChargeRequestedWebhookHandler( + transactionChargeEvent, + testEnv.TEST_SALEOR_API_URL, + ); + + expect(chargeResult.amount).toEqual(222.99); + expect(chargeResult.result).toEqual(TransactionEventTypeEnum.ChargeSuccess); + const pspReference = chargeResult.pspReference; + expect(pspReference).toEqual(expect.any(String)); + expect(chargeResult.externalUrl).toContain(pspReference); + }); + + it("should partially charge pre-authorized card", async () => { + // preauthorize + const data = {}; + const transactionInitializeEvent = await createMockTransactionInitializeSessionEvent({ + data, + action: { + actionType: TransactionFlowStrategyEnum.Authorization, + }, + }); + const initializeResult = await TransactionInitializeSessionWebhookHandler( + transactionInitializeEvent, + testEnv.TEST_SALEOR_API_URL, + ); + + invariant(initializeResult.pspReference, "Missing initializeResult.pspReference"); + + // mock frontend action – adding payment method details (card) + const stripeClient = getStripeApiClient(testEnv.TEST_PAYMENT_APP_SECRET_KEY); + await stripeClient.paymentIntents.confirm(initializeResult.pspReference, { + payment_method: paymentMethod, + }); + + // charge + const transactionChargeEvent = await createMockTransactionChargeRequestedEvent({ + action: { + amount: 49.99, + }, + transaction: { + pspReference: initializeResult.pspReference, + }, + }); + const chargeResult = await TransactionChargeRequestedWebhookHandler( + transactionChargeEvent, + testEnv.TEST_SALEOR_API_URL, + ); + + expect(chargeResult.amount).toEqual(49.99); + expect(chargeResult.result).toEqual(TransactionEventTypeEnum.ChargeSuccess); + const pspReference = chargeResult.pspReference; + expect(pspReference).toEqual(expect.any(String)); + expect(chargeResult.externalUrl).toContain(pspReference); + }); + }); +}); diff --git a/src/modules/webhooks/transaction-charge-requested.ts b/src/modules/webhooks/transaction-charge-requested.ts new file mode 100644 index 0000000..088dcc6 --- /dev/null +++ b/src/modules/webhooks/transaction-charge-requested.ts @@ -0,0 +1,79 @@ +import { paymentAppFullyConfiguredEntrySchema } from "../payment-app-configuration/config-entry"; +import { getConfigurationForChannel } from "../payment-app-configuration/payment-app-configuration"; +import { getWebhookPaymentAppConfigurator } from "../payment-app-configuration/payment-app-configuration-factory"; +import { + getStripeExternalUrlForIntentId, + processStripePaymentIntentCaptureRequest, + stripePaymentIntentToTransactionResult, +} from "../stripe/stripe-api"; +import { + getSaleorAmountFromStripeAmount, + getStripeAmountFromSaleorMoney, +} from "../stripe/currencies"; +import { type TransactionChargeRequestedResponse } from "@/schemas/TransactionChargeRequested/TransactionChargeRequestedResponse.mjs"; +import { + type TransactionChargeRequestedEventFragment, + TransactionFlowStrategyEnum, + TransactionActionEnum, +} from "generated/graphql"; +import { invariant } from "@/lib/invariant"; + +export const TransactionChargeRequestedWebhookHandler = async ( + event: TransactionChargeRequestedEventFragment, + saleorApiUrl: string, +): Promise => { + const app = event.recipient; + invariant(app, "Missing event.recipient!"); + invariant( + event.action.actionType === TransactionActionEnum.Charge, + `Incorrect action.actionType: ${event.action.actionType}`, + ); + invariant(event.transaction, "Missing transaction"); + invariant(event.action.amount, "Missing action.amount"); + invariant(event.transaction.sourceObject, "Missing transaction.sourceObject"); + + const { privateMetadata } = app; + const configurator = getWebhookPaymentAppConfigurator({ privateMetadata }, saleorApiUrl); + const appConfig = await configurator.getConfig(); + const stripeConfig = paymentAppFullyConfiguredEntrySchema.parse( + getConfigurationForChannel(appConfig, event.transaction.sourceObject?.channel.id), + ); + + const stripePaymentIntentCaptureResponse = await processStripePaymentIntentCaptureRequest({ + paymentIntentId: event.transaction.pspReference, + stripeAmount: getStripeAmountFromSaleorMoney({ + amount: event.action.amount, + currency: event.transaction.sourceObject.total.gross.currency, + }), + secretKey: stripeConfig.secretKey, + }); + + const pspReference = stripePaymentIntentCaptureResponse.id; + const amount = getSaleorAmountFromStripeAmount({ + amount: stripePaymentIntentCaptureResponse.amount_received, + currency: stripePaymentIntentCaptureResponse.currency, + }); + const externalUrl = getStripeExternalUrlForIntentId(pspReference); + + const result = stripePaymentIntentToTransactionResult( + TransactionFlowStrategyEnum.Charge, + stripePaymentIntentCaptureResponse, + ); + + if (result === "CHARGE_SUCCESS" || result === "CHARGE_FAILURE") { + // Sync flow + const transactionChargeRequestedResponse: TransactionChargeRequestedResponse = { + result, + pspReference, + amount, + externalUrl, + }; + return transactionChargeRequestedResponse; + } else { + // Async flow; waiting for confirmation + const transactionChargeRequestedResponse: TransactionChargeRequestedResponse = { + pspReference, + }; + return transactionChargeRequestedResponse; + } +}; diff --git a/src/modules/webhooks/transaction-initialize-session.test.ts b/src/modules/webhooks/transaction-initialize-session.test.ts new file mode 100644 index 0000000..a91abfd --- /dev/null +++ b/src/modules/webhooks/transaction-initialize-session.test.ts @@ -0,0 +1,72 @@ +import { describe, it, expect } from "vitest"; + +import { TransactionInitializeSessionWebhookHandler } from "./transaction-initialize-session"; +import { + createMockTransactionInitializeSessionEvent, + createMockTransactionInitializeSessionSourceObjectCheckout, + createMockTransactionInitializeSessionSourceObjectOrder, +} from "./__tests__/utils"; +import { setupRecording } from "@/__tests__/polly"; +import { testEnv } from "@/__tests__/test-env.mjs"; + +import { TransactionFlowStrategyEnum } from "generated/graphql"; + +describe("TransactionInitializeSessionWebhookHandler", () => { + setupRecording({}); + + describe.each([ + { + name: "Checkout", + getSourceObject: createMockTransactionInitializeSessionSourceObjectCheckout, + }, + { name: "Order", getSourceObject: createMockTransactionInitializeSessionSourceObjectOrder }, + ])("$name", ({ getSourceObject }) => { + it.each([ + { + title: "should work authorization", + data: { + automatic_payment_methods: { + enabled: true, + }, + }, + result: "AUTHORIZATION_ACTION_REQUIRED", + amount: 99.99 + 123.0, + actionType: TransactionFlowStrategyEnum.Authorization, + }, + { + title: "should work charge", + data: { + automatic_payment_methods: { + enabled: true, + }, + }, + result: "CHARGE_ACTION_REQUIRED", + amount: 99.99 + 123.0, + actionType: TransactionFlowStrategyEnum.Charge, + }, + ])("$title", async ({ title, data, result, amount, actionType }) => { + const event = await createMockTransactionInitializeSessionEvent({ + data, + sourceObject: getSourceObject(), + action: { + actionType, + }, + }); + const initializeResult = await TransactionInitializeSessionWebhookHandler( + event, + testEnv.TEST_SALEOR_API_URL, + ); + expect(initializeResult.data).toEqual(expect.any(Object)); + expect(initializeResult.result).toEqual(result); + expect(initializeResult.amount).toEqual(amount); + expect(initializeResult.data).toMatchSnapshot( + { + paymentIntent: { + client_secret: expect.any(String), + }, + }, + title, + ); + }); + }); +}); diff --git a/src/modules/webhooks/transaction-initialize-session.ts b/src/modules/webhooks/transaction-initialize-session.ts new file mode 100644 index 0000000..c25c871 --- /dev/null +++ b/src/modules/webhooks/transaction-initialize-session.ts @@ -0,0 +1,106 @@ +import { + getEnvironmentFromKey, + getStripeExternalUrlForIntentId, + initializeStripePaymentIntent, + stripePaymentIntentToTransactionResult, + transactionSessionInitializeEventToStripeCreate, +} from "../stripe/stripe-api"; +import { getSaleorAmountFromStripeAmount } from "../stripe/currencies"; +import { getWebhookPaymentAppConfigurator } from "../payment-app-configuration/payment-app-configuration-factory"; +import { paymentAppFullyConfiguredEntrySchema } from "../payment-app-configuration/config-entry"; +import { obfuscateConfig, obfuscateValue } from "../app-configuration/utils"; +import { getConfigurationForChannel } from "../payment-app-configuration/payment-app-configuration"; +import { type TransactionInitializeSessionResponse } from "@/schemas/TransactionInitializeSession/TransactionInitializeSessionResponse.mjs"; +import { type TransactionInitializeSessionEventFragment } from "generated/graphql"; +import { invariant } from "@/lib/invariant"; +import { createLogger } from "@/lib/logger"; + +export const TransactionInitializeSessionWebhookHandler = async ( + event: TransactionInitializeSessionEventFragment, + saleorApiUrl: string, +): Promise => { + const logger = createLogger( + { saleorApiUrl }, + { msgPrefix: "[TransactionInitializeSessionWebhookHandler] " }, + ); + logger.debug( + { + transaction: event.transaction, + action: event.action, + sourceObject: { + id: event.sourceObject.id, + channel: event.sourceObject.channel, + __typename: event.sourceObject.__typename, + }, + merchantReference: event.merchantReference, + }, + "Received event", + ); + + const app = event.recipient; + invariant(app, "Missing event.recipient!"); + + const { privateMetadata } = app; + const configurator = getWebhookPaymentAppConfigurator({ privateMetadata }, saleorApiUrl); + const appConfig = await configurator.getConfig(); + + const stripeConfig = paymentAppFullyConfiguredEntrySchema.parse( + getConfigurationForChannel(appConfig, event.sourceObject.channel.id), + ); + + logger.info({}, "Processing Transaction Initialize request"); + + const paymentIntentCreateParams = transactionSessionInitializeEventToStripeCreate(event); + logger.debug({ + paymentIntentCreateParams: obfuscateConfig(paymentIntentCreateParams), + environment: getEnvironmentFromKey(stripeConfig.publishableKey), + }); + + const stripePaymentIntent = await initializeStripePaymentIntent({ + paymentIntentCreateParams, + secretKey: stripeConfig.secretKey, + }); + + const data = { + paymentIntent: { client_secret: stripePaymentIntent.client_secret }, + publishableKey: stripeConfig.publishableKey, + }; + logger.debug( + { + paymentIntent: { + client_secret: data.paymentIntent.client_secret + ? obfuscateValue(data.paymentIntent.client_secret) + : "", + }, + publishableKey: obfuscateValue(data.publishableKey), + }, + "Transaction Initialize response", + ); + + const result = stripePaymentIntentToTransactionResult( + event.action.actionType, + stripePaymentIntent, + ); + logger.debug(result, "Stripe -> Transaction result"); + + const transactionInitializeSessionResponse: TransactionInitializeSessionResponse = { + data, + pspReference: stripePaymentIntent.id, + result, + amount: stripePaymentIntent.amount + ? getSaleorAmountFromStripeAmount({ + amount: stripePaymentIntent.amount, + currency: stripePaymentIntent.currency, + }) + : 0, + time: stripePaymentIntent.created + ? new Date(stripePaymentIntent.created * 1000).toISOString() + : undefined, + message: stripePaymentIntent.cancellation_reason || stripePaymentIntent.description || "", + externalUrl: stripePaymentIntent.id + ? getStripeExternalUrlForIntentId(stripePaymentIntent.id) + : undefined, + }; + + return transactionInitializeSessionResponse; +}; diff --git a/src/modules/webhooks/transaction-process-session.test.ts b/src/modules/webhooks/transaction-process-session.test.ts new file mode 100644 index 0000000..89003de --- /dev/null +++ b/src/modules/webhooks/transaction-process-session.test.ts @@ -0,0 +1,84 @@ +import { describe, it, expect } from "vitest"; + +import { TransactionProcessSessionWebhookHandler } from "./transaction-process-session"; +import { + createMockTransactionProcessSessionEvent, + createMockTransactionInitializeSessionSourceObjectCheckout, + createMockTransactionInitializeSessionSourceObjectOrder, + createMockTransactionInitializeSessionEvent, +} from "./__tests__/utils"; +import { TransactionInitializeSessionWebhookHandler } from "./transaction-initialize-session"; +import { setupRecording } from "@/__tests__/polly"; +import { testEnv } from "@/__tests__/test-env.mjs"; + +import { TransactionFlowStrategyEnum } from "generated/graphql"; + +describe("TransactionProcessSessionWebhookHandler", () => { + setupRecording({}); + + describe.each([ + { + name: "Checkout", + getSourceObject: createMockTransactionInitializeSessionSourceObjectCheckout, + }, + { name: "Order", getSourceObject: createMockTransactionInitializeSessionSourceObjectOrder }, + ])("$name", ({ getSourceObject }) => { + it.each([ + { + title: "should work authorization", + data: {}, + result: "AUTHORIZATION_ACTION_REQUIRED", + amount: 99.99 + 123.0, + actionType: TransactionFlowStrategyEnum.Authorization, + }, + { + title: "should work charge", + data: {}, + result: "CHARGE_ACTION_REQUIRED", + amount: 99.99 + 123.0, + actionType: TransactionFlowStrategyEnum.Charge, + }, + ])("$title", async ({ title, data, result, amount, actionType }) => { + // Create payment + const initializeEvent = await createMockTransactionInitializeSessionEvent({ + data, + sourceObject: getSourceObject(), + action: { + actionType, + }, + }); + const initializeResult = await TransactionInitializeSessionWebhookHandler( + initializeEvent, + testEnv.TEST_SALEOR_API_URL, + ); + + // Update payment + const processEvent = await createMockTransactionProcessSessionEvent({ + data: {}, + sourceObject: getSourceObject(), + action: { + amount: amount + 100, + actionType, + }, + transaction: { + pspReference: initializeResult.pspReference, + }, + }); + const processResult = await TransactionProcessSessionWebhookHandler( + processEvent, + testEnv.TEST_SALEOR_API_URL, + ); + expect(processResult.data).toEqual(expect.any(Object)); + expect(processResult.result).toEqual(result); + expect(processResult.amount).toEqual(amount); + expect(processResult.data).toMatchSnapshot( + { + paymentIntent: { + client_secret: expect.any(String), + }, + }, + title, + ); + }); + }); +}); diff --git a/src/modules/webhooks/transaction-process-session.ts b/src/modules/webhooks/transaction-process-session.ts new file mode 100644 index 0000000..2ea5810 --- /dev/null +++ b/src/modules/webhooks/transaction-process-session.ts @@ -0,0 +1,100 @@ +import { obfuscateConfig, obfuscateValue } from "../app-configuration/utils"; +import { paymentAppFullyConfiguredEntrySchema } from "../payment-app-configuration/config-entry"; +import { getConfigurationForChannel } from "../payment-app-configuration/payment-app-configuration"; +import { getWebhookPaymentAppConfigurator } from "../payment-app-configuration/payment-app-configuration-factory"; +import { + transactionSessionProcessEventToStripeUpdate, + getEnvironmentFromKey, + stripePaymentIntentToTransactionResult, + getStripeExternalUrlForIntentId, + updateStripePaymentIntent, +} from "../stripe/stripe-api"; +import { getSaleorAmountFromStripeAmount } from "../stripe/currencies"; +import { type TransactionProcessSessionEventFragment } from "generated/graphql"; +import { type TransactionProcessSessionResponse } from "@/schemas/TransactionProcessSession/TransactionProcessSessionResponse.mjs"; +import { createLogger } from "@/lib/logger"; +import { invariant } from "@/lib/invariant"; + +export const TransactionProcessSessionWebhookHandler = async ( + event: TransactionProcessSessionEventFragment, + saleorApiUrl: string, +): Promise => { + const logger = createLogger({}, { msgPrefix: "[TransactionProcessSessionWebhookHandler] " }); + logger.debug( + { + transaction: event.transaction, + action: event.action, + sourceObject: { + id: event.sourceObject.id, + channel: event.sourceObject.channel, + __typename: event.sourceObject.__typename, + }, + merchantReference: event.merchantReference, + }, + "Received event", + ); + + const app = event.recipient; + invariant(app, "Missing event.recipient!"); + + const { privateMetadata } = app; + const configurator = getWebhookPaymentAppConfigurator({ privateMetadata }, saleorApiUrl); + const appConfig = await configurator.getConfig(); + + const stripeConfig = paymentAppFullyConfiguredEntrySchema.parse( + getConfigurationForChannel(appConfig, event.sourceObject.channel.id), + ); + + logger.info({}, "Processing Transaction Initialize request"); + + const paymentIntentUpdateParams = transactionSessionProcessEventToStripeUpdate(event); + logger.debug({ + paymentIntentUpdateParams: obfuscateConfig(paymentIntentUpdateParams), + environment: getEnvironmentFromKey(stripeConfig.publishableKey), + }); + + const stripePaymentIntent = await updateStripePaymentIntent({ + intentId: event.transaction.pspReference, + paymentIntentUpdateParams, + secretKey: stripeConfig.secretKey, + }); + + const data = { + paymentIntent: { client_secret: stripePaymentIntent.client_secret }, + publishableKey: stripeConfig.publishableKey, + }; + logger.debug( + { + paymentIntent: { + client_secret: data.paymentIntent.client_secret + ? obfuscateValue(data.paymentIntent.client_secret) + : "", + }, + publishableKey: obfuscateValue(data.publishableKey), + }, + "Transaction Process response", + ); + + const result = stripePaymentIntentToTransactionResult( + event.action.actionType, + stripePaymentIntent, + ); + logger.debug(result, "Stripe -> Transaction result"); + + const transactionProcessSessionResponse: TransactionProcessSessionResponse = { + data, + pspReference: stripePaymentIntent.id, + result, + amount: stripePaymentIntent.amount + ? getSaleorAmountFromStripeAmount({ + amount: stripePaymentIntent.amount, + currency: stripePaymentIntent.currency, + }) + : 0, + message: stripePaymentIntent.cancellation_reason || stripePaymentIntent.description || "", + externalUrl: stripePaymentIntent.id + ? getStripeExternalUrlForIntentId(stripePaymentIntent.id) + : undefined, + }; + return transactionProcessSessionResponse; +}; diff --git a/src/modules/webhooks/transaction-refund-requested.test.ts b/src/modules/webhooks/transaction-refund-requested.test.ts new file mode 100644 index 0000000..2925c93 --- /dev/null +++ b/src/modules/webhooks/transaction-refund-requested.test.ts @@ -0,0 +1,227 @@ +import { describe, it, expect } from "vitest"; +import { getStripeApiClient } from "../stripe/stripe-api"; +import { TransactionRefundRequestedWebhookHandler } from "./transaction-refund-requested"; +import { + createMockStripeDataActionNotRequired, + createMockTransactionChargeRequestedEvent, + createMockTransactionInitializeSessionEvent, + createMockTransactionRefundRequestedEvent, +} from "./__tests__/utils"; +import { TransactionInitializeSessionWebhookHandler } from "./transaction-initialize-session"; +import { TransactionChargeRequestedWebhookHandler } from "./transaction-charge-requested"; +import { testEnv } from "@/__tests__/test-env.mjs"; +import { TransactionEventTypeEnum, TransactionFlowStrategyEnum } from "generated/graphql"; +import { setupRecording } from "@/__tests__/polly"; +import { invariant } from "@/lib/invariant"; + +describe("TransactionRefundRequestedWebhookHandler", () => { + setupRecording({}); + + // https://stripe.com/docs/testing?testing-method=payment-methods#visa + // ${"JCB"} | ${"pm_card_jcb"} + // @todo JCB is omitted because it doesn't work + describe.each` + brand | paymentMethod + ${"Visa"} | ${"pm_card_visa"} + ${"Visa (debit)"} | ${"pm_card_visa_debit"} + ${"Mastercard"} | ${"pm_card_mastercard"} + ${"Mastercard (debit)"} | ${"pm_card_mastercard_debit"} + ${"Mastercard (prepaid)"} | ${"pm_card_mastercard_prepaid"} + ${"American Express"} | ${"pm_card_amex"} + ${"Discover"} | ${"pm_card_discover"} + ${"Diners Club"} | ${"pm_card_diners"} + ${"UnionPay"} | ${"pm_card_unionpay"} + `("$brand $paymentMethod", ({ paymentMethod }) => { + it("should request a refund in Stripe after authorize and charge", async () => { + // preauthorize + const data = createMockStripeDataActionNotRequired(); + const transactionInitializeEvent = await createMockTransactionInitializeSessionEvent({ + data, + action: { + actionType: TransactionFlowStrategyEnum.Authorization, + }, + }); + const initializeResult = await TransactionInitializeSessionWebhookHandler( + transactionInitializeEvent, + testEnv.TEST_SALEOR_API_URL, + ); + + invariant(initializeResult.pspReference, "Missing initializeResult.pspReference"); + + // mock frontend action – adding payment method details (card) + const stripeClient = getStripeApiClient(testEnv.TEST_PAYMENT_APP_SECRET_KEY); + await stripeClient.paymentIntents.confirm(initializeResult.pspReference, { + payment_method: paymentMethod, + }); + + // charge + const transactionChargeEvent = await createMockTransactionChargeRequestedEvent({ + transaction: { + pspReference: initializeResult.pspReference, + }, + }); + await TransactionChargeRequestedWebhookHandler( + transactionChargeEvent, + testEnv.TEST_SALEOR_API_URL, + ); + + // refund + const transactionRefundEvent = await createMockTransactionRefundRequestedEvent({ + transaction: { + pspReference: initializeResult.pspReference, + }, + }); + + const refundResult = await TransactionRefundRequestedWebhookHandler( + transactionRefundEvent, + testEnv.TEST_SALEOR_API_URL, + ); + + expect(refundResult.amount).toEqual(222.99); + expect(refundResult.result).toEqual(TransactionEventTypeEnum.RefundSuccess); + const pspReference = refundResult.pspReference; + expect(pspReference).toEqual(expect.any(String)); + expect(refundResult.externalUrl).toContain(pspReference); + }); + + it("should request a refund in Stripe after a charge", async () => { + // charge + const data = createMockStripeDataActionNotRequired(); + const transactionInitializeEvent = await createMockTransactionInitializeSessionEvent({ + data, + action: { + actionType: TransactionFlowStrategyEnum.Charge, + }, + }); + const initializeResult = await TransactionInitializeSessionWebhookHandler( + transactionInitializeEvent, + testEnv.TEST_SALEOR_API_URL, + ); + + invariant(initializeResult.pspReference, "Missing initializeResult.pspReference"); + + // mock frontend action – adding payment method details (card) + const stripeClient = getStripeApiClient(testEnv.TEST_PAYMENT_APP_SECRET_KEY); + await stripeClient.paymentIntents.confirm(initializeResult.pspReference, { + payment_method: paymentMethod, + }); + + // refund + const transactionRefundEvent = await createMockTransactionRefundRequestedEvent({ + transaction: { + pspReference: initializeResult.pspReference, + }, + }); + + const refundResult = await TransactionRefundRequestedWebhookHandler( + transactionRefundEvent, + testEnv.TEST_SALEOR_API_URL, + ); + + expect(refundResult.amount).toEqual(222.99); + expect(refundResult.result).toEqual(TransactionEventTypeEnum.RefundSuccess); + const pspReference = refundResult.pspReference; + expect(pspReference).toEqual(expect.any(String)); + expect(refundResult.externalUrl).toContain(pspReference); + }); + + it("should request a partial refund in Stripe after authorize and charge", async () => { + // preauthorize + const data = createMockStripeDataActionNotRequired(); + const transactionInitializeEvent = await createMockTransactionInitializeSessionEvent({ + data, + action: { + actionType: TransactionFlowStrategyEnum.Authorization, + }, + }); + const initializeResult = await TransactionInitializeSessionWebhookHandler( + transactionInitializeEvent, + testEnv.TEST_SALEOR_API_URL, + ); + + invariant(initializeResult.pspReference, "Missing initializeResult.pspReference"); + + // mock frontend action – adding payment method details (card) + const stripeClient = getStripeApiClient(testEnv.TEST_PAYMENT_APP_SECRET_KEY); + await stripeClient.paymentIntents.confirm(initializeResult.pspReference, { + payment_method: paymentMethod, + }); + + // charge + const transactionChargeEvent = await createMockTransactionChargeRequestedEvent({ + transaction: { + pspReference: initializeResult.pspReference, + }, + }); + await TransactionChargeRequestedWebhookHandler( + transactionChargeEvent, + testEnv.TEST_SALEOR_API_URL, + ); + + // refund + const transactionRefundEvent = await createMockTransactionRefundRequestedEvent({ + action: { + amount: 49.99, + }, + transaction: { + pspReference: initializeResult.pspReference, + }, + }); + + const refundResult = await TransactionRefundRequestedWebhookHandler( + transactionRefundEvent, + testEnv.TEST_SALEOR_API_URL, + ); + + expect(refundResult.amount).toEqual(49.99); + expect(refundResult.result).toEqual(TransactionEventTypeEnum.RefundSuccess); + const pspReference = refundResult.pspReference; + expect(pspReference).toEqual(expect.any(String)); + expect(refundResult.externalUrl).toContain(pspReference); + }); + + it("should request a partial refund in Stripe after a charge", async () => { + // charge + const data = createMockStripeDataActionNotRequired(); + const transactionInitializeEvent = await createMockTransactionInitializeSessionEvent({ + data, + action: { + actionType: TransactionFlowStrategyEnum.Charge, + }, + }); + const initializeResult = await TransactionInitializeSessionWebhookHandler( + transactionInitializeEvent, + testEnv.TEST_SALEOR_API_URL, + ); + + invariant(initializeResult.pspReference, "Missing initializeResult.pspReference"); + + // mock frontend action – adding payment method details (card) + const stripeClient = getStripeApiClient(testEnv.TEST_PAYMENT_APP_SECRET_KEY); + await stripeClient.paymentIntents.confirm(initializeResult.pspReference, { + payment_method: paymentMethod, + }); + + // refund + const transactionRefundEvent = await createMockTransactionRefundRequestedEvent({ + action: { + amount: 49.99, + }, + transaction: { + pspReference: initializeResult.pspReference, + }, + }); + + const refundResult = await TransactionRefundRequestedWebhookHandler( + transactionRefundEvent, + testEnv.TEST_SALEOR_API_URL, + ); + + expect(refundResult.amount).toEqual(49.99); + expect(refundResult.result).toEqual(TransactionEventTypeEnum.RefundSuccess); + const pspReference = refundResult.pspReference; + expect(pspReference).toEqual(expect.any(String)); + expect(refundResult.externalUrl).toContain(pspReference); + }); + }); +}); diff --git a/src/modules/webhooks/transaction-refund-requested.ts b/src/modules/webhooks/transaction-refund-requested.ts new file mode 100644 index 0000000..8004cba --- /dev/null +++ b/src/modules/webhooks/transaction-refund-requested.ts @@ -0,0 +1,95 @@ +import { paymentAppFullyConfiguredEntrySchema } from "../payment-app-configuration/config-entry"; +import { getConfigurationForChannel } from "../payment-app-configuration/payment-app-configuration"; +import { getWebhookPaymentAppConfigurator } from "../payment-app-configuration/payment-app-configuration-factory"; +import { + getSaleorAmountFromStripeAmount, + getStripeAmountFromSaleorMoney, +} from "../stripe/currencies"; +import { + getStripeExternalUrlForIntentId, + processStripePaymentIntentRefundRequest, +} from "../stripe/stripe-api"; +import { invariant } from "@/lib/invariant"; +import { type TransactionRefundRequestedResponse } from "@/schemas/TransactionRefundRequesed/TransactionRefundRequestedResponse.mjs"; +import { + TransactionActionEnum, + TransactionEventTypeEnum, + type TransactionRefundRequestedEventFragment, +} from "generated/graphql"; + +export const TransactionRefundRequestedWebhookHandler = async ( + event: TransactionRefundRequestedEventFragment, + saleorApiUrl: string, +): Promise => { + const app = event.recipient; + + invariant(app, "Missing event.recipient!"); + invariant( + event.action.actionType === TransactionActionEnum.Refund, + `Incorrect action.actionType: ${event.action.actionType}`, + ); + invariant(event.transaction?.pspReference, "Missing event.transaction.pspReference!"); + + const { privateMetadata } = app; + + const configurator = getWebhookPaymentAppConfigurator({ privateMetadata }, saleorApiUrl); + const appConfig = await configurator.getConfig(); + const stripeConfig = paymentAppFullyConfiguredEntrySchema.parse( + getConfigurationForChannel(appConfig, event.transaction.sourceObject?.channel.id), + ); + + const stripePaymentIntentRefundResponse = await processStripePaymentIntentRefundRequest({ + stripeAmount: + event.action.amount && event.transaction.sourceObject?.total?.gross?.currency + ? getStripeAmountFromSaleorMoney({ + amount: event.action.amount, + currency: event.transaction.sourceObject.total.gross.currency, + }) + : undefined, + paymentIntentId: event.transaction.pspReference, + secretKey: stripeConfig.secretKey, + }); + + const pspReference = stripePaymentIntentRefundResponse.id; + const amount = getSaleorAmountFromStripeAmount({ + amount: stripePaymentIntentRefundResponse.amount, + currency: stripePaymentIntentRefundResponse.currency, + }); + const externalUrl = getStripeExternalUrlForIntentId(pspReference); + + switch (stripePaymentIntentRefundResponse.status) { + case "succeeded": { + const transactionRefundRequestedResponse: TransactionRefundRequestedResponse = { + result: TransactionEventTypeEnum.RefundSuccess, + pspReference, + amount, + externalUrl, + }; + return transactionRefundRequestedResponse; + } + case "canceled": + case "failed": { + const transactionRefundRequestedResponse: TransactionRefundRequestedResponse = { + result: TransactionEventTypeEnum.RefundFailure, + pspReference, + amount, + externalUrl, + }; + return transactionRefundRequestedResponse; + } + case "requires_action": { + const transactionRefundRequestedResponse: TransactionRefundRequestedResponse = { + pspReference, + message: "requires_action", + }; + return transactionRefundRequestedResponse; + } + case "pending": + default: { + const transactionRefundRequestedResponse: TransactionRefundRequestedResponse = { + pspReference, + }; + return transactionRefundRequestedResponse; + } + } +}; diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx new file mode 100644 index 0000000..c797049 --- /dev/null +++ b/src/pages/_app.tsx @@ -0,0 +1,66 @@ +import "../styles/global.css"; +import "@saleor/macaw-ui/next/style"; + +import { AppBridgeProvider, useAppBridge } from "@saleor/app-sdk/app-bridge"; +import { RoutePropagator } from "@saleor/app-sdk/app-bridge/next"; +import { ThemeProvider } from "@saleor/macaw-ui/next"; +import { type AppProps } from "next/app"; + +import { Provider } from "urql"; +import { type ReactNode } from "react"; +import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; // note: it's imported only in dev mode +import Head from "next/head"; +import { ThemeSynchronizer } from "../modules/ui/theme-synchronizer"; +import { NoSSRWrapper } from "../modules/ui/no-ssr-wrapper"; + +import { appBridgeInstance } from "@/app-bridge-instance"; +import { ErrorModal } from "@/modules/ui/organisms/GlobalErrorModal/modal"; +import { trpcClient } from "@/modules/trpc/trpc-client"; +import { createClient } from "@/lib/create-graphq-client"; + +const UrqlProvider = ({ children }: { children: ReactNode }) => { + const { appBridgeState } = useAppBridge(); + if (!appBridgeState?.saleorApiUrl) { + return <>{children}; + } + + const client = createClient(appBridgeState?.saleorApiUrl, async () => + appBridgeState?.token ? { token: appBridgeState.token } : null, + ); + return {children}; +}; + +function NextApp({ Component, pageProps }: AppProps) { + return ( + <> + + Saleor App Payment Stripe + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default trpcClient.withTRPC(NextApp); diff --git a/src/pages/_error.js b/src/pages/_error.js new file mode 100644 index 0000000..55c3486 --- /dev/null +++ b/src/pages/_error.js @@ -0,0 +1,39 @@ +/** + * NOTE: This requires `@sentry/nextjs` version 7.3.0 or higher. + * + * NOTE: If using this with `next` version 12.2.0 or lower, uncomment the + * penultimate line in `CustomErrorComponent`. + * + * This page is loaded by Nextjs: + * - on the server, when data-fetching methods throw or reject + * - on the client, when `getInitialProps` throws or rejects + * - on the client, when a React lifecycle method throws or rejects, and it's + * caught by the built-in Nextjs error boundary + * + * See: + * - https://nextjs.org/docs/basic-features/data-fetching/overview + * - https://nextjs.org/docs/api-reference/data-fetching/get-initial-props + * - https://reactjs.org/docs/error-boundaries.html + */ + +import * as Sentry from "@sentry/nextjs"; +import NextErrorComponent from "next/error"; + +const CustomErrorComponent = (props) => { + // If you're using a Nextjs version prior to 12.2.1, uncomment this to + // compensate for https://github.com/vercel/next.js/issues/8592 + // Sentry.captureUnderscoreErrorException(props); + + return ; +}; + +CustomErrorComponent.getInitialProps = async (contextData) => { + // In case this is running in a serverless function, await this in order to give Sentry + // time to send the error before the lambda exits + await Sentry.captureUnderscoreErrorException(contextData); + + // This will contain the status code of the response + return NextErrorComponent.getInitialProps(contextData); +}; + +export default CustomErrorComponent; diff --git a/src/pages/api/manifest.ts b/src/pages/api/manifest.ts new file mode 100644 index 0000000..2a500a8 --- /dev/null +++ b/src/pages/api/manifest.ts @@ -0,0 +1,43 @@ +import { createManifestHandler } from "@saleor/app-sdk/handlers/next"; +import { type AppManifest } from "@saleor/app-sdk/types"; + +import packageJson from "../../../package.json"; +import { paymentGatewayInitializeSessionSyncWebhook } from "./webhooks/saleor/payment-gateway-initialize-session"; +import { transactionInitializeSessionSyncWebhook } from "./webhooks/saleor/transaction-initialize-session"; +import { transactionCancelationRequestedSyncWebhook } from "./webhooks/saleor/transaction-cancelation-requested"; +import { transactionChargeRequestedSyncWebhook } from "./webhooks/saleor/transaction-charge-requested"; +import { transactionProcessSessionSyncWebhook } from "./webhooks/saleor/transaction-process-session"; +import { transactionRefundRequestedSyncWebhook } from "./webhooks/saleor/transaction-refund-requested"; + +export default createManifestHandler({ + async manifestFactory(context) { + const manifest: AppManifest = { + id: "app.saleor.stripe", + name: "Stripe", + about: packageJson.description, + tokenTargetUrl: `${context.appBaseUrl}/api/register`, + appUrl: `${context.appBaseUrl}`, + permissions: ["HANDLE_PAYMENTS"], + version: packageJson.version, + requiredSaleorVersion: ">=3.14.0", + homepageUrl: "https://github.com/saleor/saleor-app-payment-stripe", + supportUrl: "https://github.com/saleor/saleor-app-payment-stripe/issues", + brand: { + logo: { + default: `${context.appBaseUrl}/logo.png`, + }, + }, + webhooks: [ + paymentGatewayInitializeSessionSyncWebhook.getWebhookManifest(context.appBaseUrl), + transactionInitializeSessionSyncWebhook.getWebhookManifest(context.appBaseUrl), + transactionProcessSessionSyncWebhook.getWebhookManifest(context.appBaseUrl), + transactionCancelationRequestedSyncWebhook.getWebhookManifest(context.appBaseUrl), + transactionChargeRequestedSyncWebhook.getWebhookManifest(context.appBaseUrl), + transactionRefundRequestedSyncWebhook.getWebhookManifest(context.appBaseUrl), + ], + extensions: [], + }; + + return manifest; + }, +}); diff --git a/src/pages/api/register.ts b/src/pages/api/register.ts new file mode 100644 index 0000000..4d37e21 --- /dev/null +++ b/src/pages/api/register.ts @@ -0,0 +1,25 @@ +import { createAppRegisterHandler } from "@saleor/app-sdk/handlers/next"; + +import { saleorApp } from "../../saleor-app"; +import { env } from "@/lib/env.mjs"; + +const allowedUrlsPattern = env.ALLOWED_DOMAIN_PATTERN; + +/** + * Required endpoint, called by Saleor to install app. + * It will exchange tokens with app, so saleorApp.apl will contain token + */ +export default createAppRegisterHandler({ + apl: saleorApp.apl, + allowedSaleorUrls: [ + (url) => { + if (allowedUrlsPattern) { + const regex = new RegExp(allowedUrlsPattern); + + return regex.test(url); + } + + return true; + }, + ], +}); diff --git a/src/pages/api/trpc/[trpc].ts b/src/pages/api/trpc/[trpc].ts new file mode 100644 index 0000000..7d18a1f --- /dev/null +++ b/src/pages/api/trpc/[trpc].ts @@ -0,0 +1,26 @@ +import * as trpcNext from "@trpc/server/adapters/next"; +import * as Sentry from "@sentry/nextjs"; +import { appRouter } from "../../../modules/trpc/trpc-app-router"; +import { createTrpcContext } from "../../../modules/trpc/trpc-context"; +import { logger, redactError } from "@/lib/logger"; +import { BaseTrpcError, FieldError } from "@/errors"; +import { isDevelopment } from "@/lib/isEnv"; + +export default trpcNext.createNextApiHandler({ + router: appRouter, + createContext: createTrpcContext, + onError: ({ path, error, type, ctx, input }) => { + const cause = error?.cause; + if (cause instanceof BaseTrpcError || cause instanceof FieldError) { + // don't log expected errors + return; + } + + if (isDevelopment()) { + // eslint-disable-next-line @saleor/saleor-app/logger-leak + return logger.error({ input, path, error, type, ctx }, "TRPC failed"); + } + logger.error({ path, error: redactError(error), type }, "TRPC failed"); + Sentry.captureException(error); + }, +}); diff --git a/src/pages/api/webhooks/saleor/payment-gateway-initialize-session.ts b/src/pages/api/webhooks/saleor/payment-gateway-initialize-session.ts new file mode 100644 index 0000000..355bb86 --- /dev/null +++ b/src/pages/api/webhooks/saleor/payment-gateway-initialize-session.ts @@ -0,0 +1,44 @@ +import { SaleorSyncWebhook } from "@saleor/app-sdk/handlers/next"; +import { type PageConfig } from "next"; +import { saleorApp } from "@/saleor-app"; +import { + UntypedPaymentGatewayInitializeSessionDocument, + type PaymentGatewayInitializeSessionEventFragment, +} from "generated/graphql"; +import { PaymentGatewayInitializeSessionWebhookHandler } from "@/modules/webhooks/payment-gateway-initialize-session"; +import { getSyncWebhookHandler } from "@/backend-lib/api-route-utils"; +import ValidatePaymentGatewayInitializeSessionResponse from "@/schemas/PaymentGatewayInitializeSession/PaymentGatewayInitializeSessionResponse.mjs"; + +export const config: PageConfig = { + api: { + bodyParser: false, + }, +}; + +export const paymentGatewayInitializeSessionSyncWebhook = + new SaleorSyncWebhook({ + name: "PaymentGatewayInitializeSession", + apl: saleorApp.apl, + event: "PAYMENT_GATEWAY_INITIALIZE_SESSION", + query: UntypedPaymentGatewayInitializeSessionDocument, + webhookPath: "/api/webhooks/saleor/payment-gateway-initialize-session", + }); + +export default paymentGatewayInitializeSessionSyncWebhook.createHandler( + getSyncWebhookHandler( + "paymentGatewayInitializeSessionSyncWebhook", + PaymentGatewayInitializeSessionWebhookHandler, + ValidatePaymentGatewayInitializeSessionResponse, + (payload, errorResponse) => { + return { + message: errorResponse.message, + data: { + errors: errorResponse.errors, + paymentMethodsResponse: {}, + publishableKey: "", + environment: "TEST", + }, + } as const; + }, + ), +); diff --git a/src/pages/api/webhooks/saleor/transaction-cancelation-requested.ts b/src/pages/api/webhooks/saleor/transaction-cancelation-requested.ts new file mode 100644 index 0000000..10c79e1 --- /dev/null +++ b/src/pages/api/webhooks/saleor/transaction-cancelation-requested.ts @@ -0,0 +1,44 @@ +import { uuidv7 } from "uuidv7"; + +import { SaleorSyncWebhook } from "@saleor/app-sdk/handlers/next"; +import { type PageConfig } from "next"; +import { saleorApp } from "@/saleor-app"; +import { + UntypedTransactionCancelationRequestedDocument, + type TransactionCancelationRequestedEventFragment, + TransactionEventTypeEnum, +} from "generated/graphql"; +import { getSyncWebhookHandler } from "@/backend-lib/api-route-utils"; +import { TransactionCancelationRequestedWebhookHandler } from "@/modules/webhooks/transaction-cancelation-requested"; +import ValidateTransactionCancelationRequestedResponse from "@/schemas/TransactionCancelationRequested/TransactionCancelationRequestedResponse.mjs"; + +export const config: PageConfig = { + api: { + bodyParser: false, + }, +}; + +export const transactionCancelationRequestedSyncWebhook = + new SaleorSyncWebhook({ + name: "TransactionCancelationRequested", + apl: saleorApp.apl, + event: "TRANSACTION_CANCELATION_REQUESTED", + query: UntypedTransactionCancelationRequestedDocument, + webhookPath: "/api/webhooks/saleor/transaction-cancelation-requested", + }); + +export default transactionCancelationRequestedSyncWebhook.createHandler( + getSyncWebhookHandler( + "transactionCancelationRequestedSyncWebhook", + TransactionCancelationRequestedWebhookHandler, + ValidateTransactionCancelationRequestedResponse, + (_payload, errorResponse) => { + return { + message: errorResponse.message, + result: TransactionEventTypeEnum.CancelFailure, + // @todo consider making pspReference optional https://github.com/saleor/saleor/issues/12490 + pspReference: uuidv7(), + } as const; + }, + ), +); diff --git a/src/pages/api/webhooks/saleor/transaction-charge-requested.ts b/src/pages/api/webhooks/saleor/transaction-charge-requested.ts new file mode 100644 index 0000000..ddd66ac --- /dev/null +++ b/src/pages/api/webhooks/saleor/transaction-charge-requested.ts @@ -0,0 +1,43 @@ +import { SaleorSyncWebhook } from "@saleor/app-sdk/handlers/next"; +import { type PageConfig } from "next"; +import { uuidv7 } from "uuidv7"; +import { saleorApp } from "@/saleor-app"; +import { + UntypedTransactionChargeRequestedDocument, + type TransactionChargeRequestedEventFragment, + TransactionEventTypeEnum, +} from "generated/graphql"; +import { getSyncWebhookHandler } from "@/backend-lib/api-route-utils"; +import { TransactionChargeRequestedWebhookHandler } from "@/modules/webhooks/transaction-charge-requested"; +import ValidateTransactionChargeRequestedResponse from "@/schemas/TransactionChargeRequested/TransactionChargeRequestedResponse.mjs"; + +export const config: PageConfig = { + api: { + bodyParser: false, + }, +}; + +export const transactionChargeRequestedSyncWebhook = + new SaleorSyncWebhook({ + name: "TransactionChargeRequested", + apl: saleorApp.apl, + event: "TRANSACTION_CHARGE_REQUESTED", + query: UntypedTransactionChargeRequestedDocument, + webhookPath: "/api/webhooks/saleor/transaction-charge-requested", + }); + +export default transactionChargeRequestedSyncWebhook.createHandler( + getSyncWebhookHandler( + "transactionChargeRequestedSyncWebhook", + TransactionChargeRequestedWebhookHandler, + ValidateTransactionChargeRequestedResponse, + (_payload, errorResponse) => { + return { + message: errorResponse.message, + result: TransactionEventTypeEnum.ChargeFailure, + // @todo consider making pspReference optional https://github.com/saleor/saleor/issues/12490 + pspReference: uuidv7(), + } as const; + }, + ), +); diff --git a/src/pages/api/webhooks/saleor/transaction-initialize-session.ts b/src/pages/api/webhooks/saleor/transaction-initialize-session.ts new file mode 100644 index 0000000..ac6f9cd --- /dev/null +++ b/src/pages/api/webhooks/saleor/transaction-initialize-session.ts @@ -0,0 +1,49 @@ +import { SaleorSyncWebhook } from "@saleor/app-sdk/handlers/next"; +import { type PageConfig } from "next"; +import { uuidv7 } from "uuidv7"; +import { saleorApp } from "@/saleor-app"; +import { + UntypedTransactionInitializeSessionDocument, + type TransactionInitializeSessionEventFragment, + TransactionFlowStrategyEnum, + TransactionEventTypeEnum, +} from "generated/graphql"; +import { TransactionInitializeSessionWebhookHandler } from "@/modules/webhooks/transaction-initialize-session"; +import { getSyncWebhookHandler } from "@/backend-lib/api-route-utils"; +import ValidateTransactionInitializeSessionResponse from "@/schemas/TransactionInitializeSession/TransactionInitializeSessionResponse.mjs"; + +export const config: PageConfig = { + api: { + bodyParser: false, + }, +}; + +export const transactionInitializeSessionSyncWebhook = + new SaleorSyncWebhook({ + name: "TransactionInitializeSession", + apl: saleorApp.apl, + event: "TRANSACTION_INITIALIZE_SESSION", + query: UntypedTransactionInitializeSessionDocument, + webhookPath: "/api/webhooks/saleor/transaction-initialize-session", + }); + +export default transactionInitializeSessionSyncWebhook.createHandler( + getSyncWebhookHandler( + "transactionInitializeSessionSyncWebhook", + TransactionInitializeSessionWebhookHandler, + ValidateTransactionInitializeSessionResponse, + (payload, errorResponse) => { + return { + amount: 0, + result: + payload.action.actionType === TransactionFlowStrategyEnum.Authorization + ? TransactionEventTypeEnum.AuthorizationFailure + : TransactionEventTypeEnum.ChargeFailure, + message: errorResponse.message, + data: { errors: errorResponse.errors, paymentIntent: {}, publishableKey: "" }, + // @todo consider making pspReference optional https://github.com/saleor/saleor/issues/12490 + pspReference: uuidv7(), + } as const; + }, + ), +); diff --git a/src/pages/api/webhooks/saleor/transaction-process-session.ts b/src/pages/api/webhooks/saleor/transaction-process-session.ts new file mode 100644 index 0000000..1707246 --- /dev/null +++ b/src/pages/api/webhooks/saleor/transaction-process-session.ts @@ -0,0 +1,49 @@ +import { SaleorSyncWebhook } from "@saleor/app-sdk/handlers/next"; +import { type PageConfig } from "next"; +import { uuidv7 } from "uuidv7"; +import { saleorApp } from "@/saleor-app"; +import { + UntypedTransactionProcessSessionDocument, + type TransactionProcessSessionEventFragment, + TransactionFlowStrategyEnum, + TransactionEventTypeEnum, +} from "generated/graphql"; +import { TransactionProcessSessionWebhookHandler } from "@/modules/webhooks/transaction-process-session"; +import { getSyncWebhookHandler } from "@/backend-lib/api-route-utils"; +import ValidateTransactionProcessSessionResponse from "@/schemas/TransactionProcessSession/TransactionProcessSessionResponse.mjs"; + +export const config: PageConfig = { + api: { + bodyParser: false, + }, +}; + +export const transactionProcessSessionSyncWebhook = + new SaleorSyncWebhook({ + name: "TransactionProcessSession", + apl: saleorApp.apl, + event: "TRANSACTION_PROCESS_SESSION", + query: UntypedTransactionProcessSessionDocument, + webhookPath: "/api/webhooks/saleor/transaction-process-session", + }); + +export default transactionProcessSessionSyncWebhook.createHandler( + getSyncWebhookHandler( + "transactionProcessSessionSyncWebhook", + TransactionProcessSessionWebhookHandler, + ValidateTransactionProcessSessionResponse, + (payload, errorResponse) => { + return { + amount: 0, + result: + payload.action.actionType === TransactionFlowStrategyEnum.Authorization + ? TransactionEventTypeEnum.AuthorizationFailure + : TransactionEventTypeEnum.ChargeFailure, + message: errorResponse.message, + data: { errors: errorResponse.errors, paymentIntent: {}, publishableKey: "" }, + // @todo consider making pspReference optional https://github.com/saleor/saleor/issues/12490 + pspReference: uuidv7(), + } as const; + }, + ), +); diff --git a/src/pages/api/webhooks/saleor/transaction-refund-requested.ts b/src/pages/api/webhooks/saleor/transaction-refund-requested.ts new file mode 100644 index 0000000..6659b06 --- /dev/null +++ b/src/pages/api/webhooks/saleor/transaction-refund-requested.ts @@ -0,0 +1,43 @@ +import { SaleorSyncWebhook } from "@saleor/app-sdk/handlers/next"; +import { type PageConfig } from "next"; +import { uuidv7 } from "uuidv7"; +import { + UntypedTransactionRefundRequestedDocument, + type TransactionRefundRequestedEventFragment, + TransactionEventTypeEnum, +} from "generated/graphql"; +import { saleorApp } from "@/saleor-app"; +import { getSyncWebhookHandler } from "@/backend-lib/api-route-utils"; +import { TransactionRefundRequestedWebhookHandler } from "@/modules/webhooks/transaction-refund-requested"; +import ValidateTransactionRefundRequestedResponse from "@/schemas/TransactionRefundRequesed/TransactionRefundRequestedResponse.mjs"; + +export const config: PageConfig = { + api: { + bodyParser: false, + }, +}; + +export const transactionRefundRequestedSyncWebhook = + new SaleorSyncWebhook({ + name: "TransactionRefundRequested", + apl: saleorApp.apl, + event: "TRANSACTION_REFUND_REQUESTED", + query: UntypedTransactionRefundRequestedDocument, + webhookPath: "/api/webhooks/saleor/transaction-refund-requested", + }); + +export default transactionRefundRequestedSyncWebhook.createHandler( + getSyncWebhookHandler( + "transactionRefundRequested", + TransactionRefundRequestedWebhookHandler, + ValidateTransactionRefundRequestedResponse, + (_payload, errorResponse) => { + return { + message: errorResponse.message, + result: TransactionEventTypeEnum.RefundFailure, + // @todo consider making pspReference optional https://github.com/saleor/saleor/issues/12490 + pspReference: uuidv7(), + } as const; + }, + ), +); diff --git a/src/pages/api/webhooks/stripe/index.ts b/src/pages/api/webhooks/stripe/index.ts new file mode 100644 index 0000000..2bc0602 --- /dev/null +++ b/src/pages/api/webhooks/stripe/index.ts @@ -0,0 +1,58 @@ +import { type NextApiRequest, type NextApiResponse } from "next"; +import * as Sentry from "@sentry/nextjs"; +import { createLogger, redactError } from "@/lib/logger"; +import { BaseError, MissingSaleorApiUrlError, MissingAuthDataError } from "@/errors"; +import { + MissingSignatureError, + UnexpectedTransactionEventReportError, +} from "@/modules/webhooks/stripe-webhook.errors"; +import { stripeWebhookHandler } from "@/modules/webhooks/stripe-webhook"; + +export const config = { + api: { + bodyParser: false, + }, +}; + +export default async function StripeWebhookHandler( + req: NextApiRequest, + res: NextApiResponse, +): Promise { + if (req.method !== "POST") { + res.setHeader("Allow", "POST"); + res.status(405).end("Method Not Allowed"); + return; + } + + const logger = createLogger({}, { msgPrefix: "[StripeWebhookHandler] " }); + logger.info("Handler was called"); + + try { + await stripeWebhookHandler(req); + } catch (err) { + if (err instanceof BaseError) { + Sentry.captureException(err, { extra: { errors: err.errors } }); + } else { + Sentry.captureException(err); + } + logger.error(redactError(err), "stripeWebhookHandler failed"); + + if (err instanceof MissingSaleorApiUrlError) { + return res.status(400).json(MissingSaleorApiUrlError.serialize(err)); + } + if (err instanceof MissingAuthDataError) { + return res.status(412).json(MissingAuthDataError.serialize(err)); + } + if (err instanceof MissingSignatureError) { + return res.status(400).json(MissingSignatureError.serialize(err)); + } + if (err instanceof UnexpectedTransactionEventReportError) { + return res.status(500).json(UnexpectedTransactionEventReportError.serialize(err)); + } + return res.status(500).json(BaseError.serialize(err)); + } + + logger.info("StripeWebhookHandler finished OK"); + res.status(204).end(); + return; +} diff --git a/src/pages/config.tsx b/src/pages/config.tsx new file mode 100644 index 0000000..fc66789 --- /dev/null +++ b/src/pages/config.tsx @@ -0,0 +1,138 @@ +import { useAppBridge, withAuthorization } from "@saleor/app-sdk/app-bridge"; +import { useState } from "react"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { Box, Button, Text } from "@saleor/macaw-ui/next"; +import { type NextPage } from "next"; +import { FormProvider, useForm } from "react-hook-form"; +import { z } from "zod"; +import { checkTokenPermissions } from "../modules/jwt/check-token-offline"; +import { + type PaymentAppFormConfigEntry, + paymentAppCombinedFormSchema, + paymentAppConfigEntrySchema, +} from "../modules/payment-app-configuration/config-entry"; +import { FetchError, useFetch, usePost } from "../lib/use-fetch"; +import { AppLayout } from "@/modules/ui/templates/AppLayout"; +import { FormInput } from "@/modules/ui/atoms/macaw-ui/FormInput"; + +const actionId = "payment-form"; + +const ConfigPage: NextPage = () => { + const { appBridgeState, appBridge } = useAppBridge(); + const { token } = appBridgeState ?? {}; + + const hasPermissions = checkTokenPermissions(token, ["MANAGE_APPS", "MANAGE_SETTINGS"]); + + const [isLoading, setIsLoading] = useState(true); + + const formMethods = useForm({ + resolver: zodResolver(paymentAppCombinedFormSchema), + defaultValues: { + secretKey: "", + configurationName: "", + }, + }); + + const { + handleSubmit, + control, + reset, + setError, + formState: { isSubmitting }, + resetField, + } = formMethods; + + useFetch("/api/config", { + schema: paymentAppConfigEntrySchema, + onFinished: () => setIsLoading(false), + onSuccess: (data) => { + reset(data); + }, + onError: async (err) => { + const message = err instanceof FetchError ? err.body : err.message; + await appBridge?.dispatch({ + type: "notification", + payload: { + title: "Form error", + text: "Error while fetching initial form data", + status: "error", + actionId, + apiMessage: message, + }, + }); + }, + }); + + const postForm = usePost("/api/config", { + schema: z.unknown(), + onSuccess: async () => { + await appBridge?.dispatch({ + type: "notification", + payload: { + title: "Form saved", + text: "App configuration was saved successfully", + status: "success", + actionId: "payment-form", + }, + }); + }, + onError: async (err) => { + const apiMessage = err instanceof FetchError ? err.body : err.name; + await appBridge?.dispatch({ + type: "notification", + payload: { + title: "Form error", + text: err.message, + status: "error", + actionId, + apiMessage, + }, + }); + setError("root", { message: err.message }); + }, + }); + + if (!hasPermissions) { + return ( + + {"You don't have permissions to configure this app"} + + ); + } + + return ( + + + +
postForm(data))} + > + Payment Provider settings + + + + + + +
+ +
+
+
+
+
+ ); +}; + +export default withAuthorization()(ConfigPage); diff --git a/src/pages/configurations/add.tsx b/src/pages/configurations/add.tsx new file mode 100644 index 0000000..f1efe13 --- /dev/null +++ b/src/pages/configurations/add.tsx @@ -0,0 +1,26 @@ +import { Text } from "@saleor/macaw-ui/next"; +import { withAuthorization } from "@saleor/app-sdk/app-bridge"; +import { AppLayout } from "@/modules/ui/templates/AppLayout"; +import { StripeConfigurationForm } from "@/modules/ui/organisms/AddStripeConfigurationForm/AddStripeConfigurationForm"; + +const AddConfigurationPage = () => { + return ( + + + Create new Stripe configuration. + + + Stripe Webhooks will be created automatically. + + + } + > + + + ); +}; + +export default withAuthorization()(AddConfigurationPage); diff --git a/src/pages/configurations/edit/[configurationId].tsx b/src/pages/configurations/edit/[configurationId].tsx new file mode 100644 index 0000000..4a7a88e --- /dev/null +++ b/src/pages/configurations/edit/[configurationId].tsx @@ -0,0 +1,33 @@ +import { Text } from "@saleor/macaw-ui/next"; +import { withAuthorization } from "@saleor/app-sdk/app-bridge"; +import { useRouter } from "next/router"; +import { AppLayout } from "@/modules/ui/templates/AppLayout"; +import { StripeConfigurationForm } from "@/modules/ui/organisms/AddStripeConfigurationForm/AddStripeConfigurationForm"; + +const EditConfigurationPage = () => { + const router = useRouter(); + if (typeof router.query.configurationId !== "string" || !router.query.configurationId) { + // TODO: Add loading + return
; + } + + return ( + + + Edit Stripe configuration. + + + Note: Stripe Webhooks will be created automatically. + + + } + > + + + ); +}; + +export default withAuthorization()(EditConfigurationPage); diff --git a/src/pages/configurations/list.tsx b/src/pages/configurations/list.tsx new file mode 100644 index 0000000..32f3d68 --- /dev/null +++ b/src/pages/configurations/list.tsx @@ -0,0 +1,86 @@ +import { useAppBridge, withAuthorization } from "@saleor/app-sdk/app-bridge"; +import { Box, Text } from "@saleor/macaw-ui/next"; +import { AppLayout, AppLayoutRow } from "@/modules/ui/templates/AppLayout"; +import { trpcClient } from "@/modules/trpc/trpc-client"; +import { getErrorHandler } from "@/modules/trpc/utils"; +import { useFetchChannelsQuery } from "generated/graphql"; +import { StripeConfigurationsList } from "@/modules/ui/organisms/StripeConfigurationList/StripeConfigurationList"; +import { ChannelToConfigurationList } from "@/modules/ui/organisms/ChannelToConfigurationList/ChannelToConfigurationList"; +import { Skeleton } from "@/modules/ui/atoms/Skeleton/Skeleton"; + +function ListConfigurationPage() { + const { appBridge } = useAppBridge(); + const [allConfigurations, channelMappings] = trpcClient.useQueries((t) => [ + t.paymentAppConfigurationRouter.paymentConfig.getAll(undefined, { + onError: getErrorHandler({ + appBridge, + actionId: "list-all-configurations", + message: "Error while fetching the list of configurations", + title: "API Error", + }), + }), + t.paymentAppConfigurationRouter.mapping.getAll(undefined, { + onError: getErrorHandler({ + appBridge, + actionId: "channel-mappings-get-all", + message: "Error while fetching the channel mappings", + title: "API Error", + }), + }), + ]); + + const [channels] = useFetchChannelsQuery(); + + const hasAnyConfigs = allConfigurations.data && allConfigurations.data.length > 0; + const hasAnyMappings = Object.values(channelMappings.data || {}).filter(Boolean).length > 0; + + return ( + + + {allConfigurations.isLoading ? ( + + ) : ( + + )} + + + + Assign Stripe configurations to Saleor channels. + + {!channelMappings.isLoading && !hasAnyMappings && ( + + + No channels have configurations assigned. + + + This means payments are not processed by Stripe. + + + )} + + } + > + {channelMappings.isLoading ? ( + + ) : ( + + )} + + + ); +} + +export default withAuthorization()(ListConfigurationPage); diff --git a/src/pages/index.tsx b/src/pages/index.tsx new file mode 100644 index 0000000..ec7974d --- /dev/null +++ b/src/pages/index.tsx @@ -0,0 +1,136 @@ +import { type NextPage } from "next"; +import { useAppBridge } from "@saleor/app-sdk/app-bridge"; +import { Box, Button, Text } from "@saleor/macaw-ui/next"; +import { useEffect, useState } from "react"; +import { FormProvider, useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { z } from "zod"; +import { useRouter } from "next/router"; +import { FormInput } from "@/modules/ui/atoms/macaw-ui/FormInput"; + +const schema = z + .object({ + saleorUrl: z.string().url(), + }) + .required(); +type FormValues = z.infer; + +const AddToSaleorForm = () => { + const formMethods = useForm({ + resolver: zodResolver(schema), + defaultValues: { + saleorUrl: "", + }, + }); + + const { + handleSubmit, + control, + formState: { isSubmitting, errors }, + } = formMethods; + + return ( + +
{ + const manifestUrl = new URL("/api/manifest", window.location.origin).toString(); + const redirectUrl = new URL( + `/dashboard/apps/install?manifestUrl=${manifestUrl}`, + values.saleorUrl, + ).toString(); + + window.open(redirectUrl, "_blank"); + })} + > + + + + +
+
+ ); +}; + +const CopyManifest = () => { + const [copied, setCopied] = useState(false); + + useEffect(() => { + const unsetCopied = () => { + setCopied(false); + }; + + if (copied) { + setTimeout(unsetCopied, 1750); + } + }, [copied]); + + const handleClick = async () => { + await navigator.clipboard.writeText(window.location.origin + "/api/manifest"); + setCopied(true); + }; + + return ( + + ); +}; + +const IndexPage: NextPage = () => { + const { appBridgeState } = useAppBridge(); + const [mounted, setMounted] = useState(false); + const router = useRouter(); + + useEffect(() => { + setMounted(true); + }, []); + + if (!mounted) { + return null; + } + + if (appBridgeState?.ready && mounted) { + void router.replace("/configurations/list"); + return null; + } + + return ( + + + Welcome to Payment App Stripe 💰 + + + Simplify your payment process and offer a seamless online shopping experience with Stripe + payment integration for Saleor. + + + {!appBridgeState?.ready && ( +
+ + Install this app in your Saleor Dashboard to proceed! + + {mounted && } +
+ )} + + +
+ ); +}; + +export default IndexPage; diff --git a/src/run-migrations.ts b/src/run-migrations.ts new file mode 100644 index 0000000..59dcc8a --- /dev/null +++ b/src/run-migrations.ts @@ -0,0 +1,223 @@ +import "./load-env"; +import * as path from "node:path"; +import * as fsPromises from "node:fs/promises"; +import { fileURLToPath } from "node:url"; +import { parseArgs } from "node:util"; +import { type AuthData } from "@saleor/app-sdk/APL"; +import { type MetadataEntry } from "@saleor/app-sdk/settings-manager"; +import * as semver from "semver"; +import { FetchAppDetailsDocument } from "../generated/graphql"; +import { saleorApp } from "./saleor-app"; +import { createServerClient } from "./lib/create-graphq-client"; +import { invariant } from "./lib/invariant"; +import { BaseError } from "./errors"; +import { unpackPromise } from "./lib/utils"; +import { + createWebhookPrivateSettingsManager, + mutatePrivateMetadata, +} from "./modules/app-configuration/metadata-manager"; +import { PaymentAppConfigurator } from "./modules/payment-app-configuration/payment-app-configuration"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +type Migration = Awaited>[0]; + +const NotFullyMigratedError = BaseError.subclass("NotFullyMigratedError", { + props: { migrationCounter: null as null | number, lastMigration: null as null | Migration }, +}); + +const apl = saleorApp.apl; +const allAuthData = await apl.getAll(); +const migrationsFolderPath = path.join(__dirname, "migrations"); + +const { + values: { dryRun }, +} = parseArgs({ + options: { + dryRun: { + type: "boolean", + short: "d", + }, + }, +}); + +const processedInstances = await Promise.all( + allAuthData.map(async (authData) => { + const [error, result] = await unpackPromise(processInstance(authData)); + return [authData, error, result] as const; + }), +); + +processedInstances.forEach(([authData, error, result]) => { + if (error) { + if (error instanceof NotFullyMigratedError) { + console.error( + `❌ ${authData.saleorApiUrl}: Not fully migrated (last successfull: ${ + error.migrationCounter ?? "none" + })\n${JSON.stringify(error, null, 2)}`, + ); + } else { + console.error( + `❌ ${authData.saleorApiUrl}: Error while running migrations\n${JSON.stringify( + error, + null, + 2, + )}`, + ); + } + } + + if (result) { + console.info(`✅ ${authData.saleorApiUrl}: ${result.migrations} migrations`); + } +}); + +async function processInstance(authData: AuthData) { + const client = createServerClient(authData.saleorApiUrl, authData.token); + const { data: appDetailsResponse } = await client.query(FetchAppDetailsDocument, {}).toPromise(); + + if (!appDetailsResponse) { + throw new Error("Cannot fetch app details"); + } + + invariant(appDetailsResponse.app?.privateMetadata, "Missing private metadata"); + invariant(appDetailsResponse?.shop.schemaVersion, "Missing Saleor version"); + + const configurator = new PaymentAppConfigurator( + createWebhookPrivateSettingsManager( + appDetailsResponse.app.privateMetadata as MetadataEntry[], + (metadata) => mutatePrivateMetadata(client, metadata), + ), + authData.saleorApiUrl, + ); + + const migrations = await getMigrationsToRun(configurator, appDetailsResponse.shop.schemaVersion); + + if (dryRun) { + console.log(`${authData.saleorApiUrl} - migrations to run:`, migrations); + return { + migrations: 0, + }; + } + + const lastMigrationToRun = migrations.at(-1); + + if (!lastMigrationToRun) { + // No migrations to run + return { + migrations: 0, + }; + } + + let migrationCounter: number | null = null; + let recentMigration: Migration | null = null; + + for (const migration of migrations) { + recentMigration = migration; + const migrationId = `${migration.number}-${migration.name ?? ""}`; + try { + await migration.migrate(authData, configurator); + migrationCounter = migration.number; + } catch (error) { + console.error(`Error while running migration ${migrationId}`, error); + if (migration.rollback) { + try { + await migration.rollback(authData, configurator); + } catch (rollbackError) { + console.error("Error while applying a rollback", rollbackError); + } + } else { + console.warn(`No rollback to run for migration ${migrationId}`); + } + break; + } + } + + if (migrationCounter !== null) { + await configurator.setConfig({ lastMigration: migrationCounter }); + } + + if (migrationCounter !== lastMigrationToRun?.number) { + throw new NotFullyMigratedError("Not fully migrated instance", { + props: { migrationCounter, lastMigration: recentMigration }, + }); + } + + return { + migrations: migrationCounter, + }; +} + +async function getMigrationsToRun(configurator: PaymentAppConfigurator, usedSaleorVersion: string) { + const { lastMigration } = await configurator.getConfig(); + const files = await fsPromises.readdir(migrationsFolderPath, { withFileTypes: true }); + + const migrationFolders = files.filter((file) => file.isDirectory() && /^\d/.test(file.name)); + + const migrations = await Promise.all( + migrationFolders.map(async (folder) => { + const match = folder.name.match(/^(\d+)-(.+)$/); + const migrationNumber = parseInt(match?.[1] as string); + const migrationName = match?.[2]; + if (typeof migrationNumber !== "number" || Number.isNaN(migrationNumber)) { + throw new Error(`Cannot parse migration number from folder ${folder.name}`); + } + + const indexFilePath = path.join(migrationsFolderPath, folder.name, "index.ts"); + const indexFileStat = await fsPromises.stat(indexFilePath); + if (!indexFileStat.isFile()) { + throw new Error("index.ts inside migration folder is not a file"); + } + + const migrationModule = (await import(indexFilePath)) as { + migrate?: unknown; + requiredSaleorVersion?: unknown; + rollback?: unknown; + }; + + if (typeof migrationModule?.migrate !== "function") { + throw new Error(`migrate exported from ${indexFilePath} is not a function`); + } + + if (typeof migrationModule?.requiredSaleorVersion !== "string") { + throw new Error(`requiredSaleorVersion in ${indexFilePath} is not a string`); + } + + const rollbackFn = + typeof migrationModule?.rollback === "function" ? migrationModule.rollback : null; + + return { + number: migrationNumber, + name: migrationName, + migrate: migrationModule.migrate, + requiredSaleorVersion: migrationModule.requiredSaleorVersion, + rollback: rollbackFn, + }; + }), + ); + + const filteredMigrations = migrations.filter( + (migration) => migration.number > (lastMigration ?? 0), + ); + + const unappliableMigrationIndex = filteredMigrations.findIndex((migration) => + semver.gt( + semver.coerce(migration.requiredSaleorVersion) ?? "", + semver.coerce(usedSaleorVersion) ?? "", + ), + ); + + if (unappliableMigrationIndex !== -1) { + console.warn( + `⚠️ ${configurator.saleorApiUrl} uses Saleor version ${usedSaleorVersion}. There are ${ + filteredMigrations.length - unappliableMigrationIndex + } migrations that require Saleor in newer version (${ + filteredMigrations[unappliableMigrationIndex].requiredSaleorVersion + } or newer).`, + ); + return filteredMigrations.slice(0, unappliableMigrationIndex); + } + + return filteredMigrations; +} diff --git a/src/saleor-app.ts b/src/saleor-app.ts new file mode 100644 index 0000000..42457c6 --- /dev/null +++ b/src/saleor-app.ts @@ -0,0 +1,46 @@ +import { SaleorApp } from "@saleor/app-sdk/saleor-app"; +import { FileAPL, UpstashAPL, SaleorCloudAPL } from "@saleor/app-sdk/APL"; +import { invariant } from "./lib/invariant"; +import { env } from "./lib/env.mjs"; +import { isTest } from "./lib/isEnv"; + +/** + * By default auth data are stored in the `.auth-data.json` (FileAPL). + * For multi-tenant applications and deployments please use UpstashAPL. + * + * To read more about storing auth data, read the + * [APL documentation](https://github.com/saleor/saleor-app-sdk/blob/main/docs/apl.md) + */ +const getApl = async () => { + if (isTest()) { + const { TestAPL } = await import("./__tests__/testAPL"); + return new TestAPL(); + } + /* c8 ignore start */ + switch (env.APL) { + case "upstash": + invariant(env.UPSTASH_URL, "Missing UPSTASH_URL env variable!"); + invariant(env.UPSTASH_TOKEN, "Missing UPSTASH_TOKEN env variable!"); + return new UpstashAPL({ + restURL: env.UPSTASH_URL, + restToken: env.UPSTASH_TOKEN, + }); + case "saleor-cloud": { + invariant(env.REST_APL_ENDPOINT, "Missing REST_APL_ENDPOINT env variable!"); + invariant(env.REST_APL_TOKEN, "Missing REST_APL_TOKEN env variable!"); + return new SaleorCloudAPL({ + resourceUrl: env.REST_APL_ENDPOINT, + token: env.REST_APL_TOKEN, + }); + } + default: + return new FileAPL(); + } + /* c8 ignore stop */ +}; + +const apl = await getApl(); + +export const saleorApp = new SaleorApp({ + apl, +}); diff --git a/src/schemas/.gitignore b/src/schemas/.gitignore new file mode 100644 index 0000000..e780a40 --- /dev/null +++ b/src/schemas/.gitignore @@ -0,0 +1,6 @@ +*/*.ts +*/*.mts +*/*.cts +*/*.js +*/*.mjs +*/*.cjs diff --git a/src/schemas/PaymentGatewayInitializeSession/PaymentGatewayInitializeSessionRequestData.schema.json b/src/schemas/PaymentGatewayInitializeSession/PaymentGatewayInitializeSessionRequestData.schema.json new file mode 100644 index 0000000..09143ae --- /dev/null +++ b/src/schemas/PaymentGatewayInitializeSession/PaymentGatewayInitializeSessionRequestData.schema.json @@ -0,0 +1,17 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "anyOf": [ + { + "type": "object", + "properties": { + "action": { "type": "string", "enum": ["APPLEPAY_onvalidatemerchant"] }, + "validationURL": { "type": "string" }, + "domain": { "type": "string" }, + "merchantIdentifier": { "type": "string" }, + "merchantName": { "type": "string" } + }, + "additionalProperties": false, + "required": ["action", "validationURL", "domain", "merchantIdentifier", "merchantName"] + } + ] +} diff --git a/src/schemas/PaymentGatewayInitializeSession/PaymentGatewayInitializeSessionResponse.schema.json b/src/schemas/PaymentGatewayInitializeSession/PaymentGatewayInitializeSessionResponse.schema.json new file mode 100644 index 0000000..91e578a --- /dev/null +++ b/src/schemas/PaymentGatewayInitializeSession/PaymentGatewayInitializeSessionResponse.schema.json @@ -0,0 +1,21 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "type": "object", + "properties": { + "data": { + "anyOf": [ + { + "type": "object", + "additionalProperties": true, + "properties": { + "publishableKey": { "type": "string" }, + "errors": { "$ref": "definitions.json#/definitions/SyncWebhookAppErrors" } + }, + "required": ["publishableKey"] + } + ] + } + }, + "additionalProperties": false, + "required": ["data"] +} diff --git a/src/schemas/TransactionCancelationRequested/TransactionCancelationRequestedResponse.schema.json b/src/schemas/TransactionCancelationRequested/TransactionCancelationRequestedResponse.schema.json new file mode 100644 index 0000000..64deff2 --- /dev/null +++ b/src/schemas/TransactionCancelationRequested/TransactionCancelationRequestedResponse.schema.json @@ -0,0 +1,16 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "type": "object", + "properties": { + "pspReference": { "type": "string" }, + "result": { + "$ref": "definitions.json#/definitions/TransactionCancelationRequestedAllowedResult" + }, + "amount": { "$ref": "definitions.json#/definitions/PositiveDecimal" }, + "time": { "$ref": "definitions.json#/definitions/DateTime" }, + "externalUrl": { "type": "string" }, + "message": { "type": "string" } + }, + "additionalProperties": false, + "required": ["pspReference"] +} diff --git a/src/schemas/TransactionChargeRequested/TransactionChargeRequestedResponse.schema.json b/src/schemas/TransactionChargeRequested/TransactionChargeRequestedResponse.schema.json new file mode 100644 index 0000000..96d2d23 --- /dev/null +++ b/src/schemas/TransactionChargeRequested/TransactionChargeRequestedResponse.schema.json @@ -0,0 +1,14 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "type": "object", + "properties": { + "pspReference": { "type": "string" }, + "result": { "$ref": "definitions.json#/definitions/TransactionChargeRequestedAllowedResult" }, + "amount": { "$ref": "definitions.json#/definitions/PositiveDecimal" }, + "time": { "$ref": "definitions.json#/definitions/DateTime" }, + "externalUrl": { "type": "string" }, + "message": { "type": "string" } + }, + "additionalProperties": false, + "required": ["pspReference"] +} diff --git a/src/schemas/TransactionInitializeSession/TransactionInitializeSessionResponse.schema.json b/src/schemas/TransactionInitializeSession/TransactionInitializeSessionResponse.schema.json new file mode 100644 index 0000000..aadb640 --- /dev/null +++ b/src/schemas/TransactionInitializeSession/TransactionInitializeSessionResponse.schema.json @@ -0,0 +1,24 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "type": "object", + "properties": { + "pspReference": { "type": "string" }, + "data": { + "type": "object", + "additionalProperties": true, + "properties": { + "paymentIntent": { "$ref": "definitions.json#/definitions/JSON" }, + "publishableKey": { "type": "string" }, + "errors": { "$ref": "definitions.json#/definitions/SyncWebhookAppErrors" } + }, + "required": ["paymentIntent", "publishableKey"] + }, + "result": { "$ref": "definitions.json#/definitions/TransactionSessionResult" }, + "amount": { "$ref": "definitions.json#/definitions/PositiveDecimal" }, + "time": { "$ref": "definitions.json#/definitions/DateTime" }, + "externalUrl": { "type": "string" }, + "message": { "type": "string" } + }, + "additionalProperties": false, + "required": ["result", "amount"] +} diff --git a/src/schemas/TransactionProcessSession/TransactionProcessSessionResponse.schema.json b/src/schemas/TransactionProcessSession/TransactionProcessSessionResponse.schema.json new file mode 100644 index 0000000..aadb640 --- /dev/null +++ b/src/schemas/TransactionProcessSession/TransactionProcessSessionResponse.schema.json @@ -0,0 +1,24 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "type": "object", + "properties": { + "pspReference": { "type": "string" }, + "data": { + "type": "object", + "additionalProperties": true, + "properties": { + "paymentIntent": { "$ref": "definitions.json#/definitions/JSON" }, + "publishableKey": { "type": "string" }, + "errors": { "$ref": "definitions.json#/definitions/SyncWebhookAppErrors" } + }, + "required": ["paymentIntent", "publishableKey"] + }, + "result": { "$ref": "definitions.json#/definitions/TransactionSessionResult" }, + "amount": { "$ref": "definitions.json#/definitions/PositiveDecimal" }, + "time": { "$ref": "definitions.json#/definitions/DateTime" }, + "externalUrl": { "type": "string" }, + "message": { "type": "string" } + }, + "additionalProperties": false, + "required": ["result", "amount"] +} diff --git a/src/schemas/TransactionRefundRequesed/TransactionRefundRequestedResponse.schema.json b/src/schemas/TransactionRefundRequesed/TransactionRefundRequestedResponse.schema.json new file mode 100644 index 0000000..ee511d3 --- /dev/null +++ b/src/schemas/TransactionRefundRequesed/TransactionRefundRequestedResponse.schema.json @@ -0,0 +1,14 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "type": "object", + "properties": { + "pspReference": { "type": "string" }, + "result": { "$ref": "definitions.json#/definitions/TransactionRefundRequestedAllowedResult" }, + "amount": { "$ref": "definitions.json#/definitions/PositiveDecimal" }, + "time": { "$ref": "definitions.json#/definitions/DateTime" }, + "externalUrl": { "type": "string", "format": "uri" }, + "message": { "type": "string" } + }, + "additionalProperties": false, + "required": ["pspReference"] +} diff --git a/src/schemas/__snapshots__/compiler.test.ts.snap b/src/schemas/__snapshots__/compiler.test.ts.snap new file mode 100644 index 0000000..eed3c39 --- /dev/null +++ b/src/schemas/__snapshots__/compiler.test.ts.snap @@ -0,0 +1,6 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`JSON schema compiler > compileSchemaToJs > compileSchemaToJs compiles schema to JS code 1`] = ` +"/* c8 ignore start */ +\\"use strict\\";export const validate = validate10;export default validate10;const schema11 = {\\"$schema\\":\\"http://json-schema.org/draft-07/schema\\",\\"type\\":\\"object\\",\\"properties\\":{\\"pspReference\\":{\\"type\\":\\"string\\"},\\"data\\":{\\"type\\":\\"object\\",\\"additionalProperties\\":true,\\"properties\\":{}},\\"result\\":{\\"anyOf\\":[{\\"type\\":\\"string\\",\\"const\\":\\"CHARGE_SUCCESS\\"},{\\"type\\":\\"string\\",\\"const\\":\\"CHARGE_FAILURE\\"},{\\"type\\":\\"string\\",\\"const\\":\\"CHARGE_REQUESTED\\"},{\\"type\\":\\"string\\",\\"const\\":\\"AUTHORIZATION_SUCCESS\\"},{\\"type\\":\\"string\\",\\"const\\":\\"AUTHORIZATION_FAILURE\\"},{\\"type\\":\\"string\\",\\"const\\":\\"AUTHORIZATION_REQUESTED\\"}]},\\"amount\\":{\\"type\\":\\"number\\",\\"minimum\\":0},\\"time\\":{\\"type\\":\\"string\\",\\"format\\":\\"date-time\\"},\\"externalUrl\\":{\\"type\\":\\"string\\"},\\"message\\":{\\"type\\":\\"string\\"}},\\"required\\":[\\"pspReference\\",\\"data\\",\\"result\\",\\"amount\\",\\"time\\",\\"externalUrl\\",\\"message\\"]};const formats0 = require(\\"ajv-formats/dist/formats\\").fullFormats[\\"date-time\\"];function validate10(data, {instancePath=\\"\\", parentData, parentDataProperty, rootData=data}={}){let vErrors = null;let errors = 0;if(errors === 0){if(data && typeof data == \\"object\\" && !Array.isArray(data)){let missing0;if((((((((data.pspReference === undefined) && (missing0 = \\"pspReference\\")) || ((data.data === undefined) && (missing0 = \\"data\\"))) || ((data.result === undefined) && (missing0 = \\"result\\"))) || ((data.amount === undefined) && (missing0 = \\"amount\\"))) || ((data.time === undefined) && (missing0 = \\"time\\"))) || ((data.externalUrl === undefined) && (missing0 = \\"externalUrl\\"))) || ((data.message === undefined) && (missing0 = \\"message\\"))){validate10.errors = [{instancePath,schemaPath:\\"#/required\\",keyword:\\"required\\",params:{missingProperty: missing0},message:\\"must have required property '\\"+missing0+\\"'\\"}];return false;}else {if(data.pspReference !== undefined){const _errs1 = errors;if(typeof data.pspReference !== \\"string\\"){validate10.errors = [{instancePath:instancePath+\\"/pspReference\\",schemaPath:\\"#/properties/pspReference/type\\",keyword:\\"type\\",params:{type: \\"string\\"},message:\\"must be string\\"}];return false;}var valid0 = _errs1 === errors;}else {var valid0 = true;}if(valid0){if(data.data !== undefined){let data1 = data.data;const _errs3 = errors;if(errors === _errs3){if(data1 && typeof data1 == \\"object\\" && !Array.isArray(data1)){}else {validate10.errors = [{instancePath:instancePath+\\"/data\\",schemaPath:\\"#/properties/data/type\\",keyword:\\"type\\",params:{type: \\"object\\"},message:\\"must be object\\"}];return false;}}var valid0 = _errs3 === errors;}else {var valid0 = true;}if(valid0){if(data.result !== undefined){let data2 = data.result;const _errs6 = errors;const _errs7 = errors;let valid1 = false;const _errs8 = errors;if(typeof data2 !== \\"string\\"){const err0 = {instancePath:instancePath+\\"/result\\",schemaPath:\\"#/properties/result/anyOf/0/type\\",keyword:\\"type\\",params:{type: \\"string\\"},message:\\"must be string\\"};if(vErrors === null){vErrors = [err0];}else {vErrors.push(err0);}errors++;}if(\\"CHARGE_SUCCESS\\" !== data2){const err1 = {instancePath:instancePath+\\"/result\\",schemaPath:\\"#/properties/result/anyOf/0/const\\",keyword:\\"const\\",params:{allowedValue: \\"CHARGE_SUCCESS\\"},message:\\"must be equal to constant\\"};if(vErrors === null){vErrors = [err1];}else {vErrors.push(err1);}errors++;}var _valid0 = _errs8 === errors;valid1 = valid1 || _valid0;if(!valid1){const _errs10 = errors;if(typeof data2 !== \\"string\\"){const err2 = {instancePath:instancePath+\\"/result\\",schemaPath:\\"#/properties/result/anyOf/1/type\\",keyword:\\"type\\",params:{type: \\"string\\"},message:\\"must be string\\"};if(vErrors === null){vErrors = [err2];}else {vErrors.push(err2);}errors++;}if(\\"CHARGE_FAILURE\\" !== data2){const err3 = {instancePath:instancePath+\\"/result\\",schemaPath:\\"#/properties/result/anyOf/1/const\\",keyword:\\"const\\",params:{allowedValue: \\"CHARGE_FAILURE\\"},message:\\"must be equal to constant\\"};if(vErrors === null){vErrors = [err3];}else {vErrors.push(err3);}errors++;}var _valid0 = _errs10 === errors;valid1 = valid1 || _valid0;if(!valid1){const _errs12 = errors;if(typeof data2 !== \\"string\\"){const err4 = {instancePath:instancePath+\\"/result\\",schemaPath:\\"#/properties/result/anyOf/2/type\\",keyword:\\"type\\",params:{type: \\"string\\"},message:\\"must be string\\"};if(vErrors === null){vErrors = [err4];}else {vErrors.push(err4);}errors++;}if(\\"CHARGE_REQUESTED\\" !== data2){const err5 = {instancePath:instancePath+\\"/result\\",schemaPath:\\"#/properties/result/anyOf/2/const\\",keyword:\\"const\\",params:{allowedValue: \\"CHARGE_REQUESTED\\"},message:\\"must be equal to constant\\"};if(vErrors === null){vErrors = [err5];}else {vErrors.push(err5);}errors++;}var _valid0 = _errs12 === errors;valid1 = valid1 || _valid0;if(!valid1){const _errs14 = errors;if(typeof data2 !== \\"string\\"){const err6 = {instancePath:instancePath+\\"/result\\",schemaPath:\\"#/properties/result/anyOf/3/type\\",keyword:\\"type\\",params:{type: \\"string\\"},message:\\"must be string\\"};if(vErrors === null){vErrors = [err6];}else {vErrors.push(err6);}errors++;}if(\\"AUTHORIZATION_SUCCESS\\" !== data2){const err7 = {instancePath:instancePath+\\"/result\\",schemaPath:\\"#/properties/result/anyOf/3/const\\",keyword:\\"const\\",params:{allowedValue: \\"AUTHORIZATION_SUCCESS\\"},message:\\"must be equal to constant\\"};if(vErrors === null){vErrors = [err7];}else {vErrors.push(err7);}errors++;}var _valid0 = _errs14 === errors;valid1 = valid1 || _valid0;if(!valid1){const _errs16 = errors;if(typeof data2 !== \\"string\\"){const err8 = {instancePath:instancePath+\\"/result\\",schemaPath:\\"#/properties/result/anyOf/4/type\\",keyword:\\"type\\",params:{type: \\"string\\"},message:\\"must be string\\"};if(vErrors === null){vErrors = [err8];}else {vErrors.push(err8);}errors++;}if(\\"AUTHORIZATION_FAILURE\\" !== data2){const err9 = {instancePath:instancePath+\\"/result\\",schemaPath:\\"#/properties/result/anyOf/4/const\\",keyword:\\"const\\",params:{allowedValue: \\"AUTHORIZATION_FAILURE\\"},message:\\"must be equal to constant\\"};if(vErrors === null){vErrors = [err9];}else {vErrors.push(err9);}errors++;}var _valid0 = _errs16 === errors;valid1 = valid1 || _valid0;if(!valid1){const _errs18 = errors;if(typeof data2 !== \\"string\\"){const err10 = {instancePath:instancePath+\\"/result\\",schemaPath:\\"#/properties/result/anyOf/5/type\\",keyword:\\"type\\",params:{type: \\"string\\"},message:\\"must be string\\"};if(vErrors === null){vErrors = [err10];}else {vErrors.push(err10);}errors++;}if(\\"AUTHORIZATION_REQUESTED\\" !== data2){const err11 = {instancePath:instancePath+\\"/result\\",schemaPath:\\"#/properties/result/anyOf/5/const\\",keyword:\\"const\\",params:{allowedValue: \\"AUTHORIZATION_REQUESTED\\"},message:\\"must be equal to constant\\"};if(vErrors === null){vErrors = [err11];}else {vErrors.push(err11);}errors++;}var _valid0 = _errs18 === errors;valid1 = valid1 || _valid0;}}}}}if(!valid1){const err12 = {instancePath:instancePath+\\"/result\\",schemaPath:\\"#/properties/result/anyOf\\",keyword:\\"anyOf\\",params:{},message:\\"must match a schema in anyOf\\"};if(vErrors === null){vErrors = [err12];}else {vErrors.push(err12);}errors++;validate10.errors = vErrors;return false;}else {errors = _errs7;if(vErrors !== null){if(_errs7){vErrors.length = _errs7;}else {vErrors = null;}}}var valid0 = _errs6 === errors;}else {var valid0 = true;}if(valid0){if(data.amount !== undefined){let data3 = data.amount;const _errs20 = errors;if(errors === _errs20){if((typeof data3 == \\"number\\") && (isFinite(data3))){if(data3 < 0 || isNaN(data3)){validate10.errors = [{instancePath:instancePath+\\"/amount\\",schemaPath:\\"#/properties/amount/minimum\\",keyword:\\"minimum\\",params:{comparison: \\">=\\", limit: 0},message:\\"must be >= 0\\"}];return false;}}else {validate10.errors = [{instancePath:instancePath+\\"/amount\\",schemaPath:\\"#/properties/amount/type\\",keyword:\\"type\\",params:{type: \\"number\\"},message:\\"must be number\\"}];return false;}}var valid0 = _errs20 === errors;}else {var valid0 = true;}if(valid0){if(data.time !== undefined){let data4 = data.time;const _errs22 = errors;if(errors === _errs22){if(errors === _errs22){if(typeof data4 === \\"string\\"){if(!(formats0.validate(data4))){validate10.errors = [{instancePath:instancePath+\\"/time\\",schemaPath:\\"#/properties/time/format\\",keyword:\\"format\\",params:{format: \\"date-time\\"},message:\\"must match format \\\\\\"\\"+\\"date-time\\"+\\"\\\\\\"\\"}];return false;}}else {validate10.errors = [{instancePath:instancePath+\\"/time\\",schemaPath:\\"#/properties/time/type\\",keyword:\\"type\\",params:{type: \\"string\\"},message:\\"must be string\\"}];return false;}}}var valid0 = _errs22 === errors;}else {var valid0 = true;}if(valid0){if(data.externalUrl !== undefined){const _errs24 = errors;if(typeof data.externalUrl !== \\"string\\"){validate10.errors = [{instancePath:instancePath+\\"/externalUrl\\",schemaPath:\\"#/properties/externalUrl/type\\",keyword:\\"type\\",params:{type: \\"string\\"},message:\\"must be string\\"}];return false;}var valid0 = _errs24 === errors;}else {var valid0 = true;}if(valid0){if(data.message !== undefined){const _errs26 = errors;if(typeof data.message !== \\"string\\"){validate10.errors = [{instancePath:instancePath+\\"/message\\",schemaPath:\\"#/properties/message/type\\",keyword:\\"type\\",params:{type: \\"string\\"},message:\\"must be string\\"}];return false;}var valid0 = _errs26 === errors;}else {var valid0 = true;}}}}}}}}}else {validate10.errors = [{instancePath,schemaPath:\\"#/type\\",keyword:\\"type\\",params:{type: \\"object\\"},message:\\"must be object\\"}];return false;}}validate10.errors = vErrors;return errors === 0;}" +`; diff --git a/src/schemas/definitions.json b/src/schemas/definitions.json new file mode 100644 index 0000000..ca04cb5 --- /dev/null +++ b/src/schemas/definitions.json @@ -0,0 +1,84 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "$id": "definitions.json", + "definitions": { + "PositiveDecimal": { "type": "number", "minimum": 0 }, + "DateTime": { "type": "string", "format": "date-time" }, + "JSON": { + "type": "object", + "additionalProperties": true, + "properties": {}, + "tsType": "JSONObject" + }, + "TransactionActions": { + "type": "array", + "items": { + "anyOf": [ + { "type": "string", "const": "CHARGE" }, + { "type": "string", "const": "REFUND" }, + { "type": "string", "const": "CANCEL" } + ] + } + }, + "TransactionSessionResult": { + "type": "string", + "enum": [ + "AUTHORIZATION_SUCCESS", + "AUTHORIZATION_FAILURE", + "AUTHORIZATION_REQUEST", + "AUTHORIZATION_ACTION_REQUIRED", + "CHARGE_SUCCESS", + "CHARGE_FAILURE", + "CHARGE_REQUEST", + "CHARGE_ACTION_REQUIRED" + ] + }, + "TransactionEventType": { + "type": "string", + "enum": [ + "AUTHORIZATION_SUCCESS", + "AUTHORIZATION_FAILURE", + "AUTHORIZATION_ADJUSTMENT", + "AUTHORIZATION_REQUEST", + "CHARGE_SUCCESS", + "CHARGE_FAILURE", + "CHARGE_BACK", + "CHARGE_REQUEST", + "REFUND_SUCCESS", + "REFUND_FAILURE", + "REFUND_REVERSE", + "REFUND_REQUEST", + "CANCEL_SUCCESS", + "CANCEL_FAILURE", + "CANCEL_REQUEST" + ] + }, + "TransactionCancelationRequestedAllowedResult": { + "type": "string", + "enum": ["CANCEL_SUCCESS", "CANCEL_FAILURE"] + }, + "TransactionChargeRequestedAllowedResult": { + "type": "string", + "enum": ["CHARGE_SUCCESS", "CHARGE_FAILURE"] + }, + "TransactionRefundRequestedAllowedResult": { + "type": "string", + "enum": ["REFUND_SUCCESS", "REFUND_FAILURE"] + }, + "SyncWebhookAppError": { + "type": "object", + "additionalProperties": false, + "properties": { + "code": { "type": "string" }, + "message": { "type": "string" }, + "details": { "$ref": "definitions.json#/definitions/JSON" } + } + }, + "SyncWebhookAppErrors": { + "type": "array", + "items": { + "$ref": "definitions.json#/definitions/SyncWebhookAppError" + } + } + } +} diff --git a/src/setup-tests.ts b/src/setup-tests.ts new file mode 100644 index 0000000..87d4880 --- /dev/null +++ b/src/setup-tests.ts @@ -0,0 +1,19 @@ +import "next"; +import { loadEnvConfig } from "@next/env"; +import { expect, afterEach } from "vitest"; +import * as matchers from "@testing-library/jest-dom/matchers"; +import { cleanup } from "@testing-library/react"; +import "@testing-library/jest-dom/vitest"; + +loadEnvConfig("."); + +/** + * Vitest setup logic + * https://vitest.dev/config/#setupfiles + */ + +expect.extend(matchers); + +afterEach(() => { + cleanup(); +}); diff --git a/src/styles/global.css.ts b/src/styles/global.css.ts new file mode 100644 index 0000000..782e5bd --- /dev/null +++ b/src/styles/global.css.ts @@ -0,0 +1,20 @@ +import { globalStyle } from "@vanilla-extract/css"; + +globalStyle("#__next", { + padding: "1rem 2rem", +}); + +globalStyle("*", { + WebkitFontSmoothing: "subpixel-antialiased", + MozOsxFontSmoothing: "grayscale", +}); + +globalStyle(".visually-hidden", { + clip: "rect(0 0 0 0)", + clipPath: "inset(50%)", + height: "1px", + overflow: "hidden", + position: "absolute", + whiteSpace: "nowrap", + width: "1px", +}); diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..1df61cf --- /dev/null +++ b/src/types.ts @@ -0,0 +1,16 @@ +export type JSONValue = string | number | boolean | JSONObject | JSONArray | null; + +export type JSONObject = { + readonly [x in string]: JSONValue; +}; + +type JSONArray = readonly JSONValue[]; + +export type StrictRequired = { + [P in keyof T]-?: NonNullable; +}; + +export type Channel = { + readonly id: string; + readonly name: string; +}; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..bc2372f --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,36 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "compilerOptions": { + "target": "es2022", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + }, + "typeRoots": ["node_modules/@types", "typings"] + }, + "include": [ + "next-env.d.ts", + "**/*.js", + "**/*.cjs", + "**/*.mjs", + "**/*.jsx", + "**/*.ts", + "**/*.cts", + "**/*.mts", + "**/*.tsx" + ], + "exclude": ["node_modules"] +} diff --git a/typings/vanilla-extract__next-plugin/index.d.ts b/typings/vanilla-extract__next-plugin/index.d.ts new file mode 100644 index 0000000..b0a2c4a --- /dev/null +++ b/typings/vanilla-extract__next-plugin/index.d.ts @@ -0,0 +1,6 @@ +declare module "@vanilla-extract/next-plugin" { + declare const createVanillaExtractPlugin: () => ( + config: import("next").NextConfig, + ) => import("next").NextConfig; + export { createVanillaExtractPlugin }; +} diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..9ef5b81 --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,30 @@ +import react from "@vitejs/plugin-react"; +import { vanillaExtractPlugin } from "@vanilla-extract/vite-plugin"; +import tsConfigPaths from "vite-tsconfig-paths"; +import { defineConfig } from "vitest/config"; + +// https://vitejs.dev/config/ +// eslint-disable-next-line import/no-default-export +export default defineConfig({ + plugins: [tsConfigPaths(), vanillaExtractPlugin(), react()], + test: { + globals: true, + passWithNoTests: true, + environment: "jsdom", + setupFiles: "./src/setup-tests.ts", + css: false, + outputFile: { + json: "coverage/report.json", + }, + coverage: { + reporter: ["text", "json", "html", "text-summary"], + }, + clearMocks: true, + mockReset: true, + restoreMocks: true, + unstubGlobals: true, + unstubEnvs: true, + include: ["**/?(*.)test.?(c|m)[jt]s?(x)"], + useAtomics: true, + }, +});