@shopify/shopify-api 13.1.0 → 14.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/lib/auth/oauth/create-session.js +1 -1
- package/dist/cjs/lib/auth/oauth/create-session.js.map +1 -1
- package/dist/cjs/lib/auth/oauth/oauth.js +4 -1
- package/dist/cjs/lib/auth/oauth/oauth.js.map +1 -1
- package/dist/cjs/lib/billing/types.js.map +1 -1
- package/dist/cjs/lib/config.js +2 -2
- package/dist/cjs/lib/config.js.map +1 -1
- package/dist/cjs/lib/types.js +1 -1
- package/dist/cjs/lib/types.js.map +1 -1
- package/dist/cjs/lib/utils/hmac-validator.js +53 -7
- package/dist/cjs/lib/utils/hmac-validator.js.map +1 -1
- package/dist/cjs/lib/utils/processed-query.js +1 -1
- package/dist/cjs/lib/utils/processed-query.js.map +1 -1
- package/dist/cjs/lib/version.js +1 -1
- package/dist/cjs/lib/version.js.map +1 -1
- package/dist/cjs/lib/webhooks/process.js +2 -2
- package/dist/cjs/lib/webhooks/process.js.map +1 -1
- package/dist/cjs/lib/webhooks/register.js +0 -4
- package/dist/cjs/lib/webhooks/register.js.map +1 -1
- package/dist/cjs/lib/webhooks/types.js +0 -1
- package/dist/cjs/lib/webhooks/types.js.map +1 -1
- package/dist/cjs/lib/webhooks/validate.js +0 -3
- package/dist/cjs/lib/webhooks/validate.js.map +1 -1
- package/dist/cjs/rest/admin/2026-07/abandoned_checkout.js +85 -0
- package/dist/cjs/rest/admin/2026-07/abandoned_checkout.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/access_scope.js +36 -0
- package/dist/cjs/rest/admin/2026-07/access_scope.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/apple_pay_certificate.js +62 -0
- package/dist/cjs/rest/admin/2026-07/apple_pay_certificate.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/application_charge.js +56 -0
- package/dist/cjs/rest/admin/2026-07/application_charge.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/application_credit.js +50 -0
- package/dist/cjs/rest/admin/2026-07/application_credit.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/article.js +114 -0
- package/dist/cjs/rest/admin/2026-07/article.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/asset.js +57 -0
- package/dist/cjs/rest/admin/2026-07/asset.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/assigned_fulfillment_order.js +41 -0
- package/dist/cjs/rest/admin/2026-07/assigned_fulfillment_order.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/balance.js +34 -0
- package/dist/cjs/rest/admin/2026-07/balance.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/blog.js +83 -0
- package/dist/cjs/rest/admin/2026-07/blog.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/cancellation_request.js +52 -0
- package/dist/cjs/rest/admin/2026-07/cancellation_request.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/carrier_service.js +63 -0
- package/dist/cjs/rest/admin/2026-07/carrier_service.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/checkout.js +103 -0
- package/dist/cjs/rest/admin/2026-07/checkout.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/collect.js +74 -0
- package/dist/cjs/rest/admin/2026-07/collect.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/collection.js +59 -0
- package/dist/cjs/rest/admin/2026-07/collection.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/collection_listing.js +80 -0
- package/dist/cjs/rest/admin/2026-07/collection_listing.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/comment.js +135 -0
- package/dist/cjs/rest/admin/2026-07/comment.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/country.js +76 -0
- package/dist/cjs/rest/admin/2026-07/country.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/currency.js +35 -0
- package/dist/cjs/rest/admin/2026-07/currency.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/custom_collection.js +79 -0
- package/dist/cjs/rest/admin/2026-07/custom_collection.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/customer.js +150 -0
- package/dist/cjs/rest/admin/2026-07/customer.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/deprecated_api_call.js +35 -0
- package/dist/cjs/rest/admin/2026-07/deprecated_api_call.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/discount_code.js +115 -0
- package/dist/cjs/rest/admin/2026-07/discount_code.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/dispute.js +53 -0
- package/dist/cjs/rest/admin/2026-07/dispute.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/dispute_evidence.js +57 -0
- package/dist/cjs/rest/admin/2026-07/dispute_evidence.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/dispute_file_upload.js +45 -0
- package/dist/cjs/rest/admin/2026-07/dispute_file_upload.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/draft_order.js +126 -0
- package/dist/cjs/rest/admin/2026-07/draft_order.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/event.js +67 -0
- package/dist/cjs/rest/admin/2026-07/event.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/fulfillment.js +102 -0
- package/dist/cjs/rest/admin/2026-07/fulfillment.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/fulfillment_event.js +79 -0
- package/dist/cjs/rest/admin/2026-07/fulfillment_event.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/fulfillment_order.js +164 -0
- package/dist/cjs/rest/admin/2026-07/fulfillment_order.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/fulfillment_request.js +61 -0
- package/dist/cjs/rest/admin/2026-07/fulfillment_request.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/fulfillment_service.js +66 -0
- package/dist/cjs/rest/admin/2026-07/fulfillment_service.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/gift_card.js +105 -0
- package/dist/cjs/rest/admin/2026-07/gift_card.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/gift_card_adjustment.js +58 -0
- package/dist/cjs/rest/admin/2026-07/gift_card_adjustment.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/image.js +77 -0
- package/dist/cjs/rest/admin/2026-07/image.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/index.js +155 -0
- package/dist/cjs/rest/admin/2026-07/index.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/inventory_item.js +54 -0
- package/dist/cjs/rest/admin/2026-07/inventory_item.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/inventory_level.js +87 -0
- package/dist/cjs/rest/admin/2026-07/inventory_level.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/location.js +85 -0
- package/dist/cjs/rest/admin/2026-07/location.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/locations_for_move.js +34 -0
- package/dist/cjs/rest/admin/2026-07/locations_for_move.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/marketing_event.js +98 -0
- package/dist/cjs/rest/admin/2026-07/marketing_event.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/metafield.js +154 -0
- package/dist/cjs/rest/admin/2026-07/metafield.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/mobile_platform_application.js +63 -0
- package/dist/cjs/rest/admin/2026-07/mobile_platform_application.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/order.js +202 -0
- package/dist/cjs/rest/admin/2026-07/order.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/order_risk.js +68 -0
- package/dist/cjs/rest/admin/2026-07/order_risk.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/page.js +83 -0
- package/dist/cjs/rest/admin/2026-07/page.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/payment.js +46 -0
- package/dist/cjs/rest/admin/2026-07/payment.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/payment_gateway.js +72 -0
- package/dist/cjs/rest/admin/2026-07/payment_gateway.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/payment_transaction.js +56 -0
- package/dist/cjs/rest/admin/2026-07/payment_transaction.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/payout.js +47 -0
- package/dist/cjs/rest/admin/2026-07/payout.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/policy.js +39 -0
- package/dist/cjs/rest/admin/2026-07/policy.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/price_rule.js +97 -0
- package/dist/cjs/rest/admin/2026-07/price_rule.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/product.js +89 -0
- package/dist/cjs/rest/admin/2026-07/product.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/product_listing.js +99 -0
- package/dist/cjs/rest/admin/2026-07/product_listing.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/product_resource_feedback.js +46 -0
- package/dist/cjs/rest/admin/2026-07/product_resource_feedback.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/province.js +65 -0
- package/dist/cjs/rest/admin/2026-07/province.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/recurring_application_charge.js +87 -0
- package/dist/cjs/rest/admin/2026-07/recurring_application_charge.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/redirect.js +71 -0
- package/dist/cjs/rest/admin/2026-07/redirect.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/refund.js +72 -0
- package/dist/cjs/rest/admin/2026-07/refund.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/resource_feedback.js +41 -0
- package/dist/cjs/rest/admin/2026-07/resource_feedback.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/script_tag.js +75 -0
- package/dist/cjs/rest/admin/2026-07/script_tag.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/shipping_zone.js +47 -0
- package/dist/cjs/rest/admin/2026-07/shipping_zone.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/shop.js +96 -0
- package/dist/cjs/rest/admin/2026-07/shop.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/smart_collection.js +93 -0
- package/dist/cjs/rest/admin/2026-07/smart_collection.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/storefront_access_token.js +50 -0
- package/dist/cjs/rest/admin/2026-07/storefront_access_token.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/tender_transaction.js +43 -0
- package/dist/cjs/rest/admin/2026-07/tender_transaction.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/theme.js +64 -0
- package/dist/cjs/rest/admin/2026-07/theme.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/transaction.js +83 -0
- package/dist/cjs/rest/admin/2026-07/transaction.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/usage_charge.js +53 -0
- package/dist/cjs/rest/admin/2026-07/usage_charge.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/user.js +69 -0
- package/dist/cjs/rest/admin/2026-07/user.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/variant.js +96 -0
- package/dist/cjs/rest/admin/2026-07/variant.js.map +1 -0
- package/dist/cjs/rest/admin/2026-07/webhook.js +78 -0
- package/dist/cjs/rest/admin/2026-07/webhook.js.map +1 -0
- package/dist/cjs/runtime/crypto/utils.js.map +1 -1
- package/dist/cjs/tsconfig.build.tsbuildinfo +1 -1
- package/dist/esm/lib/auth/oauth/create-session.mjs +1 -1
- package/dist/esm/lib/auth/oauth/create-session.mjs.map +1 -1
- package/dist/esm/lib/auth/oauth/oauth.mjs +4 -1
- package/dist/esm/lib/auth/oauth/oauth.mjs.map +1 -1
- package/dist/esm/lib/billing/types.mjs.map +1 -1
- package/dist/esm/lib/config.mjs +2 -2
- package/dist/esm/lib/config.mjs.map +1 -1
- package/dist/esm/lib/types.mjs +1 -1
- package/dist/esm/lib/types.mjs.map +1 -1
- package/dist/esm/lib/utils/hmac-validator.mjs +53 -7
- package/dist/esm/lib/utils/hmac-validator.mjs.map +1 -1
- package/dist/esm/lib/utils/processed-query.mjs +1 -1
- package/dist/esm/lib/utils/processed-query.mjs.map +1 -1
- package/dist/esm/lib/version.mjs +1 -1
- package/dist/esm/lib/version.mjs.map +1 -1
- package/dist/esm/lib/webhooks/process.mjs +2 -2
- package/dist/esm/lib/webhooks/process.mjs.map +1 -1
- package/dist/esm/lib/webhooks/register.mjs +0 -4
- package/dist/esm/lib/webhooks/register.mjs.map +1 -1
- package/dist/esm/lib/webhooks/types.mjs +0 -1
- package/dist/esm/lib/webhooks/types.mjs.map +1 -1
- package/dist/esm/lib/webhooks/validate.mjs +0 -3
- package/dist/esm/lib/webhooks/validate.mjs.map +1 -1
- package/dist/esm/rest/admin/2026-07/abandoned_checkout.mjs +83 -0
- package/dist/esm/rest/admin/2026-07/abandoned_checkout.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/access_scope.mjs +34 -0
- package/dist/esm/rest/admin/2026-07/access_scope.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/apple_pay_certificate.mjs +60 -0
- package/dist/esm/rest/admin/2026-07/apple_pay_certificate.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/application_charge.mjs +54 -0
- package/dist/esm/rest/admin/2026-07/application_charge.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/application_credit.mjs +48 -0
- package/dist/esm/rest/admin/2026-07/application_credit.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/article.mjs +112 -0
- package/dist/esm/rest/admin/2026-07/article.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/asset.mjs +55 -0
- package/dist/esm/rest/admin/2026-07/asset.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/assigned_fulfillment_order.mjs +39 -0
- package/dist/esm/rest/admin/2026-07/assigned_fulfillment_order.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/balance.mjs +32 -0
- package/dist/esm/rest/admin/2026-07/balance.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/blog.mjs +81 -0
- package/dist/esm/rest/admin/2026-07/blog.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/cancellation_request.mjs +50 -0
- package/dist/esm/rest/admin/2026-07/cancellation_request.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/carrier_service.mjs +61 -0
- package/dist/esm/rest/admin/2026-07/carrier_service.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/checkout.mjs +101 -0
- package/dist/esm/rest/admin/2026-07/checkout.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/collect.mjs +72 -0
- package/dist/esm/rest/admin/2026-07/collect.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/collection.mjs +57 -0
- package/dist/esm/rest/admin/2026-07/collection.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/collection_listing.mjs +78 -0
- package/dist/esm/rest/admin/2026-07/collection_listing.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/comment.mjs +133 -0
- package/dist/esm/rest/admin/2026-07/comment.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/country.mjs +74 -0
- package/dist/esm/rest/admin/2026-07/country.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/currency.mjs +33 -0
- package/dist/esm/rest/admin/2026-07/currency.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/custom_collection.mjs +77 -0
- package/dist/esm/rest/admin/2026-07/custom_collection.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/customer.mjs +148 -0
- package/dist/esm/rest/admin/2026-07/customer.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/deprecated_api_call.mjs +33 -0
- package/dist/esm/rest/admin/2026-07/deprecated_api_call.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/discount_code.mjs +113 -0
- package/dist/esm/rest/admin/2026-07/discount_code.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/dispute.mjs +51 -0
- package/dist/esm/rest/admin/2026-07/dispute.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/dispute_evidence.mjs +55 -0
- package/dist/esm/rest/admin/2026-07/dispute_evidence.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/dispute_file_upload.mjs +43 -0
- package/dist/esm/rest/admin/2026-07/dispute_file_upload.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/draft_order.mjs +124 -0
- package/dist/esm/rest/admin/2026-07/draft_order.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/event.mjs +65 -0
- package/dist/esm/rest/admin/2026-07/event.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/fulfillment.mjs +100 -0
- package/dist/esm/rest/admin/2026-07/fulfillment.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/fulfillment_event.mjs +77 -0
- package/dist/esm/rest/admin/2026-07/fulfillment_event.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/fulfillment_order.mjs +162 -0
- package/dist/esm/rest/admin/2026-07/fulfillment_order.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/fulfillment_request.mjs +59 -0
- package/dist/esm/rest/admin/2026-07/fulfillment_request.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/fulfillment_service.mjs +64 -0
- package/dist/esm/rest/admin/2026-07/fulfillment_service.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/gift_card.mjs +103 -0
- package/dist/esm/rest/admin/2026-07/gift_card.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/gift_card_adjustment.mjs +56 -0
- package/dist/esm/rest/admin/2026-07/gift_card_adjustment.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/image.mjs +75 -0
- package/dist/esm/rest/admin/2026-07/image.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/index.mjs +153 -0
- package/dist/esm/rest/admin/2026-07/index.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/inventory_item.mjs +52 -0
- package/dist/esm/rest/admin/2026-07/inventory_item.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/inventory_level.mjs +85 -0
- package/dist/esm/rest/admin/2026-07/inventory_level.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/location.mjs +83 -0
- package/dist/esm/rest/admin/2026-07/location.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/locations_for_move.mjs +32 -0
- package/dist/esm/rest/admin/2026-07/locations_for_move.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/marketing_event.mjs +96 -0
- package/dist/esm/rest/admin/2026-07/marketing_event.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/metafield.mjs +152 -0
- package/dist/esm/rest/admin/2026-07/metafield.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/mobile_platform_application.mjs +61 -0
- package/dist/esm/rest/admin/2026-07/mobile_platform_application.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/order.mjs +200 -0
- package/dist/esm/rest/admin/2026-07/order.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/order_risk.mjs +66 -0
- package/dist/esm/rest/admin/2026-07/order_risk.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/page.mjs +81 -0
- package/dist/esm/rest/admin/2026-07/page.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/payment.mjs +44 -0
- package/dist/esm/rest/admin/2026-07/payment.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/payment_gateway.mjs +70 -0
- package/dist/esm/rest/admin/2026-07/payment_gateway.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/payment_transaction.mjs +54 -0
- package/dist/esm/rest/admin/2026-07/payment_transaction.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/payout.mjs +45 -0
- package/dist/esm/rest/admin/2026-07/payout.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/policy.mjs +37 -0
- package/dist/esm/rest/admin/2026-07/policy.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/price_rule.mjs +95 -0
- package/dist/esm/rest/admin/2026-07/price_rule.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/product.mjs +87 -0
- package/dist/esm/rest/admin/2026-07/product.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/product_listing.mjs +97 -0
- package/dist/esm/rest/admin/2026-07/product_listing.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/product_resource_feedback.mjs +44 -0
- package/dist/esm/rest/admin/2026-07/product_resource_feedback.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/province.mjs +63 -0
- package/dist/esm/rest/admin/2026-07/province.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/recurring_application_charge.mjs +85 -0
- package/dist/esm/rest/admin/2026-07/recurring_application_charge.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/redirect.mjs +69 -0
- package/dist/esm/rest/admin/2026-07/redirect.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/refund.mjs +70 -0
- package/dist/esm/rest/admin/2026-07/refund.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/resource_feedback.mjs +39 -0
- package/dist/esm/rest/admin/2026-07/resource_feedback.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/script_tag.mjs +73 -0
- package/dist/esm/rest/admin/2026-07/script_tag.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/shipping_zone.mjs +45 -0
- package/dist/esm/rest/admin/2026-07/shipping_zone.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/shop.mjs +94 -0
- package/dist/esm/rest/admin/2026-07/shop.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/smart_collection.mjs +91 -0
- package/dist/esm/rest/admin/2026-07/smart_collection.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/storefront_access_token.mjs +48 -0
- package/dist/esm/rest/admin/2026-07/storefront_access_token.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/tender_transaction.mjs +41 -0
- package/dist/esm/rest/admin/2026-07/tender_transaction.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/theme.mjs +62 -0
- package/dist/esm/rest/admin/2026-07/theme.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/transaction.mjs +81 -0
- package/dist/esm/rest/admin/2026-07/transaction.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/usage_charge.mjs +51 -0
- package/dist/esm/rest/admin/2026-07/usage_charge.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/user.mjs +67 -0
- package/dist/esm/rest/admin/2026-07/user.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/variant.mjs +94 -0
- package/dist/esm/rest/admin/2026-07/variant.mjs.map +1 -0
- package/dist/esm/rest/admin/2026-07/webhook.mjs +76 -0
- package/dist/esm/rest/admin/2026-07/webhook.mjs.map +1 -0
- package/dist/esm/runtime/crypto/utils.mjs.map +1 -1
- package/dist/esm/tsconfig.build.tsbuildinfo +1 -1
- package/dist/ts/lib/auth/oauth/oauth.d.ts.map +1 -1
- package/dist/ts/lib/base-types.d.ts +28 -0
- package/dist/ts/lib/base-types.d.ts.map +1 -1
- package/dist/ts/lib/billing/types.d.ts.map +1 -1
- package/dist/ts/lib/types.d.ts +1 -1
- package/dist/ts/lib/types.d.ts.map +1 -1
- package/dist/ts/lib/utils/hmac-validator.d.ts +3 -1
- package/dist/ts/lib/utils/hmac-validator.d.ts.map +1 -1
- package/dist/ts/lib/utils/index.d.ts +1 -1
- package/dist/ts/lib/version.d.ts +1 -1
- package/dist/ts/lib/webhooks/register.d.ts.map +1 -1
- package/dist/ts/lib/webhooks/types.d.ts +1 -4
- package/dist/ts/lib/webhooks/types.d.ts.map +1 -1
- package/dist/ts/rest/admin/2026-07/abandoned_checkout.d.ts +90 -0
- package/dist/ts/rest/admin/2026-07/abandoned_checkout.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/access_scope.d.ts +30 -0
- package/dist/ts/rest/admin/2026-07/access_scope.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/apple_pay_certificate.d.ts +39 -0
- package/dist/ts/rest/admin/2026-07/apple_pay_certificate.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/application_charge.d.ts +46 -0
- package/dist/ts/rest/admin/2026-07/application_charge.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/application_credit.d.ts +40 -0
- package/dist/ts/rest/admin/2026-07/application_credit.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/article.d.ts +99 -0
- package/dist/ts/rest/admin/2026-07/article.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/asset.d.ts +49 -0
- package/dist/ts/rest/admin/2026-07/asset.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/assigned_fulfillment_order.d.ts +39 -0
- package/dist/ts/rest/admin/2026-07/assigned_fulfillment_order.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/balance.d.ts +28 -0
- package/dist/ts/rest/admin/2026-07/balance.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/blog.d.ts +60 -0
- package/dist/ts/rest/admin/2026-07/blog.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/cancellation_request.d.ts +36 -0
- package/dist/ts/rest/admin/2026-07/cancellation_request.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/carrier_service.d.ts +43 -0
- package/dist/ts/rest/admin/2026-07/carrier_service.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/checkout.d.ts +95 -0
- package/dist/ts/rest/admin/2026-07/checkout.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/collect.d.ts +51 -0
- package/dist/ts/rest/admin/2026-07/collect.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/collection.d.ts +46 -0
- package/dist/ts/rest/admin/2026-07/collection.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/collection_listing.d.ts +58 -0
- package/dist/ts/rest/admin/2026-07/collection_listing.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/comment.d.ts +103 -0
- package/dist/ts/rest/admin/2026-07/comment.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/country.d.ts +51 -0
- package/dist/ts/rest/admin/2026-07/country.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/currency.d.ts +27 -0
- package/dist/ts/rest/admin/2026-07/currency.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/custom_collection.d.ts +73 -0
- package/dist/ts/rest/admin/2026-07/custom_collection.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/customer.d.ts +121 -0
- package/dist/ts/rest/admin/2026-07/customer.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/deprecated_api_call.d.ts +29 -0
- package/dist/ts/rest/admin/2026-07/deprecated_api_call.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/discount_code.d.ts +76 -0
- package/dist/ts/rest/admin/2026-07/discount_code.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/dispute.d.ts +45 -0
- package/dist/ts/rest/admin/2026-07/dispute.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/dispute_evidence.d.ts +56 -0
- package/dist/ts/rest/admin/2026-07/dispute_evidence.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/dispute_file_upload.d.ts +35 -0
- package/dist/ts/rest/admin/2026-07/dispute_file_upload.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/draft_order.d.ts +116 -0
- package/dist/ts/rest/admin/2026-07/draft_order.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/event.d.ts +57 -0
- package/dist/ts/rest/admin/2026-07/event.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/fulfillment.d.ts +92 -0
- package/dist/ts/rest/admin/2026-07/fulfillment.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/fulfillment_event.d.ts +66 -0
- package/dist/ts/rest/admin/2026-07/fulfillment_event.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/fulfillment_order.d.ts +129 -0
- package/dist/ts/rest/admin/2026-07/fulfillment_order.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/fulfillment_request.d.ts +47 -0
- package/dist/ts/rest/admin/2026-07/fulfillment_request.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/fulfillment_service.d.ts +47 -0
- package/dist/ts/rest/admin/2026-07/fulfillment_service.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/gift_card.d.ts +83 -0
- package/dist/ts/rest/admin/2026-07/gift_card.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/gift_card_adjustment.d.ts +45 -0
- package/dist/ts/rest/admin/2026-07/gift_card_adjustment.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/image.d.ts +57 -0
- package/dist/ts/rest/admin/2026-07/image.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/index.d.ts +152 -0
- package/dist/ts/rest/admin/2026-07/index.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/inventory_item.d.ts +45 -0
- package/dist/ts/rest/admin/2026-07/inventory_item.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/inventory_level.d.ts +70 -0
- package/dist/ts/rest/admin/2026-07/inventory_level.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/location.d.ts +59 -0
- package/dist/ts/rest/admin/2026-07/location.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/locations_for_move.d.ts +29 -0
- package/dist/ts/rest/admin/2026-07/locations_for_move.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/marketing_event.d.ts +79 -0
- package/dist/ts/rest/admin/2026-07/marketing_event.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/metafield.d.ts +111 -0
- package/dist/ts/rest/admin/2026-07/metafield.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/mobile_platform_application.d.ts +43 -0
- package/dist/ts/rest/admin/2026-07/mobile_platform_application.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/order.d.ts +239 -0
- package/dist/ts/rest/admin/2026-07/order.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/order_risk.d.ts +49 -0
- package/dist/ts/rest/admin/2026-07/order_risk.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/page.d.ts +76 -0
- package/dist/ts/rest/admin/2026-07/page.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/payment.d.ts +43 -0
- package/dist/ts/rest/admin/2026-07/payment.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/payment_gateway.d.ts +52 -0
- package/dist/ts/rest/admin/2026-07/payment_gateway.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/payment_transaction.d.ts +51 -0
- package/dist/ts/rest/admin/2026-07/payment_transaction.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/payout.d.ts +41 -0
- package/dist/ts/rest/admin/2026-07/payout.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/policy.d.ts +31 -0
- package/dist/ts/rest/admin/2026-07/policy.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/price_rule.d.ts +90 -0
- package/dist/ts/rest/admin/2026-07/price_rule.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/product.d.ts +95 -0
- package/dist/ts/rest/admin/2026-07/product.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/product_listing.d.ts +73 -0
- package/dist/ts/rest/admin/2026-07/product_listing.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/product_resource_feedback.d.ts +36 -0
- package/dist/ts/rest/admin/2026-07/product_resource_feedback.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/province.d.ts +50 -0
- package/dist/ts/rest/admin/2026-07/province.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/recurring_application_charge.d.ts +65 -0
- package/dist/ts/rest/admin/2026-07/recurring_application_charge.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/redirect.d.ts +51 -0
- package/dist/ts/rest/admin/2026-07/redirect.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/refund.d.ts +73 -0
- package/dist/ts/rest/admin/2026-07/refund.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/resource_feedback.d.ts +32 -0
- package/dist/ts/rest/admin/2026-07/resource_feedback.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/script_tag.d.ts +57 -0
- package/dist/ts/rest/admin/2026-07/script_tag.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/shipping_zone.d.ts +45 -0
- package/dist/ts/rest/admin/2026-07/shipping_zone.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/shop.d.ts +82 -0
- package/dist/ts/rest/admin/2026-07/shop.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/smart_collection.d.ts +87 -0
- package/dist/ts/rest/admin/2026-07/smart_collection.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/storefront_access_token.d.ts +35 -0
- package/dist/ts/rest/admin/2026-07/storefront_access_token.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/tender_transaction.d.ts +43 -0
- package/dist/ts/rest/admin/2026-07/tender_transaction.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/theme.d.ts +46 -0
- package/dist/ts/rest/admin/2026-07/theme.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/transaction.d.ts +82 -0
- package/dist/ts/rest/admin/2026-07/transaction.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/usage_charge.d.ts +44 -0
- package/dist/ts/rest/admin/2026-07/usage_charge.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/user.d.ts +51 -0
- package/dist/ts/rest/admin/2026-07/user.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/variant.d.ts +78 -0
- package/dist/ts/rest/admin/2026-07/variant.d.ts.map +1 -0
- package/dist/ts/rest/admin/2026-07/webhook.d.ts +62 -0
- package/dist/ts/rest/admin/2026-07/webhook.d.ts.map +1 -0
- package/dist/ts/tsconfig.build.tsbuildinfo +1 -1
- package/lib/__test-helpers__/graphql-base-request.ts +1 -1
- package/lib/auth/oauth/create-session.ts +1 -1
- package/lib/auth/oauth/oauth.ts +5 -1
- package/lib/base-types.ts +28 -0
- package/lib/billing/types.ts +2 -4
- package/lib/config.ts +2 -2
- package/lib/types.ts +1 -1
- package/lib/utils/hmac-validator.ts +78 -8
- package/lib/utils/processed-query.ts +1 -1
- package/lib/version.ts +1 -1
- package/lib/webhooks/process.ts +1 -2
- package/lib/webhooks/register.ts +0 -5
- package/lib/webhooks/types.ts +1 -7
- package/lib/webhooks/validate.ts +0 -3
- package/package.json +10 -11
- package/rest/admin/2026-07/abandoned_checkout.ts +112 -0
- package/rest/admin/2026-07/access_scope.ts +48 -0
- package/rest/admin/2026-07/apple_pay_certificate.ts +97 -0
- package/rest/admin/2026-07/application_charge.ts +85 -0
- package/rest/admin/2026-07/application_credit.ts +77 -0
- package/rest/admin/2026-07/article.ts +237 -0
- package/rest/admin/2026-07/asset.ts +88 -0
- package/rest/admin/2026-07/assigned_fulfillment_order.ts +57 -0
- package/rest/admin/2026-07/balance.ts +46 -0
- package/rest/admin/2026-07/blog.ts +138 -0
- package/rest/admin/2026-07/cancellation_request.ts +78 -0
- package/rest/admin/2026-07/carrier_service.ts +96 -0
- package/rest/admin/2026-07/checkout.ts +139 -0
- package/rest/admin/2026-07/collect.ts +126 -0
- package/rest/admin/2026-07/collection.ts +88 -0
- package/rest/admin/2026-07/collection_listing.ts +131 -0
- package/rest/admin/2026-07/comment.ts +263 -0
- package/rest/admin/2026-07/country.ts +127 -0
- package/rest/admin/2026-07/currency.ts +47 -0
- package/rest/admin/2026-07/custom_collection.ts +163 -0
- package/rest/admin/2026-07/customer.ts +277 -0
- package/rest/admin/2026-07/deprecated_api_call.ts +47 -0
- package/rest/admin/2026-07/discount_code.ts +212 -0
- package/rest/admin/2026-07/dispute.ts +83 -0
- package/rest/admin/2026-07/dispute_evidence.ts +69 -0
- package/rest/admin/2026-07/dispute_file_upload.ts +59 -0
- package/rest/admin/2026-07/draft_order.ts +221 -0
- package/rest/admin/2026-07/event.ts +124 -0
- package/rest/admin/2026-07/fulfillment.ts +193 -0
- package/rest/admin/2026-07/fulfillment_event.ts +129 -0
- package/rest/admin/2026-07/fulfillment_order.ts +296 -0
- package/rest/admin/2026-07/fulfillment_request.ts +91 -0
- package/rest/admin/2026-07/fulfillment_service.ts +101 -0
- package/rest/admin/2026-07/gift_card.ts +187 -0
- package/rest/admin/2026-07/gift_card_adjustment.ts +86 -0
- package/rest/admin/2026-07/image.ts +137 -0
- package/rest/admin/2026-07/index.ts +228 -0
- package/rest/admin/2026-07/inventory_item.ts +80 -0
- package/rest/admin/2026-07/inventory_level.ts +173 -0
- package/rest/admin/2026-07/location.ts +133 -0
- package/rest/admin/2026-07/locations_for_move.ts +48 -0
- package/rest/admin/2026-07/marketing_event.ts +175 -0
- package/rest/admin/2026-07/metafield.ts +300 -0
- package/rest/admin/2026-07/mobile_platform_application.ts +96 -0
- package/rest/admin/2026-07/order.ts +338 -0
- package/rest/admin/2026-07/order_risk.ts +109 -0
- package/rest/admin/2026-07/page.ts +170 -0
- package/rest/admin/2026-07/payment.ts +60 -0
- package/rest/admin/2026-07/payment_gateway.ts +105 -0
- package/rest/admin/2026-07/payment_transaction.ts +79 -0
- package/rest/admin/2026-07/payout.ts +81 -0
- package/rest/admin/2026-07/policy.ts +51 -0
- package/rest/admin/2026-07/price_rule.ts +163 -0
- package/rest/admin/2026-07/product.ts +192 -0
- package/rest/admin/2026-07/product_listing.ts +167 -0
- package/rest/admin/2026-07/product_resource_feedback.ts +62 -0
- package/rest/admin/2026-07/province.ts +110 -0
- package/rest/admin/2026-07/recurring_application_charge.ts +138 -0
- package/rest/admin/2026-07/redirect.ts +131 -0
- package/rest/admin/2026-07/refund.ts +126 -0
- package/rest/admin/2026-07/resource_feedback.ts +53 -0
- package/rest/admin/2026-07/script_tag.ts +139 -0
- package/rest/admin/2026-07/shipping_zone.ts +62 -0
- package/rest/admin/2026-07/shop.ts +118 -0
- package/rest/admin/2026-07/smart_collection.ts +192 -0
- package/rest/admin/2026-07/storefront_access_token.ts +73 -0
- package/rest/admin/2026-07/tender_transaction.ts +67 -0
- package/rest/admin/2026-07/theme.ts +101 -0
- package/rest/admin/2026-07/transaction.ts +132 -0
- package/rest/admin/2026-07/usage_charge.ts +84 -0
- package/rest/admin/2026-07/user.ts +106 -0
- package/rest/admin/2026-07/variant.ts +156 -0
- package/rest/admin/2026-07/webhook.ts +146 -0
- package/runtime/crypto/utils.ts +1 -1
|
@@ -9,7 +9,7 @@ function createSession({ config, accessTokenResponse, shop, state, }) {
|
|
|
9
9
|
logger(config).info('Creating new session', { shop, isOnline });
|
|
10
10
|
const getSessionExpiration = (expires_in) => new Date(Date.now() + expires_in * 1000);
|
|
11
11
|
const getOnlineSessionProperties = (responseBody) => {
|
|
12
|
-
const { access_token, scope, ...rest } = responseBody;
|
|
12
|
+
const { access_token: _access_token, scope: _scope, ...rest } = responseBody;
|
|
13
13
|
const sessionId = config.isEmbeddedApp
|
|
14
14
|
? getJwtSessionId(config)(shop, `${rest.associated_user.id}`)
|
|
15
15
|
: crypto.randomUUID();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-session.mjs","sources":["../../../../../../../lib/auth/oauth/create-session.ts"],"sourcesContent":["import {Session} from '../../session/session';\nimport {ConfigInterface} from '../../base-types';\nimport {logger} from '../../logger';\nimport {getJwtSessionId, getOfflineId} from '../../session/session-utils';\n\nimport {\n AccessTokenResponse,\n OnlineAccessResponse,\n OnlineAccessInfo,\n OfflineAccessResponse,\n} from './types';\n\nexport function createSession({\n config,\n accessTokenResponse,\n shop,\n state,\n}: {\n config: ConfigInterface;\n accessTokenResponse: AccessTokenResponse;\n shop: string;\n state: string;\n}): Session {\n const associatedUser = (accessTokenResponse as OnlineAccessResponse)\n .associated_user;\n const isOnline = Boolean(associatedUser);\n\n logger(config).info('Creating new session', {shop, isOnline});\n\n const getSessionExpiration = (expires_in: number) =>\n new Date(Date.now() + expires_in * 1000);\n\n const getOnlineSessionProperties = (responseBody: OnlineAccessResponse) => {\n const {access_token, scope, ...rest} = responseBody;\n const sessionId = config.isEmbeddedApp\n ? getJwtSessionId(config)(\n shop,\n `${(rest as OnlineAccessInfo).associated_user.id}`,\n )\n : crypto.randomUUID();\n\n return {\n id: sessionId,\n onlineAccessInfo: rest,\n expires: getSessionExpiration(rest.expires_in),\n };\n };\n\n const getOfflineSessionProperties = (responseBody: OfflineAccessResponse) => {\n const {expires_in, refresh_token, refresh_token_expires_in} = responseBody;\n return {\n id: getOfflineId(config)(shop),\n ...(expires_in && {expires: getSessionExpiration(expires_in)}),\n ...(refresh_token &&\n refresh_token_expires_in && {\n refreshToken: refresh_token,\n refreshTokenExpires: getSessionExpiration(refresh_token_expires_in),\n }),\n };\n };\n\n return new Session({\n shop,\n state,\n isOnline,\n accessToken: accessTokenResponse.access_token,\n scope: accessTokenResponse.scope,\n ...(isOnline\n ? getOnlineSessionProperties(accessTokenResponse as OnlineAccessResponse)\n : getOfflineSessionProperties(\n accessTokenResponse as OfflineAccessResponse,\n )),\n });\n}\n"],"names":[],"mappings":";;;;AAYM,SAAU,aAAa,CAAC,EAC5B,MAAM,EACN,mBAAmB,EACnB,IAAI,EACJ,KAAK,GAMN,EAAA;IACC,MAAM,cAAc,GAAI;AACrB,SAAA,eAAe;AAClB,IAAA,MAAM,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC;AAExC,IAAA,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,sBAAsB,EAAE,EAAC,IAAI,EAAE,QAAQ,EAAC,CAAC;AAE7D,IAAA,MAAM,oBAAoB,GAAG,CAAC,UAAkB,KAC9C,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,GAAG,IAAI,CAAC;AAE1C,IAAA,MAAM,0BAA0B,GAAG,CAAC,YAAkC,KAAI;
|
|
1
|
+
{"version":3,"file":"create-session.mjs","sources":["../../../../../../../lib/auth/oauth/create-session.ts"],"sourcesContent":["import {Session} from '../../session/session';\nimport {ConfigInterface} from '../../base-types';\nimport {logger} from '../../logger';\nimport {getJwtSessionId, getOfflineId} from '../../session/session-utils';\n\nimport {\n AccessTokenResponse,\n OnlineAccessResponse,\n OnlineAccessInfo,\n OfflineAccessResponse,\n} from './types';\n\nexport function createSession({\n config,\n accessTokenResponse,\n shop,\n state,\n}: {\n config: ConfigInterface;\n accessTokenResponse: AccessTokenResponse;\n shop: string;\n state: string;\n}): Session {\n const associatedUser = (accessTokenResponse as OnlineAccessResponse)\n .associated_user;\n const isOnline = Boolean(associatedUser);\n\n logger(config).info('Creating new session', {shop, isOnline});\n\n const getSessionExpiration = (expires_in: number) =>\n new Date(Date.now() + expires_in * 1000);\n\n const getOnlineSessionProperties = (responseBody: OnlineAccessResponse) => {\n const {access_token: _access_token, scope: _scope, ...rest} = responseBody;\n const sessionId = config.isEmbeddedApp\n ? getJwtSessionId(config)(\n shop,\n `${(rest as OnlineAccessInfo).associated_user.id}`,\n )\n : crypto.randomUUID();\n\n return {\n id: sessionId,\n onlineAccessInfo: rest,\n expires: getSessionExpiration(rest.expires_in),\n };\n };\n\n const getOfflineSessionProperties = (responseBody: OfflineAccessResponse) => {\n const {expires_in, refresh_token, refresh_token_expires_in} = responseBody;\n return {\n id: getOfflineId(config)(shop),\n ...(expires_in && {expires: getSessionExpiration(expires_in)}),\n ...(refresh_token &&\n refresh_token_expires_in && {\n refreshToken: refresh_token,\n refreshTokenExpires: getSessionExpiration(refresh_token_expires_in),\n }),\n };\n };\n\n return new Session({\n shop,\n state,\n isOnline,\n accessToken: accessTokenResponse.access_token,\n scope: accessTokenResponse.scope,\n ...(isOnline\n ? getOnlineSessionProperties(accessTokenResponse as OnlineAccessResponse)\n : getOfflineSessionProperties(\n accessTokenResponse as OfflineAccessResponse,\n )),\n });\n}\n"],"names":[],"mappings":";;;;AAYM,SAAU,aAAa,CAAC,EAC5B,MAAM,EACN,mBAAmB,EACnB,IAAI,EACJ,KAAK,GAMN,EAAA;IACC,MAAM,cAAc,GAAI;AACrB,SAAA,eAAe;AAClB,IAAA,MAAM,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC;AAExC,IAAA,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,sBAAsB,EAAE,EAAC,IAAI,EAAE,QAAQ,EAAC,CAAC;AAE7D,IAAA,MAAM,oBAAoB,GAAG,CAAC,UAAkB,KAC9C,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,GAAG,IAAI,CAAC;AAE1C,IAAA,MAAM,0BAA0B,GAAG,CAAC,YAAkC,KAAI;AACxE,QAAA,MAAM,EAAC,YAAY,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAC,GAAG,YAAY;AAC1E,QAAA,MAAM,SAAS,GAAG,MAAM,CAAC;AACvB,cAAE,eAAe,CAAC,MAAM,CAAC,CACrB,IAAI,EACJ,CAAA,EAAI,IAAyB,CAAC,eAAe,CAAC,EAAE,EAAE;AAEtD,cAAE,MAAM,CAAC,UAAU,EAAE;QAEvB,OAAO;AACL,YAAA,EAAE,EAAE,SAAS;AACb,YAAA,gBAAgB,EAAE,IAAI;AACtB,YAAA,OAAO,EAAE,oBAAoB,CAAC,IAAI,CAAC,UAAU,CAAC;SAC/C;AACH,IAAA,CAAC;AAED,IAAA,MAAM,2BAA2B,GAAG,CAAC,YAAmC,KAAI;QAC1E,MAAM,EAAC,UAAU,EAAE,aAAa,EAAE,wBAAwB,EAAC,GAAG,YAAY;QAC1E,OAAO;AACL,YAAA,EAAE,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC;YAC9B,IAAI,UAAU,IAAI,EAAC,OAAO,EAAE,oBAAoB,CAAC,UAAU,CAAC,EAAC,CAAC;AAC9D,YAAA,IAAI,aAAa;AACf,gBAAA,wBAAwB,IAAI;AAC1B,gBAAA,YAAY,EAAE,aAAa;AAC3B,gBAAA,mBAAmB,EAAE,oBAAoB,CAAC,wBAAwB,CAAC;aACpE,CAAC;SACL;AACH,IAAA,CAAC;IAED,OAAO,IAAI,OAAO,CAAC;QACjB,IAAI;QACJ,KAAK;QACL,QAAQ;QACR,WAAW,EAAE,mBAAmB,CAAC,YAAY;QAC7C,KAAK,EAAE,mBAAmB,CAAC,KAAK;AAChC,QAAA,IAAI;AACF,cAAE,0BAA0B,CAAC,mBAA2C;AACxE,cAAE,2BAA2B,CACzB,mBAA4C,CAC7C,CAAC;AACP,KAAA,CAAC;AACJ;;;;"}
|
|
@@ -127,11 +127,14 @@ function callback(config) {
|
|
|
127
127
|
config,
|
|
128
128
|
});
|
|
129
129
|
if (!config.isEmbeddedApp) {
|
|
130
|
+
const cookiePath = typeof config.cookiePath === 'function'
|
|
131
|
+
? config.cookiePath(session)
|
|
132
|
+
: (config.cookiePath ?? '/');
|
|
130
133
|
await cookies.setAndSign(SESSION_COOKIE_NAME, session.id, {
|
|
131
134
|
expires: session.expires,
|
|
132
135
|
sameSite: 'lax',
|
|
133
136
|
secure: true,
|
|
134
|
-
path:
|
|
137
|
+
path: cookiePath,
|
|
135
138
|
});
|
|
136
139
|
}
|
|
137
140
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth.mjs","sources":["../../../../../../../lib/auth/oauth/oauth.ts"],"sourcesContent":["import {isbot} from 'isbot';\n\nimport {throwFailedRequest} from '../../clients/common';\nimport ProcessedQuery from '../../utils/processed-query';\nimport {ConfigInterface} from '../../base-types';\nimport * as ShopifyErrors from '../../error';\nimport {validateHmac} from '../../utils/hmac-validator';\nimport {sanitizeShop} from '../../utils/shop-validator';\nimport {Session} from '../../session/session';\nimport {\n abstractConvertRequest,\n abstractConvertIncomingResponse,\n abstractConvertResponse,\n abstractConvertHeaders,\n AdapterResponse,\n AdapterHeaders,\n Cookies,\n NormalizedResponse,\n NormalizedRequest,\n} from '../../../runtime/http';\nimport {logger, ShopifyLogger} from '../../logger';\nimport {DataType} from '../../clients/types';\nimport {fetchRequestFactory} from '../../utils/fetch-request';\n\nimport {\n SESSION_COOKIE_NAME,\n STATE_COOKIE_NAME,\n BeginParams,\n CallbackParams,\n AuthQuery,\n AccessTokenResponse,\n} from './types';\nimport {nonce} from './nonce';\nimport {safeCompare} from './safe-compare';\nimport {createSession} from './create-session';\n\nexport type OAuthBegin = (beginParams: BeginParams) => Promise<AdapterResponse>;\n\nexport interface CallbackResponse<T = AdapterHeaders> {\n headers: T;\n session: Session;\n}\n\nexport type OAuthCallback = <T = AdapterHeaders>(\n callbackParams: CallbackParams,\n) => Promise<CallbackResponse<T>>;\n\ninterface BotLog {\n request: NormalizedRequest;\n log: ShopifyLogger;\n func: string;\n}\n\nconst logForBot = ({request, log, func}: BotLog) => {\n log.debug(`Possible bot request to auth ${func}: `, {\n userAgent: request.headers['User-Agent'],\n });\n};\n\nexport function begin(config: ConfigInterface): OAuthBegin {\n return async ({\n shop,\n callbackPath,\n isOnline,\n ...adapterArgs\n }: BeginParams): Promise<AdapterResponse> => {\n throwIfCustomStoreApp(\n config.isCustomStoreApp,\n 'Cannot perform OAuth for private apps',\n );\n\n const log = logger(config);\n log.info('Beginning OAuth', {shop, isOnline, callbackPath});\n\n const request = await abstractConvertRequest(adapterArgs);\n const response = await abstractConvertIncomingResponse(adapterArgs);\n\n let userAgent = request.headers['User-Agent'];\n if (Array.isArray(userAgent)) {\n userAgent = userAgent[0];\n }\n if (isbot(userAgent)) {\n logForBot({request, log, func: 'begin'});\n response.statusCode = 410;\n return abstractConvertResponse(response, adapterArgs);\n }\n\n const cookies = new Cookies(request, response, {\n keys: [config.apiSecretKey],\n secure: true,\n });\n\n const state = nonce();\n\n await cookies.setAndSign(STATE_COOKIE_NAME, state, {\n expires: new Date(Date.now() + 60000),\n sameSite: 'lax',\n secure: true,\n path: callbackPath,\n });\n\n const scopes = config.scopes ? config.scopes.toString() : '';\n const query = {\n client_id: config.apiKey,\n scope: scopes,\n redirect_uri: `${config.hostScheme}://${config.hostName}${callbackPath}`,\n state,\n 'grant_options[]': isOnline ? 'per-user' : '',\n };\n const processedQuery = new ProcessedQuery();\n processedQuery.putAll(query);\n\n const cleanShop = sanitizeShop(config)(shop, true)!;\n const redirectUrl = `https://${cleanShop}/admin/oauth/authorize${processedQuery.stringify()}`;\n response.statusCode = 302;\n response.statusText = 'Found';\n response.headers = {\n ...response.headers,\n ...cookies.response.headers!,\n Location: redirectUrl,\n };\n\n log.debug(`OAuth started, redirecting to ${redirectUrl}`, {shop, isOnline});\n\n return abstractConvertResponse(response, adapterArgs);\n };\n}\n\nexport function callback(config: ConfigInterface): OAuthCallback {\n return async function callback<T = AdapterHeaders>({\n expiring,\n ...adapterArgs\n }: CallbackParams): Promise<CallbackResponse<T>> {\n throwIfCustomStoreApp(\n config.isCustomStoreApp,\n 'Cannot perform OAuth for private apps',\n );\n\n const log = logger(config);\n\n const request = await abstractConvertRequest(adapterArgs);\n\n const query = new URL(\n request.url,\n `${config.hostScheme}://${config.hostName}`,\n ).searchParams;\n const shop = query.get('shop')!;\n\n const response = {} as NormalizedResponse;\n let userAgent = request.headers['User-Agent'];\n if (Array.isArray(userAgent)) {\n userAgent = userAgent[0];\n }\n if (isbot(userAgent)) {\n logForBot({request, log, func: 'callback'});\n throw new ShopifyErrors.BotActivityDetected(\n 'Invalid OAuth callback initiated by bot',\n );\n }\n\n log.info('Completing OAuth', {shop});\n\n const cookies = new Cookies(request, response, {\n keys: [config.apiSecretKey],\n secure: true,\n });\n\n const stateFromCookie = await cookies.getAndVerify(STATE_COOKIE_NAME);\n cookies.deleteCookie(STATE_COOKIE_NAME);\n if (!stateFromCookie) {\n log.error('Could not find OAuth cookie', {shop});\n\n throw new ShopifyErrors.CookieNotFound(\n `Cannot complete OAuth process. Could not find an OAuth cookie for shop url: ${shop}`,\n );\n }\n\n const authQuery: AuthQuery = Object.fromEntries(query.entries());\n if (!(await validQuery({config, query: authQuery, stateFromCookie}))) {\n log.error('Invalid OAuth callback', {shop, stateFromCookie});\n\n throw new ShopifyErrors.InvalidOAuthError('Invalid OAuth callback.');\n }\n\n log.debug('OAuth request is valid, requesting access token', {shop});\n\n const body = {\n client_id: config.apiKey,\n client_secret: config.apiSecretKey,\n code: query.get('code'),\n expiring: expiring ? '1' : '0',\n };\n\n const cleanShop = sanitizeShop(config)(query.get('shop')!, true)!;\n\n const postResponse = await fetchRequestFactory(config)(\n `https://${cleanShop}/admin/oauth/access_token`,\n {\n method: 'POST',\n body: JSON.stringify(body),\n headers: {\n 'Content-Type': DataType.JSON,\n Accept: DataType.JSON,\n },\n },\n );\n\n if (!postResponse.ok) {\n throwFailedRequest(await postResponse.json(), false, postResponse);\n }\n\n const session: Session = createSession({\n accessTokenResponse: await postResponse.json<AccessTokenResponse>(),\n shop: cleanShop,\n state: stateFromCookie,\n config,\n });\n\n if (!config.isEmbeddedApp) {\n await cookies.setAndSign(SESSION_COOKIE_NAME, session.id, {\n expires: session.expires,\n sameSite: 'lax',\n secure: true,\n path: '/',\n });\n }\n\n return {\n headers: (await abstractConvertHeaders(\n cookies.response.headers!,\n adapterArgs,\n )) as T,\n session,\n };\n };\n}\n\nasync function validQuery({\n config,\n query,\n stateFromCookie,\n}: {\n config: ConfigInterface;\n query: AuthQuery;\n stateFromCookie: string;\n}): Promise<boolean> {\n return (\n (await validateHmac(config)(query)) &&\n safeCompare(query.state!, stateFromCookie)\n );\n}\n\nfunction throwIfCustomStoreApp(\n isCustomStoreApp: boolean,\n message: string,\n): void {\n if (isCustomStoreApp) {\n throw new ShopifyErrors.PrivateAppError(message);\n }\n}\n"],"names":["ShopifyErrors.BotActivityDetected","ShopifyErrors.CookieNotFound","ShopifyErrors.InvalidOAuthError","ShopifyErrors.PrivateAppError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"oauth.mjs","sources":["../../../../../../../lib/auth/oauth/oauth.ts"],"sourcesContent":["import {isbot} from 'isbot';\n\nimport {throwFailedRequest} from '../../clients/common';\nimport ProcessedQuery from '../../utils/processed-query';\nimport {ConfigInterface} from '../../base-types';\nimport * as ShopifyErrors from '../../error';\nimport {validateHmac} from '../../utils/hmac-validator';\nimport {sanitizeShop} from '../../utils/shop-validator';\nimport {Session} from '../../session/session';\nimport {\n abstractConvertRequest,\n abstractConvertIncomingResponse,\n abstractConvertResponse,\n abstractConvertHeaders,\n AdapterResponse,\n AdapterHeaders,\n Cookies,\n NormalizedResponse,\n NormalizedRequest,\n} from '../../../runtime/http';\nimport {logger, ShopifyLogger} from '../../logger';\nimport {DataType} from '../../clients/types';\nimport {fetchRequestFactory} from '../../utils/fetch-request';\n\nimport {\n SESSION_COOKIE_NAME,\n STATE_COOKIE_NAME,\n BeginParams,\n CallbackParams,\n AuthQuery,\n AccessTokenResponse,\n} from './types';\nimport {nonce} from './nonce';\nimport {safeCompare} from './safe-compare';\nimport {createSession} from './create-session';\n\nexport type OAuthBegin = (beginParams: BeginParams) => Promise<AdapterResponse>;\n\nexport interface CallbackResponse<T = AdapterHeaders> {\n headers: T;\n session: Session;\n}\n\nexport type OAuthCallback = <T = AdapterHeaders>(\n callbackParams: CallbackParams,\n) => Promise<CallbackResponse<T>>;\n\ninterface BotLog {\n request: NormalizedRequest;\n log: ShopifyLogger;\n func: string;\n}\n\nconst logForBot = ({request, log, func}: BotLog) => {\n log.debug(`Possible bot request to auth ${func}: `, {\n userAgent: request.headers['User-Agent'],\n });\n};\n\nexport function begin(config: ConfigInterface): OAuthBegin {\n return async ({\n shop,\n callbackPath,\n isOnline,\n ...adapterArgs\n }: BeginParams): Promise<AdapterResponse> => {\n throwIfCustomStoreApp(\n config.isCustomStoreApp,\n 'Cannot perform OAuth for private apps',\n );\n\n const log = logger(config);\n log.info('Beginning OAuth', {shop, isOnline, callbackPath});\n\n const request = await abstractConvertRequest(adapterArgs);\n const response = await abstractConvertIncomingResponse(adapterArgs);\n\n let userAgent = request.headers['User-Agent'];\n if (Array.isArray(userAgent)) {\n userAgent = userAgent[0];\n }\n if (isbot(userAgent)) {\n logForBot({request, log, func: 'begin'});\n response.statusCode = 410;\n return abstractConvertResponse(response, adapterArgs);\n }\n\n const cookies = new Cookies(request, response, {\n keys: [config.apiSecretKey],\n secure: true,\n });\n\n const state = nonce();\n\n await cookies.setAndSign(STATE_COOKIE_NAME, state, {\n expires: new Date(Date.now() + 60000),\n sameSite: 'lax',\n secure: true,\n path: callbackPath,\n });\n\n const scopes = config.scopes ? config.scopes.toString() : '';\n const query = {\n client_id: config.apiKey,\n scope: scopes,\n redirect_uri: `${config.hostScheme}://${config.hostName}${callbackPath}`,\n state,\n 'grant_options[]': isOnline ? 'per-user' : '',\n };\n const processedQuery = new ProcessedQuery();\n processedQuery.putAll(query);\n\n const cleanShop = sanitizeShop(config)(shop, true)!;\n const redirectUrl = `https://${cleanShop}/admin/oauth/authorize${processedQuery.stringify()}`;\n response.statusCode = 302;\n response.statusText = 'Found';\n response.headers = {\n ...response.headers,\n ...cookies.response.headers!,\n Location: redirectUrl,\n };\n\n log.debug(`OAuth started, redirecting to ${redirectUrl}`, {shop, isOnline});\n\n return abstractConvertResponse(response, adapterArgs);\n };\n}\n\nexport function callback(config: ConfigInterface): OAuthCallback {\n return async function callback<T = AdapterHeaders>({\n expiring,\n ...adapterArgs\n }: CallbackParams): Promise<CallbackResponse<T>> {\n throwIfCustomStoreApp(\n config.isCustomStoreApp,\n 'Cannot perform OAuth for private apps',\n );\n\n const log = logger(config);\n\n const request = await abstractConvertRequest(adapterArgs);\n\n const query = new URL(\n request.url,\n `${config.hostScheme}://${config.hostName}`,\n ).searchParams;\n const shop = query.get('shop')!;\n\n const response = {} as NormalizedResponse;\n let userAgent = request.headers['User-Agent'];\n if (Array.isArray(userAgent)) {\n userAgent = userAgent[0];\n }\n if (isbot(userAgent)) {\n logForBot({request, log, func: 'callback'});\n throw new ShopifyErrors.BotActivityDetected(\n 'Invalid OAuth callback initiated by bot',\n );\n }\n\n log.info('Completing OAuth', {shop});\n\n const cookies = new Cookies(request, response, {\n keys: [config.apiSecretKey],\n secure: true,\n });\n\n const stateFromCookie = await cookies.getAndVerify(STATE_COOKIE_NAME);\n cookies.deleteCookie(STATE_COOKIE_NAME);\n if (!stateFromCookie) {\n log.error('Could not find OAuth cookie', {shop});\n\n throw new ShopifyErrors.CookieNotFound(\n `Cannot complete OAuth process. Could not find an OAuth cookie for shop url: ${shop}`,\n );\n }\n\n const authQuery: AuthQuery = Object.fromEntries(query.entries());\n if (!(await validQuery({config, query: authQuery, stateFromCookie}))) {\n log.error('Invalid OAuth callback', {shop, stateFromCookie});\n\n throw new ShopifyErrors.InvalidOAuthError('Invalid OAuth callback.');\n }\n\n log.debug('OAuth request is valid, requesting access token', {shop});\n\n const body = {\n client_id: config.apiKey,\n client_secret: config.apiSecretKey,\n code: query.get('code'),\n expiring: expiring ? '1' : '0',\n };\n\n const cleanShop = sanitizeShop(config)(query.get('shop')!, true)!;\n\n const postResponse = await fetchRequestFactory(config)(\n `https://${cleanShop}/admin/oauth/access_token`,\n {\n method: 'POST',\n body: JSON.stringify(body),\n headers: {\n 'Content-Type': DataType.JSON,\n Accept: DataType.JSON,\n },\n },\n );\n\n if (!postResponse.ok) {\n throwFailedRequest(await postResponse.json(), false, postResponse);\n }\n\n const session: Session = createSession({\n accessTokenResponse: await postResponse.json<AccessTokenResponse>(),\n shop: cleanShop,\n state: stateFromCookie,\n config,\n });\n\n if (!config.isEmbeddedApp) {\n const cookiePath =\n typeof config.cookiePath === 'function'\n ? config.cookiePath(session)\n : (config.cookiePath ?? '/');\n await cookies.setAndSign(SESSION_COOKIE_NAME, session.id, {\n expires: session.expires,\n sameSite: 'lax',\n secure: true,\n path: cookiePath,\n });\n }\n\n return {\n headers: (await abstractConvertHeaders(\n cookies.response.headers!,\n adapterArgs,\n )) as T,\n session,\n };\n };\n}\n\nasync function validQuery({\n config,\n query,\n stateFromCookie,\n}: {\n config: ConfigInterface;\n query: AuthQuery;\n stateFromCookie: string;\n}): Promise<boolean> {\n return (\n (await validateHmac(config)(query)) &&\n safeCompare(query.state!, stateFromCookie)\n );\n}\n\nfunction throwIfCustomStoreApp(\n isCustomStoreApp: boolean,\n message: string,\n): void {\n if (isCustomStoreApp) {\n throw new ShopifyErrors.PrivateAppError(message);\n }\n}\n"],"names":["ShopifyErrors.BotActivityDetected","ShopifyErrors.CookieNotFound","ShopifyErrors.InvalidOAuthError","ShopifyErrors.PrivateAppError"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.mjs","sources":["../../../../../../lib/billing/types.ts"],"sourcesContent":["import {BillingInterval, BillingReplacementBehavior} from '../types';\nimport {Session} from '../session/session';\nimport {FeatureEnabled, FutureFlagOptions} from '../../future/flags';\n\nexport interface BillingConfigPlan {\n /**\n * Amount to charge for this plan.\n */\n amount: number;\n /**\n * Currency code for this plan.\n */\n currencyCode: string;\n}\n\nexport interface BillingConfigOneTimePlan extends BillingConfigPlan {\n /**\n * Interval for this plan.\n *\n * Must be set to `OneTime`.\n */\n interval: BillingInterval.OneTime;\n}\n\nexport interface BillingConfigSubscriptionPlanDiscountAmount {\n /**\n * The amount to discount.\n *\n * Cannot be set if `percentage` is set.\n */\n amount: number;\n /**\n * The percentage to discount.\n *\n * Cannot be set if `amount` is set.\n */\n percentage?: never;\n}\n\nexport interface BillingConfigSubscriptionPlanDiscountPercentage {\n /**\n * The amount to discount.\n *\n * Cannot be set if `percentage` is set.\n */\n amount?: never;\n /**\n * The percentage to discount.\n *\n * Cannot be set if `amount` is set.\n */\n percentage: number;\n}\n\nexport interface BillingConfigSubscriptionPlanDiscount {\n /**\n * The number of intervals to apply the discount for.\n */\n durationLimitInIntervals?: number;\n /**\n * The discount to apply.\n */\n value:\n | BillingConfigSubscriptionPlanDiscountAmount\n | BillingConfigSubscriptionPlanDiscountPercentage;\n}\n\nexport type BillingConfigItem =\n | BillingConfigOneTimePlan\n | BillingConfigSubscriptionLineItemPlan;\n\n// Type this as an interface to improve TSDoc support for it.\n\n/**\n * Billing configuration options, indexed by an app-specific plan name.\n */\nexport interface BillingConfig {\n /**\n * An individual billing plan.\n */\n [plan: string]: BillingConfigItem;\n}\n\nexport type RequestConfigOverrides = Partial<BillingConfigOneTimePlan>;\n\nexport interface BillingConfigLineItem {\n /**\n * The amount to charge for this line item.\n */\n amount: number;\n /**\n * The currency code for this line item.\n */\n currencyCode: string;\n}\n\nexport interface BillingConfigRecurringLineItem extends BillingConfigLineItem {\n /**\n * The recurring interval for this line item.\n *\n * Must be either `Every30Days` or `Annual`.\n */\n interval: BillingInterval.Every30Days | BillingInterval.Annual;\n /**\n * An optional discount to apply for this line item.\n */\n discount?: BillingConfigSubscriptionPlanDiscount;\n}\n\nexport interface BillingConfigUsageLineItem extends BillingConfigLineItem {\n /**\n * The usage interval for this line item.\n *\n * Must be set to `Usage`.\n */\n interval: BillingInterval.Usage;\n /**\n * The capped amount or the maximum amount to be charged in the interval.\n */\n amount: number;\n /**\n * Usage terms for this line item.\n */\n terms: string;\n}\n\nexport interface BillingConfigSubscriptionLineItemPlan {\n /**\n * The replacement behavior to use for this plan.\n */\n replacementBehavior?: BillingReplacementBehavior;\n /**\n * How many trial days to give before charging for this plan.\n */\n trialDays?: number;\n /**\n * The line items for this plan.\n */\n lineItems: (BillingConfigRecurringLineItem | BillingConfigUsageLineItem)[];\n}\n\ntype DeepPartial<T> = T extends object\n ? {[P in keyof T]?: DeepPartial<T[P]>}\n : T;\nexport type RequestConfigLineItemOverrides =\n DeepPartial<BillingConfigSubscriptionLineItemPlan>;\n\ninterface BillingCheckParamsNew {\n /**\n * The session to use for this check.\n */\n session: Session;\n /**\n * The plans to accept for this check.\n */\n plans?: string[] | string;\n /**\n * Whether to include charges that were created on test mode. Test shops and demo shops cannot be charged.\n */\n isTest?: boolean;\n}\n\ninterface BillingCheckParamsOld extends BillingCheckParamsNew {\n /**\n * The plans to accept for this check.\n */\n plans: string[] | string;\n /**\n * Whether to return the full response object.\n */\n returnObject?: boolean;\n}\n\nexport type BillingCheckParams<\n Future extends FutureFlagOptions = FutureFlagOptions,\n> =\n FeatureEnabled<Future, 'unstable_managedPricingSupport'> extends true\n ? BillingCheckParamsNew\n : BillingCheckParamsOld;\n\nexport interface BillingCheckResponseObject {\n /**\n * Whether the user has an active payment method.\n */\n hasActivePayment: boolean;\n /**\n * The one-time purchases the shop has.\n */\n oneTimePurchases: OneTimePurchase[];\n /**\n * The active subscriptions the shop has.\n */\n appSubscriptions: AppSubscription[];\n}\n\nexport type BillingCheckResponse<\n Params extends BillingCheckParams<Future>,\n Future extends FutureFlagOptions = FutureFlagOptions,\n> =\n FeatureEnabled<Future, 'unstable_managedPricingSupport'> extends true\n ? BillingCheckResponseObject\n : Params extends BillingCheckParamsOld\n ? Params['returnObject'] extends true\n ? BillingCheckResponseObject\n : boolean\n : never;\n\ntype BillingRequestOverridesType = RequestConfigOverrides &\n RequestConfigLineItemOverrides;\n\nexport type BillingRequestParams = {\n /**\n * The session to use for this request.\n */\n session: Session;\n /**\n * The plan to request.\n */\n plan: string;\n /**\n * Whether this is a test purchase.\n */\n isTest?: boolean;\n /**\n * Override the return URL after the purchase is complete.\n */\n returnUrl?: string;\n /**\n * Whether to return the full response object.\n */\n returnObject?: boolean;\n} & BillingRequestOverridesType;\n\nexport interface BillingRequestResponseObject {\n /**\n * The confirmation URL for this request.\n */\n confirmationUrl: string;\n /**\n * The one-time purchase created by this request.\n */\n oneTimePurchase?: OneTimePurchase;\n /**\n * The app subscription created by this request.\n */\n appSubscription?: AppSubscription;\n}\n\nexport type BillingRequestResponse<Params extends BillingRequestParams> =\n Params['returnObject'] extends true ? BillingRequestResponseObject : string;\n\nexport interface BillingCancelParams {\n /**\n * The session to use for this request.\n */\n session: Session;\n /**\n * The subscription ID to cancel.\n */\n subscriptionId: string;\n /**\n * Whether to prorate the cancellation.\n */\n prorate?: boolean;\n /**\n * Whether to consider test purchases.\n */\n isTest?: boolean;\n}\n\nexport interface BillingSubscriptionParams {\n /**\n * The session to use for this request.\n */\n session: Session;\n}\n\nexport interface AppSubscription {\n /**\n * The ID of the app subscription.\n */\n id: string;\n /**\n * The name of the purchased plan.\n */\n name: string;\n /**\n * Whether this is a test subscription.\n */\n test: boolean;\n /**\n * The number of trial days for this subscription.\n */\n trialDays: number;\n /**\n * The date and time when the subscription was created.\n */\n createdAt: string;\n /**\n * The date and time when the current period ends.\n */\n currentPeriodEnd: string;\n /**\n * The return URL for this subscription.\n */\n returnUrl: string;\n\n /*\n * The line items for this plan.\n */\n lineItems: ActiveSubscriptionLineItem[];\n\n /*\n * The status of the subscription. [ACTIVE, CANCELLED, PENDING, DECLINED, EXPIRED, FROZEN, ACCEPTED]\n */\n status:\n | 'ACTIVE'\n | 'CANCELLED'\n | 'PENDING'\n | 'DECLINED'\n | 'EXPIRED'\n | 'FROZEN'\n | 'ACCEPTED';\n}\n\nexport interface ActiveSubscriptions {\n activeSubscriptions: AppSubscription[];\n}\n\nexport interface ActiveSubscriptionLineItem {\n /*\n * The ID of the line item.\n */\n id: string;\n /*\n * The details of the plan.\n */\n plan: AppPlan;\n}\n\nexport interface RecurringAppPlan {\n /*\n * The interval for this plan is charged on.\n */\n interval: BillingInterval.Every30Days | BillingInterval.Annual;\n /*\n * The price of the plan.\n */\n price: Money;\n /*\n * The discount applied to the plan.\n */\n discount: AppPlanDiscount;\n}\n\nexport interface UsageAppPlan {\n /*\n * The total usage records for interval.\n */\n balanceUsed: Money;\n /*\n * The capped amount prevents the merchant from being charged for any usage over that amount during a billing period.\n */\n cappedAmount: Money;\n /*\n * The terms and conditions for app usage pricing.\n */\n terms: string;\n}\n\nexport interface Money {\n amount: number;\n currencyCode: string;\n}\n\nexport interface AppPlanDiscount {\n /*\n * The total number of intervals the discount applies to.\n */\n durationLimitInIntervals: number;\n /*\n * The remaining number of intervals the discount applies to.\n */\n remainingDurationInIntervals: number;\n /*\n * The price after the discount is applied.\n */\n priceAfterDiscount: Money;\n /*\n * The value of the discount applied every billing interval.\n */\n value: AppPlanDiscountAmount;\n}\n\nexport interface AppSubscriptionLineItemUpdatePayload {\n userErrors: string[];\n confirmationUrl: string;\n appSubscription: AppSubscription;\n}\n\nexport type UpdateCappedAmountConfirmation = Omit<\n AppSubscriptionLineItemUpdatePayload,\n 'userErrors'\n>;\n\ntype AppPlanDiscountAmount =\n | BillingConfigSubscriptionPlanDiscountAmount\n | BillingConfigSubscriptionPlanDiscountPercentage;\n\nexport interface AppPlan {\n /*\n * The pricing details of the plan.\n */\n pricingDetails: RecurringAppPlan | UsageAppPlan;\n}\nexport interface OneTimePurchase {\n /**\n * The ID of the one-time purchase.\n */\n id: string;\n /**\n * The name of the purchased plan.\n */\n name: string;\n /**\n * Whether this is a test purchase.\n */\n test: boolean;\n /*\n * The status of the subscription. [ACTIVE, CANCELLED, PENDING, DECLINED, EXPIRED, FROZEN, ACCEPTED]\n */\n status:\n | 'ACTIVE'\n | 'CANCELLED'\n | 'PENDING'\n | 'DECLINED'\n | 'EXPIRED'\n | 'FROZEN'\n | 'ACCEPTED';\n}\n\nexport interface BillingCreateUsageRecordParams {\n /**\n * The session to use for this request.\n */\n session: Session;\n /**\n * The description of the usage record.\n */\n description: string;\n /**\n * The price and currency of the usage record.\n */\n price: {\n /**\n * The amount to charge for this usage record.\n */\n amount: number;\n /**\n * The currency code for this usage record.\n */\n currencyCode: string;\n };\n /**\n * The subscription line item ID to associate the usage record with.\n */\n subscriptionLineItemId?: string;\n /**\n * The idempotency key for this request.\n */\n idempotencyKey?: string;\n /**\n * Whether this is a test charge.\n * */\n isTest?: boolean;\n}\n\nexport interface UsageRecord {\n /**\n * The ID of the usage record.\n */\n id: string;\n /**\n * The description of the usage record.\n */\n description: string;\n /**\n * The price and currency of the usage record.\n */\n price: {\n /**\n * The amount to charge for this usage record.\n */\n amount: number;\n /**\n * The currency code for this usage record.\n */\n currencyCode: string;\n };\n /**\n * The subscription line item associated with the usage record.\n */\n plan: ActiveSubscriptionLineItem;\n /**\n * The idempotency key for this request.\n */\n idempotencyKey?: string;\n /**\n * The subscription line item associated with the usage record.\n */\n subscriptionLineItem: AppSubscriptionLineItem;\n}\n\nexport interface AppSubscriptionLineItem {\n /**\n * The ID of the subscription line item.\n */\n id: string;\n /**\n * The plan associated with the subscription line item.\n */\n plan: AppPlan;\n}\n\nexport interface BillingUpdateUsageCappedAmountParams {\n /**\n * The session to use for this request.\n */\n session: Session;\n /**\n * The subscription line item ID to update.\n */\n subscriptionLineItemId: string;\n /**\n * The maximum charge for the usage billing plan.\n */\n cappedAmount: {\n /**\n * The amount to update.\n */\n amount: number;\n /**\n * The currency code to update.\n */\n currencyCode: string;\n };\n}\n\ninterface OneTimePurchases {\n oneTimePurchases: {\n edges: {\n node: OneTimePurchase;\n }[];\n pageInfo: {\n endCursor: string;\n hasNextPage: boolean;\n };\n };\n}\n\nexport type CurrentAppInstallation = OneTimePurchases & ActiveSubscriptions;\n\nexport interface CurrentAppInstallations {\n currentAppInstallation?: CurrentAppInstallation;\n}\n\nexport interface RequestResponse {\n userErrors: string[];\n confirmationUrl: string;\n}\n\ninterface AppSubscriptionCreate {\n userErrors: string[];\n confirmationUrl: string;\n appSubscription: AppSubscription;\n}\n\ninterface AppPurchaseOneTimeCreate {\n userErrors: string[];\n confirmationUrl: string;\n oneTimePurchase: OneTimePurchase;\n}\n\nexport interface RecurringPaymentResponse {\n appSubscriptionCreate?: AppSubscriptionCreate;\n}\n\nexport interface SinglePaymentResponse {\n appPurchaseOneTimeCreate?: AppPurchaseOneTimeCreate;\n}\n\nexport type RequestResponseData =\n | AppSubscriptionCreate\n | AppPurchaseOneTimeCreate;\n\nexport interface SubscriptionResponse {\n currentAppInstallation?: ActiveSubscriptions;\n}\n\nexport interface CancelResponse {\n appSubscriptionCancel?: {\n appSubscription: AppSubscription;\n userErrors: string[];\n };\n}\n\nexport interface UsageRecordCreateResponse {\n appUsageRecordCreate?: {\n appUsageRecord: UsageRecord;\n userErrors: string[];\n };\n}\n\nexport interface BillingUpdateUsageCappedAmountResponse {\n appSubscriptionLineItemUpdate?: AppSubscriptionLineItemUpdatePayload;\n}\n\nexport type BillingCheck<Future extends FutureFlagOptions> = <\n Params extends BillingCheckParams<Future>,\n>(\n params: Params,\n) => Promise<BillingCheckResponse<Params, Future>>;\n\nexport type BillingRequest = <Params extends BillingRequestParams>(\n params: Params,\n) => Promise<BillingRequestResponse<Params>>;\n\nexport type BillingCancel = (\n params: BillingCancelParams,\n) => Promise<AppSubscription>;\n\nexport type BillingSubscriptions = (\n params: BillingSubscriptionParams,\n) => Promise<ActiveSubscriptions>;\n\nexport type BillingCreateUsageRecord = (\n params: BillingCreateUsageRecordParams,\n) => Promise<UsageRecord>;\n\nexport type BillingUpdateUsageCappedAmount = (\n params: BillingUpdateUsageCappedAmountParams,\n) => Promise<UpdateCappedAmountConfirmation>;\n\nexport interface ShopifyBilling<Future extends FutureFlagOptions> {\n check: BillingCheck<Future>;\n request: BillingRequest;\n cancel: BillingCancel;\n subscriptions: BillingSubscriptions;\n createUsageRecord: BillingCreateUsageRecord;\n updateUsageCappedAmount: BillingUpdateUsageCappedAmount;\n}\n\nexport const APP_SUBSCRIPTION_FRAGMENT = `\n fragment AppSubscriptionFragment on AppSubscription {\n id\n name\n test\n status\n trialDays\n createdAt\n currentPeriodEnd\n returnUrl\n lineItems {\n id\n plan {\n pricingDetails {\n ... on AppRecurringPricing {\n price {\n amount\n currencyCode\n }\n interval\n discount {\n durationLimitInIntervals\n remainingDurationInIntervals\n priceAfterDiscount {\n amount\n }\n value {\n ... on AppSubscriptionDiscountAmount {\n amount {\n amount\n currencyCode\n }\n }\n ... on AppSubscriptionDiscountPercentage {\n percentage\n }\n }\n }\n }\n ... on AppUsagePricing {\n balanceUsed {\n amount\n currencyCode\n }\n cappedAmount {\n amount\n currencyCode\n }\n terms\n }\n }\n }\n }\n }\n`;\n"],"names":[],"mappings":"AA4oBO,MAAM,yBAAyB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"types.mjs","sources":["../../../../../../lib/billing/types.ts"],"sourcesContent":["import {BillingInterval, BillingReplacementBehavior} from '../types';\nimport {Session} from '../session/session';\nimport {FeatureEnabled, FutureFlagOptions} from '../../future/flags';\n\nexport interface BillingConfigPlan {\n /**\n * Amount to charge for this plan.\n */\n amount: number;\n /**\n * Currency code for this plan.\n */\n currencyCode: string;\n}\n\nexport interface BillingConfigOneTimePlan extends BillingConfigPlan {\n /**\n * Interval for this plan.\n *\n * Must be set to `OneTime`.\n */\n interval: BillingInterval.OneTime;\n}\n\nexport interface BillingConfigSubscriptionPlanDiscountAmount {\n /**\n * The amount to discount.\n *\n * Cannot be set if `percentage` is set.\n */\n amount: number;\n /**\n * The percentage to discount.\n *\n * Cannot be set if `amount` is set.\n */\n percentage?: never;\n}\n\nexport interface BillingConfigSubscriptionPlanDiscountPercentage {\n /**\n * The amount to discount.\n *\n * Cannot be set if `percentage` is set.\n */\n amount?: never;\n /**\n * The percentage to discount.\n *\n * Cannot be set if `amount` is set.\n */\n percentage: number;\n}\n\nexport interface BillingConfigSubscriptionPlanDiscount {\n /**\n * The number of intervals to apply the discount for.\n */\n durationLimitInIntervals?: number;\n /**\n * The discount to apply.\n */\n value:\n | BillingConfigSubscriptionPlanDiscountAmount\n | BillingConfigSubscriptionPlanDiscountPercentage;\n}\n\nexport type BillingConfigItem =\n BillingConfigOneTimePlan | BillingConfigSubscriptionLineItemPlan;\n\n// Type this as an interface to improve TSDoc support for it.\n\n/**\n * Billing configuration options, indexed by an app-specific plan name.\n */\nexport interface BillingConfig {\n /**\n * An individual billing plan.\n */\n [plan: string]: BillingConfigItem;\n}\n\nexport type RequestConfigOverrides = Partial<BillingConfigOneTimePlan>;\n\nexport interface BillingConfigLineItem {\n /**\n * The amount to charge for this line item.\n */\n amount: number;\n /**\n * The currency code for this line item.\n */\n currencyCode: string;\n}\n\nexport interface BillingConfigRecurringLineItem extends BillingConfigLineItem {\n /**\n * The recurring interval for this line item.\n *\n * Must be either `Every30Days` or `Annual`.\n */\n interval: BillingInterval.Every30Days | BillingInterval.Annual;\n /**\n * An optional discount to apply for this line item.\n */\n discount?: BillingConfigSubscriptionPlanDiscount;\n}\n\nexport interface BillingConfigUsageLineItem extends BillingConfigLineItem {\n /**\n * The usage interval for this line item.\n *\n * Must be set to `Usage`.\n */\n interval: BillingInterval.Usage;\n /**\n * The capped amount or the maximum amount to be charged in the interval.\n */\n amount: number;\n /**\n * Usage terms for this line item.\n */\n terms: string;\n}\n\nexport interface BillingConfigSubscriptionLineItemPlan {\n /**\n * The replacement behavior to use for this plan.\n */\n replacementBehavior?: BillingReplacementBehavior;\n /**\n * How many trial days to give before charging for this plan.\n */\n trialDays?: number;\n /**\n * The line items for this plan.\n */\n lineItems: (BillingConfigRecurringLineItem | BillingConfigUsageLineItem)[];\n}\n\ntype DeepPartial<T> = T extends object\n ? {[P in keyof T]?: DeepPartial<T[P]>}\n : T;\nexport type RequestConfigLineItemOverrides =\n DeepPartial<BillingConfigSubscriptionLineItemPlan>;\n\ninterface BillingCheckParamsNew {\n /**\n * The session to use for this check.\n */\n session: Session;\n /**\n * The plans to accept for this check.\n */\n plans?: string[] | string;\n /**\n * Whether to include charges that were created on test mode. Test shops and demo shops cannot be charged.\n */\n isTest?: boolean;\n}\n\ninterface BillingCheckParamsOld extends BillingCheckParamsNew {\n /**\n * The plans to accept for this check.\n */\n plans: string[] | string;\n /**\n * Whether to return the full response object.\n */\n returnObject?: boolean;\n}\n\nexport type BillingCheckParams<\n Future extends FutureFlagOptions = FutureFlagOptions,\n> =\n FeatureEnabled<Future, 'unstable_managedPricingSupport'> extends true\n ? BillingCheckParamsNew\n : BillingCheckParamsOld;\n\nexport interface BillingCheckResponseObject {\n /**\n * Whether the user has an active payment method.\n */\n hasActivePayment: boolean;\n /**\n * The one-time purchases the shop has.\n */\n oneTimePurchases: OneTimePurchase[];\n /**\n * The active subscriptions the shop has.\n */\n appSubscriptions: AppSubscription[];\n}\n\nexport type BillingCheckResponse<\n Params extends BillingCheckParams<Future>,\n Future extends FutureFlagOptions = FutureFlagOptions,\n> =\n FeatureEnabled<Future, 'unstable_managedPricingSupport'> extends true\n ? BillingCheckResponseObject\n : Params extends BillingCheckParamsOld\n ? Params['returnObject'] extends true\n ? BillingCheckResponseObject\n : boolean\n : never;\n\ntype BillingRequestOverridesType = RequestConfigOverrides &\n RequestConfigLineItemOverrides;\n\nexport type BillingRequestParams = {\n /**\n * The session to use for this request.\n */\n session: Session;\n /**\n * The plan to request.\n */\n plan: string;\n /**\n * Whether this is a test purchase.\n */\n isTest?: boolean;\n /**\n * Override the return URL after the purchase is complete.\n */\n returnUrl?: string;\n /**\n * Whether to return the full response object.\n */\n returnObject?: boolean;\n} & BillingRequestOverridesType;\n\nexport interface BillingRequestResponseObject {\n /**\n * The confirmation URL for this request.\n */\n confirmationUrl: string;\n /**\n * The one-time purchase created by this request.\n */\n oneTimePurchase?: OneTimePurchase;\n /**\n * The app subscription created by this request.\n */\n appSubscription?: AppSubscription;\n}\n\nexport type BillingRequestResponse<Params extends BillingRequestParams> =\n Params['returnObject'] extends true ? BillingRequestResponseObject : string;\n\nexport interface BillingCancelParams {\n /**\n * The session to use for this request.\n */\n session: Session;\n /**\n * The subscription ID to cancel.\n */\n subscriptionId: string;\n /**\n * Whether to prorate the cancellation.\n */\n prorate?: boolean;\n /**\n * Whether to consider test purchases.\n */\n isTest?: boolean;\n}\n\nexport interface BillingSubscriptionParams {\n /**\n * The session to use for this request.\n */\n session: Session;\n}\n\nexport interface AppSubscription {\n /**\n * The ID of the app subscription.\n */\n id: string;\n /**\n * The name of the purchased plan.\n */\n name: string;\n /**\n * Whether this is a test subscription.\n */\n test: boolean;\n /**\n * The number of trial days for this subscription.\n */\n trialDays: number;\n /**\n * The date and time when the subscription was created.\n */\n createdAt: string;\n /**\n * The date and time when the current period ends.\n */\n currentPeriodEnd: string;\n /**\n * The return URL for this subscription.\n */\n returnUrl: string;\n\n /*\n * The line items for this plan.\n */\n lineItems: ActiveSubscriptionLineItem[];\n\n /*\n * The status of the subscription. [ACTIVE, CANCELLED, PENDING, DECLINED, EXPIRED, FROZEN, ACCEPTED]\n */\n status:\n | 'ACTIVE'\n | 'CANCELLED'\n | 'PENDING'\n | 'DECLINED'\n | 'EXPIRED'\n | 'FROZEN'\n | 'ACCEPTED';\n}\n\nexport interface ActiveSubscriptions {\n activeSubscriptions: AppSubscription[];\n}\n\nexport interface ActiveSubscriptionLineItem {\n /*\n * The ID of the line item.\n */\n id: string;\n /*\n * The details of the plan.\n */\n plan: AppPlan;\n}\n\nexport interface RecurringAppPlan {\n /*\n * The interval for this plan is charged on.\n */\n interval: BillingInterval.Every30Days | BillingInterval.Annual;\n /*\n * The price of the plan.\n */\n price: Money;\n /*\n * The discount applied to the plan.\n */\n discount: AppPlanDiscount;\n}\n\nexport interface UsageAppPlan {\n /*\n * The total usage records for interval.\n */\n balanceUsed: Money;\n /*\n * The capped amount prevents the merchant from being charged for any usage over that amount during a billing period.\n */\n cappedAmount: Money;\n /*\n * The terms and conditions for app usage pricing.\n */\n terms: string;\n}\n\nexport interface Money {\n amount: number;\n currencyCode: string;\n}\n\nexport interface AppPlanDiscount {\n /*\n * The total number of intervals the discount applies to.\n */\n durationLimitInIntervals: number;\n /*\n * The remaining number of intervals the discount applies to.\n */\n remainingDurationInIntervals: number;\n /*\n * The price after the discount is applied.\n */\n priceAfterDiscount: Money;\n /*\n * The value of the discount applied every billing interval.\n */\n value: AppPlanDiscountAmount;\n}\n\nexport interface AppSubscriptionLineItemUpdatePayload {\n userErrors: string[];\n confirmationUrl: string;\n appSubscription: AppSubscription;\n}\n\nexport type UpdateCappedAmountConfirmation = Omit<\n AppSubscriptionLineItemUpdatePayload,\n 'userErrors'\n>;\n\ntype AppPlanDiscountAmount =\n | BillingConfigSubscriptionPlanDiscountAmount\n | BillingConfigSubscriptionPlanDiscountPercentage;\n\nexport interface AppPlan {\n /*\n * The pricing details of the plan.\n */\n pricingDetails: RecurringAppPlan | UsageAppPlan;\n}\nexport interface OneTimePurchase {\n /**\n * The ID of the one-time purchase.\n */\n id: string;\n /**\n * The name of the purchased plan.\n */\n name: string;\n /**\n * Whether this is a test purchase.\n */\n test: boolean;\n /*\n * The status of the subscription. [ACTIVE, CANCELLED, PENDING, DECLINED, EXPIRED, FROZEN, ACCEPTED]\n */\n status:\n | 'ACTIVE'\n | 'CANCELLED'\n | 'PENDING'\n | 'DECLINED'\n | 'EXPIRED'\n | 'FROZEN'\n | 'ACCEPTED';\n}\n\nexport interface BillingCreateUsageRecordParams {\n /**\n * The session to use for this request.\n */\n session: Session;\n /**\n * The description of the usage record.\n */\n description: string;\n /**\n * The price and currency of the usage record.\n */\n price: {\n /**\n * The amount to charge for this usage record.\n */\n amount: number;\n /**\n * The currency code for this usage record.\n */\n currencyCode: string;\n };\n /**\n * The subscription line item ID to associate the usage record with.\n */\n subscriptionLineItemId?: string;\n /**\n * The idempotency key for this request.\n */\n idempotencyKey?: string;\n /**\n * Whether this is a test charge.\n * */\n isTest?: boolean;\n}\n\nexport interface UsageRecord {\n /**\n * The ID of the usage record.\n */\n id: string;\n /**\n * The description of the usage record.\n */\n description: string;\n /**\n * The price and currency of the usage record.\n */\n price: {\n /**\n * The amount to charge for this usage record.\n */\n amount: number;\n /**\n * The currency code for this usage record.\n */\n currencyCode: string;\n };\n /**\n * The subscription line item associated with the usage record.\n */\n plan: ActiveSubscriptionLineItem;\n /**\n * The idempotency key for this request.\n */\n idempotencyKey?: string;\n /**\n * The subscription line item associated with the usage record.\n */\n subscriptionLineItem: AppSubscriptionLineItem;\n}\n\nexport interface AppSubscriptionLineItem {\n /**\n * The ID of the subscription line item.\n */\n id: string;\n /**\n * The plan associated with the subscription line item.\n */\n plan: AppPlan;\n}\n\nexport interface BillingUpdateUsageCappedAmountParams {\n /**\n * The session to use for this request.\n */\n session: Session;\n /**\n * The subscription line item ID to update.\n */\n subscriptionLineItemId: string;\n /**\n * The maximum charge for the usage billing plan.\n */\n cappedAmount: {\n /**\n * The amount to update.\n */\n amount: number;\n /**\n * The currency code to update.\n */\n currencyCode: string;\n };\n}\n\ninterface OneTimePurchases {\n oneTimePurchases: {\n edges: {\n node: OneTimePurchase;\n }[];\n pageInfo: {\n endCursor: string;\n hasNextPage: boolean;\n };\n };\n}\n\nexport type CurrentAppInstallation = OneTimePurchases & ActiveSubscriptions;\n\nexport interface CurrentAppInstallations {\n currentAppInstallation?: CurrentAppInstallation;\n}\n\nexport interface RequestResponse {\n userErrors: string[];\n confirmationUrl: string;\n}\n\ninterface AppSubscriptionCreate {\n userErrors: string[];\n confirmationUrl: string;\n appSubscription: AppSubscription;\n}\n\ninterface AppPurchaseOneTimeCreate {\n userErrors: string[];\n confirmationUrl: string;\n oneTimePurchase: OneTimePurchase;\n}\n\nexport interface RecurringPaymentResponse {\n appSubscriptionCreate?: AppSubscriptionCreate;\n}\n\nexport interface SinglePaymentResponse {\n appPurchaseOneTimeCreate?: AppPurchaseOneTimeCreate;\n}\n\nexport type RequestResponseData =\n AppSubscriptionCreate | AppPurchaseOneTimeCreate;\n\nexport interface SubscriptionResponse {\n currentAppInstallation?: ActiveSubscriptions;\n}\n\nexport interface CancelResponse {\n appSubscriptionCancel?: {\n appSubscription: AppSubscription;\n userErrors: string[];\n };\n}\n\nexport interface UsageRecordCreateResponse {\n appUsageRecordCreate?: {\n appUsageRecord: UsageRecord;\n userErrors: string[];\n };\n}\n\nexport interface BillingUpdateUsageCappedAmountResponse {\n appSubscriptionLineItemUpdate?: AppSubscriptionLineItemUpdatePayload;\n}\n\nexport type BillingCheck<Future extends FutureFlagOptions> = <\n Params extends BillingCheckParams<Future>,\n>(\n params: Params,\n) => Promise<BillingCheckResponse<Params, Future>>;\n\nexport type BillingRequest = <Params extends BillingRequestParams>(\n params: Params,\n) => Promise<BillingRequestResponse<Params>>;\n\nexport type BillingCancel = (\n params: BillingCancelParams,\n) => Promise<AppSubscription>;\n\nexport type BillingSubscriptions = (\n params: BillingSubscriptionParams,\n) => Promise<ActiveSubscriptions>;\n\nexport type BillingCreateUsageRecord = (\n params: BillingCreateUsageRecordParams,\n) => Promise<UsageRecord>;\n\nexport type BillingUpdateUsageCappedAmount = (\n params: BillingUpdateUsageCappedAmountParams,\n) => Promise<UpdateCappedAmountConfirmation>;\n\nexport interface ShopifyBilling<Future extends FutureFlagOptions> {\n check: BillingCheck<Future>;\n request: BillingRequest;\n cancel: BillingCancel;\n subscriptions: BillingSubscriptions;\n createUsageRecord: BillingCreateUsageRecord;\n updateUsageCappedAmount: BillingUpdateUsageCappedAmount;\n}\n\nexport const APP_SUBSCRIPTION_FRAGMENT = `\n fragment AppSubscriptionFragment on AppSubscription {\n id\n name\n test\n status\n trialDays\n createdAt\n currentPeriodEnd\n returnUrl\n lineItems {\n id\n plan {\n pricingDetails {\n ... on AppRecurringPricing {\n price {\n amount\n currencyCode\n }\n interval\n discount {\n durationLimitInIntervals\n remainingDurationInIntervals\n priceAfterDiscount {\n amount\n }\n value {\n ... on AppSubscriptionDiscountAmount {\n amount {\n amount\n currencyCode\n }\n }\n ... on AppSubscriptionDiscountPercentage {\n percentage\n }\n }\n }\n }\n ... on AppUsagePricing {\n balanceUsed {\n amount\n currencyCode\n }\n cappedAmount {\n amount\n currencyCode\n }\n terms\n }\n }\n }\n }\n }\n`;\n"],"names":[],"mappings":"AA0oBO,MAAM,yBAAyB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/esm/lib/config.mjs
CHANGED
|
@@ -42,7 +42,7 @@ function validateConfig(params) {
|
|
|
42
42
|
}
|
|
43
43
|
});
|
|
44
44
|
if (missing.length) {
|
|
45
|
-
throw new ShopifyError(`Cannot initialize Shopify API Library. Missing values for: ${missing.join(', ')}. For apiVersion, please specify an explicit API version (e.g., ApiVersion.
|
|
45
|
+
throw new ShopifyError(`Cannot initialize Shopify API Library. Missing values for: ${missing.join(', ')}. For apiVersion, please specify an explicit API version (e.g., ApiVersion.July26). See https://shopify.dev/docs/api/usage/versioning for more information.`);
|
|
46
46
|
}
|
|
47
47
|
const { hostScheme, isCustomStoreApp, adminApiAccessToken, userAgentPrefix, logger: logger$1, privateAppStorefrontAccessToken, billing, future, ...mandatoryParams } = params;
|
|
48
48
|
let scopes;
|
|
@@ -62,7 +62,7 @@ function validateConfig(params) {
|
|
|
62
62
|
isCustomStoreApp: isCustomStoreApp ?? config.isCustomStoreApp,
|
|
63
63
|
adminApiAccessToken: adminApiAccessToken ?? config.adminApiAccessToken,
|
|
64
64
|
userAgentPrefix: userAgentPrefix ?? config.userAgentPrefix,
|
|
65
|
-
logger: { ...config.logger, ...
|
|
65
|
+
logger: { ...config.logger, ...logger$1 },
|
|
66
66
|
privateAppStorefrontAccessToken: privateAppStorefrontAccessToken ?? config.privateAppStorefrontAccessToken,
|
|
67
67
|
billing: billing ?? config.billing,
|
|
68
68
|
future: future ?? config.future,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.mjs","sources":["../../../../../lib/config.ts"],"sourcesContent":["import {ShopifyError} from './error';\nimport {ConfigInterface, ConfigParams} from './base-types';\nimport {LogSeverity} from './types';\nimport {AuthScopes} from './auth/scopes';\nimport {logger as createLogger} from './logger';\n\nexport function validateConfig<Params extends ConfigParams>(\n params: Params,\n): ConfigInterface<Params> {\n const config = {\n apiKey: '',\n apiSecretKey: '',\n hostName: '',\n hostScheme: 'https',\n isEmbeddedApp: true,\n isCustomStoreApp: false,\n logger: {\n log: defaultLogFunction,\n level: LogSeverity.Info,\n httpRequests: false,\n timestamps: false,\n },\n future: {},\n _logDisabledFutureFlags: true,\n } as ConfigInterface<Params>;\n\n // Make sure that the essential params actually have content in them\n const mandatory: (keyof Params)[] = [\n 'apiSecretKey',\n 'hostName',\n 'apiVersion',\n ];\n if (!('isCustomStoreApp' in params) || !params.isCustomStoreApp) {\n mandatory.push('apiKey');\n }\n if ('isCustomStoreApp' in params && params.isCustomStoreApp) {\n if (\n !('adminApiAccessToken' in params) ||\n params.adminApiAccessToken?.length === 0\n ) {\n mandatory.push('adminApiAccessToken');\n }\n }\n\n const missing: (keyof Params)[] = [];\n mandatory.forEach((key) => {\n if (!notEmpty(params[key])) {\n missing.push(key);\n }\n });\n\n if (missing.length) {\n throw new ShopifyError(\n `Cannot initialize Shopify API Library. Missing values for: ${missing.join(\n ', ',\n )}. For apiVersion, please specify an explicit API version (e.g., ApiVersion.
|
|
1
|
+
{"version":3,"file":"config.mjs","sources":["../../../../../lib/config.ts"],"sourcesContent":["import {ShopifyError} from './error';\nimport {ConfigInterface, ConfigParams} from './base-types';\nimport {LogSeverity} from './types';\nimport {AuthScopes} from './auth/scopes';\nimport {logger as createLogger} from './logger';\n\nexport function validateConfig<Params extends ConfigParams>(\n params: Params,\n): ConfigInterface<Params> {\n const config = {\n apiKey: '',\n apiSecretKey: '',\n hostName: '',\n hostScheme: 'https',\n isEmbeddedApp: true,\n isCustomStoreApp: false,\n logger: {\n log: defaultLogFunction,\n level: LogSeverity.Info,\n httpRequests: false,\n timestamps: false,\n },\n future: {},\n _logDisabledFutureFlags: true,\n } as ConfigInterface<Params>;\n\n // Make sure that the essential params actually have content in them\n const mandatory: (keyof Params)[] = [\n 'apiSecretKey',\n 'hostName',\n 'apiVersion',\n ];\n if (!('isCustomStoreApp' in params) || !params.isCustomStoreApp) {\n mandatory.push('apiKey');\n }\n if ('isCustomStoreApp' in params && params.isCustomStoreApp) {\n if (\n !('adminApiAccessToken' in params) ||\n params.adminApiAccessToken?.length === 0\n ) {\n mandatory.push('adminApiAccessToken');\n }\n }\n\n const missing: (keyof Params)[] = [];\n mandatory.forEach((key) => {\n if (!notEmpty(params[key])) {\n missing.push(key);\n }\n });\n\n if (missing.length) {\n throw new ShopifyError(\n `Cannot initialize Shopify API Library. Missing values for: ${missing.join(\n ', ',\n )}. For apiVersion, please specify an explicit API version (e.g., ApiVersion.July26). See https://shopify.dev/docs/api/usage/versioning for more information.`,\n );\n }\n\n const {\n hostScheme,\n isCustomStoreApp,\n adminApiAccessToken,\n userAgentPrefix,\n logger,\n privateAppStorefrontAccessToken,\n billing,\n future,\n ...mandatoryParams\n } = params;\n\n let scopes;\n if (params.scopes === undefined) {\n scopes = undefined;\n } else if (params.scopes instanceof AuthScopes) {\n scopes = params.scopes;\n } else {\n scopes = new AuthScopes(params.scopes);\n }\n\n Object.assign(config, mandatoryParams, {\n hostName: params.hostName.replace(/\\/$/, ''),\n scopes,\n hostScheme: hostScheme ?? config.hostScheme,\n isCustomStoreApp: isCustomStoreApp ?? config.isCustomStoreApp,\n adminApiAccessToken: adminApiAccessToken ?? config.adminApiAccessToken,\n userAgentPrefix: userAgentPrefix ?? config.userAgentPrefix,\n logger: {...config.logger, ...logger},\n privateAppStorefrontAccessToken:\n privateAppStorefrontAccessToken ?? config.privateAppStorefrontAccessToken,\n billing: billing ?? config.billing,\n future: future ?? config.future,\n });\n\n if (\n config.isCustomStoreApp &&\n params.adminApiAccessToken === params.apiSecretKey\n ) {\n createLogger(config).warning(\n \"adminApiAccessToken is set to the same value as apiSecretKey. adminApiAccessToken should be set to the Admin API access token for custom store apps; apiSecretKey should be set to the custom store app's API secret key.\",\n );\n }\n\n return config;\n}\n\nfunction notEmpty<T>(value: T): value is NonNullable<T> {\n if (value == null) {\n return false;\n }\n return typeof value === 'string' || Array.isArray(value)\n ? value.length > 0\n : true;\n}\n\nfunction defaultLogFunction(severity: LogSeverity, message: string): void {\n switch (severity) {\n case LogSeverity.Debug:\n console.debug(message);\n break;\n case LogSeverity.Info:\n console.log(message);\n break;\n case LogSeverity.Warning:\n console.warn(message);\n break;\n case LogSeverity.Error:\n console.error(message);\n break;\n }\n}\n"],"names":["logger","createLogger"],"mappings":"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"}
|
package/dist/esm/lib/types.mjs
CHANGED
|
@@ -15,6 +15,7 @@ var ApiVersion;
|
|
|
15
15
|
ApiVersion["January26"] = "2026-01";
|
|
16
16
|
ApiVersion["April26"] = "2026-04";
|
|
17
17
|
ApiVersion["July26"] = "2026-07";
|
|
18
|
+
ApiVersion["October26"] = "2026-10";
|
|
18
19
|
ApiVersion["Unstable"] = "unstable";
|
|
19
20
|
})(ApiVersion || (ApiVersion = {}));
|
|
20
21
|
const LIBRARY_NAME = 'Shopify API Library';
|
|
@@ -26,7 +27,6 @@ var ShopifyHeader;
|
|
|
26
27
|
ShopifyHeader["Domain"] = "X-Shopify-Shop-Domain";
|
|
27
28
|
ShopifyHeader["Hmac"] = "X-Shopify-Hmac-Sha256";
|
|
28
29
|
ShopifyHeader["Topic"] = "X-Shopify-Topic";
|
|
29
|
-
ShopifyHeader["SubTopic"] = "X-Shopify-Sub-Topic";
|
|
30
30
|
ShopifyHeader["WebhookId"] = "X-Shopify-Webhook-Id";
|
|
31
31
|
ShopifyHeader["Name"] = "X-Shopify-Name";
|
|
32
32
|
ShopifyHeader["TriggeredAt"] = "X-Shopify-Triggered-At";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.mjs","sources":["../../../../../lib/types.ts"],"sourcesContent":["export enum LogSeverity {\n Error,\n Warning,\n Info,\n Debug,\n}\n\nexport enum ApiVersion {\n October24 = '2024-10',\n January25 = '2025-01',\n April25 = '2025-04',\n July25 = '2025-07',\n October25 = '2025-10',\n January26 = '2026-01',\n April26 = '2026-04',\n July26 = '2026-07',\n Unstable = 'unstable',\n}\n\nexport const LIBRARY_NAME = 'Shopify API Library';\n\n/* eslint-disable @shopify/typescript-prefer-pascal-case-enums */\nexport enum ShopifyHeader {\n AccessToken = 'X-Shopify-Access-Token',\n ApiVersion = 'X-Shopify-API-Version',\n Domain = 'X-Shopify-Shop-Domain',\n Hmac = 'X-Shopify-Hmac-Sha256',\n Topic = 'X-Shopify-Topic',\n SubTopic = 'X-Shopify-Sub-Topic',\n WebhookId = 'X-Shopify-Webhook-Id',\n Name = 'X-Shopify-Name',\n TriggeredAt = 'X-Shopify-Triggered-At',\n EventId = 'X-Shopify-Event-Id',\n StorefrontPrivateToken = 'Shopify-Storefront-Private-Token',\n StorefrontSDKVariant = 'X-SDK-Variant',\n StorefrontSDKVersion = 'X-SDK-Version',\n}\n/* eslint-enable @shopify/typescript-prefer-pascal-case-enums */\n\nexport const ShopifyEventsHeader = {\n Hmac: 'shopify-hmac-sha256',\n Topic: 'shopify-topic',\n Domain: 'shopify-shop-domain',\n ApiVersion: 'shopify-api-version',\n EventId: 'shopify-event-id',\n WebhookId: 'shopify-webhook-id',\n Handle: 'shopify-handle',\n Action: 'shopify-action',\n ResourceId: 'shopify-resource-id',\n TriggeredAt: 'shopify-triggered-at',\n} as const;\n\nexport enum ClientType {\n Rest = 'rest',\n Graphql = 'graphql',\n}\n\nexport const privacyTopics: string[] = [\n 'CUSTOMERS_DATA_REQUEST',\n 'CUSTOMERS_REDACT',\n 'SHOP_REDACT',\n];\n\nexport enum BillingInterval {\n OneTime = 'ONE_TIME',\n Every30Days = 'EVERY_30_DAYS',\n Annual = 'ANNUAL',\n Usage = 'USAGE',\n}\n\nexport type RecurringBillingIntervals = Exclude<\n BillingInterval,\n BillingInterval.OneTime\n>;\n\nexport enum BillingReplacementBehavior {\n ApplyImmediately = 'APPLY_IMMEDIATELY',\n ApplyOnNextBillingCycle = 'APPLY_ON_NEXT_BILLING_CYCLE',\n Standard = 'STANDARD',\n}\n\nexport enum StatusCode {\n Continue = 100,\n SwitchingProtocols = 101,\n Ok = 200,\n Created = 201,\n Accepted = 202,\n NonAuthoritativeInformation = 203,\n NoContent = 204,\n ResetContent = 205,\n PartialContent = 206,\n MultipleChoices = 300,\n MovedPermanently = 301,\n Found = 302,\n SeeOther = 303,\n NotModified = 304,\n UseProxy = 305,\n TemporaryRedirect = 307,\n BadRequest = 400,\n Unauthorized = 401,\n PaymentRequired = 402,\n Forbidden = 403,\n NotFound = 404,\n MethodNotAllowed = 405,\n NotAcceptable = 406,\n ProxyAuthenticationRequired = 407,\n RequestTimeout = 408,\n Conflict = 409,\n Gone = 410,\n LengthRequired = 411,\n PreconditionFailed = 412,\n RequestEntityTooLarge = 413,\n RequestUriTooLong = 414,\n UnsupportedMediaType = 415,\n RequestedRangeNotSatisfiable = 416,\n ExpectationFailed = 417,\n ImATeapot = 418,\n UnprocessableEntity = 422,\n TooManyRequests = 429,\n InternalServerError = 500,\n NotImplemented = 501,\n BadGateway = 502,\n ServiceUnavailable = 503,\n GatewayTimeout = 504,\n HttpVersionNotSupported = 505,\n}\n\nexport enum Method {\n Get = 'GET',\n Post = 'POST',\n Put = 'PUT',\n Patch = 'PATCH',\n Delete = 'DELETE',\n Head = 'HEAD',\n Options = 'OPTIONS',\n Connect = 'CONNECT',\n}\n\n/**\n * Configuration for transforming shop domains in split-domain architectures.\n *\n * @example\n * // Template-based transformation\n * {\n * match: /^([a-zA-Z0-9][a-zA-Z0-9-_]*)\\.my\\.shop\\.dev$/,\n * transform: '$1.dev-api.shop.dev'\n * }\n *\n * @example\n * // Function-based transformation\n * {\n * match: /^([^.]+)\\.ui\\.example\\.com$/,\n * transform: (matches) => `${matches[1]}.api.example.com`\n * }\n */\nexport interface DomainTransformation {\n /**\n * Pattern to match against shop domains (source domain).\n * Can be a RegExp or string (converted to RegExp internally).\n */\n match: RegExp | string;\n\n /**\n * Transformation function or template string.\n * - Template string: Uses $1, $2, etc. for capture group substitution\n * - Function: Receives regex match groups and returns transformed domain\n */\n transform: ((matches: RegExpMatchArray) => string | null) | string;\n\n /**\n * Whether this transformation should also apply to host validation.\n * @default true\n */\n includeHost?: boolean;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.mjs","sources":["../../../../../lib/types.ts"],"sourcesContent":["export enum LogSeverity {\n Error,\n Warning,\n Info,\n Debug,\n}\n\nexport enum ApiVersion {\n October24 = '2024-10',\n January25 = '2025-01',\n April25 = '2025-04',\n July25 = '2025-07',\n October25 = '2025-10',\n January26 = '2026-01',\n April26 = '2026-04',\n July26 = '2026-07',\n October26 = '2026-10',\n Unstable = 'unstable',\n}\n\nexport const LIBRARY_NAME = 'Shopify API Library';\n\n/* eslint-disable @shopify/typescript-prefer-pascal-case-enums */\nexport enum ShopifyHeader {\n AccessToken = 'X-Shopify-Access-Token',\n ApiVersion = 'X-Shopify-API-Version',\n Domain = 'X-Shopify-Shop-Domain',\n Hmac = 'X-Shopify-Hmac-Sha256',\n Topic = 'X-Shopify-Topic',\n WebhookId = 'X-Shopify-Webhook-Id',\n Name = 'X-Shopify-Name',\n TriggeredAt = 'X-Shopify-Triggered-At',\n EventId = 'X-Shopify-Event-Id',\n StorefrontPrivateToken = 'Shopify-Storefront-Private-Token',\n StorefrontSDKVariant = 'X-SDK-Variant',\n StorefrontSDKVersion = 'X-SDK-Version',\n}\n/* eslint-enable @shopify/typescript-prefer-pascal-case-enums */\n\nexport const ShopifyEventsHeader = {\n Hmac: 'shopify-hmac-sha256',\n Topic: 'shopify-topic',\n Domain: 'shopify-shop-domain',\n ApiVersion: 'shopify-api-version',\n EventId: 'shopify-event-id',\n WebhookId: 'shopify-webhook-id',\n Handle: 'shopify-handle',\n Action: 'shopify-action',\n ResourceId: 'shopify-resource-id',\n TriggeredAt: 'shopify-triggered-at',\n} as const;\n\nexport enum ClientType {\n Rest = 'rest',\n Graphql = 'graphql',\n}\n\nexport const privacyTopics: string[] = [\n 'CUSTOMERS_DATA_REQUEST',\n 'CUSTOMERS_REDACT',\n 'SHOP_REDACT',\n];\n\nexport enum BillingInterval {\n OneTime = 'ONE_TIME',\n Every30Days = 'EVERY_30_DAYS',\n Annual = 'ANNUAL',\n Usage = 'USAGE',\n}\n\nexport type RecurringBillingIntervals = Exclude<\n BillingInterval,\n BillingInterval.OneTime\n>;\n\nexport enum BillingReplacementBehavior {\n ApplyImmediately = 'APPLY_IMMEDIATELY',\n ApplyOnNextBillingCycle = 'APPLY_ON_NEXT_BILLING_CYCLE',\n Standard = 'STANDARD',\n}\n\nexport enum StatusCode {\n Continue = 100,\n SwitchingProtocols = 101,\n Ok = 200,\n Created = 201,\n Accepted = 202,\n NonAuthoritativeInformation = 203,\n NoContent = 204,\n ResetContent = 205,\n PartialContent = 206,\n MultipleChoices = 300,\n MovedPermanently = 301,\n Found = 302,\n SeeOther = 303,\n NotModified = 304,\n UseProxy = 305,\n TemporaryRedirect = 307,\n BadRequest = 400,\n Unauthorized = 401,\n PaymentRequired = 402,\n Forbidden = 403,\n NotFound = 404,\n MethodNotAllowed = 405,\n NotAcceptable = 406,\n ProxyAuthenticationRequired = 407,\n RequestTimeout = 408,\n Conflict = 409,\n Gone = 410,\n LengthRequired = 411,\n PreconditionFailed = 412,\n RequestEntityTooLarge = 413,\n RequestUriTooLong = 414,\n UnsupportedMediaType = 415,\n RequestedRangeNotSatisfiable = 416,\n ExpectationFailed = 417,\n ImATeapot = 418,\n UnprocessableEntity = 422,\n TooManyRequests = 429,\n InternalServerError = 500,\n NotImplemented = 501,\n BadGateway = 502,\n ServiceUnavailable = 503,\n GatewayTimeout = 504,\n HttpVersionNotSupported = 505,\n}\n\nexport enum Method {\n Get = 'GET',\n Post = 'POST',\n Put = 'PUT',\n Patch = 'PATCH',\n Delete = 'DELETE',\n Head = 'HEAD',\n Options = 'OPTIONS',\n Connect = 'CONNECT',\n}\n\n/**\n * Configuration for transforming shop domains in split-domain architectures.\n *\n * @example\n * // Template-based transformation\n * {\n * match: /^([a-zA-Z0-9][a-zA-Z0-9-_]*)\\.my\\.shop\\.dev$/,\n * transform: '$1.dev-api.shop.dev'\n * }\n *\n * @example\n * // Function-based transformation\n * {\n * match: /^([^.]+)\\.ui\\.example\\.com$/,\n * transform: (matches) => `${matches[1]}.api.example.com`\n * }\n */\nexport interface DomainTransformation {\n /**\n * Pattern to match against shop domains (source domain).\n * Can be a RegExp or string (converted to RegExp internally).\n */\n match: RegExp | string;\n\n /**\n * Transformation function or template string.\n * - Template string: Uses $1, $2, etc. for capture group substitution\n * - Function: Receives regex match groups and returns transformed domain\n */\n transform: ((matches: RegExpMatchArray) => string | null) | string;\n\n /**\n * Whether this transformation should also apply to host validation.\n * @default true\n */\n includeHost?: boolean;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -11,6 +11,12 @@ import { ValidationErrorReason } from './types.mjs';
|
|
|
11
11
|
import { getHeader } from '../../runtime/http/headers.mjs';
|
|
12
12
|
|
|
13
13
|
const HMAC_TIMESTAMP_PERMITTED_CLOCK_TOLERANCE_SEC = 90;
|
|
14
|
+
const APP_PROXY_SINGLE_VALUE_PARAMS = new Set([
|
|
15
|
+
'hmac',
|
|
16
|
+
'shop',
|
|
17
|
+
'signature',
|
|
18
|
+
'timestamp',
|
|
19
|
+
]);
|
|
14
20
|
function stringifyQueryForAdmin(query) {
|
|
15
21
|
const processedQuery = new ProcessedQuery();
|
|
16
22
|
Object.keys(query)
|
|
@@ -27,7 +33,7 @@ function stringifyQueryForAppProxy(query) {
|
|
|
27
33
|
}
|
|
28
34
|
function generateLocalHmac(config) {
|
|
29
35
|
return async (params, signator = 'admin') => {
|
|
30
|
-
const { hmac, signature, ...query } = params;
|
|
36
|
+
const { hmac: _hmac, signature: _signature, ...query } = params;
|
|
31
37
|
const queryString = signator === 'admin'
|
|
32
38
|
? stringifyQueryForAdmin(query)
|
|
33
39
|
: stringifyQueryForAppProxy(query);
|
|
@@ -36,18 +42,48 @@ function generateLocalHmac(config) {
|
|
|
36
42
|
}
|
|
37
43
|
function validateHmac(config) {
|
|
38
44
|
return async (query, { signator } = { signator: 'admin' }) => {
|
|
39
|
-
|
|
45
|
+
const normalizedQuery = normalizeQuery(query, signator);
|
|
46
|
+
if (signator === 'admin' && !normalizedQuery.hmac) {
|
|
40
47
|
throw new InvalidHmacError('Query does not contain an HMAC value.');
|
|
41
48
|
}
|
|
42
|
-
if (signator === 'appProxy' && !
|
|
49
|
+
if (signator === 'appProxy' && !normalizedQuery.signature) {
|
|
43
50
|
throw new InvalidHmacError('Query does not contain a signature value.');
|
|
44
51
|
}
|
|
45
|
-
validateHmacTimestamp(
|
|
46
|
-
const hmac = signator === 'appProxy'
|
|
47
|
-
|
|
52
|
+
validateHmacTimestamp(normalizedQuery);
|
|
53
|
+
const hmac = signator === 'appProxy'
|
|
54
|
+
? normalizedQuery.signature
|
|
55
|
+
: normalizedQuery.hmac;
|
|
56
|
+
const localHmac = await generateLocalHmac(config)(normalizedQuery, signator);
|
|
48
57
|
return safeCompare(hmac, localHmac);
|
|
49
58
|
};
|
|
50
59
|
}
|
|
60
|
+
function normalizeQuery(query, signator) {
|
|
61
|
+
if (!(query instanceof URLSearchParams)) {
|
|
62
|
+
if (signator === 'appProxy') {
|
|
63
|
+
for (const key of APP_PROXY_SINGLE_VALUE_PARAMS) {
|
|
64
|
+
if (Array.isArray(query[key])) {
|
|
65
|
+
throw new InvalidHmacError(`Query parameter "${key}" must not appear more than once.`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return query;
|
|
70
|
+
}
|
|
71
|
+
const normalizedQuery = Object.create(null);
|
|
72
|
+
for (const [key, value] of query.entries()) {
|
|
73
|
+
const existingValue = normalizedQuery[key];
|
|
74
|
+
if (existingValue === undefined) {
|
|
75
|
+
normalizedQuery[key] = value;
|
|
76
|
+
}
|
|
77
|
+
else if (signator === 'appProxy' &&
|
|
78
|
+
APP_PROXY_SINGLE_VALUE_PARAMS.has(key)) {
|
|
79
|
+
throw new InvalidHmacError(`Query parameter "${key}" must not appear more than once.`);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
normalizedQuery[key] = `${existingValue},${value}`;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return normalizedQuery;
|
|
86
|
+
}
|
|
51
87
|
async function validateHmacString(config, data, hmac, format) {
|
|
52
88
|
const localHmac = await createSHA256HMAC(config.apiSecretKey, data, format);
|
|
53
89
|
return safeCompare(hmac, localHmac);
|
|
@@ -77,7 +113,17 @@ function validateHmacFromRequestFactory(config) {
|
|
|
77
113
|
};
|
|
78
114
|
}
|
|
79
115
|
function validateHmacTimestamp(query) {
|
|
80
|
-
|
|
116
|
+
const { timestamp } = query;
|
|
117
|
+
if (timestamp === undefined ||
|
|
118
|
+
timestamp === null ||
|
|
119
|
+
Array.isArray(timestamp)) {
|
|
120
|
+
throw new InvalidHmacError('HMAC timestamp is missing or invalid');
|
|
121
|
+
}
|
|
122
|
+
const parsedTimestamp = Number(timestamp);
|
|
123
|
+
if (!Number.isInteger(parsedTimestamp)) {
|
|
124
|
+
throw new InvalidHmacError('HMAC timestamp is missing or invalid');
|
|
125
|
+
}
|
|
126
|
+
if (Math.abs(getCurrentTimeInSec() - parsedTimestamp) >
|
|
81
127
|
HMAC_TIMESTAMP_PERMITTED_CLOCK_TOLERANCE_SEC) {
|
|
82
128
|
throw new InvalidHmacError('HMAC timestamp is outside of the tolerance range');
|
|
83
129
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hmac-validator.mjs","sources":["../../../../../../lib/utils/hmac-validator.ts"],"sourcesContent":["import {logger} from '../logger';\nimport {ShopifyHeader} from '../types';\nimport {\n AdapterArgs,\n abstractConvertRequest,\n getHeader,\n} from '../../runtime/http';\nimport {ConfigInterface} from '../base-types';\nimport {createSHA256HMAC} from '../../runtime/crypto';\nimport {HashFormat} from '../../runtime/crypto/types';\nimport {AuthQuery} from '../auth/oauth/types';\nimport * as ShopifyErrors from '../error';\nimport {safeCompare} from '../auth/oauth/safe-compare';\nimport {WEBHOOK_HEADER_NAMES, WebhookTypeValue} from '../webhooks/types';\n\nimport ProcessedQuery from './processed-query';\nimport {\n ValidationErrorReason,\n ValidationInvalid,\n HmacValidationType,\n ValidationValid,\n ValidationErrorReasonType,\n} from './types';\n\nconst HMAC_TIMESTAMP_PERMITTED_CLOCK_TOLERANCE_SEC = 90;\n\nexport type HMACSignator = 'admin' | 'appProxy';\n\nexport interface ValidateParams extends AdapterArgs {\n /**\n * The type of validation to perform, either 'flow' or 'webhook'.\n */\n type: HmacValidationType;\n /**\n * The raw body of the request.\n */\n rawBody: string;\n /**\n * The webhook type for header selection (optional, only for webhooks).\n */\n webhookType?: WebhookTypeValue;\n}\n\nfunction stringifyQueryForAdmin(query: AuthQuery): string {\n const processedQuery = new ProcessedQuery();\n Object.keys(query)\n .sort((val1, val2) => val1.localeCompare(val2))\n .forEach((key: string) => processedQuery.put(key, query[key]));\n\n return processedQuery.stringify(true);\n}\n\nfunction stringifyQueryForAppProxy(query: AuthQuery): string {\n return Object.entries(query)\n .sort(([val1], [val2]) => val1.localeCompare(val2))\n .reduce((acc, [key, value]) => {\n return `${acc}${key}=${Array.isArray(value) ? value.join(',') : value}`;\n }, '');\n}\n\nexport function generateLocalHmac(config: ConfigInterface) {\n return async (\n params: AuthQuery,\n signator: HMACSignator = 'admin',\n ): Promise<string> => {\n const {hmac, signature, ...query} = params;\n\n const queryString =\n signator === 'admin'\n ? stringifyQueryForAdmin(query)\n : stringifyQueryForAppProxy(query);\n\n return createSHA256HMAC(config.apiSecretKey, queryString, HashFormat.Hex);\n };\n}\n\nexport function validateHmac(config: ConfigInterface) {\n return async (\n query: AuthQuery,\n {signator}: {signator: HMACSignator} = {signator: 'admin'},\n ): Promise<boolean> => {\n if (signator === 'admin' && !query.hmac) {\n throw new ShopifyErrors.InvalidHmacError(\n 'Query does not contain an HMAC value.',\n );\n }\n\n if (signator === 'appProxy' && !query.signature) {\n throw new ShopifyErrors.InvalidHmacError(\n 'Query does not contain a signature value.',\n );\n }\n\n validateHmacTimestamp(query);\n\n const hmac = signator === 'appProxy' ? query.signature : query.hmac;\n const localHmac = await generateLocalHmac(config)(query, signator);\n\n return safeCompare(hmac as string, localHmac);\n };\n}\n\nexport async function validateHmacString(\n config: ConfigInterface,\n data: string,\n hmac: string,\n format: HashFormat,\n) {\n const localHmac = await createSHA256HMAC(config.apiSecretKey, data, format);\n\n return safeCompare(hmac, localHmac);\n}\n\nexport function getCurrentTimeInSec() {\n return Math.trunc(Date.now() / 1000);\n}\n\nexport function validateHmacFromRequestFactory(config: ConfigInterface) {\n return async function validateHmacFromRequest({\n type,\n rawBody,\n webhookType,\n ...adapterArgs\n }: ValidateParams): Promise<ValidationInvalid | ValidationValid> {\n const request = await abstractConvertRequest(adapterArgs);\n if (!rawBody.length) {\n return fail(ValidationErrorReason.MissingBody, type, config);\n }\n\n // Use appropriate header based on webhook type\n const hmacHeaderName = webhookType\n ? WEBHOOK_HEADER_NAMES[webhookType].hmac\n : ShopifyHeader.Hmac;\n\n const hmac = getHeader(request.headers, hmacHeaderName);\n if (!hmac) {\n return fail(ValidationErrorReason.MissingHmac, type, config);\n }\n const validHmac = await validateHmacString(\n config,\n rawBody,\n hmac,\n HashFormat.Base64,\n );\n if (!validHmac) {\n return fail(ValidationErrorReason.InvalidHmac, type, config);\n }\n\n return succeed(type, config);\n };\n}\n\nfunction validateHmacTimestamp(query: AuthQuery) {\n if (\n Math.abs(getCurrentTimeInSec() - Number(query.timestamp)) >\n HMAC_TIMESTAMP_PERMITTED_CLOCK_TOLERANCE_SEC\n ) {\n throw new ShopifyErrors.InvalidHmacError(\n 'HMAC timestamp is outside of the tolerance range',\n );\n }\n}\n\nasync function fail(\n reason: ValidationErrorReasonType,\n type: HmacValidationType,\n config: ConfigInterface,\n): Promise<ValidationInvalid> {\n const log = logger(config);\n await log.debug(`${type} request is not valid`, {reason});\n\n return {\n valid: false,\n reason,\n };\n}\n\nasync function succeed(\n type: HmacValidationType,\n config: ConfigInterface,\n): Promise<ValidationValid> {\n const log = logger(config);\n await log.debug(`${type} request is valid`);\n\n return {\n valid: true,\n };\n}\n"],"names":["ShopifyErrors.InvalidHmacError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"hmac-validator.mjs","sources":["../../../../../../lib/utils/hmac-validator.ts"],"sourcesContent":["import {logger} from '../logger';\nimport {ShopifyHeader} from '../types';\nimport {\n AdapterArgs,\n abstractConvertRequest,\n getHeader,\n} from '../../runtime/http';\nimport {ConfigInterface} from '../base-types';\nimport {createSHA256HMAC} from '../../runtime/crypto';\nimport {HashFormat} from '../../runtime/crypto/types';\nimport {AuthQuery} from '../auth/oauth/types';\nimport * as ShopifyErrors from '../error';\nimport {safeCompare} from '../auth/oauth/safe-compare';\nimport {WEBHOOK_HEADER_NAMES, WebhookTypeValue} from '../webhooks/types';\n\nimport ProcessedQuery from './processed-query';\nimport {\n ValidationErrorReason,\n ValidationInvalid,\n HmacValidationType,\n ValidationValid,\n ValidationErrorReasonType,\n} from './types';\n\nconst HMAC_TIMESTAMP_PERMITTED_CLOCK_TOLERANCE_SEC = 90;\nconst APP_PROXY_SINGLE_VALUE_PARAMS = new Set([\n 'hmac',\n 'shop',\n 'signature',\n 'timestamp',\n]);\n\nexport type HMACSignator = 'admin' | 'appProxy';\ntype HmacQuery = AuthQuery | URLSearchParams;\n\nexport interface ValidateParams extends AdapterArgs {\n /**\n * The type of validation to perform, either 'flow' or 'webhook'.\n */\n type: HmacValidationType;\n /**\n * The raw body of the request.\n */\n rawBody: string;\n /**\n * The webhook type for header selection (optional, only for webhooks).\n */\n webhookType?: WebhookTypeValue;\n}\n\nfunction stringifyQueryForAdmin(query: AuthQuery): string {\n const processedQuery = new ProcessedQuery();\n Object.keys(query)\n .sort((val1, val2) => val1.localeCompare(val2))\n .forEach((key: string) => processedQuery.put(key, query[key]));\n\n return processedQuery.stringify(true);\n}\n\nfunction stringifyQueryForAppProxy(query: AuthQuery): string {\n return Object.entries(query)\n .sort(([val1], [val2]) => val1.localeCompare(val2))\n .reduce((acc, [key, value]) => {\n return `${acc}${key}=${Array.isArray(value) ? value.join(',') : value}`;\n }, '');\n}\n\nexport function generateLocalHmac(config: ConfigInterface) {\n return async (\n params: AuthQuery,\n signator: HMACSignator = 'admin',\n ): Promise<string> => {\n const {hmac: _hmac, signature: _signature, ...query} = params;\n\n const queryString =\n signator === 'admin'\n ? stringifyQueryForAdmin(query)\n : stringifyQueryForAppProxy(query);\n\n return createSHA256HMAC(config.apiSecretKey, queryString, HashFormat.Hex);\n };\n}\n\nexport function validateHmac(config: ConfigInterface) {\n return async (\n query: HmacQuery,\n {signator}: {signator: HMACSignator} = {signator: 'admin'},\n ): Promise<boolean> => {\n const normalizedQuery = normalizeQuery(query, signator);\n\n if (signator === 'admin' && !normalizedQuery.hmac) {\n throw new ShopifyErrors.InvalidHmacError(\n 'Query does not contain an HMAC value.',\n );\n }\n\n if (signator === 'appProxy' && !normalizedQuery.signature) {\n throw new ShopifyErrors.InvalidHmacError(\n 'Query does not contain a signature value.',\n );\n }\n\n validateHmacTimestamp(normalizedQuery);\n\n const hmac =\n signator === 'appProxy'\n ? normalizedQuery.signature\n : normalizedQuery.hmac;\n const localHmac = await generateLocalHmac(config)(\n normalizedQuery,\n signator,\n );\n\n return safeCompare(hmac as string, localHmac);\n };\n}\n\nfunction normalizeQuery(query: HmacQuery, signator: HMACSignator): AuthQuery {\n if (!(query instanceof URLSearchParams)) {\n if (signator === 'appProxy') {\n for (const key of APP_PROXY_SINGLE_VALUE_PARAMS) {\n if (Array.isArray(query[key])) {\n throw new ShopifyErrors.InvalidHmacError(\n `Query parameter \"${key}\" must not appear more than once.`,\n );\n }\n }\n }\n\n return query;\n }\n\n const normalizedQuery = Object.create(null) as AuthQuery;\n for (const [key, value] of query.entries()) {\n const existingValue = normalizedQuery[key];\n if (existingValue === undefined) {\n normalizedQuery[key] = value;\n } else if (\n signator === 'appProxy' &&\n APP_PROXY_SINGLE_VALUE_PARAMS.has(key)\n ) {\n throw new ShopifyErrors.InvalidHmacError(\n `Query parameter \"${key}\" must not appear more than once.`,\n );\n } else {\n normalizedQuery[key] = `${existingValue},${value}`;\n }\n }\n\n return normalizedQuery;\n}\n\nexport async function validateHmacString(\n config: ConfigInterface,\n data: string,\n hmac: string,\n format: HashFormat,\n) {\n const localHmac = await createSHA256HMAC(config.apiSecretKey, data, format);\n\n return safeCompare(hmac, localHmac);\n}\n\nexport function getCurrentTimeInSec() {\n return Math.trunc(Date.now() / 1000);\n}\n\nexport function validateHmacFromRequestFactory(config: ConfigInterface) {\n return async function validateHmacFromRequest({\n type,\n rawBody,\n webhookType,\n ...adapterArgs\n }: ValidateParams): Promise<ValidationInvalid | ValidationValid> {\n const request = await abstractConvertRequest(adapterArgs);\n if (!rawBody.length) {\n return fail(ValidationErrorReason.MissingBody, type, config);\n }\n\n // Use appropriate header based on webhook type\n const hmacHeaderName = webhookType\n ? WEBHOOK_HEADER_NAMES[webhookType].hmac\n : ShopifyHeader.Hmac;\n\n const hmac = getHeader(request.headers, hmacHeaderName);\n if (!hmac) {\n return fail(ValidationErrorReason.MissingHmac, type, config);\n }\n const validHmac = await validateHmacString(\n config,\n rawBody,\n hmac,\n HashFormat.Base64,\n );\n if (!validHmac) {\n return fail(ValidationErrorReason.InvalidHmac, type, config);\n }\n\n return succeed(type, config);\n };\n}\n\nfunction validateHmacTimestamp(query: AuthQuery) {\n const {timestamp} = query;\n\n if (\n timestamp === undefined ||\n timestamp === null ||\n Array.isArray(timestamp)\n ) {\n throw new ShopifyErrors.InvalidHmacError(\n 'HMAC timestamp is missing or invalid',\n );\n }\n\n const parsedTimestamp = Number(timestamp);\n\n if (!Number.isInteger(parsedTimestamp)) {\n throw new ShopifyErrors.InvalidHmacError(\n 'HMAC timestamp is missing or invalid',\n );\n }\n\n if (\n Math.abs(getCurrentTimeInSec() - parsedTimestamp) >\n HMAC_TIMESTAMP_PERMITTED_CLOCK_TOLERANCE_SEC\n ) {\n throw new ShopifyErrors.InvalidHmacError(\n 'HMAC timestamp is outside of the tolerance range',\n );\n }\n}\n\nasync function fail(\n reason: ValidationErrorReasonType,\n type: HmacValidationType,\n config: ConfigInterface,\n): Promise<ValidationInvalid> {\n const log = logger(config);\n await log.debug(`${type} request is not valid`, {reason});\n\n return {\n valid: false,\n reason,\n };\n}\n\nasync function succeed(\n type: HmacValidationType,\n config: ConfigInterface,\n): Promise<ValidationValid> {\n const log = logger(config);\n await log.debug(`${type} request is valid`);\n\n return {\n valid: true,\n };\n}\n"],"names":["ShopifyErrors.InvalidHmacError"],"mappings":"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"}
|
|
@@ -35,7 +35,7 @@ class ProcessedQuery {
|
|
|
35
35
|
this.processedQuery.append(key, `${value}`);
|
|
36
36
|
}
|
|
37
37
|
stringify(omitQuestionMark = false) {
|
|
38
|
-
const queryString = this.processedQuery.toString();
|
|
38
|
+
const queryString = this.processedQuery.toString().replace(/\+/g, '%20');
|
|
39
39
|
return omitQuestionMark ? queryString : `?${queryString}`;
|
|
40
40
|
}
|
|
41
41
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"processed-query.mjs","sources":["../../../../../../lib/utils/processed-query.ts"],"sourcesContent":["export default class ProcessedQuery {\n static stringify(keyValuePairs?: Record<string, any>): string {\n if (!keyValuePairs || Object.keys(keyValuePairs).length === 0) return '';\n\n return new ProcessedQuery().putAll(keyValuePairs).stringify();\n }\n\n processedQuery: URLSearchParams;\n\n constructor() {\n this.processedQuery = new URLSearchParams();\n }\n\n putAll(keyValuePairs: Record<string, any>): ProcessedQuery {\n Object.entries(keyValuePairs).forEach(([key, value]: [string, any]) =>\n this.put(key, value),\n );\n return this;\n }\n\n put(key: string, value: any): void {\n if (Array.isArray(value)) {\n this.putArray(key, value);\n } else if (value?.constructor === Object) {\n this.putObject(key, value);\n } else {\n this.putSimple(key, value);\n }\n }\n\n putArray(key: string, value: (string | number)[]): void {\n value.forEach((arrayValue) =>\n this.processedQuery.append(`${key}[]`, `${arrayValue}`),\n );\n }\n\n putObject(key: string, value: object): void {\n Object.entries(value).forEach(\n ([entry, entryValue]: [string, string | number]) => {\n this.processedQuery.append(`${key}[${entry}]`, `${entryValue}`);\n },\n );\n }\n\n putSimple(key: string, value: string | number): void {\n this.processedQuery.append(key, `${value}`);\n }\n\n stringify(omitQuestionMark = false): string {\n const queryString = this.processedQuery.toString();\n return omitQuestionMark ? queryString : `?${queryString}`;\n }\n}\n"],"names":[],"mappings":"AAAc,MAAO,cAAc,CAAA;IACjC,OAAO,SAAS,CAAC,aAAmC,EAAA;AAClD,QAAA,IAAI,CAAC,aAAa,IAAI,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,MAAM,KAAK,CAAC;AAAE,YAAA,OAAO,EAAE;QAExE,OAAO,IAAI,cAAc,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,SAAS,EAAE;IAC/D;AAEA,IAAA,cAAc;AAEd,IAAA,WAAA,GAAA;AACE,QAAA,IAAI,CAAC,cAAc,GAAG,IAAI,eAAe,EAAE;IAC7C;AAEA,IAAA,MAAM,CAAC,aAAkC,EAAA;QACvC,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAgB,KAChE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CACrB;AACD,QAAA,OAAO,IAAI;IACb;IAEA,GAAG,CAAC,GAAW,EAAE,KAAU,EAAA;AACzB,QAAA,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;AACxB,YAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC;QAC3B;AAAO,aAAA,IAAI,KAAK,EAAE,WAAW,KAAK,MAAM,EAAE;AACxC,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC;QAC5B;aAAO;AACL,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC;QAC5B;IACF;IAEA,QAAQ,CAAC,GAAW,EAAE,KAA0B,EAAA;QAC9C,KAAK,CAAC,OAAO,CAAC,CAAC,UAAU,KACvB,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAA,EAAG,GAAG,CAAA,EAAA,CAAI,EAAE,GAAG,UAAU,CAAA,CAAE,CAAC,CACxD;IACH;IAEA,SAAS,CAAC,GAAW,EAAE,KAAa,EAAA;AAClC,QAAA,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,OAAO,CAC3B,CAAC,CAAC,KAAK,EAAE,UAAU,CAA4B,KAAI;AACjD,YAAA,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAA,EAAG,GAAG,CAAA,CAAA,EAAI,KAAK,GAAG,EAAE,CAAA,EAAG,UAAU,CAAA,CAAE,CAAC;AACjE,QAAA,CAAC,CACF;IACH;IAEA,SAAS,CAAC,GAAW,EAAE,KAAsB,EAAA;QAC3C,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG,EAAE,CAAA,EAAG,KAAK,CAAA,CAAE,CAAC;IAC7C;IAEA,SAAS,CAAC,gBAAgB,GAAG,KAAK,EAAA;
|
|
1
|
+
{"version":3,"file":"processed-query.mjs","sources":["../../../../../../lib/utils/processed-query.ts"],"sourcesContent":["export default class ProcessedQuery {\n static stringify(keyValuePairs?: Record<string, any>): string {\n if (!keyValuePairs || Object.keys(keyValuePairs).length === 0) return '';\n\n return new ProcessedQuery().putAll(keyValuePairs).stringify();\n }\n\n processedQuery: URLSearchParams;\n\n constructor() {\n this.processedQuery = new URLSearchParams();\n }\n\n putAll(keyValuePairs: Record<string, any>): ProcessedQuery {\n Object.entries(keyValuePairs).forEach(([key, value]: [string, any]) =>\n this.put(key, value),\n );\n return this;\n }\n\n put(key: string, value: any): void {\n if (Array.isArray(value)) {\n this.putArray(key, value);\n } else if (value?.constructor === Object) {\n this.putObject(key, value);\n } else {\n this.putSimple(key, value);\n }\n }\n\n putArray(key: string, value: (string | number)[]): void {\n value.forEach((arrayValue) =>\n this.processedQuery.append(`${key}[]`, `${arrayValue}`),\n );\n }\n\n putObject(key: string, value: object): void {\n Object.entries(value).forEach(\n ([entry, entryValue]: [string, string | number]) => {\n this.processedQuery.append(`${key}[${entry}]`, `${entryValue}`);\n },\n );\n }\n\n putSimple(key: string, value: string | number): void {\n this.processedQuery.append(key, `${value}`);\n }\n\n stringify(omitQuestionMark = false): string {\n const queryString = this.processedQuery.toString().replace(/\\+/g, '%20');\n return omitQuestionMark ? queryString : `?${queryString}`;\n }\n}\n"],"names":[],"mappings":"AAAc,MAAO,cAAc,CAAA;IACjC,OAAO,SAAS,CAAC,aAAmC,EAAA;AAClD,QAAA,IAAI,CAAC,aAAa,IAAI,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,MAAM,KAAK,CAAC;AAAE,YAAA,OAAO,EAAE;QAExE,OAAO,IAAI,cAAc,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,SAAS,EAAE;IAC/D;AAEA,IAAA,cAAc;AAEd,IAAA,WAAA,GAAA;AACE,QAAA,IAAI,CAAC,cAAc,GAAG,IAAI,eAAe,EAAE;IAC7C;AAEA,IAAA,MAAM,CAAC,aAAkC,EAAA;QACvC,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAgB,KAChE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CACrB;AACD,QAAA,OAAO,IAAI;IACb;IAEA,GAAG,CAAC,GAAW,EAAE,KAAU,EAAA;AACzB,QAAA,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;AACxB,YAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC;QAC3B;AAAO,aAAA,IAAI,KAAK,EAAE,WAAW,KAAK,MAAM,EAAE;AACxC,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC;QAC5B;aAAO;AACL,YAAA,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC;QAC5B;IACF;IAEA,QAAQ,CAAC,GAAW,EAAE,KAA0B,EAAA;QAC9C,KAAK,CAAC,OAAO,CAAC,CAAC,UAAU,KACvB,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAA,EAAG,GAAG,CAAA,EAAA,CAAI,EAAE,GAAG,UAAU,CAAA,CAAE,CAAC,CACxD;IACH;IAEA,SAAS,CAAC,GAAW,EAAE,KAAa,EAAA;AAClC,QAAA,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,OAAO,CAC3B,CAAC,CAAC,KAAK,EAAE,UAAU,CAA4B,KAAI;AACjD,YAAA,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAA,EAAG,GAAG,CAAA,CAAA,EAAI,KAAK,GAAG,EAAE,CAAA,EAAG,UAAU,CAAA,CAAE,CAAC;AACjE,QAAA,CAAC,CACF;IACH;IAEA,SAAS,CAAC,GAAW,EAAE,KAAsB,EAAA;QAC3C,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG,EAAE,CAAA,EAAG,KAAK,CAAA,CAAE,CAAC;IAC7C;IAEA,SAAS,CAAC,gBAAgB,GAAG,KAAK,EAAA;AAChC,QAAA,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;QACxE,OAAO,gBAAgB,GAAG,WAAW,GAAG,CAAA,CAAA,EAAI,WAAW,CAAA,CAAE;IAC3D;AACD;;;;"}
|
package/dist/esm/lib/version.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.mjs","sources":["../../../../../lib/version.ts"],"sourcesContent":["export const SHOPIFY_API_LIBRARY_VERSION = '
|
|
1
|
+
{"version":3,"file":"version.mjs","sources":["../../../../../lib/version.ts"],"sourcesContent":["export const SHOPIFY_API_LIBRARY_VERSION = '14.0.0';\n"],"names":[],"mappings":"AAAO,MAAM,2BAA2B,GAAG;;;;"}
|
|
@@ -78,9 +78,9 @@ async function callWebhookHandlers(config, webhookRegistry, webhookCheck, rawBod
|
|
|
78
78
|
response,
|
|
79
79
|
});
|
|
80
80
|
}
|
|
81
|
-
const { webhookId
|
|
81
|
+
const { webhookId } = webhookCheck;
|
|
82
82
|
try {
|
|
83
|
-
await handler.callback(webhookCheck.topic, webhookCheck.domain, rawBody, webhookId, webhookCheck.apiVersion,
|
|
83
|
+
await handler.callback(webhookCheck.topic, webhookCheck.domain, rawBody, webhookId, webhookCheck.apiVersion, context);
|
|
84
84
|
}
|
|
85
85
|
catch (error) {
|
|
86
86
|
response.statusCode = StatusCode.InternalServerError;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process.mjs","sources":["../../../../../../lib/webhooks/process.ts"],"sourcesContent":["import {StatusCode} from '../types';\nimport {\n abstractConvertResponse,\n AdapterResponse,\n isOK,\n NormalizedResponse,\n} from '../../runtime/http';\nimport {ConfigInterface} from '../base-types';\nimport * as ShopifyErrors from '../error';\nimport {logger} from '../logger';\n\nimport {\n DeliveryMethod,\n HttpWebhookHandlerWithCallback,\n WebhookProcessParams,\n WebhookRegistry,\n WebhookType,\n WebhookValidationErrorReason,\n WebhookValidationInvalid,\n WebhookValidationMissingHeaders,\n WebhookValidationValid,\n} from './types';\nimport {validateFactory} from './validate';\n\ninterface HandlerCallResult {\n statusCode: StatusCode;\n errorMessage?: string;\n}\n\ninterface ErrorCallResult {\n statusCode: StatusCode;\n errorMessage: string;\n}\n\nconst STATUS_TEXT_LOOKUP: Record<string, string> = {\n [StatusCode.Ok]: 'OK',\n [StatusCode.BadRequest]: 'Bad Request',\n [StatusCode.Unauthorized]: 'Unauthorized',\n [StatusCode.NotFound]: 'Not Found',\n [StatusCode.InternalServerError]: 'Internal Server Error',\n};\n\nexport function process(\n config: ConfigInterface,\n webhookRegistry: WebhookRegistry<HttpWebhookHandlerWithCallback>,\n) {\n return async function process({\n context,\n rawBody,\n ...adapterArgs\n }: WebhookProcessParams): Promise<AdapterResponse> {\n const response: NormalizedResponse = {\n statusCode: StatusCode.Ok,\n statusText: STATUS_TEXT_LOOKUP[StatusCode.Ok],\n headers: {},\n };\n\n await logger(config).info('Receiving webhook request');\n\n const webhookCheck = await validateFactory(config)({\n rawBody,\n ...adapterArgs,\n });\n\n let errorMessage = 'Unknown error while handling webhook';\n if (webhookCheck.valid) {\n const handlerResult = await callWebhookHandlers(\n config,\n webhookRegistry,\n webhookCheck,\n rawBody,\n context,\n );\n\n response.statusCode = handlerResult.statusCode;\n if (!isOK(response)) {\n errorMessage = handlerResult.errorMessage || errorMessage;\n }\n } else {\n const errorResult = await handleInvalidWebhook(config, webhookCheck);\n\n response.statusCode = errorResult.statusCode;\n response.statusText = STATUS_TEXT_LOOKUP[response.statusCode];\n errorMessage = errorResult.errorMessage;\n }\n\n const returnResponse = await abstractConvertResponse(response, adapterArgs);\n if (!isOK(response)) {\n throw new ShopifyErrors.InvalidWebhookError({\n message: errorMessage,\n response: returnResponse,\n });\n }\n\n return Promise.resolve(returnResponse);\n };\n}\n\nasync function callWebhookHandlers(\n config: ConfigInterface,\n webhookRegistry: WebhookRegistry<HttpWebhookHandlerWithCallback>,\n webhookCheck: WebhookValidationValid,\n rawBody: string,\n context: any,\n): Promise<HandlerCallResult> {\n const log = logger(config);\n const {hmac: _hmac, valid: _valid, ...loggingContext} = webhookCheck;\n\n await log.debug(\n 'Webhook request is valid, looking for HTTP handlers to call',\n loggingContext,\n );\n\n const handlers = webhookRegistry[webhookCheck.topic] || [];\n\n const response: HandlerCallResult = {statusCode: StatusCode.Ok};\n\n let found = false;\n for (const handler of handlers) {\n if (handler.deliveryMethod !== DeliveryMethod.Http) {\n continue;\n }\n if (!handler.callback) {\n response.statusCode = StatusCode.InternalServerError;\n response.errorMessage =\n \"Cannot call webhooks.process with a webhook handler that doesn't have a callback\";\n\n throw new ShopifyErrors.MissingWebhookCallbackError({\n message: response.errorMessage,\n response,\n });\n }\n\n found = true;\n\n await log.debug('Found HTTP handler, triggering it', loggingContext);\n\n // process() only handles programmatically-registered HTTP webhooks;\n // events are registered via app TOML and don't use this code path.\n if (webhookCheck.webhookType !== WebhookType.Webhooks) {\n throw new ShopifyErrors.InvalidWebhookError({\n message: 'process() only supports traditional webhooks, not events',\n response,\n });\n }\n const {webhookId, subTopic} = webhookCheck;\n\n try {\n await handler.callback(\n webhookCheck.topic,\n webhookCheck.domain,\n rawBody,\n webhookId,\n webhookCheck.apiVersion,\n ...(subTopic ? subTopic : ''),\n context,\n );\n } catch (error) {\n response.statusCode = StatusCode.InternalServerError;\n response.errorMessage = error.message;\n }\n }\n\n if (!found) {\n await log.debug('No HTTP handlers found', loggingContext);\n\n response.statusCode = StatusCode.NotFound;\n response.errorMessage = `No HTTP webhooks registered for topic ${webhookCheck.topic}`;\n }\n\n return response;\n}\n\nasync function handleInvalidWebhook(\n config: ConfigInterface,\n webhookCheck: WebhookValidationInvalid,\n): Promise<ErrorCallResult> {\n const response: ErrorCallResult = {\n statusCode: StatusCode.InternalServerError,\n errorMessage: 'Unknown error while handling webhook',\n };\n\n switch (webhookCheck.reason) {\n case WebhookValidationErrorReason.MissingHeaders:\n response.statusCode = StatusCode.BadRequest;\n response.errorMessage = `Missing one or more of the required HTTP headers to process webhooks: [${(\n webhookCheck as WebhookValidationMissingHeaders\n ).missingHeaders.join(', ')}]`;\n break;\n case WebhookValidationErrorReason.MissingBody:\n response.statusCode = StatusCode.BadRequest;\n response.errorMessage = 'No body was received when processing webhook';\n break;\n case WebhookValidationErrorReason.MissingHmac:\n response.statusCode = StatusCode.BadRequest;\n response.errorMessage = `Missing HMAC header in request`;\n break;\n case WebhookValidationErrorReason.InvalidHmac:\n response.statusCode = StatusCode.Unauthorized;\n response.errorMessage = `Could not validate request HMAC`;\n break;\n }\n\n await logger(config).debug(\n `Webhook request is invalid, returning ${response.statusCode}: ${response.errorMessage}`,\n );\n\n return response;\n}\n"],"names":["ShopifyErrors.InvalidWebhookError","ShopifyErrors.MissingWebhookCallbackError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"process.mjs","sources":["../../../../../../lib/webhooks/process.ts"],"sourcesContent":["import {StatusCode} from '../types';\nimport {\n abstractConvertResponse,\n AdapterResponse,\n isOK,\n NormalizedResponse,\n} from '../../runtime/http';\nimport {ConfigInterface} from '../base-types';\nimport * as ShopifyErrors from '../error';\nimport {logger} from '../logger';\n\nimport {\n DeliveryMethod,\n HttpWebhookHandlerWithCallback,\n WebhookProcessParams,\n WebhookRegistry,\n WebhookType,\n WebhookValidationErrorReason,\n WebhookValidationInvalid,\n WebhookValidationMissingHeaders,\n WebhookValidationValid,\n} from './types';\nimport {validateFactory} from './validate';\n\ninterface HandlerCallResult {\n statusCode: StatusCode;\n errorMessage?: string;\n}\n\ninterface ErrorCallResult {\n statusCode: StatusCode;\n errorMessage: string;\n}\n\nconst STATUS_TEXT_LOOKUP: Record<string, string> = {\n [StatusCode.Ok]: 'OK',\n [StatusCode.BadRequest]: 'Bad Request',\n [StatusCode.Unauthorized]: 'Unauthorized',\n [StatusCode.NotFound]: 'Not Found',\n [StatusCode.InternalServerError]: 'Internal Server Error',\n};\n\nexport function process(\n config: ConfigInterface,\n webhookRegistry: WebhookRegistry<HttpWebhookHandlerWithCallback>,\n) {\n return async function process({\n context,\n rawBody,\n ...adapterArgs\n }: WebhookProcessParams): Promise<AdapterResponse> {\n const response: NormalizedResponse = {\n statusCode: StatusCode.Ok,\n statusText: STATUS_TEXT_LOOKUP[StatusCode.Ok],\n headers: {},\n };\n\n await logger(config).info('Receiving webhook request');\n\n const webhookCheck = await validateFactory(config)({\n rawBody,\n ...adapterArgs,\n });\n\n let errorMessage = 'Unknown error while handling webhook';\n if (webhookCheck.valid) {\n const handlerResult = await callWebhookHandlers(\n config,\n webhookRegistry,\n webhookCheck,\n rawBody,\n context,\n );\n\n response.statusCode = handlerResult.statusCode;\n if (!isOK(response)) {\n errorMessage = handlerResult.errorMessage || errorMessage;\n }\n } else {\n const errorResult = await handleInvalidWebhook(config, webhookCheck);\n\n response.statusCode = errorResult.statusCode;\n response.statusText = STATUS_TEXT_LOOKUP[response.statusCode];\n errorMessage = errorResult.errorMessage;\n }\n\n const returnResponse = await abstractConvertResponse(response, adapterArgs);\n if (!isOK(response)) {\n throw new ShopifyErrors.InvalidWebhookError({\n message: errorMessage,\n response: returnResponse,\n });\n }\n\n return Promise.resolve(returnResponse);\n };\n}\n\nasync function callWebhookHandlers(\n config: ConfigInterface,\n webhookRegistry: WebhookRegistry<HttpWebhookHandlerWithCallback>,\n webhookCheck: WebhookValidationValid,\n rawBody: string,\n context: any,\n): Promise<HandlerCallResult> {\n const log = logger(config);\n const {hmac: _hmac, valid: _valid, ...loggingContext} = webhookCheck;\n\n await log.debug(\n 'Webhook request is valid, looking for HTTP handlers to call',\n loggingContext,\n );\n\n const handlers = webhookRegistry[webhookCheck.topic] || [];\n\n const response: HandlerCallResult = {statusCode: StatusCode.Ok};\n\n let found = false;\n for (const handler of handlers) {\n if (handler.deliveryMethod !== DeliveryMethod.Http) {\n continue;\n }\n if (!handler.callback) {\n response.statusCode = StatusCode.InternalServerError;\n response.errorMessage =\n \"Cannot call webhooks.process with a webhook handler that doesn't have a callback\";\n\n throw new ShopifyErrors.MissingWebhookCallbackError({\n message: response.errorMessage,\n response,\n });\n }\n\n found = true;\n\n await log.debug('Found HTTP handler, triggering it', loggingContext);\n\n // process() only handles programmatically-registered HTTP webhooks;\n // events are registered via app TOML and don't use this code path.\n if (webhookCheck.webhookType !== WebhookType.Webhooks) {\n throw new ShopifyErrors.InvalidWebhookError({\n message: 'process() only supports traditional webhooks, not events',\n response,\n });\n }\n const {webhookId} = webhookCheck;\n\n try {\n await handler.callback(\n webhookCheck.topic,\n webhookCheck.domain,\n rawBody,\n webhookId,\n webhookCheck.apiVersion,\n context,\n );\n } catch (error) {\n response.statusCode = StatusCode.InternalServerError;\n response.errorMessage = error.message;\n }\n }\n\n if (!found) {\n await log.debug('No HTTP handlers found', loggingContext);\n\n response.statusCode = StatusCode.NotFound;\n response.errorMessage = `No HTTP webhooks registered for topic ${webhookCheck.topic}`;\n }\n\n return response;\n}\n\nasync function handleInvalidWebhook(\n config: ConfigInterface,\n webhookCheck: WebhookValidationInvalid,\n): Promise<ErrorCallResult> {\n const response: ErrorCallResult = {\n statusCode: StatusCode.InternalServerError,\n errorMessage: 'Unknown error while handling webhook',\n };\n\n switch (webhookCheck.reason) {\n case WebhookValidationErrorReason.MissingHeaders:\n response.statusCode = StatusCode.BadRequest;\n response.errorMessage = `Missing one or more of the required HTTP headers to process webhooks: [${(\n webhookCheck as WebhookValidationMissingHeaders\n ).missingHeaders.join(', ')}]`;\n break;\n case WebhookValidationErrorReason.MissingBody:\n response.statusCode = StatusCode.BadRequest;\n response.errorMessage = 'No body was received when processing webhook';\n break;\n case WebhookValidationErrorReason.MissingHmac:\n response.statusCode = StatusCode.BadRequest;\n response.errorMessage = `Missing HMAC header in request`;\n break;\n case WebhookValidationErrorReason.InvalidHmac:\n response.statusCode = StatusCode.Unauthorized;\n response.errorMessage = `Could not validate request HMAC`;\n break;\n }\n\n await logger(config).debug(\n `Webhook request is invalid, returning ${response.statusCode}: ${response.errorMessage}`,\n );\n\n return response;\n}\n"],"names":["ShopifyErrors.InvalidWebhookError","ShopifyErrors.MissingWebhookCallbackError"],"mappings":";;;;;;;AAkCA,MAAM,kBAAkB,GAA2B;AACjD,IAAA,CAAC,UAAU,CAAC,EAAE,GAAG,IAAI;AACrB,IAAA,CAAC,UAAU,CAAC,UAAU,GAAG,aAAa;AACtC,IAAA,CAAC,UAAU,CAAC,YAAY,GAAG,cAAc;AACzC,IAAA,CAAC,UAAU,CAAC,QAAQ,GAAG,WAAW;AAClC,IAAA,CAAC,UAAU,CAAC,mBAAmB,GAAG,uBAAuB;CAC1D;AAEK,SAAU,OAAO,CACrB,MAAuB,EACvB,eAAgE,EAAA;IAEhE,OAAO,eAAe,OAAO,CAAC,EAC5B,OAAO,EACP,OAAO,EACP,GAAG,WAAW,EACO,EAAA;AACrB,QAAA,MAAM,QAAQ,GAAuB;YACnC,UAAU,EAAE,UAAU,CAAC,EAAE;AACzB,YAAA,UAAU,EAAE,kBAAkB,CAAC,UAAU,CAAC,EAAE,CAAC;AAC7C,YAAA,OAAO,EAAE,EAAE;SACZ;QAED,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,2BAA2B,CAAC;AAEtD,QAAA,MAAM,YAAY,GAAG,MAAM,eAAe,CAAC,MAAM,CAAC,CAAC;YACjD,OAAO;AACP,YAAA,GAAG,WAAW;AACf,SAAA,CAAC;QAEF,IAAI,YAAY,GAAG,sCAAsC;AACzD,QAAA,IAAI,YAAY,CAAC,KAAK,EAAE;AACtB,YAAA,MAAM,aAAa,GAAG,MAAM,mBAAmB,CAC7C,MAAM,EACN,eAAe,EACf,YAAY,EACZ,OAAO,EACP,OAAO,CACR;AAED,YAAA,QAAQ,CAAC,UAAU,GAAG,aAAa,CAAC,UAAU;AAC9C,YAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;AACnB,gBAAA,YAAY,GAAG,aAAa,CAAC,YAAY,IAAI,YAAY;YAC3D;QACF;aAAO;YACL,MAAM,WAAW,GAAG,MAAM,oBAAoB,CAAC,MAAM,EAAE,YAAY,CAAC;AAEpE,YAAA,QAAQ,CAAC,UAAU,GAAG,WAAW,CAAC,UAAU;YAC5C,QAAQ,CAAC,UAAU,GAAG,kBAAkB,CAAC,QAAQ,CAAC,UAAU,CAAC;AAC7D,YAAA,YAAY,GAAG,WAAW,CAAC,YAAY;QACzC;QAEA,MAAM,cAAc,GAAG,MAAM,uBAAuB,CAAC,QAAQ,EAAE,WAAW,CAAC;AAC3E,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;AACnB,YAAA,MAAM,IAAIA,mBAAiC,CAAC;AAC1C,gBAAA,OAAO,EAAE,YAAY;AACrB,gBAAA,QAAQ,EAAE,cAAc;AACzB,aAAA,CAAC;QACJ;AAEA,QAAA,OAAO,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC;AACxC,IAAA,CAAC;AACH;AAEA,eAAe,mBAAmB,CAChC,MAAuB,EACvB,eAAgE,EAChE,YAAoC,EACpC,OAAe,EACf,OAAY,EAAA;AAEZ,IAAA,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC;AAC1B,IAAA,MAAM,EAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,cAAc,EAAC,GAAG,YAAY;IAEpE,MAAM,GAAG,CAAC,KAAK,CACb,6DAA6D,EAC7D,cAAc,CACf;IAED,MAAM,QAAQ,GAAG,eAAe,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE;IAE1D,MAAM,QAAQ,GAAsB,EAAC,UAAU,EAAE,UAAU,CAAC,EAAE,EAAC;IAE/D,IAAI,KAAK,GAAG,KAAK;AACjB,IAAA,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;QAC9B,IAAI,OAAO,CAAC,cAAc,KAAK,cAAc,CAAC,IAAI,EAAE;YAClD;QACF;AACA,QAAA,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE;AACrB,YAAA,QAAQ,CAAC,UAAU,GAAG,UAAU,CAAC,mBAAmB;AACpD,YAAA,QAAQ,CAAC,YAAY;AACnB,gBAAA,kFAAkF;AAEpF,YAAA,MAAM,IAAIC,2BAAyC,CAAC;gBAClD,OAAO,EAAE,QAAQ,CAAC,YAAY;gBAC9B,QAAQ;AACT,aAAA,CAAC;QACJ;QAEA,KAAK,GAAG,IAAI;QAEZ,MAAM,GAAG,CAAC,KAAK,CAAC,mCAAmC,EAAE,cAAc,CAAC;;;QAIpE,IAAI,YAAY,CAAC,WAAW,KAAK,WAAW,CAAC,QAAQ,EAAE;AACrD,YAAA,MAAM,IAAID,mBAAiC,CAAC;AAC1C,gBAAA,OAAO,EAAE,0DAA0D;gBACnE,QAAQ;AACT,aAAA,CAAC;QACJ;AACA,QAAA,MAAM,EAAC,SAAS,EAAC,GAAG,YAAY;AAEhC,QAAA,IAAI;YACF,MAAM,OAAO,CAAC,QAAQ,CACpB,YAAY,CAAC,KAAK,EAClB,YAAY,CAAC,MAAM,EACnB,OAAO,EACP,SAAS,EACT,YAAY,CAAC,UAAU,EACvB,OAAO,CACR;QACH;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,QAAQ,CAAC,UAAU,GAAG,UAAU,CAAC,mBAAmB;AACpD,YAAA,QAAQ,CAAC,YAAY,GAAG,KAAK,CAAC,OAAO;QACvC;IACF;IAEA,IAAI,CAAC,KAAK,EAAE;QACV,MAAM,GAAG,CAAC,KAAK,CAAC,wBAAwB,EAAE,cAAc,CAAC;AAEzD,QAAA,QAAQ,CAAC,UAAU,GAAG,UAAU,CAAC,QAAQ;QACzC,QAAQ,CAAC,YAAY,GAAG,CAAA,sCAAA,EAAyC,YAAY,CAAC,KAAK,EAAE;IACvF;AAEA,IAAA,OAAO,QAAQ;AACjB;AAEA,eAAe,oBAAoB,CACjC,MAAuB,EACvB,YAAsC,EAAA;AAEtC,IAAA,MAAM,QAAQ,GAAoB;QAChC,UAAU,EAAE,UAAU,CAAC,mBAAmB;AAC1C,QAAA,YAAY,EAAE,sCAAsC;KACrD;AAED,IAAA,QAAQ,YAAY,CAAC,MAAM;QACzB,KAAK,4BAA4B,CAAC,cAAc;AAC9C,YAAA,QAAQ,CAAC,UAAU,GAAG,UAAU,CAAC,UAAU;AAC3C,YAAA,QAAQ,CAAC,YAAY,GAAG,CAAA,uEAAA,EACtB,YACD,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;YAC9B;QACF,KAAK,4BAA4B,CAAC,WAAW;AAC3C,YAAA,QAAQ,CAAC,UAAU,GAAG,UAAU,CAAC,UAAU;AAC3C,YAAA,QAAQ,CAAC,YAAY,GAAG,8CAA8C;YACtE;QACF,KAAK,4BAA4B,CAAC,WAAW;AAC3C,YAAA,QAAQ,CAAC,UAAU,GAAG,UAAU,CAAC,UAAU;AAC3C,YAAA,QAAQ,CAAC,YAAY,GAAG,CAAA,8BAAA,CAAgC;YACxD;QACF,KAAK,4BAA4B,CAAC,WAAW;AAC3C,YAAA,QAAQ,CAAC,UAAU,GAAG,UAAU,CAAC,YAAY;AAC7C,YAAA,QAAQ,CAAC,YAAY,GAAG,CAAA,+BAAA,CAAiC;YACzD;;AAGJ,IAAA,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,CACxB,CAAA,sCAAA,EAAyC,QAAQ,CAAC,UAAU,CAAA,EAAA,EAAK,QAAQ,CAAC,YAAY,CAAA,CAAE,CACzF;AAED,IAAA,OAAO,QAAQ;AACjB;;;;"}
|
|
@@ -248,10 +248,6 @@ function buildMutation(config, topic, handler, operation) {
|
|
|
248
248
|
if (handler.metafieldNamespaces) {
|
|
249
249
|
params.metafieldNamespaces = JSON.stringify(handler.metafieldNamespaces);
|
|
250
250
|
}
|
|
251
|
-
if (handler.subTopic) {
|
|
252
|
-
const subTopicString = `subTopic: "${handler.subTopic}",`;
|
|
253
|
-
mutationArguments.MUTATION_PARAMS = subTopicString;
|
|
254
|
-
}
|
|
255
251
|
const paramsString = Object.entries(params)
|
|
256
252
|
.map(([key, value]) => `${key}: ${value}`)
|
|
257
253
|
.join(', ');
|