@shopify/shopify-app-remix 4.2.0 → 4.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/dist/cjs/react/components/AppProvider/AppProvider.js.map +1 -1
  2. package/dist/cjs/react/components/AppProxyForm/AppProxyForm.js +4 -3
  3. package/dist/cjs/react/components/AppProxyForm/AppProxyForm.js.map +1 -1
  4. package/dist/cjs/react/components/AppProxyLink/AppProxyLink.js +4 -3
  5. package/dist/cjs/react/components/AppProxyLink/AppProxyLink.js.map +1 -1
  6. package/dist/cjs/react/components/AppProxyProvider/AppProxyProvider.js.map +1 -1
  7. package/dist/cjs/server/authenticate/admin/helpers/redirect.js +2 -2
  8. package/dist/cjs/server/authenticate/admin/helpers/redirect.js.map +1 -1
  9. package/dist/cjs/server/authenticate/webhooks/authenticate.js +1 -1
  10. package/dist/cjs/server/authenticate/webhooks/authenticate.js.map +1 -1
  11. package/dist/cjs/server/future/flags.js.map +1 -1
  12. package/dist/cjs/server/shopify-app.js +1 -0
  13. package/dist/cjs/server/shopify-app.js.map +1 -1
  14. package/dist/cjs/server/version.js +1 -1
  15. package/dist/cjs/server/version.js.map +1 -1
  16. package/dist/esm/react/components/AppProvider/AppProvider.mjs.map +1 -1
  17. package/dist/esm/react/components/AppProxyForm/AppProxyForm.mjs +5 -4
  18. package/dist/esm/react/components/AppProxyForm/AppProxyForm.mjs.map +1 -1
  19. package/dist/esm/react/components/AppProxyLink/AppProxyLink.mjs +5 -4
  20. package/dist/esm/react/components/AppProxyLink/AppProxyLink.mjs.map +1 -1
  21. package/dist/esm/react/components/AppProxyProvider/AppProxyProvider.mjs.map +1 -1
  22. package/dist/esm/server/authenticate/admin/helpers/redirect.mjs +2 -2
  23. package/dist/esm/server/authenticate/admin/helpers/redirect.mjs.map +1 -1
  24. package/dist/esm/server/authenticate/webhooks/authenticate.mjs +1 -1
  25. package/dist/esm/server/authenticate/webhooks/authenticate.mjs.map +1 -1
  26. package/dist/esm/server/future/flags.mjs.map +1 -1
  27. package/dist/esm/server/shopify-app.mjs +1 -0
  28. package/dist/esm/server/shopify-app.mjs.map +1 -1
  29. package/dist/esm/server/version.mjs +1 -1
  30. package/dist/esm/server/version.mjs.map +1 -1
  31. package/dist/ts/react/components/AppProvider/AppProvider.d.ts +5 -1
  32. package/dist/ts/react/components/AppProvider/AppProvider.d.ts.map +1 -1
  33. package/dist/ts/react/components/AppProxyForm/AppProxyForm.d.ts +2 -1
  34. package/dist/ts/react/components/AppProxyForm/AppProxyForm.d.ts.map +1 -1
  35. package/dist/ts/react/components/AppProxyLink/AppProxyLink.d.ts +2 -1
  36. package/dist/ts/react/components/AppProxyLink/AppProxyLink.d.ts.map +1 -1
  37. package/dist/ts/react/components/AppProxyProvider/AppProxyProvider.d.ts +5 -1
  38. package/dist/ts/react/components/AppProxyProvider/AppProxyProvider.d.ts.map +1 -1
  39. package/dist/ts/server/authenticate/admin/billing/types.d.ts +4 -0
  40. package/dist/ts/server/authenticate/admin/billing/types.d.ts.map +1 -1
  41. package/dist/ts/server/authenticate/admin/scope/types.d.ts +2 -1
  42. package/dist/ts/server/authenticate/admin/scope/types.d.ts.map +1 -1
  43. package/dist/ts/server/authenticate/admin/types.d.ts +10 -0
  44. package/dist/ts/server/authenticate/admin/types.d.ts.map +1 -1
  45. package/dist/ts/server/authenticate/flow/types.d.ts +4 -0
  46. package/dist/ts/server/authenticate/flow/types.d.ts.map +1 -1
  47. package/dist/ts/server/authenticate/fulfillment-service/types.d.ts +4 -0
  48. package/dist/ts/server/authenticate/fulfillment-service/types.d.ts.map +1 -1
  49. package/dist/ts/server/authenticate/public/appProxy/types.d.ts +4 -0
  50. package/dist/ts/server/authenticate/public/appProxy/types.d.ts.map +1 -1
  51. package/dist/ts/server/authenticate/public/checkout/types.d.ts +4 -0
  52. package/dist/ts/server/authenticate/public/checkout/types.d.ts.map +1 -1
  53. package/dist/ts/server/authenticate/public/customer-account/types.d.ts +4 -0
  54. package/dist/ts/server/authenticate/public/customer-account/types.d.ts.map +1 -1
  55. package/dist/ts/server/authenticate/webhooks/types.d.ts +6 -5
  56. package/dist/ts/server/authenticate/webhooks/types.d.ts.map +1 -1
  57. package/dist/ts/server/boundary/error.d.ts +1 -1
  58. package/dist/ts/server/boundary/error.d.ts.map +1 -1
  59. package/dist/ts/server/clients/admin/types.d.ts +4 -0
  60. package/dist/ts/server/clients/admin/types.d.ts.map +1 -1
  61. package/dist/ts/server/clients/storefront/types.d.ts +4 -0
  62. package/dist/ts/server/clients/storefront/types.d.ts.map +1 -1
  63. package/dist/ts/server/future/flags.d.ts +6 -0
  64. package/dist/ts/server/future/flags.d.ts.map +1 -1
  65. package/dist/ts/server/shopify-app.d.ts +1 -0
  66. package/dist/ts/server/shopify-app.d.ts.map +1 -1
  67. package/dist/ts/server/unauthenticated/admin/types.d.ts +4 -0
  68. package/dist/ts/server/unauthenticated/admin/types.d.ts.map +1 -1
  69. package/dist/ts/server/unauthenticated/storefront/types.d.ts +4 -0
  70. package/dist/ts/server/unauthenticated/storefront/types.d.ts.map +1 -1
  71. package/dist/ts/server/version.d.ts +1 -1
  72. package/dist/tsconfig.build.tsbuildinfo +1 -1
  73. package/package.json +12 -12
  74. package/src/react/components/AppProvider/AppProvider.tsx +4 -0
  75. package/src/react/components/AppProxyForm/AppProxyForm.tsx +18 -15
  76. package/src/react/components/AppProxyLink/AppProxyLink.tsx +18 -15
  77. package/src/react/components/AppProxyProvider/AppProxyProvider.tsx +4 -0
  78. package/src/server/__test-helpers/setup-non-embedded-flow.ts +1 -1
  79. package/src/server/__test-helpers/sign-request-cookie.ts +21 -10
  80. package/src/server/authenticate/admin/billing/types.ts +4 -0
  81. package/src/server/authenticate/admin/helpers/redirect.ts +2 -2
  82. package/src/server/authenticate/admin/scope/types.ts +2 -1
  83. package/src/server/authenticate/admin/types.ts +10 -0
  84. package/src/server/authenticate/flow/types.ts +4 -0
  85. package/src/server/authenticate/fulfillment-service/types.ts +4 -0
  86. package/src/server/authenticate/public/appProxy/types.ts +4 -0
  87. package/src/server/authenticate/public/checkout/types.ts +4 -0
  88. package/src/server/authenticate/public/customer-account/types.ts +4 -0
  89. package/src/server/authenticate/webhooks/authenticate.ts +1 -1
  90. package/src/server/authenticate/webhooks/types.ts +6 -5
  91. package/src/server/clients/admin/types.ts +4 -0
  92. package/src/server/clients/storefront/types.ts +4 -0
  93. package/src/server/future/flags.ts +6 -0
  94. package/src/server/shopify-app.ts +1 -0
  95. package/src/server/unauthenticated/admin/types.ts +4 -0
  96. package/src/server/unauthenticated/storefront/types.ts +4 -0
  97. package/src/server/version.ts +1 -1
  98. package/dist/ts/react/components/AppProvider/AppProvider.doc.d.ts +0 -4
  99. package/dist/ts/react/components/AppProvider/AppProvider.doc.d.ts.map +0 -1
  100. package/dist/ts/react/components/AppProxyForm/AppProxyForm.doc.d.ts +0 -4
  101. package/dist/ts/react/components/AppProxyForm/AppProxyForm.doc.d.ts.map +0 -1
  102. package/dist/ts/react/components/AppProxyLink/AppProxyLink.doc.d.ts +0 -4
  103. package/dist/ts/react/components/AppProxyLink/AppProxyLink.doc.d.ts.map +0 -1
  104. package/dist/ts/react/components/AppProxyProvider/AppProxyProvider.doc.d.ts +0 -4
  105. package/dist/ts/react/components/AppProxyProvider/AppProxyProvider.doc.d.ts.map +0 -1
  106. package/dist/ts/server/authenticate/admin/authenticate.admin.doc.d.ts +0 -4
  107. package/dist/ts/server/authenticate/admin/authenticate.admin.doc.d.ts.map +0 -1
  108. package/dist/ts/server/authenticate/admin/billing/authenticate.admin.billing.doc.d.ts +0 -4
  109. package/dist/ts/server/authenticate/admin/billing/authenticate.admin.billing.doc.d.ts.map +0 -1
  110. package/dist/ts/server/authenticate/admin/scope/authenticate.admin.scopes.doc.d.ts +0 -4
  111. package/dist/ts/server/authenticate/admin/scope/authenticate.admin.scopes.doc.d.ts.map +0 -1
  112. package/dist/ts/server/authenticate/flow/authenticate.flow.doc.d.ts +0 -4
  113. package/dist/ts/server/authenticate/flow/authenticate.flow.doc.d.ts.map +0 -1
  114. package/dist/ts/server/authenticate/fulfillment-service/authenticate.fulfillment-service.doc.d.ts +0 -4
  115. package/dist/ts/server/authenticate/fulfillment-service/authenticate.fulfillment-service.doc.d.ts.map +0 -1
  116. package/dist/ts/server/authenticate/public/appProxy/authenticate.public.app-proxy.doc.d.ts +0 -4
  117. package/dist/ts/server/authenticate/public/appProxy/authenticate.public.app-proxy.doc.d.ts.map +0 -1
  118. package/dist/ts/server/authenticate/public/checkout/authenticate.public.checkout.doc.d.ts +0 -4
  119. package/dist/ts/server/authenticate/public/checkout/authenticate.public.checkout.doc.d.ts.map +0 -1
  120. package/dist/ts/server/authenticate/public/customer-account/authenticate.public.customerAccount.doc.d.ts +0 -4
  121. package/dist/ts/server/authenticate/public/customer-account/authenticate.public.customerAccount.doc.d.ts.map +0 -1
  122. package/dist/ts/server/authenticate/webhooks/authenticate.webhooks.doc.d.ts +0 -4
  123. package/dist/ts/server/authenticate/webhooks/authenticate.webhooks.doc.d.ts.map +0 -1
  124. package/dist/ts/server/clients/admin/authenticate.admin.api.doc.d.ts +0 -4
  125. package/dist/ts/server/clients/admin/authenticate.admin.api.doc.d.ts.map +0 -1
  126. package/dist/ts/server/clients/storefront/authenticate.storefront.api.doc.d.ts +0 -4
  127. package/dist/ts/server/clients/storefront/authenticate.storefront.api.doc.d.ts.map +0 -1
  128. package/dist/ts/server/shopify-app.doc.d.ts +0 -4
  129. package/dist/ts/server/shopify-app.doc.d.ts.map +0 -1
  130. package/dist/ts/server/unauthenticated/admin/unauthenticated.admin.doc.d.ts +0 -4
  131. package/dist/ts/server/unauthenticated/admin/unauthenticated.admin.doc.d.ts.map +0 -1
  132. package/dist/ts/server/unauthenticated/storefront/unauthenticated.storefront.doc.d.ts +0 -4
  133. package/dist/ts/server/unauthenticated/storefront/unauthenticated.storefront.doc.d.ts.map +0 -1
  134. package/src/react/components/AppProvider/AppProvider.doc.ts +0 -35
  135. package/src/react/components/AppProxyForm/AppProxyForm.doc.ts +0 -28
  136. package/src/react/components/AppProxyLink/AppProxyLink.doc.ts +0 -28
  137. package/src/react/components/AppProxyProvider/AppProxyProvider.doc.ts +0 -40
  138. package/src/server/authenticate/admin/authenticate.admin.doc.ts +0 -51
  139. package/src/server/authenticate/admin/billing/authenticate.admin.billing.doc.ts +0 -29
  140. package/src/server/authenticate/admin/scope/authenticate.admin.scopes.doc.ts +0 -28
  141. package/src/server/authenticate/flow/authenticate.flow.doc.ts +0 -47
  142. package/src/server/authenticate/fulfillment-service/authenticate.fulfillment-service.doc.ts +0 -48
  143. package/src/server/authenticate/public/appProxy/authenticate.public.app-proxy.doc.ts +0 -55
  144. package/src/server/authenticate/public/checkout/authenticate.public.checkout.doc.ts +0 -49
  145. package/src/server/authenticate/public/customer-account/authenticate.public.customerAccount.doc.ts +0 -49
  146. package/src/server/authenticate/webhooks/authenticate.webhooks.doc.ts +0 -39
  147. package/src/server/clients/admin/authenticate.admin.api.doc.ts +0 -34
  148. package/src/server/clients/storefront/authenticate.storefront.api.doc.ts +0 -34
  149. package/src/server/shopify-app.doc.ts +0 -45
  150. package/src/server/unauthenticated/admin/unauthenticated.admin.doc.ts +0 -40
  151. package/src/server/unauthenticated/storefront/unauthenticated.storefront.doc.ts +0 -40
@@ -1 +1 @@
1
- {"version":3,"file":"AppProvider.js","sources":["../../../../../../src/react/components/AppProvider/AppProvider.tsx"],"sourcesContent":["import {\n AppProvider as PolarisAppProvider,\n AppProviderProps as PolarisAppProviderProps,\n} from '@shopify/polaris';\n// This leads to some TS errors, but it does compile to something that works\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport englishI18n from '@shopify/polaris/locales/en.json' with {type: 'json'};\nimport {useNavigate} from '@remix-run/react';\nimport {useEffect} from 'react';\n\nimport {APP_BRIDGE_URL} from '../../const';\nimport {RemixPolarisLink} from '../RemixPolarisLink';\n\nexport interface AppProviderProps extends Omit<\n PolarisAppProviderProps,\n 'linkComponent' | 'i18n'\n> {\n /**\n * The API key for your Shopify app. This is the `Client ID` from the Partner Dashboard.\n *\n * When using the Shopify CLI, this is the `SHOPIFY_API_KEY` environment variable. If you're using the environment\n * variable, then you need to pass it from the loader to the component.\n */\n apiKey: string;\n /**\n * Whether the app is loaded inside the Shopify Admin. Default is `true`.\n *\n * {@link https://shopify.dev/docs/apps/admin/embedded-app-home}\n */\n isEmbeddedApp?: boolean;\n /**\n * The internationalization (i18n) configuration for your Polaris provider.\n *\n * {@link https://polaris.shopify.com/components/utilities/app-provider}\n */\n i18n?: PolarisAppProviderProps['i18n'];\n /**\n * Used internally by Shopify. You don't need to set this.\n * @private\n */\n __APP_BRIDGE_URL?: string;\n}\n\n/**\n * Sets up the Polaris `AppProvider` and injects the App Bridge script.\n *\n * This component extends the [`AppProvider`](https://polaris.shopify.com/components/utilities/app-provider) component\n * from Polaris, and accepts all of its props except for `linkComponent`, which is overridden to use the Remix `Link`\n * component.\n *\n * {@link https://polaris.shopify.com/components/utilities/app-provider}\n * {@link https://shopify.dev/tools/app-bridge}\n *\n * @example\n * <caption>Set up AppProvider.</caption>\n * <description>Wrap your app in the `AppProvider` component and pass in your API key.</description>\n * ```ts\n * // /app/routes/**\\/*.ts\n * import {authenticate} from '~/shopify.server';\n * import {AppProvider} from '@shopify/shopify-app-remix/react';\n *\n * export async function loader({ request }) {\n * await authenticate.admin(request);\n *\n * return json({ apiKey: process.env.SHOPIFY_API_KEY });\n * }\n *\n * export default function App() {\n * const { apiKey } = useLoaderData();\n *\n * return (\n * <AppProvider isEmbeddedApp apiKey={apiKey}>\n * <Outlet />\n * </AppProvider>\n * );\n * }\n * ```\n *\n * @example\n * <caption>Localize Polaris components.</caption>\n * <description>Pass in a different locale for Polaris to translate its components.</description>\n * ```ts\n * // /app/routes/**\\/*.ts\n * import {authenticate} from '~/shopify.server';\n * import {AppProvider} from '@shopify/shopify-app-remix/react';\n *\n * export async function loader({ request }) {\n * await authenticate.admin(request);\n *\n * return json({\n * apiKey: process.env.SHOPIFY_API_KEY,\n * polarisTranslations: require(\"@shopify/polaris/locales/fr.json\"),\n * });\n * }\n *\n * export default function App() {\n * const { apiKey, polarisTranslations } = useLoaderData();\n *\n * return (\n * <AppProvider apiKey={apiKey} i18n={polarisTranslations}>\n * <Outlet />\n * </AppProvider>\n * );\n * }\n * ```\n */\nexport function AppProvider(props: AppProviderProps) {\n const {\n children,\n apiKey,\n i18n,\n isEmbeddedApp = true,\n __APP_BRIDGE_URL = APP_BRIDGE_URL,\n ...polarisProps\n } = props;\n\n const navigate = useNavigate();\n\n useEffect(() => {\n const handleNavigate = (event: Event) => {\n const href = (event.target as HTMLElement)?.getAttribute('href');\n if (href) {\n navigate(href);\n }\n };\n\n addEventListener('shopify:navigate', handleNavigate);\n\n return () => {\n removeEventListener('shopify:navigate', handleNavigate);\n };\n }, [navigate]);\n\n return (\n <>\n {isEmbeddedApp && <script src={__APP_BRIDGE_URL} data-api-key={apiKey} />}\n <PolarisAppProvider\n {...polarisProps}\n linkComponent={RemixPolarisLink}\n i18n={i18n || englishI18n}\n >\n {children}\n </PolarisAppProvider>\n </>\n );\n}\n"],"names":["APP_BRIDGE_URL","useNavigate","useEffect","_jsxs","_Fragment","_jsx","PolarisAppProvider","RemixPolarisLink"],"mappings":";;;;;;;;;;AA4CA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8DG;AACG,SAAU,WAAW,CAAC,KAAuB,EAAA;IACjD,MAAM,EACJ,QAAQ,EACR,MAAM,EACN,IAAI,EACJ,aAAa,GAAG,IAAI,EACpB,gBAAgB,GAAGA,qBAAc,EACjC,GAAG,YAAY,EAChB,GAAG,KAAK;AAET,IAAA,MAAM,QAAQ,GAAGC,iBAAW,EAAE;IAE9BC,eAAS,CAAC,MAAK;AACb,QAAA,MAAM,cAAc,GAAG,CAAC,KAAY,KAAI;YACtC,MAAM,IAAI,GAAI,KAAK,CAAC,MAAsB,EAAE,YAAY,CAAC,MAAM,CAAC;YAChE,IAAI,IAAI,EAAE;gBACR,QAAQ,CAAC,IAAI,CAAC;YAChB;AACF,QAAA,CAAC;AAED,QAAA,gBAAgB,CAAC,kBAAkB,EAAE,cAAc,CAAC;AAEpD,QAAA,OAAO,MAAK;AACV,YAAA,mBAAmB,CAAC,kBAAkB,EAAE,cAAc,CAAC;AACzD,QAAA,CAAC;AACH,IAAA,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;AAEd,IAAA,QACEC,eAAA,CAAAC,mBAAA,EAAA,EAAA,QAAA,EAAA,CACG,aAAa,IAAIC,cAAA,CAAA,QAAA,EAAA,EAAQ,GAAG,EAAE,gBAAgB,EAAA,cAAA,EAAgB,MAAM,EAAA,CAAI,EACzEA,eAACC,mBAAkB,EAAA,EAAA,GACb,YAAY,EAChB,aAAa,EAAEC,iCAAgB,EAC/B,IAAI,EAAE,IAAI,IAAI,WAAW,EAAA,QAAA,EAExB,QAAQ,EAAA,CACU,CAAA,EAAA,CACpB;AAEP;;;;"}
1
+ {"version":3,"file":"AppProvider.js","sources":["../../../../../../src/react/components/AppProvider/AppProvider.tsx"],"sourcesContent":["import {\n AppProvider as PolarisAppProvider,\n AppProviderProps as PolarisAppProviderProps,\n} from '@shopify/polaris';\n// This leads to some TS errors, but it does compile to something that works\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport englishI18n from '@shopify/polaris/locales/en.json' with {type: 'json'};\nimport {useNavigate} from '@remix-run/react';\nimport {useEffect} from 'react';\n\nimport {APP_BRIDGE_URL} from '../../const';\nimport {RemixPolarisLink} from '../RemixPolarisLink';\n\n/**\n * Props for the `AppProvider` component.\n * @publicDocs\n */\nexport interface AppProviderProps extends Omit<\n PolarisAppProviderProps,\n 'linkComponent' | 'i18n'\n> {\n /**\n * The API key for your Shopify app. This is the `Client ID` from the Partner Dashboard.\n *\n * When using the Shopify CLI, this is the `SHOPIFY_API_KEY` environment variable. If you're using the environment\n * variable, then you need to pass it from the loader to the component.\n */\n apiKey: string;\n /**\n * Whether the app is loaded inside the Shopify Admin. Default is `true`.\n *\n * {@link https://shopify.dev/docs/apps/admin/embedded-app-home}\n */\n isEmbeddedApp?: boolean;\n /**\n * The internationalization (i18n) configuration for your Polaris provider.\n *\n * {@link https://polaris.shopify.com/components/utilities/app-provider}\n */\n i18n?: PolarisAppProviderProps['i18n'];\n /**\n * Used internally by Shopify. You don't need to set this.\n * @private\n */\n __APP_BRIDGE_URL?: string;\n}\n\n/**\n * Sets up the Polaris `AppProvider` and injects the App Bridge script.\n *\n * This component extends the [`AppProvider`](https://polaris.shopify.com/components/utilities/app-provider) component\n * from Polaris, and accepts all of its props except for `linkComponent`, which is overridden to use the Remix `Link`\n * component.\n *\n * {@link https://polaris.shopify.com/components/utilities/app-provider}\n * {@link https://shopify.dev/tools/app-bridge}\n *\n * @example\n * <caption>Set up AppProvider.</caption>\n * <description>Wrap your app in the `AppProvider` component and pass in your API key.</description>\n * ```ts\n * // /app/routes/**\\/*.ts\n * import {authenticate} from '~/shopify.server';\n * import {AppProvider} from '@shopify/shopify-app-remix/react';\n *\n * export async function loader({ request }) {\n * await authenticate.admin(request);\n *\n * return json({ apiKey: process.env.SHOPIFY_API_KEY });\n * }\n *\n * export default function App() {\n * const { apiKey } = useLoaderData();\n *\n * return (\n * <AppProvider isEmbeddedApp apiKey={apiKey}>\n * <Outlet />\n * </AppProvider>\n * );\n * }\n * ```\n *\n * @example\n * <caption>Localize Polaris components.</caption>\n * <description>Pass in a different locale for Polaris to translate its components.</description>\n * ```ts\n * // /app/routes/**\\/*.ts\n * import {authenticate} from '~/shopify.server';\n * import {AppProvider} from '@shopify/shopify-app-remix/react';\n *\n * export async function loader({ request }) {\n * await authenticate.admin(request);\n *\n * return json({\n * apiKey: process.env.SHOPIFY_API_KEY,\n * polarisTranslations: require(\"@shopify/polaris/locales/fr.json\"),\n * });\n * }\n *\n * export default function App() {\n * const { apiKey, polarisTranslations } = useLoaderData();\n *\n * return (\n * <AppProvider apiKey={apiKey} i18n={polarisTranslations}>\n * <Outlet />\n * </AppProvider>\n * );\n * }\n * ```\n */\nexport function AppProvider(props: AppProviderProps) {\n const {\n children,\n apiKey,\n i18n,\n isEmbeddedApp = true,\n __APP_BRIDGE_URL = APP_BRIDGE_URL,\n ...polarisProps\n } = props;\n\n const navigate = useNavigate();\n\n useEffect(() => {\n const handleNavigate = (event: Event) => {\n const href = (event.target as HTMLElement)?.getAttribute('href');\n if (href) {\n navigate(href);\n }\n };\n\n addEventListener('shopify:navigate', handleNavigate);\n\n return () => {\n removeEventListener('shopify:navigate', handleNavigate);\n };\n }, [navigate]);\n\n return (\n <>\n {isEmbeddedApp && <script src={__APP_BRIDGE_URL} data-api-key={apiKey} />}\n <PolarisAppProvider\n {...polarisProps}\n linkComponent={RemixPolarisLink}\n i18n={i18n || englishI18n}\n >\n {children}\n </PolarisAppProvider>\n </>\n );\n}\n"],"names":["APP_BRIDGE_URL","useNavigate","useEffect","_jsxs","_Fragment","_jsx","PolarisAppProvider","RemixPolarisLink"],"mappings":";;;;;;;;;;AAgDA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8DG;AACG,SAAU,WAAW,CAAC,KAAuB,EAAA;IACjD,MAAM,EACJ,QAAQ,EACR,MAAM,EACN,IAAI,EACJ,aAAa,GAAG,IAAI,EACpB,gBAAgB,GAAGA,qBAAc,EACjC,GAAG,YAAY,EAChB,GAAG,KAAK;AAET,IAAA,MAAM,QAAQ,GAAGC,iBAAW,EAAE;IAE9BC,eAAS,CAAC,MAAK;AACb,QAAA,MAAM,cAAc,GAAG,CAAC,KAAY,KAAI;YACtC,MAAM,IAAI,GAAI,KAAK,CAAC,MAAsB,EAAE,YAAY,CAAC,MAAM,CAAC;YAChE,IAAI,IAAI,EAAE;gBACR,QAAQ,CAAC,IAAI,CAAC;YAChB;AACF,QAAA,CAAC;AAED,QAAA,gBAAgB,CAAC,kBAAkB,EAAE,cAAc,CAAC;AAEpD,QAAA,OAAO,MAAK;AACV,YAAA,mBAAmB,CAAC,kBAAkB,EAAE,cAAc,CAAC;AACzD,QAAA,CAAC;AACH,IAAA,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;AAEd,IAAA,QACEC,eAAA,CAAAC,mBAAA,EAAA,EAAA,QAAA,EAAA,CACG,aAAa,IAAIC,cAAA,CAAA,QAAA,EAAA,EAAQ,GAAG,EAAE,gBAAgB,EAAA,cAAA,EAAgB,MAAM,EAAA,CAAI,EACzEA,eAACC,mBAAkB,EAAA,EAAA,GACb,YAAY,EAChB,aAAa,EAAEC,iCAAgB,EAC/B,IAAI,EAAE,IAAI,IAAI,WAAW,EAAA,QAAA,EAExB,QAAQ,EAAA,CACU,CAAA,EAAA,CACpB;AAEP;;;;"}
@@ -60,15 +60,16 @@ var AppProxyProvider = require('../AppProxyProvider/AppProxyProvider.js');
60
60
  * );
61
61
  * }
62
62
  * ```
63
+ * @publicDocs
63
64
  */
64
- function AppProxyForm(props) {
65
+ const AppProxyForm = React.forwardRef(function AppProxyForm(props, ref) {
65
66
  const context = React.useContext(AppProxyProvider.AppProxyProviderContext);
66
67
  if (!context) {
67
68
  throw new Error('AppProxyForm must be used within an AppProxyProvider component');
68
69
  }
69
70
  const { children, action, ...otherProps } = props;
70
- return (jsxRuntime.jsx(react.Form, { action: context.formatUrl(action, false), ...otherProps, children: children }));
71
- }
71
+ return (jsxRuntime.jsx(react.Form, { action: context.formatUrl(action, false), ...otherProps, ref: ref, children: children }));
72
+ });
72
73
 
73
74
  exports.AppProxyForm = AppProxyForm;
74
75
  //# sourceMappingURL=AppProxyForm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AppProxyForm.js","sources":["../../../../../../src/react/components/AppProxyForm/AppProxyForm.tsx"],"sourcesContent":["import {useContext} from 'react';\nimport {Form, type FormProps} from '@remix-run/react';\n\nimport {AppProxyProviderContext} from '../AppProxyProvider';\n\nexport interface AppProxyFormProps extends FormProps {\n action: string;\n}\n\n/**\n * Sets up a Remix `<Form>` component that works when rendered on an app proxy page.\n *\n * Supports any properties accepted by the `<Form>` component.\n *\n * Because Remix doesn't support URL rewriting, any route using this component should <b>match the pathname of the proxy\n * URL exactly</b>, and <b>end in a trailing slash</b> (e.g., `https://<shop>/apps/proxy/`), or set the Remix Form prop\n * `navigate` to `false`.\n *\n * @example\n * <caption>Render a form element in a proxied route.</caption>\n * <description>Use an `AppProxyForm` within an `AppProxy` to create a form.</description>\n * ```ts\n * // /app/routes/apps/appProxy.ts\n * import {\n * AppProxyProvider,\n * AppProxyForm,\n * } from \"@shopify/shopify-app-remix/react\";\n * import { authenticate } from \"~/shopify.server\";\n *\n * export async function loader({ request }) {\n * await authenticate.public.appProxy(request);\n *\n * return json({ appUrl: process.env.SHOPIFY_APP_URL });\n * }\n *\n * export async function action({ request }) {\n * await authenticate.public.appProxy(request);\n *\n * const formData = await request.formData();\n * const field = formData.get(\"field\")?.toString();\n *\n * // Perform actions\n * if (field) {\n * console.log(\"Field:\", field);\n * }\n *\n * // Return JSON to the client\n * return json({ message: \"Success!\" });\n * }\n *\n * export default function App() {\n * const { appUrl } = useLoaderData();\n *\n * return (\n * <AppProxyProvider appUrl={appUrl}>\n * <AppProxyForm action=\"/apps/appProxy\" method=\"post\">\n * <input type=\"text\" name=\"field\" />\n *\n * <input type=\"submit\" name=\"Submit\" />\n * </AppProxyForm>\n * </AppProxyProvider>\n * );\n * }\n * ```\n */\nexport function AppProxyForm(props: AppProxyFormProps) {\n const context = useContext(AppProxyProviderContext);\n\n if (!context) {\n throw new Error(\n 'AppProxyForm must be used within an AppProxyProvider component',\n );\n }\n\n const {children, action, ...otherProps} = props;\n\n return (\n <Form action={context.formatUrl(action, false)} {...otherProps}>\n {children}\n </Form>\n );\n}\n"],"names":["useContext","AppProxyProviderContext","_jsx","Form"],"mappings":";;;;;;;AASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuDG;AACG,SAAU,YAAY,CAAC,KAAwB,EAAA;AACnD,IAAA,MAAM,OAAO,GAAGA,gBAAU,CAACC,wCAAuB,CAAC;IAEnD,IAAI,CAAC,OAAO,EAAE;AACZ,QAAA,MAAM,IAAI,KAAK,CACb,gEAAgE,CACjE;IACH;IAEA,MAAM,EAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAC,GAAG,KAAK;IAE/C,QACEC,eAACC,UAAI,EAAA,EAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,EAAA,GAAM,UAAU,YAC3D,QAAQ,EAAA,CACJ;AAEX;;;;"}
1
+ {"version":3,"file":"AppProxyForm.js","sources":["../../../../../../src/react/components/AppProxyForm/AppProxyForm.tsx"],"sourcesContent":["import {forwardRef, useContext} from 'react';\nimport {Form, type FormProps} from '@remix-run/react';\n\nimport {AppProxyProviderContext} from '../AppProxyProvider';\n\nexport interface AppProxyFormProps extends FormProps {\n action: string;\n}\n\n/**\n * Sets up a Remix `<Form>` component that works when rendered on an app proxy page.\n *\n * Supports any properties accepted by the `<Form>` component.\n *\n * Because Remix doesn't support URL rewriting, any route using this component should <b>match the pathname of the proxy\n * URL exactly</b>, and <b>end in a trailing slash</b> (e.g., `https://<shop>/apps/proxy/`), or set the Remix Form prop\n * `navigate` to `false`.\n *\n * @example\n * <caption>Render a form element in a proxied route.</caption>\n * <description>Use an `AppProxyForm` within an `AppProxy` to create a form.</description>\n * ```ts\n * // /app/routes/apps/appProxy.ts\n * import {\n * AppProxyProvider,\n * AppProxyForm,\n * } from \"@shopify/shopify-app-remix/react\";\n * import { authenticate } from \"~/shopify.server\";\n *\n * export async function loader({ request }) {\n * await authenticate.public.appProxy(request);\n *\n * return json({ appUrl: process.env.SHOPIFY_APP_URL });\n * }\n *\n * export async function action({ request }) {\n * await authenticate.public.appProxy(request);\n *\n * const formData = await request.formData();\n * const field = formData.get(\"field\")?.toString();\n *\n * // Perform actions\n * if (field) {\n * console.log(\"Field:\", field);\n * }\n *\n * // Return JSON to the client\n * return json({ message: \"Success!\" });\n * }\n *\n * export default function App() {\n * const { appUrl } = useLoaderData();\n *\n * return (\n * <AppProxyProvider appUrl={appUrl}>\n * <AppProxyForm action=\"/apps/appProxy\" method=\"post\">\n * <input type=\"text\" name=\"field\" />\n *\n * <input type=\"submit\" name=\"Submit\" />\n * </AppProxyForm>\n * </AppProxyProvider>\n * );\n * }\n * ```\n * @publicDocs\n */\nexport const AppProxyForm = forwardRef<HTMLFormElement, AppProxyFormProps>(\n function AppProxyForm(props, ref) {\n const context = useContext(AppProxyProviderContext);\n\n if (!context) {\n throw new Error(\n 'AppProxyForm must be used within an AppProxyProvider component',\n );\n }\n\n const {children, action, ...otherProps} = props;\n\n return (\n <Form action={context.formatUrl(action, false)} {...otherProps} ref={ref}>\n {children}\n </Form>\n );\n },\n);\n"],"names":["forwardRef","useContext","AppProxyProviderContext","_jsx","Form"],"mappings":";;;;;;;AASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwDG;AACI,MAAM,YAAY,GAAGA,gBAAU,CACpC,SAAS,YAAY,CAAC,KAAK,EAAE,GAAG,EAAA;AAC9B,IAAA,MAAM,OAAO,GAAGC,gBAAU,CAACC,wCAAuB,CAAC;IAEnD,IAAI,CAAC,OAAO,EAAE;AACZ,QAAA,MAAM,IAAI,KAAK,CACb,gEAAgE,CACjE;IACH;IAEA,MAAM,EAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAC,GAAG,KAAK;IAE/C,QACEC,cAAA,CAACC,UAAI,EAAA,EAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,EAAA,GAAM,UAAU,EAAE,GAAG,EAAE,GAAG,EAAA,QAAA,EACrE,QAAQ,EAAA,CACJ;AAEX,CAAC;;;;"}
@@ -33,15 +33,16 @@ var AppProxyProvider = require('../AppProxyProvider/AppProxyProvider.js');
33
33
  * );
34
34
  * }
35
35
  * ```
36
+ * @publicDocs
36
37
  */
37
- function AppProxyLink(props) {
38
+ const AppProxyLink = React.forwardRef(function AppProxyLink(props, ref) {
38
39
  const context = React.useContext(AppProxyProvider.AppProxyProviderContext);
39
40
  if (!context) {
40
41
  throw new Error('AppProxyLink must be used within an AppProxyProvider component');
41
42
  }
42
43
  const { children, href, ...otherProps } = props;
43
- return (jsxRuntime.jsx("a", { href: context.formatUrl(href), ...otherProps, children: children }));
44
- }
44
+ return (jsxRuntime.jsx("a", { href: context.formatUrl(href), ...otherProps, ref: ref, children: children }));
45
+ });
45
46
 
46
47
  exports.AppProxyLink = AppProxyLink;
47
48
  //# sourceMappingURL=AppProxyLink.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AppProxyLink.js","sources":["../../../../../../src/react/components/AppProxyLink/AppProxyLink.tsx"],"sourcesContent":["import {useContext} from 'react';\n\nimport {AppProxyProviderContext} from '../AppProxyProvider';\n\nexport interface AppProxyLinkProps extends React.DetailedHTMLProps<\n React.AnchorHTMLAttributes<HTMLAnchorElement>,\n HTMLAnchorElement\n> {\n href: string;\n}\n\n/**\n * Sets up an `<a />` HTML element that works when rendered behind an app proxy.\n *\n * Supports any properties accepted by the `<a />` HTML element.\n *\n * @example\n * <caption>Link to a different route.</caption>\n * <description>Use an `AppProxyLink` within an `AppProxyProvider` to link to a different proxied route.</description>\n * ```ts\n * // /app/routes/**\\/*.ts\n * import {authenticate} from '~/shopify.server';\n * import {AppProxyProvider, AppProxyLink} from '@shopify/shopify-app-remix/react';\n *\n * export async function loader({ request }) {\n * await authenticate.public.appProxy(request);\n *\n * return json({ appUrl: process.env.SHOPIFY_APP_URL });\n * }\n *\n * export default function App() {\n * const { appUrl } = useLoaderData();\n *\n * return (\n * <AppProxyProvider appUrl={appUrl}>\n * <AppProxyLink href=\"/other-proxy-route\">Link to another route</AppProxyLink>\n * </AppProxyProvider>\n * );\n * }\n * ```\n */\nexport function AppProxyLink(props: AppProxyLinkProps) {\n const context = useContext(AppProxyProviderContext);\n\n if (!context) {\n throw new Error(\n 'AppProxyLink must be used within an AppProxyProvider component',\n );\n }\n\n const {children, href, ...otherProps} = props;\n\n return (\n <a href={context.formatUrl(href)} {...otherProps}>\n {children}\n </a>\n );\n}\n"],"names":["useContext","AppProxyProviderContext","_jsx"],"mappings":";;;;;;AAWA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BG;AACG,SAAU,YAAY,CAAC,KAAwB,EAAA;AACnD,IAAA,MAAM,OAAO,GAAGA,gBAAU,CAACC,wCAAuB,CAAC;IAEnD,IAAI,CAAC,OAAO,EAAE;AACZ,QAAA,MAAM,IAAI,KAAK,CACb,gEAAgE,CACjE;IACH;IAEA,MAAM,EAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,UAAU,EAAC,GAAG,KAAK;AAE7C,IAAA,QACEC,cAAA,CAAA,GAAA,EAAA,EAAG,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,KAAM,UAAU,EAAA,QAAA,EAC7C,QAAQ,EAAA,CACP;AAER;;;;"}
1
+ {"version":3,"file":"AppProxyLink.js","sources":["../../../../../../src/react/components/AppProxyLink/AppProxyLink.tsx"],"sourcesContent":["import {forwardRef, useContext} from 'react';\n\nimport {AppProxyProviderContext} from '../AppProxyProvider';\n\nexport interface AppProxyLinkProps extends React.DetailedHTMLProps<\n React.AnchorHTMLAttributes<HTMLAnchorElement>,\n HTMLAnchorElement\n> {\n href: string;\n}\n\n/**\n * Sets up an `<a />` HTML element that works when rendered behind an app proxy.\n *\n * Supports any properties accepted by the `<a />` HTML element.\n *\n * @example\n * <caption>Link to a different route.</caption>\n * <description>Use an `AppProxyLink` within an `AppProxyProvider` to link to a different proxied route.</description>\n * ```ts\n * // /app/routes/**\\/*.ts\n * import {authenticate} from '~/shopify.server';\n * import {AppProxyProvider, AppProxyLink} from '@shopify/shopify-app-remix/react';\n *\n * export async function loader({ request }) {\n * await authenticate.public.appProxy(request);\n *\n * return json({ appUrl: process.env.SHOPIFY_APP_URL });\n * }\n *\n * export default function App() {\n * const { appUrl } = useLoaderData();\n *\n * return (\n * <AppProxyProvider appUrl={appUrl}>\n * <AppProxyLink href=\"/other-proxy-route\">Link to another route</AppProxyLink>\n * </AppProxyProvider>\n * );\n * }\n * ```\n * @publicDocs\n */\nexport const AppProxyLink = forwardRef<HTMLAnchorElement, AppProxyLinkProps>(\n function AppProxyLink(props, ref) {\n const context = useContext(AppProxyProviderContext);\n\n if (!context) {\n throw new Error(\n 'AppProxyLink must be used within an AppProxyProvider component',\n );\n }\n\n const {children, href, ...otherProps} = props;\n\n return (\n <a href={context.formatUrl(href)} {...otherProps} ref={ref}>\n {children}\n </a>\n );\n },\n);\n"],"names":["forwardRef","useContext","AppProxyProviderContext","_jsx"],"mappings":";;;;;;AAWA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BG;AACI,MAAM,YAAY,GAAGA,gBAAU,CACpC,SAAS,YAAY,CAAC,KAAK,EAAE,GAAG,EAAA;AAC9B,IAAA,MAAM,OAAO,GAAGC,gBAAU,CAACC,wCAAuB,CAAC;IAEnD,IAAI,CAAC,OAAO,EAAE;AACZ,QAAA,MAAM,IAAI,KAAK,CACb,gEAAgE,CACjE;IACH;IAEA,MAAM,EAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,UAAU,EAAC,GAAG,KAAK;IAE7C,QACEC,sBAAG,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,KAAM,UAAU,EAAE,GAAG,EAAE,GAAG,YACvD,QAAQ,EAAA,CACP;AAER,CAAC;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"AppProxyProvider.js","sources":["../../../../../../src/react/components/AppProxyProvider/AppProxyProvider.tsx"],"sourcesContent":["import {createContext, useEffect, useState} from 'react';\n\nexport interface AppProxyProviderProps {\n /**\n * The URL where the app is hosted. You can set this from the `SHOPIFY_APP_URL` environment variable.\n */\n appUrl: string;\n\n /**\n * The children to render.\n */\n children?: React.ReactNode;\n}\n\ntype FormatUrlFunction = (\n url: string | undefined,\n addOrigin?: boolean,\n) => string | undefined;\n\ninterface AppProxyProviderContextProps {\n appUrl: string;\n formatUrl: FormatUrlFunction;\n requestUrl?: URL;\n}\n\nexport const AppProxyProviderContext =\n createContext<AppProxyProviderContextProps | null>(null);\n\n/**\n * Sets up a page to render behind a Shopify app proxy, enabling JavaScript and CSS to be loaded from the app.\n *\n * Also provides components that enable using other components such as links and forms within proxies.\n *\n * > Caution:\n * Because Remix doesn't support URL rewriting, any route using this component should <b>match the pathname of the proxy\n * URL exactly</b>, and <b>end in a trailing slash</b> (e.g., `https://<shop>/apps/proxy/`).\n *\n * @example\n * <caption>Wrap a route with an AppProxyProvider component.</caption>\n * <description>Wrap your route component in the `AppProxyProvider` component and pass in your app URL.</description>\n * ```ts\n * // /app/routes/**\\/*.ts\n * import {authenticate} from '~/shopify.server';\n * import {AppProxyProvider} from '@shopify/shopify-app-remix/react';\n *\n * export async function loader({ request }) {\n * await authenticate.public.appProxy(request);\n *\n * return json({ appUrl: process.env.SHOPIFY_APP_URL });\n * }\n *\n * export default function App() {\n * const { appUrl } = useLoaderData();\n *\n * return (\n * <AppProxyProvider appUrl={appUrl}>\n * Page content\n * </AppProxyProvider>\n * );\n * }\n * ```\n */\nexport function AppProxyProvider(props: AppProxyProviderProps) {\n const {children, appUrl} = props;\n const [requestUrl, setRequestUrl] = useState<URL | undefined>();\n\n useEffect(\n () => setRequestUrl(new URL(window.location.href)),\n [setRequestUrl],\n );\n\n return (\n <AppProxyProviderContext.Provider\n value={{appUrl, requestUrl, formatUrl: formatProxyUrl(requestUrl)}}\n >\n <base href={appUrl} />\n\n {children}\n </AppProxyProviderContext.Provider>\n );\n}\n\nfunction formatProxyUrl(requestUrl: URL | undefined): FormatUrlFunction {\n return (url: string | undefined, addOrigin = true) => {\n if (!url) {\n return url;\n }\n\n let finalUrl = url;\n\n if (addOrigin && requestUrl && finalUrl.startsWith('/')) {\n finalUrl = new URL(`${requestUrl.origin}${url}`).href;\n }\n if (!finalUrl.endsWith('/')) {\n finalUrl = `${finalUrl}/`;\n }\n\n return finalUrl;\n };\n}\n"],"names":["createContext","useState","useEffect","_jsxs","_jsx"],"mappings":";;;;;MAyBa,uBAAuB,GAClCA,mBAAa,CAAsC,IAAI;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCG;AACG,SAAU,gBAAgB,CAAC,KAA4B,EAAA;AAC3D,IAAA,MAAM,EAAC,QAAQ,EAAE,MAAM,EAAC,GAAG,KAAK;IAChC,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAGC,cAAQ,EAAmB;IAE/DC,eAAS,CACP,MAAM,aAAa,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAClD,CAAC,aAAa,CAAC,CAChB;AAED,IAAA,QACEC,eAAA,CAAC,uBAAuB,CAAC,QAAQ,EAAA,EAC/B,KAAK,EAAE,EAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,cAAc,CAAC,UAAU,CAAC,EAAC,EAAA,QAAA,EAAA,CAElEC,cAAA,CAAA,MAAA,EAAA,EAAM,IAAI,EAAE,MAAM,EAAA,CAAI,EAErB,QAAQ,CAAA,EAAA,CACwB;AAEvC;AAEA,SAAS,cAAc,CAAC,UAA2B,EAAA;AACjD,IAAA,OAAO,CAAC,GAAuB,EAAE,SAAS,GAAG,IAAI,KAAI;QACnD,IAAI,CAAC,GAAG,EAAE;AACR,YAAA,OAAO,GAAG;QACZ;QAEA,IAAI,QAAQ,GAAG,GAAG;QAElB,IAAI,SAAS,IAAI,UAAU,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;AACvD,YAAA,QAAQ,GAAG,IAAI,GAAG,CAAC,GAAG,UAAU,CAAC,MAAM,CAAA,EAAG,GAAG,CAAA,CAAE,CAAC,CAAC,IAAI;QACvD;QACA,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;AAC3B,YAAA,QAAQ,GAAG,CAAA,EAAG,QAAQ,CAAA,CAAA,CAAG;QAC3B;AAEA,QAAA,OAAO,QAAQ;AACjB,IAAA,CAAC;AACH;;;;;"}
1
+ {"version":3,"file":"AppProxyProvider.js","sources":["../../../../../../src/react/components/AppProxyProvider/AppProxyProvider.tsx"],"sourcesContent":["import {createContext, useEffect, useState} from 'react';\n\n/**\n * Props for the `AppProxyProvider` component.\n * @publicDocs\n */\nexport interface AppProxyProviderProps {\n /**\n * The URL where the app is hosted. You can set this from the `SHOPIFY_APP_URL` environment variable.\n */\n appUrl: string;\n\n /**\n * The children to render.\n */\n children?: React.ReactNode;\n}\n\ntype FormatUrlFunction = (\n url: string | undefined,\n addOrigin?: boolean,\n) => string | undefined;\n\ninterface AppProxyProviderContextProps {\n appUrl: string;\n formatUrl: FormatUrlFunction;\n requestUrl?: URL;\n}\n\nexport const AppProxyProviderContext =\n createContext<AppProxyProviderContextProps | null>(null);\n\n/**\n * Sets up a page to render behind a Shopify app proxy, enabling JavaScript and CSS to be loaded from the app.\n *\n * Also provides components that enable using other components such as links and forms within proxies.\n *\n * > Caution:\n * Because Remix doesn't support URL rewriting, any route using this component should <b>match the pathname of the proxy\n * URL exactly</b>, and <b>end in a trailing slash</b> (e.g., `https://<shop>/apps/proxy/`).\n *\n * @example\n * <caption>Wrap a route with an AppProxyProvider component.</caption>\n * <description>Wrap your route component in the `AppProxyProvider` component and pass in your app URL.</description>\n * ```ts\n * // /app/routes/**\\/*.ts\n * import {authenticate} from '~/shopify.server';\n * import {AppProxyProvider} from '@shopify/shopify-app-remix/react';\n *\n * export async function loader({ request }) {\n * await authenticate.public.appProxy(request);\n *\n * return json({ appUrl: process.env.SHOPIFY_APP_URL });\n * }\n *\n * export default function App() {\n * const { appUrl } = useLoaderData();\n *\n * return (\n * <AppProxyProvider appUrl={appUrl}>\n * Page content\n * </AppProxyProvider>\n * );\n * }\n * ```\n */\nexport function AppProxyProvider(props: AppProxyProviderProps) {\n const {children, appUrl} = props;\n const [requestUrl, setRequestUrl] = useState<URL | undefined>();\n\n useEffect(\n () => setRequestUrl(new URL(window.location.href)),\n [setRequestUrl],\n );\n\n return (\n <AppProxyProviderContext.Provider\n value={{appUrl, requestUrl, formatUrl: formatProxyUrl(requestUrl)}}\n >\n <base href={appUrl} />\n\n {children}\n </AppProxyProviderContext.Provider>\n );\n}\n\nfunction formatProxyUrl(requestUrl: URL | undefined): FormatUrlFunction {\n return (url: string | undefined, addOrigin = true) => {\n if (!url) {\n return url;\n }\n\n let finalUrl = url;\n\n if (addOrigin && requestUrl && finalUrl.startsWith('/')) {\n finalUrl = new URL(`${requestUrl.origin}${url}`).href;\n }\n if (!finalUrl.endsWith('/')) {\n finalUrl = `${finalUrl}/`;\n }\n\n return finalUrl;\n };\n}\n"],"names":["createContext","useState","useEffect","_jsxs","_jsx"],"mappings":";;;;;MA6Ba,uBAAuB,GAClCA,mBAAa,CAAsC,IAAI;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCG;AACG,SAAU,gBAAgB,CAAC,KAA4B,EAAA;AAC3D,IAAA,MAAM,EAAC,QAAQ,EAAE,MAAM,EAAC,GAAG,KAAK;IAChC,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAGC,cAAQ,EAAmB;IAE/DC,eAAS,CACP,MAAM,aAAa,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAClD,CAAC,aAAa,CAAC,CAChB;AAED,IAAA,QACEC,eAAA,CAAC,uBAAuB,CAAC,QAAQ,EAAA,EAC/B,KAAK,EAAE,EAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,cAAc,CAAC,UAAU,CAAC,EAAC,EAAA,QAAA,EAAA,CAElEC,cAAA,CAAA,MAAA,EAAA,EAAM,IAAI,EAAE,MAAM,EAAA,CAAI,EAErB,QAAQ,CAAA,EAAA,CACwB;AAEvC;AAEA,SAAS,cAAc,CAAC,UAA2B,EAAA;AACjD,IAAA,OAAO,CAAC,GAAuB,EAAE,SAAS,GAAG,IAAI,KAAI;QACnD,IAAI,CAAC,GAAG,EAAE;AACR,YAAA,OAAO,GAAG;QACZ;QAEA,IAAI,QAAQ,GAAG,GAAG;QAElB,IAAI,SAAS,IAAI,UAAU,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;AACvD,YAAA,QAAQ,GAAG,IAAI,GAAG,CAAC,GAAG,UAAU,CAAC,MAAM,CAAA,EAAG,GAAG,CAAA,CAAE,CAAC,CAAC,IAAI;QACvD;QACA,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;AAC3B,YAAA,QAAQ,GAAG,CAAA,EAAG,QAAQ,CAAA,CAAA,CAAG;QAC3B;AAEA,QAAA,OAAO,QAAQ;AACjB,IAAA,CAAC;AACH;;;;;"}
@@ -17,8 +17,8 @@ function redirectFactory(params, request, shop) {
17
17
  init,
18
18
  });
19
19
  logger.debug('Redirecting', { shop, url: parsedUrl.toString() });
20
- const isSameOrigin = parsedUrl.origin === config.appUrl;
21
- if (isSameOrigin || url.startsWith('/')) {
20
+ const isSameOrigin = parsedUrl.origin === new URL(config.appUrl).origin;
21
+ if (isSameOrigin) {
22
22
  searchParams.forEach((value, key) => {
23
23
  if (!parsedUrl.searchParams.has(key)) {
24
24
  parsedUrl.searchParams.set(key, value);
@@ -1 +1 @@
1
- {"version":3,"file":"redirect.js","sources":["../../../../../../../src/server/authenticate/admin/helpers/redirect.ts"],"sourcesContent":["import {\n TypedResponse,\n redirect as remixRedirect,\n} from '@remix-run/server-runtime';\n\nimport {BasicParams} from '../../../types';\nimport {getSessionTokenHeader} from '../../helpers/get-session-token-header';\n\nimport {renderAppBridge} from './render-app-bridge';\nimport {redirectWithAppBridgeHeaders} from './redirect-with-app-bridge-headers';\n\nexport type RedirectTarget = '_self' | '_parent' | '_top' | '_blank';\nexport type RedirectInit = number | (ResponseInit & {target?: RedirectTarget});\nexport type RedirectFunction = (\n url: string,\n init?: RedirectInit,\n) => TypedResponse<never>;\n\ninterface ParseURLOptions {\n params: BasicParams;\n url: string;\n base: string;\n shop: string;\n init: RedirectInit;\n}\n\ninterface ParsedURL {\n url: URL;\n target: RedirectTarget;\n}\n\nexport function redirectFactory(\n params: BasicParams,\n request: Request,\n shop: string,\n): RedirectFunction {\n const {config, logger} = params;\n\n return function redirect(url, init: RedirectInit) {\n const {searchParams} = new URL(request.url);\n const {url: parsedUrl, target} = parseURL({\n params,\n url,\n base: config.appUrl,\n shop,\n init,\n });\n\n logger.debug('Redirecting', {shop, url: parsedUrl.toString()});\n\n const isSameOrigin = parsedUrl.origin === config.appUrl;\n if (isSameOrigin || url.startsWith('/')) {\n searchParams.forEach((value, key) => {\n if (!parsedUrl.searchParams.has(key)) {\n parsedUrl.searchParams.set(key, value);\n }\n });\n }\n\n if (target === '_self') {\n if (isBounceRequest(request)) {\n throw renderAppBridge(params, request, {\n url: parsedUrl.toString(),\n target,\n });\n } else {\n return remixRedirect(parsedUrl.toString(), init);\n }\n } else if (isDataRequest(request)) {\n throw redirectWithAppBridgeHeaders(parsedUrl.toString());\n } else if (isEmbeddedRequest(request)) {\n throw renderAppBridge(params, request, {\n url: parsedUrl.toString(),\n target,\n });\n }\n return remixRedirect(url, init);\n };\n}\n\nfunction isBounceRequest(request: Request) {\n return (\n Boolean(getSessionTokenHeader(request)) &&\n request.headers.has('X-Shopify-Bounce')\n );\n}\n\nfunction isDataRequest(request: Request) {\n const isGet = request.method === 'GET';\n const sessionTokenHeader = Boolean(getSessionTokenHeader(request));\n\n return (\n sessionTokenHeader &&\n !isBounceRequest(request) &&\n (!isEmbeddedRequest(request) || !isGet)\n );\n}\n\nfunction isEmbeddedRequest(request: Request) {\n const {searchParams} = new URL(request.url);\n\n return searchParams.get('embedded') === '1';\n}\n\nfunction parseURL({params, base, init, shop, url}: ParseURLOptions): ParsedURL {\n let target: RedirectTarget | undefined =\n typeof init !== 'number' && init?.target ? init.target : undefined;\n\n if (isAdminRemotePath(url)) {\n const {config} = params;\n\n const adminPath = getAdminRemotePath(url);\n const cleanShopName = shop.replace('.myshopify.com', '');\n\n if (!target) {\n target = config.isEmbeddedApp ? '_parent' : '_self';\n }\n\n return {\n url: new URL(\n `https://admin.shopify.com/store/${cleanShopName}${adminPath}`,\n ),\n target,\n };\n } else {\n return {\n url: new URL(url, base),\n target: target ?? '_self',\n };\n }\n}\n\nconst ADMIN_REGEX = /^shopify:\\/*admin\\//i;\n\nfunction isAdminRemotePath(url: string) {\n return ADMIN_REGEX.test(url);\n}\n\nfunction getAdminRemotePath(url: string | URL) {\n const parsedUrl = removeRestrictedParams(new URL(url)).href;\n return parsedUrl.replace(ADMIN_REGEX, '/');\n}\n\nconst embeddedFrameParamsToRemove = [\n 'hmac',\n 'locale',\n 'protocol',\n 'session',\n 'id_token',\n 'shop',\n 'timestamp',\n 'host',\n 'embedded',\n // sent when clicking rel=\"home\" nav item\n 'appLoadId',\n];\n\nfunction removeRestrictedParams(url: URL | string) {\n const newUrl = new URL(url);\n embeddedFrameParamsToRemove.forEach((param) =>\n newUrl.searchParams.delete(param),\n );\n return newUrl;\n}\n"],"names":["renderAppBridge","remixRedirect","redirectWithAppBridgeHeaders","getSessionTokenHeader"],"mappings":"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"}
1
+ {"version":3,"file":"redirect.js","sources":["../../../../../../../src/server/authenticate/admin/helpers/redirect.ts"],"sourcesContent":["import {\n TypedResponse,\n redirect as remixRedirect,\n} from '@remix-run/server-runtime';\n\nimport {BasicParams} from '../../../types';\nimport {getSessionTokenHeader} from '../../helpers/get-session-token-header';\n\nimport {renderAppBridge} from './render-app-bridge';\nimport {redirectWithAppBridgeHeaders} from './redirect-with-app-bridge-headers';\n\nexport type RedirectTarget = '_self' | '_parent' | '_top' | '_blank';\nexport type RedirectInit = number | (ResponseInit & {target?: RedirectTarget});\nexport type RedirectFunction = (\n url: string,\n init?: RedirectInit,\n) => TypedResponse<never>;\n\ninterface ParseURLOptions {\n params: BasicParams;\n url: string;\n base: string;\n shop: string;\n init: RedirectInit;\n}\n\ninterface ParsedURL {\n url: URL;\n target: RedirectTarget;\n}\n\nexport function redirectFactory(\n params: BasicParams,\n request: Request,\n shop: string,\n): RedirectFunction {\n const {config, logger} = params;\n\n return function redirect(url, init: RedirectInit) {\n const {searchParams} = new URL(request.url);\n const {url: parsedUrl, target} = parseURL({\n params,\n url,\n base: config.appUrl,\n shop,\n init,\n });\n\n logger.debug('Redirecting', {shop, url: parsedUrl.toString()});\n\n const isSameOrigin = parsedUrl.origin === new URL(config.appUrl).origin;\n if (isSameOrigin) {\n searchParams.forEach((value, key) => {\n if (!parsedUrl.searchParams.has(key)) {\n parsedUrl.searchParams.set(key, value);\n }\n });\n }\n\n if (target === '_self') {\n if (isBounceRequest(request)) {\n throw renderAppBridge(params, request, {\n url: parsedUrl.toString(),\n target,\n });\n } else {\n return remixRedirect(parsedUrl.toString(), init);\n }\n } else if (isDataRequest(request)) {\n throw redirectWithAppBridgeHeaders(parsedUrl.toString());\n } else if (isEmbeddedRequest(request)) {\n throw renderAppBridge(params, request, {\n url: parsedUrl.toString(),\n target,\n });\n }\n return remixRedirect(url, init);\n };\n}\n\nfunction isBounceRequest(request: Request) {\n return (\n Boolean(getSessionTokenHeader(request)) &&\n request.headers.has('X-Shopify-Bounce')\n );\n}\n\nfunction isDataRequest(request: Request) {\n const isGet = request.method === 'GET';\n const sessionTokenHeader = Boolean(getSessionTokenHeader(request));\n\n return (\n sessionTokenHeader &&\n !isBounceRequest(request) &&\n (!isEmbeddedRequest(request) || !isGet)\n );\n}\n\nfunction isEmbeddedRequest(request: Request) {\n const {searchParams} = new URL(request.url);\n\n return searchParams.get('embedded') === '1';\n}\n\nfunction parseURL({params, base, init, shop, url}: ParseURLOptions): ParsedURL {\n let target: RedirectTarget | undefined =\n typeof init !== 'number' && init?.target ? init.target : undefined;\n\n if (isAdminRemotePath(url)) {\n const {config} = params;\n\n const adminPath = getAdminRemotePath(url);\n const cleanShopName = shop.replace('.myshopify.com', '');\n\n if (!target) {\n target = config.isEmbeddedApp ? '_parent' : '_self';\n }\n\n return {\n url: new URL(\n `https://admin.shopify.com/store/${cleanShopName}${adminPath}`,\n ),\n target,\n };\n } else {\n return {\n url: new URL(url, base),\n target: target ?? '_self',\n };\n }\n}\n\nconst ADMIN_REGEX = /^shopify:\\/*admin\\//i;\n\nfunction isAdminRemotePath(url: string) {\n return ADMIN_REGEX.test(url);\n}\n\nfunction getAdminRemotePath(url: string | URL) {\n const parsedUrl = removeRestrictedParams(new URL(url)).href;\n return parsedUrl.replace(ADMIN_REGEX, '/');\n}\n\nconst embeddedFrameParamsToRemove = [\n 'hmac',\n 'locale',\n 'protocol',\n 'session',\n 'id_token',\n 'shop',\n 'timestamp',\n 'host',\n 'embedded',\n // sent when clicking rel=\"home\" nav item\n 'appLoadId',\n];\n\nfunction removeRestrictedParams(url: URL | string) {\n const newUrl = new URL(url);\n embeddedFrameParamsToRemove.forEach((param) =>\n newUrl.searchParams.delete(param),\n );\n return newUrl;\n}\n"],"names":["renderAppBridge","remixRedirect","redirectWithAppBridgeHeaders","getSessionTokenHeader"],"mappings":"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"}
@@ -58,7 +58,7 @@ function authenticateWebhookFactory(params) {
58
58
  apiVersion: check.apiVersion,
59
59
  shop: check.domain,
60
60
  topic: check.topic,
61
- webhookId: check.eventId,
61
+ webhookId: check.webhookId,
62
62
  payload: JSON.parse(rawBody),
63
63
  session: undefined,
64
64
  admin: undefined,
@@ -1 +1 @@
1
- {"version":3,"file":"authenticate.js","sources":["../../../../../../src/server/authenticate/webhooks/authenticate.ts"],"sourcesContent":["import {WebhookValidationErrorReason, WebhookType} from '@shopify/shopify-api';\n\nimport type {BasicParams} from '../../types';\nimport {adminClientFactory} from '../../clients';\nimport {handleClientErrorFactory} from '../admin/helpers';\nimport {ensureValidOfflineSession} from '../../helpers';\n\nimport type {\n AuthenticateWebhook,\n WebhookContext,\n WebhookContextWithoutSession,\n} from './types';\n\nexport function authenticateWebhookFactory<Topics extends string>(\n params: BasicParams,\n): AuthenticateWebhook<Topics> {\n const {api, logger} = params;\n\n return async function authenticate(\n request: Request,\n ): Promise<WebhookContext<Topics>> {\n if (request.method !== 'POST') {\n logger.debug(\n 'Received a non-POST request for a webhook. Only POST requests are allowed.',\n {url: request.url, method: request.method},\n );\n throw new Response(undefined, {\n status: 405,\n statusText: 'Method not allowed',\n });\n }\n\n const rawBody = await request.text();\n\n const check = await api.webhooks.validate({\n rawBody,\n rawRequest: request,\n });\n\n if (!check.valid) {\n if (check.reason === WebhookValidationErrorReason.InvalidHmac) {\n logger.debug('Webhook HMAC validation failed', check);\n throw new Response(undefined, {\n status: 401,\n statusText: 'Unauthorized',\n });\n } else {\n logger.debug('Webhook validation failed', check);\n throw new Response(undefined, {status: 400, statusText: 'Bad Request'});\n }\n }\n const session = await ensureValidOfflineSession(params, check.domain);\n\n let webhookContext: WebhookContextWithoutSession<Topics>;\n\n if (check.webhookType === WebhookType.Webhooks) {\n webhookContext = {\n apiVersion: check.apiVersion,\n shop: check.domain,\n topic: check.topic as Topics,\n webhookId: check.webhookId,\n payload: JSON.parse(rawBody),\n subTopic: check.subTopic || undefined,\n session: undefined,\n admin: undefined,\n webhookType: check.webhookType,\n name: check.name,\n triggeredAt: check.triggeredAt,\n eventId: check.eventId,\n };\n } else {\n webhookContext = {\n apiVersion: check.apiVersion,\n shop: check.domain,\n topic: check.topic as Topics,\n webhookId: check.eventId,\n payload: JSON.parse(rawBody),\n session: undefined,\n admin: undefined,\n webhookType: check.webhookType,\n handle: check.handle,\n action: check.action,\n resourceId: check.resourceId,\n triggeredAt: check.triggeredAt,\n eventId: check.eventId,\n };\n }\n\n if (!session) {\n return webhookContext;\n }\n\n const admin = adminClientFactory({\n params,\n session,\n handleClientError: handleClientErrorFactory({request}),\n });\n\n return {\n ...webhookContext,\n session,\n admin,\n };\n };\n}\n"],"names":["WebhookValidationErrorReason","ensureValidOfflineSession","WebhookType","adminClientFactory","handleClientErrorFactory"],"mappings":"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"}
1
+ {"version":3,"file":"authenticate.js","sources":["../../../../../../src/server/authenticate/webhooks/authenticate.ts"],"sourcesContent":["import {WebhookValidationErrorReason, WebhookType} from '@shopify/shopify-api';\n\nimport type {BasicParams} from '../../types';\nimport {adminClientFactory} from '../../clients';\nimport {handleClientErrorFactory} from '../admin/helpers';\nimport {ensureValidOfflineSession} from '../../helpers';\n\nimport type {\n AuthenticateWebhook,\n WebhookContext,\n WebhookContextWithoutSession,\n} from './types';\n\nexport function authenticateWebhookFactory<Topics extends string>(\n params: BasicParams,\n): AuthenticateWebhook<Topics> {\n const {api, logger} = params;\n\n return async function authenticate(\n request: Request,\n ): Promise<WebhookContext<Topics>> {\n if (request.method !== 'POST') {\n logger.debug(\n 'Received a non-POST request for a webhook. Only POST requests are allowed.',\n {url: request.url, method: request.method},\n );\n throw new Response(undefined, {\n status: 405,\n statusText: 'Method not allowed',\n });\n }\n\n const rawBody = await request.text();\n\n const check = await api.webhooks.validate({\n rawBody,\n rawRequest: request,\n });\n\n if (!check.valid) {\n if (check.reason === WebhookValidationErrorReason.InvalidHmac) {\n logger.debug('Webhook HMAC validation failed', check);\n throw new Response(undefined, {\n status: 401,\n statusText: 'Unauthorized',\n });\n } else {\n logger.debug('Webhook validation failed', check);\n throw new Response(undefined, {status: 400, statusText: 'Bad Request'});\n }\n }\n const session = await ensureValidOfflineSession(params, check.domain);\n\n let webhookContext: WebhookContextWithoutSession<Topics>;\n\n if (check.webhookType === WebhookType.Webhooks) {\n webhookContext = {\n apiVersion: check.apiVersion,\n shop: check.domain,\n topic: check.topic as Topics,\n webhookId: check.webhookId,\n payload: JSON.parse(rawBody),\n subTopic: check.subTopic || undefined,\n session: undefined,\n admin: undefined,\n webhookType: check.webhookType,\n name: check.name,\n triggeredAt: check.triggeredAt,\n eventId: check.eventId,\n };\n } else {\n webhookContext = {\n apiVersion: check.apiVersion,\n shop: check.domain,\n topic: check.topic as Topics,\n webhookId: check.webhookId,\n payload: JSON.parse(rawBody),\n session: undefined,\n admin: undefined,\n webhookType: check.webhookType,\n handle: check.handle,\n action: check.action,\n resourceId: check.resourceId,\n triggeredAt: check.triggeredAt,\n eventId: check.eventId,\n };\n }\n\n if (!session) {\n return webhookContext;\n }\n\n const admin = adminClientFactory({\n params,\n session,\n handleClientError: handleClientErrorFactory({request}),\n });\n\n return {\n ...webhookContext,\n session,\n admin,\n };\n };\n}\n"],"names":["WebhookValidationErrorReason","ensureValidOfflineSession","WebhookType","adminClientFactory","handleClientErrorFactory"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"flags.js","sources":["../../../../../src/server/future/flags.ts"],"sourcesContent":["import type {ConfigParams, Shopify} from '@shopify/shopify-api';\n\nimport {AppConfig} from '../config-types';\n\n// When adding new flags, you should also add them to the `TEST_FUTURE_FLAGS` object in `test-config.ts` to ensure that\n// it doesn't cause regressions.\nexport interface FutureFlags {\n /**\n * When enabled, embedded apps will fetch access tokens via [token exchange](https://shopify.dev/docs/apps/auth/get-access-tokens/token-exchange).\n * This assumes the app has scopes declared for [Shopify managing installation](https://shopify.dev/docs/apps/auth/installation#shopify-managed-installation).\n *\n * Learn more about this [new embedded app auth strategy](https://shopify.dev/docs/api/shopify-app-remix#embedded-auth-strategy).\n *\n * @default false\n */\n unstable_newEmbeddedAuthStrategy?: boolean;\n /**\n * When enabled, the app will start using expiring offline access tokens and automatically refresh them when they are close to expiring.\n *\n * @default false\n */\n expiringOfflineAccessTokens?: boolean;\n}\n\n// When adding new flags, use this format:\n// apiFutureFlag: Future extends FutureFlags ? Future['remixFutureFlag'] : false;\nexport interface ApiFutureFlags<Future extends FutureFlagOptions> {\n expiringOfflineAccessTokens: Future extends FutureFlags\n ? Future['expiringOfflineAccessTokens']\n : false;\n unstable_managedPricingSupport: true;\n}\n\nexport type ApiConfigWithFutureFlags<Future extends FutureFlagOptions> =\n ConfigParams<ApiFutureFlags<Future>>;\n\nexport type FutureFlagOptions = FutureFlags | undefined;\n\nexport type FeatureEnabled<\n Future extends FutureFlagOptions,\n Flag extends keyof FutureFlags,\n> = Future extends FutureFlags\n ? Future[Flag] extends true\n ? true\n : false\n : false;\n\nexport function logDisabledFutureFlags(\n config: AppConfig,\n logger: Shopify['logger'],\n) {\n const logFlag = (flag: string, message: string) =>\n logger.info(`Future flag ${flag} is disabled.\\n\\n ${message}\\n`);\n\n if (!config.future.unstable_newEmbeddedAuthStrategy) {\n logFlag(\n 'unstable_newEmbeddedAuthStrategy',\n 'Enable this to use OAuth token exchange instead of auth code to generate API access tokens.' +\n '\\n Your app must be using Shopify managed install: https://shopify.dev/docs/apps/auth/installation',\n );\n }\n}\n"],"names":[],"mappings":";;AA+CM,SAAU,sBAAsB,CACpC,MAAiB,EACjB,MAAyB,EAAA;AAEzB,IAAA,MAAM,OAAO,GAAG,CAAC,IAAY,EAAE,OAAe,KAC5C,MAAM,CAAC,IAAI,CAAC,CAAA,YAAA,EAAe,IAAI,sBAAsB,OAAO,CAAA,EAAA,CAAI,CAAC;AAEnE,IAAA,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,gCAAgC,EAAE;QACnD,OAAO,CACL,kCAAkC,EAClC,6FAA6F;AAC3F,YAAA,qGAAqG,CACxG;IACH;AACF;;;;"}
1
+ {"version":3,"file":"flags.js","sources":["../../../../../src/server/future/flags.ts"],"sourcesContent":["import type {ConfigParams, Shopify} from '@shopify/shopify-api';\n\nimport {AppConfig} from '../config-types';\n\n// When adding new flags, you should also add them to the `TEST_FUTURE_FLAGS` object in `test-config.ts` to ensure that\n// it doesn't cause regressions.\n/**\n * Set future flags using the `future` configuration field to opt in to upcoming breaking changes.\n *\n * With this feature, you can prepare for major releases ahead of time, as well as try out new features before they are released.\n * @publicDocs\n */\nexport interface FutureFlags {\n /**\n * When enabled, embedded apps will fetch access tokens via [token exchange](https://shopify.dev/docs/apps/auth/get-access-tokens/token-exchange).\n * This assumes the app has scopes declared for [Shopify managing installation](https://shopify.dev/docs/apps/auth/installation#shopify-managed-installation).\n *\n * Learn more about this [new embedded app auth strategy](https://shopify.dev/docs/api/shopify-app-remix#embedded-auth-strategy).\n *\n * @default false\n */\n unstable_newEmbeddedAuthStrategy?: boolean;\n /**\n * When enabled, the app will start using expiring offline access tokens and automatically refresh them when they are close to expiring.\n *\n * @default false\n */\n expiringOfflineAccessTokens?: boolean;\n}\n\n// When adding new flags, use this format:\n// apiFutureFlag: Future extends FutureFlags ? Future['remixFutureFlag'] : false;\nexport interface ApiFutureFlags<Future extends FutureFlagOptions> {\n expiringOfflineAccessTokens: Future extends FutureFlags\n ? Future['expiringOfflineAccessTokens']\n : false;\n unstable_managedPricingSupport: true;\n}\n\nexport type ApiConfigWithFutureFlags<Future extends FutureFlagOptions> =\n ConfigParams<ApiFutureFlags<Future>>;\n\nexport type FutureFlagOptions = FutureFlags | undefined;\n\nexport type FeatureEnabled<\n Future extends FutureFlagOptions,\n Flag extends keyof FutureFlags,\n> = Future extends FutureFlags\n ? Future[Flag] extends true\n ? true\n : false\n : false;\n\nexport function logDisabledFutureFlags(\n config: AppConfig,\n logger: Shopify['logger'],\n) {\n const logFlag = (flag: string, message: string) =>\n logger.info(`Future flag ${flag} is disabled.\\n\\n ${message}\\n`);\n\n if (!config.future.unstable_newEmbeddedAuthStrategy) {\n logFlag(\n 'unstable_newEmbeddedAuthStrategy',\n 'Enable this to use OAuth token exchange instead of auth code to generate API access tokens.' +\n '\\n Your app must be using Shopify managed install: https://shopify.dev/docs/apps/auth/installation',\n );\n }\n}\n"],"names":[],"mappings":";;AAqDM,SAAU,sBAAsB,CACpC,MAAiB,EACjB,MAAyB,EAAA;AAEzB,IAAA,MAAM,OAAO,GAAG,CAAC,IAAY,EAAE,OAAe,KAC5C,MAAM,CAAC,IAAI,CAAC,CAAA,YAAA,EAAe,IAAI,sBAAsB,OAAO,CAAA,EAAA,CAAI,CAAC;AAEnE,IAAA,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,gCAAgC,EAAE;QACnD,OAAO,CACL,kCAAkC,EAClC,6FAA6F;AAC3F,YAAA,qGAAqG,CACxG;IACH;AACF;;;;"}
@@ -28,6 +28,7 @@ var flags = require('./future/flags.js');
28
28
  *
29
29
  * @param appConfig Configuration options for your Shopify app, such as the scopes your app needs.
30
30
  * @returns `ShopifyApp` An object constructed using your appConfig. It has methods for interacting with Shopify.
31
+ * @publicDocs
31
32
  *
32
33
  * @example
33
34
  * <caption>The minimum viable configuration</caption>
@@ -1 +1 @@
1
- {"version":3,"file":"shopify-app.js","sources":["../../../../src/server/shopify-app.ts"],"sourcesContent":["import '@shopify/shopify-api/adapters/web-api';\nimport {\n ConfigInterface as ApiConfig,\n ShopifyError,\n shopifyApi,\n} from '@shopify/shopify-api';\nimport {SessionStorage} from '@shopify/shopify-app-session-storage';\n\nimport {type AppConfig, type AppConfigArg} from './config-types';\nimport {\n AppDistribution,\n type BasicParams,\n type ShopifyApp,\n type ShopifyAppBase,\n type AdminApp,\n type SingleMerchantApp,\n type AppStoreApp,\n} from './types';\nimport {SHOPIFY_REMIX_LIBRARY_VERSION} from './version';\nimport {registerWebhooksFactory} from './authenticate/webhooks';\nimport {authStrategyFactory} from './authenticate/admin/authenticate';\nimport {authenticateWebhookFactory} from './authenticate/webhooks/authenticate';\nimport {overrideLogger} from './override-logger';\nimport {addDocumentResponseHeadersFactory} from './authenticate/helpers';\nimport {loginFactory} from './authenticate/login/login';\nimport {unauthenticatedAdminContextFactory} from './unauthenticated/admin';\nimport {authenticatePublicFactory} from './authenticate/public';\nimport {unauthenticatedStorefrontContextFactory} from './unauthenticated/storefront';\nimport {AuthCodeFlowStrategy} from './authenticate/admin/strategies/auth-code-flow';\nimport {TokenExchangeStrategy} from './authenticate/admin/strategies/token-exchange';\nimport {MerchantCustomAuth} from './authenticate/admin/strategies/merchant-custom-app';\nimport {IdempotentPromiseHandler} from './authenticate/helpers/idempotent-promise-handler';\nimport {authenticateFlowFactory} from './authenticate/flow/authenticate';\nimport {authenticateFulfillmentServiceFactory} from './authenticate/fulfillment-service/authenticate';\nimport {FutureFlagOptions, logDisabledFutureFlags} from './future/flags';\n\n/**\n * Creates an object your app will use to interact with Shopify.\n *\n * @param appConfig Configuration options for your Shopify app, such as the scopes your app needs.\n * @returns `ShopifyApp` An object constructed using your appConfig. It has methods for interacting with Shopify.\n *\n * @example\n * <caption>The minimum viable configuration</caption>\n * ```ts\n * // /shopify.server.ts\n * import { shopifyApp } from \"@shopify/shopify-app-remix/server\";\n *\n * const shopify = shopifyApp({\n * apiKey: process.env.SHOPIFY_API_KEY!,\n * apiSecretKey: process.env.SHOPIFY_API_SECRET!,\n * scopes: process.env.SCOPES?.split(\",\")!,\n * appUrl: process.env.SHOPIFY_APP_URL!,\n * });\n * export default shopify;\n * ```\n */\nexport function shopifyApp<\n Config extends AppConfigArg<Storage, Future>,\n Storage extends SessionStorage,\n Future extends FutureFlagOptions = Config['future'],\n>(appConfig: Readonly<Config>): ShopifyApp<Config> {\n const api = deriveApi(appConfig);\n const config = deriveConfig<Storage>(appConfig, api.config);\n const logger = overrideLogger(api.logger);\n\n if (appConfig.webhooks) {\n api.webhooks.addHandlers(appConfig.webhooks);\n }\n\n const params: BasicParams = {api, config, logger};\n\n let strategy;\n if (config.distribution === AppDistribution.ShopifyAdmin) {\n strategy = new MerchantCustomAuth(params);\n } else if (\n config.future.unstable_newEmbeddedAuthStrategy &&\n config.isEmbeddedApp\n ) {\n strategy = new TokenExchangeStrategy(params);\n } else {\n strategy = new AuthCodeFlowStrategy(params);\n }\n\n const authStrategy = authStrategyFactory<Config>({\n ...params,\n strategy,\n });\n\n const shopify:\n | AdminApp<Config>\n | AppStoreApp<Config>\n | SingleMerchantApp<Config> = {\n sessionStorage: config.sessionStorage,\n addDocumentResponseHeaders: addDocumentResponseHeadersFactory(params),\n registerWebhooks: registerWebhooksFactory(params),\n authenticate: {\n admin: authStrategy,\n flow: authenticateFlowFactory(params),\n public: authenticatePublicFactory(params),\n fulfillmentService: authenticateFulfillmentServiceFactory(params),\n webhook: authenticateWebhookFactory<string>(params),\n },\n unauthenticated: {\n admin: unauthenticatedAdminContextFactory(params),\n storefront: unauthenticatedStorefrontContextFactory(params),\n },\n };\n\n if (\n isAppStoreApp(shopify, appConfig) ||\n isSingleMerchantApp(shopify, appConfig)\n ) {\n shopify.login = loginFactory(params);\n }\n\n logDisabledFutureFlags(config, logger);\n\n return shopify as ShopifyApp<Config>;\n}\n\nfunction isAppStoreApp<Config extends AppConfigArg>(\n _shopify: ShopifyAppBase<Config>,\n config: Config,\n): _shopify is AppStoreApp<Config> {\n return config.distribution === AppDistribution.AppStore;\n}\n\nfunction isSingleMerchantApp<Config extends AppConfigArg>(\n _shopify: ShopifyAppBase<Config>,\n config: Config,\n): _shopify is SingleMerchantApp<Config> {\n return config.distribution === AppDistribution.SingleMerchant;\n}\n\n// This function is only exported so we can unit test it without having to mock the underlying module.\n// It's not available to consumers of the library because it is not exported in the index module, and never should be.\nexport function deriveApi(appConfig: AppConfigArg): BasicParams['api'] {\n let appUrl: URL;\n try {\n appUrl = new URL(appConfig.appUrl);\n } catch (error) {\n const message =\n appConfig.appUrl === ''\n ? `Detected an empty appUrl configuration, please make sure to set the necessary environment variables.\\n` +\n `If you're deploying your app, you can find more information at https://shopify.dev/docs/apps/launch/deployment/deploy-web-app/deploy-to-hosting-service#step-4-set-up-environment-variables`\n : `Invalid appUrl configuration '${appConfig.appUrl}', please provide a valid URL.`;\n throw new ShopifyError(message);\n }\n\n /* eslint-disable no-process-env */\n if (appUrl.hostname === 'localhost' && !appUrl.port && process.env.PORT) {\n appUrl.port = process.env.PORT;\n }\n /* eslint-enable no-process-env */\n appConfig.appUrl = appUrl.origin;\n\n let userAgentPrefix = `Shopify Remix Library v${SHOPIFY_REMIX_LIBRARY_VERSION}`;\n if (appConfig.userAgentPrefix) {\n userAgentPrefix = `${appConfig.userAgentPrefix} | ${userAgentPrefix}`;\n }\n\n return shopifyApi({\n ...appConfig,\n hostName: appUrl.host,\n hostScheme: appUrl.protocol.replace(':', '') as 'http' | 'https',\n userAgentPrefix,\n isEmbeddedApp: appConfig.isEmbeddedApp ?? true,\n apiVersion: appConfig.apiVersion,\n isCustomStoreApp: appConfig.distribution === AppDistribution.ShopifyAdmin,\n billing: appConfig.billing as ApiConfig['billing'],\n future: {\n unstable_managedPricingSupport: true,\n },\n _logDisabledFutureFlags: false,\n });\n}\n\nfunction deriveConfig<Storage extends SessionStorage>(\n appConfig: AppConfigArg,\n apiConfig: ApiConfig,\n): AppConfig<Storage> {\n if (\n !appConfig.sessionStorage &&\n appConfig.distribution !== AppDistribution.ShopifyAdmin\n ) {\n throw new ShopifyError(\n 'Please provide a valid session storage. Refer to https://github.com/Shopify/shopify-app-js/blob/main/README.md#session-storage-options for options.',\n );\n }\n\n const authPathPrefix = appConfig.authPathPrefix || '/auth';\n appConfig.distribution = appConfig.distribution ?? AppDistribution.AppStore;\n\n return {\n ...appConfig,\n ...apiConfig,\n billing: appConfig.billing as ApiConfig['billing'],\n scopes: apiConfig.scopes,\n idempotentPromiseHandler: new IdempotentPromiseHandler(),\n canUseLoginForm: appConfig.distribution !== AppDistribution.ShopifyAdmin,\n useOnlineTokens: appConfig.useOnlineTokens ?? false,\n hooks: appConfig.hooks ?? {},\n sessionStorage: appConfig.sessionStorage as Storage,\n future: appConfig.future ?? {},\n auth: {\n path: authPathPrefix,\n callbackPath: `${authPathPrefix}/callback`,\n patchSessionTokenPath: `${authPathPrefix}/session-token`,\n exitIframePath: `${authPathPrefix}/exit-iframe`,\n loginPath: `${authPathPrefix}/login`,\n },\n distribution: appConfig.distribution,\n };\n}\n"],"names":["overrideLogger","AppDistribution","MerchantCustomAuth","TokenExchangeStrategy","AuthCodeFlowStrategy","authStrategyFactory","addDocumentResponseHeadersFactory","registerWebhooksFactory","authenticateFlowFactory","authenticatePublicFactory","authenticateFulfillmentServiceFactory","authenticateWebhookFactory","unauthenticatedAdminContextFactory","unauthenticatedStorefrontContextFactory","loginFactory","logDisabledFutureFlags","ShopifyError","SHOPIFY_REMIX_LIBRARY_VERSION","shopifyApi","IdempotentPromiseHandler"],"mappings":"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"}
1
+ {"version":3,"file":"shopify-app.js","sources":["../../../../src/server/shopify-app.ts"],"sourcesContent":["import '@shopify/shopify-api/adapters/web-api';\nimport {\n ConfigInterface as ApiConfig,\n ShopifyError,\n shopifyApi,\n} from '@shopify/shopify-api';\nimport {SessionStorage} from '@shopify/shopify-app-session-storage';\n\nimport {type AppConfig, type AppConfigArg} from './config-types';\nimport {\n AppDistribution,\n type BasicParams,\n type ShopifyApp,\n type ShopifyAppBase,\n type AdminApp,\n type SingleMerchantApp,\n type AppStoreApp,\n} from './types';\nimport {SHOPIFY_REMIX_LIBRARY_VERSION} from './version';\nimport {registerWebhooksFactory} from './authenticate/webhooks';\nimport {authStrategyFactory} from './authenticate/admin/authenticate';\nimport {authenticateWebhookFactory} from './authenticate/webhooks/authenticate';\nimport {overrideLogger} from './override-logger';\nimport {addDocumentResponseHeadersFactory} from './authenticate/helpers';\nimport {loginFactory} from './authenticate/login/login';\nimport {unauthenticatedAdminContextFactory} from './unauthenticated/admin';\nimport {authenticatePublicFactory} from './authenticate/public';\nimport {unauthenticatedStorefrontContextFactory} from './unauthenticated/storefront';\nimport {AuthCodeFlowStrategy} from './authenticate/admin/strategies/auth-code-flow';\nimport {TokenExchangeStrategy} from './authenticate/admin/strategies/token-exchange';\nimport {MerchantCustomAuth} from './authenticate/admin/strategies/merchant-custom-app';\nimport {IdempotentPromiseHandler} from './authenticate/helpers/idempotent-promise-handler';\nimport {authenticateFlowFactory} from './authenticate/flow/authenticate';\nimport {authenticateFulfillmentServiceFactory} from './authenticate/fulfillment-service/authenticate';\nimport {FutureFlagOptions, logDisabledFutureFlags} from './future/flags';\n\n/**\n * Creates an object your app will use to interact with Shopify.\n *\n * @param appConfig Configuration options for your Shopify app, such as the scopes your app needs.\n * @returns `ShopifyApp` An object constructed using your appConfig. It has methods for interacting with Shopify.\n * @publicDocs\n *\n * @example\n * <caption>The minimum viable configuration</caption>\n * ```ts\n * // /shopify.server.ts\n * import { shopifyApp } from \"@shopify/shopify-app-remix/server\";\n *\n * const shopify = shopifyApp({\n * apiKey: process.env.SHOPIFY_API_KEY!,\n * apiSecretKey: process.env.SHOPIFY_API_SECRET!,\n * scopes: process.env.SCOPES?.split(\",\")!,\n * appUrl: process.env.SHOPIFY_APP_URL!,\n * });\n * export default shopify;\n * ```\n */\nexport function shopifyApp<\n Config extends AppConfigArg<Storage, Future>,\n Storage extends SessionStorage,\n Future extends FutureFlagOptions = Config['future'],\n>(appConfig: Readonly<Config>): ShopifyApp<Config> {\n const api = deriveApi(appConfig);\n const config = deriveConfig<Storage>(appConfig, api.config);\n const logger = overrideLogger(api.logger);\n\n if (appConfig.webhooks) {\n api.webhooks.addHandlers(appConfig.webhooks);\n }\n\n const params: BasicParams = {api, config, logger};\n\n let strategy;\n if (config.distribution === AppDistribution.ShopifyAdmin) {\n strategy = new MerchantCustomAuth(params);\n } else if (\n config.future.unstable_newEmbeddedAuthStrategy &&\n config.isEmbeddedApp\n ) {\n strategy = new TokenExchangeStrategy(params);\n } else {\n strategy = new AuthCodeFlowStrategy(params);\n }\n\n const authStrategy = authStrategyFactory<Config>({\n ...params,\n strategy,\n });\n\n const shopify:\n | AdminApp<Config>\n | AppStoreApp<Config>\n | SingleMerchantApp<Config> = {\n sessionStorage: config.sessionStorage,\n addDocumentResponseHeaders: addDocumentResponseHeadersFactory(params),\n registerWebhooks: registerWebhooksFactory(params),\n authenticate: {\n admin: authStrategy,\n flow: authenticateFlowFactory(params),\n public: authenticatePublicFactory(params),\n fulfillmentService: authenticateFulfillmentServiceFactory(params),\n webhook: authenticateWebhookFactory<string>(params),\n },\n unauthenticated: {\n admin: unauthenticatedAdminContextFactory(params),\n storefront: unauthenticatedStorefrontContextFactory(params),\n },\n };\n\n if (\n isAppStoreApp(shopify, appConfig) ||\n isSingleMerchantApp(shopify, appConfig)\n ) {\n shopify.login = loginFactory(params);\n }\n\n logDisabledFutureFlags(config, logger);\n\n return shopify as ShopifyApp<Config>;\n}\n\nfunction isAppStoreApp<Config extends AppConfigArg>(\n _shopify: ShopifyAppBase<Config>,\n config: Config,\n): _shopify is AppStoreApp<Config> {\n return config.distribution === AppDistribution.AppStore;\n}\n\nfunction isSingleMerchantApp<Config extends AppConfigArg>(\n _shopify: ShopifyAppBase<Config>,\n config: Config,\n): _shopify is SingleMerchantApp<Config> {\n return config.distribution === AppDistribution.SingleMerchant;\n}\n\n// This function is only exported so we can unit test it without having to mock the underlying module.\n// It's not available to consumers of the library because it is not exported in the index module, and never should be.\nexport function deriveApi(appConfig: AppConfigArg): BasicParams['api'] {\n let appUrl: URL;\n try {\n appUrl = new URL(appConfig.appUrl);\n } catch (error) {\n const message =\n appConfig.appUrl === ''\n ? `Detected an empty appUrl configuration, please make sure to set the necessary environment variables.\\n` +\n `If you're deploying your app, you can find more information at https://shopify.dev/docs/apps/launch/deployment/deploy-web-app/deploy-to-hosting-service#step-4-set-up-environment-variables`\n : `Invalid appUrl configuration '${appConfig.appUrl}', please provide a valid URL.`;\n throw new ShopifyError(message);\n }\n\n /* eslint-disable no-process-env */\n if (appUrl.hostname === 'localhost' && !appUrl.port && process.env.PORT) {\n appUrl.port = process.env.PORT;\n }\n /* eslint-enable no-process-env */\n appConfig.appUrl = appUrl.origin;\n\n let userAgentPrefix = `Shopify Remix Library v${SHOPIFY_REMIX_LIBRARY_VERSION}`;\n if (appConfig.userAgentPrefix) {\n userAgentPrefix = `${appConfig.userAgentPrefix} | ${userAgentPrefix}`;\n }\n\n return shopifyApi({\n ...appConfig,\n hostName: appUrl.host,\n hostScheme: appUrl.protocol.replace(':', '') as 'http' | 'https',\n userAgentPrefix,\n isEmbeddedApp: appConfig.isEmbeddedApp ?? true,\n apiVersion: appConfig.apiVersion,\n isCustomStoreApp: appConfig.distribution === AppDistribution.ShopifyAdmin,\n billing: appConfig.billing as ApiConfig['billing'],\n future: {\n unstable_managedPricingSupport: true,\n },\n _logDisabledFutureFlags: false,\n });\n}\n\nfunction deriveConfig<Storage extends SessionStorage>(\n appConfig: AppConfigArg,\n apiConfig: ApiConfig,\n): AppConfig<Storage> {\n if (\n !appConfig.sessionStorage &&\n appConfig.distribution !== AppDistribution.ShopifyAdmin\n ) {\n throw new ShopifyError(\n 'Please provide a valid session storage. Refer to https://github.com/Shopify/shopify-app-js/blob/main/README.md#session-storage-options for options.',\n );\n }\n\n const authPathPrefix = appConfig.authPathPrefix || '/auth';\n appConfig.distribution = appConfig.distribution ?? AppDistribution.AppStore;\n\n return {\n ...appConfig,\n ...apiConfig,\n billing: appConfig.billing as ApiConfig['billing'],\n scopes: apiConfig.scopes,\n idempotentPromiseHandler: new IdempotentPromiseHandler(),\n canUseLoginForm: appConfig.distribution !== AppDistribution.ShopifyAdmin,\n useOnlineTokens: appConfig.useOnlineTokens ?? false,\n hooks: appConfig.hooks ?? {},\n sessionStorage: appConfig.sessionStorage as Storage,\n future: appConfig.future ?? {},\n auth: {\n path: authPathPrefix,\n callbackPath: `${authPathPrefix}/callback`,\n patchSessionTokenPath: `${authPathPrefix}/session-token`,\n exitIframePath: `${authPathPrefix}/exit-iframe`,\n loginPath: `${authPathPrefix}/login`,\n },\n distribution: appConfig.distribution,\n };\n}\n"],"names":["overrideLogger","AppDistribution","MerchantCustomAuth","TokenExchangeStrategy","AuthCodeFlowStrategy","authStrategyFactory","addDocumentResponseHeadersFactory","registerWebhooksFactory","authenticateFlowFactory","authenticatePublicFactory","authenticateFulfillmentServiceFactory","authenticateWebhookFactory","unauthenticatedAdminContextFactory","unauthenticatedStorefrontContextFactory","loginFactory","logDisabledFutureFlags","ShopifyError","SHOPIFY_REMIX_LIBRARY_VERSION","shopifyApi","IdempotentPromiseHandler"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const SHOPIFY_REMIX_LIBRARY_VERSION = '4.2.0';
3
+ const SHOPIFY_REMIX_LIBRARY_VERSION = '4.2.1';
4
4
 
5
5
  exports.SHOPIFY_REMIX_LIBRARY_VERSION = SHOPIFY_REMIX_LIBRARY_VERSION;
6
6
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sources":["../../../../src/server/version.ts"],"sourcesContent":["export const SHOPIFY_REMIX_LIBRARY_VERSION = '4.2.0';\n"],"names":[],"mappings":";;AAAO,MAAM,6BAA6B,GAAG;;;;"}
1
+ {"version":3,"file":"version.js","sources":["../../../../src/server/version.ts"],"sourcesContent":["export const SHOPIFY_REMIX_LIBRARY_VERSION = '4.2.1';\n"],"names":[],"mappings":";;AAAO,MAAM,6BAA6B,GAAG;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"AppProvider.mjs","sources":["../../../../../../src/react/components/AppProvider/AppProvider.tsx"],"sourcesContent":["import {\n AppProvider as PolarisAppProvider,\n AppProviderProps as PolarisAppProviderProps,\n} from '@shopify/polaris';\n// This leads to some TS errors, but it does compile to something that works\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport englishI18n from '@shopify/polaris/locales/en.json' with {type: 'json'};\nimport {useNavigate} from '@remix-run/react';\nimport {useEffect} from 'react';\n\nimport {APP_BRIDGE_URL} from '../../const';\nimport {RemixPolarisLink} from '../RemixPolarisLink';\n\nexport interface AppProviderProps extends Omit<\n PolarisAppProviderProps,\n 'linkComponent' | 'i18n'\n> {\n /**\n * The API key for your Shopify app. This is the `Client ID` from the Partner Dashboard.\n *\n * When using the Shopify CLI, this is the `SHOPIFY_API_KEY` environment variable. If you're using the environment\n * variable, then you need to pass it from the loader to the component.\n */\n apiKey: string;\n /**\n * Whether the app is loaded inside the Shopify Admin. Default is `true`.\n *\n * {@link https://shopify.dev/docs/apps/admin/embedded-app-home}\n */\n isEmbeddedApp?: boolean;\n /**\n * The internationalization (i18n) configuration for your Polaris provider.\n *\n * {@link https://polaris.shopify.com/components/utilities/app-provider}\n */\n i18n?: PolarisAppProviderProps['i18n'];\n /**\n * Used internally by Shopify. You don't need to set this.\n * @private\n */\n __APP_BRIDGE_URL?: string;\n}\n\n/**\n * Sets up the Polaris `AppProvider` and injects the App Bridge script.\n *\n * This component extends the [`AppProvider`](https://polaris.shopify.com/components/utilities/app-provider) component\n * from Polaris, and accepts all of its props except for `linkComponent`, which is overridden to use the Remix `Link`\n * component.\n *\n * {@link https://polaris.shopify.com/components/utilities/app-provider}\n * {@link https://shopify.dev/tools/app-bridge}\n *\n * @example\n * <caption>Set up AppProvider.</caption>\n * <description>Wrap your app in the `AppProvider` component and pass in your API key.</description>\n * ```ts\n * // /app/routes/**\\/*.ts\n * import {authenticate} from '~/shopify.server';\n * import {AppProvider} from '@shopify/shopify-app-remix/react';\n *\n * export async function loader({ request }) {\n * await authenticate.admin(request);\n *\n * return json({ apiKey: process.env.SHOPIFY_API_KEY });\n * }\n *\n * export default function App() {\n * const { apiKey } = useLoaderData();\n *\n * return (\n * <AppProvider isEmbeddedApp apiKey={apiKey}>\n * <Outlet />\n * </AppProvider>\n * );\n * }\n * ```\n *\n * @example\n * <caption>Localize Polaris components.</caption>\n * <description>Pass in a different locale for Polaris to translate its components.</description>\n * ```ts\n * // /app/routes/**\\/*.ts\n * import {authenticate} from '~/shopify.server';\n * import {AppProvider} from '@shopify/shopify-app-remix/react';\n *\n * export async function loader({ request }) {\n * await authenticate.admin(request);\n *\n * return json({\n * apiKey: process.env.SHOPIFY_API_KEY,\n * polarisTranslations: require(\"@shopify/polaris/locales/fr.json\"),\n * });\n * }\n *\n * export default function App() {\n * const { apiKey, polarisTranslations } = useLoaderData();\n *\n * return (\n * <AppProvider apiKey={apiKey} i18n={polarisTranslations}>\n * <Outlet />\n * </AppProvider>\n * );\n * }\n * ```\n */\nexport function AppProvider(props: AppProviderProps) {\n const {\n children,\n apiKey,\n i18n,\n isEmbeddedApp = true,\n __APP_BRIDGE_URL = APP_BRIDGE_URL,\n ...polarisProps\n } = props;\n\n const navigate = useNavigate();\n\n useEffect(() => {\n const handleNavigate = (event: Event) => {\n const href = (event.target as HTMLElement)?.getAttribute('href');\n if (href) {\n navigate(href);\n }\n };\n\n addEventListener('shopify:navigate', handleNavigate);\n\n return () => {\n removeEventListener('shopify:navigate', handleNavigate);\n };\n }, [navigate]);\n\n return (\n <>\n {isEmbeddedApp && <script src={__APP_BRIDGE_URL} data-api-key={apiKey} />}\n <PolarisAppProvider\n {...polarisProps}\n linkComponent={RemixPolarisLink}\n i18n={i18n || englishI18n}\n >\n {children}\n </PolarisAppProvider>\n </>\n );\n}\n"],"names":["_jsxs","_Fragment","_jsx","PolarisAppProvider"],"mappings":";;;;;;;;AA4CA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8DG;AACG,SAAU,WAAW,CAAC,KAAuB,EAAA;IACjD,MAAM,EACJ,QAAQ,EACR,MAAM,EACN,IAAI,EACJ,aAAa,GAAG,IAAI,EACpB,gBAAgB,GAAG,cAAc,EACjC,GAAG,YAAY,EAChB,GAAG,KAAK;AAET,IAAA,MAAM,QAAQ,GAAG,WAAW,EAAE;IAE9B,SAAS,CAAC,MAAK;AACb,QAAA,MAAM,cAAc,GAAG,CAAC,KAAY,KAAI;YACtC,MAAM,IAAI,GAAI,KAAK,CAAC,MAAsB,EAAE,YAAY,CAAC,MAAM,CAAC;YAChE,IAAI,IAAI,EAAE;gBACR,QAAQ,CAAC,IAAI,CAAC;YAChB;AACF,QAAA,CAAC;AAED,QAAA,gBAAgB,CAAC,kBAAkB,EAAE,cAAc,CAAC;AAEpD,QAAA,OAAO,MAAK;AACV,YAAA,mBAAmB,CAAC,kBAAkB,EAAE,cAAc,CAAC;AACzD,QAAA,CAAC;AACH,IAAA,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;AAEd,IAAA,QACEA,IAAA,CAAAC,QAAA,EAAA,EAAA,QAAA,EAAA,CACG,aAAa,IAAIC,GAAA,CAAA,QAAA,EAAA,EAAQ,GAAG,EAAE,gBAAgB,EAAA,cAAA,EAAgB,MAAM,EAAA,CAAI,EACzEA,IAACC,aAAkB,EAAA,EAAA,GACb,YAAY,EAChB,aAAa,EAAE,gBAAgB,EAC/B,IAAI,EAAE,IAAI,IAAI,WAAW,EAAA,QAAA,EAExB,QAAQ,EAAA,CACU,CAAA,EAAA,CACpB;AAEP;;;;"}
1
+ {"version":3,"file":"AppProvider.mjs","sources":["../../../../../../src/react/components/AppProvider/AppProvider.tsx"],"sourcesContent":["import {\n AppProvider as PolarisAppProvider,\n AppProviderProps as PolarisAppProviderProps,\n} from '@shopify/polaris';\n// This leads to some TS errors, but it does compile to something that works\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport englishI18n from '@shopify/polaris/locales/en.json' with {type: 'json'};\nimport {useNavigate} from '@remix-run/react';\nimport {useEffect} from 'react';\n\nimport {APP_BRIDGE_URL} from '../../const';\nimport {RemixPolarisLink} from '../RemixPolarisLink';\n\n/**\n * Props for the `AppProvider` component.\n * @publicDocs\n */\nexport interface AppProviderProps extends Omit<\n PolarisAppProviderProps,\n 'linkComponent' | 'i18n'\n> {\n /**\n * The API key for your Shopify app. This is the `Client ID` from the Partner Dashboard.\n *\n * When using the Shopify CLI, this is the `SHOPIFY_API_KEY` environment variable. If you're using the environment\n * variable, then you need to pass it from the loader to the component.\n */\n apiKey: string;\n /**\n * Whether the app is loaded inside the Shopify Admin. Default is `true`.\n *\n * {@link https://shopify.dev/docs/apps/admin/embedded-app-home}\n */\n isEmbeddedApp?: boolean;\n /**\n * The internationalization (i18n) configuration for your Polaris provider.\n *\n * {@link https://polaris.shopify.com/components/utilities/app-provider}\n */\n i18n?: PolarisAppProviderProps['i18n'];\n /**\n * Used internally by Shopify. You don't need to set this.\n * @private\n */\n __APP_BRIDGE_URL?: string;\n}\n\n/**\n * Sets up the Polaris `AppProvider` and injects the App Bridge script.\n *\n * This component extends the [`AppProvider`](https://polaris.shopify.com/components/utilities/app-provider) component\n * from Polaris, and accepts all of its props except for `linkComponent`, which is overridden to use the Remix `Link`\n * component.\n *\n * {@link https://polaris.shopify.com/components/utilities/app-provider}\n * {@link https://shopify.dev/tools/app-bridge}\n *\n * @example\n * <caption>Set up AppProvider.</caption>\n * <description>Wrap your app in the `AppProvider` component and pass in your API key.</description>\n * ```ts\n * // /app/routes/**\\/*.ts\n * import {authenticate} from '~/shopify.server';\n * import {AppProvider} from '@shopify/shopify-app-remix/react';\n *\n * export async function loader({ request }) {\n * await authenticate.admin(request);\n *\n * return json({ apiKey: process.env.SHOPIFY_API_KEY });\n * }\n *\n * export default function App() {\n * const { apiKey } = useLoaderData();\n *\n * return (\n * <AppProvider isEmbeddedApp apiKey={apiKey}>\n * <Outlet />\n * </AppProvider>\n * );\n * }\n * ```\n *\n * @example\n * <caption>Localize Polaris components.</caption>\n * <description>Pass in a different locale for Polaris to translate its components.</description>\n * ```ts\n * // /app/routes/**\\/*.ts\n * import {authenticate} from '~/shopify.server';\n * import {AppProvider} from '@shopify/shopify-app-remix/react';\n *\n * export async function loader({ request }) {\n * await authenticate.admin(request);\n *\n * return json({\n * apiKey: process.env.SHOPIFY_API_KEY,\n * polarisTranslations: require(\"@shopify/polaris/locales/fr.json\"),\n * });\n * }\n *\n * export default function App() {\n * const { apiKey, polarisTranslations } = useLoaderData();\n *\n * return (\n * <AppProvider apiKey={apiKey} i18n={polarisTranslations}>\n * <Outlet />\n * </AppProvider>\n * );\n * }\n * ```\n */\nexport function AppProvider(props: AppProviderProps) {\n const {\n children,\n apiKey,\n i18n,\n isEmbeddedApp = true,\n __APP_BRIDGE_URL = APP_BRIDGE_URL,\n ...polarisProps\n } = props;\n\n const navigate = useNavigate();\n\n useEffect(() => {\n const handleNavigate = (event: Event) => {\n const href = (event.target as HTMLElement)?.getAttribute('href');\n if (href) {\n navigate(href);\n }\n };\n\n addEventListener('shopify:navigate', handleNavigate);\n\n return () => {\n removeEventListener('shopify:navigate', handleNavigate);\n };\n }, [navigate]);\n\n return (\n <>\n {isEmbeddedApp && <script src={__APP_BRIDGE_URL} data-api-key={apiKey} />}\n <PolarisAppProvider\n {...polarisProps}\n linkComponent={RemixPolarisLink}\n i18n={i18n || englishI18n}\n >\n {children}\n </PolarisAppProvider>\n </>\n );\n}\n"],"names":["_jsxs","_Fragment","_jsx","PolarisAppProvider"],"mappings":";;;;;;;;AAgDA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8DG;AACG,SAAU,WAAW,CAAC,KAAuB,EAAA;IACjD,MAAM,EACJ,QAAQ,EACR,MAAM,EACN,IAAI,EACJ,aAAa,GAAG,IAAI,EACpB,gBAAgB,GAAG,cAAc,EACjC,GAAG,YAAY,EAChB,GAAG,KAAK;AAET,IAAA,MAAM,QAAQ,GAAG,WAAW,EAAE;IAE9B,SAAS,CAAC,MAAK;AACb,QAAA,MAAM,cAAc,GAAG,CAAC,KAAY,KAAI;YACtC,MAAM,IAAI,GAAI,KAAK,CAAC,MAAsB,EAAE,YAAY,CAAC,MAAM,CAAC;YAChE,IAAI,IAAI,EAAE;gBACR,QAAQ,CAAC,IAAI,CAAC;YAChB;AACF,QAAA,CAAC;AAED,QAAA,gBAAgB,CAAC,kBAAkB,EAAE,cAAc,CAAC;AAEpD,QAAA,OAAO,MAAK;AACV,YAAA,mBAAmB,CAAC,kBAAkB,EAAE,cAAc,CAAC;AACzD,QAAA,CAAC;AACH,IAAA,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;AAEd,IAAA,QACEA,IAAA,CAAAC,QAAA,EAAA,EAAA,QAAA,EAAA,CACG,aAAa,IAAIC,GAAA,CAAA,QAAA,EAAA,EAAQ,GAAG,EAAE,gBAAgB,EAAA,cAAA,EAAgB,MAAM,EAAA,CAAI,EACzEA,IAACC,aAAkB,EAAA,EAAA,GACb,YAAY,EAChB,aAAa,EAAE,gBAAgB,EAC/B,IAAI,EAAE,IAAI,IAAI,WAAW,EAAA,QAAA,EAExB,QAAQ,EAAA,CACU,CAAA,EAAA,CACpB;AAEP;;;;"}
@@ -1,5 +1,5 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
- import { useContext } from 'react';
2
+ import { forwardRef, useContext } from 'react';
3
3
  import { Form } from '@remix-run/react';
4
4
  import { AppProxyProviderContext } from '../AppProxyProvider/AppProxyProvider.mjs';
5
5
 
@@ -58,15 +58,16 @@ import { AppProxyProviderContext } from '../AppProxyProvider/AppProxyProvider.mj
58
58
  * );
59
59
  * }
60
60
  * ```
61
+ * @publicDocs
61
62
  */
62
- function AppProxyForm(props) {
63
+ const AppProxyForm = forwardRef(function AppProxyForm(props, ref) {
63
64
  const context = useContext(AppProxyProviderContext);
64
65
  if (!context) {
65
66
  throw new Error('AppProxyForm must be used within an AppProxyProvider component');
66
67
  }
67
68
  const { children, action, ...otherProps } = props;
68
- return (jsx(Form, { action: context.formatUrl(action, false), ...otherProps, children: children }));
69
- }
69
+ return (jsx(Form, { action: context.formatUrl(action, false), ...otherProps, ref: ref, children: children }));
70
+ });
70
71
 
71
72
  export { AppProxyForm };
72
73
  //# sourceMappingURL=AppProxyForm.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"AppProxyForm.mjs","sources":["../../../../../../src/react/components/AppProxyForm/AppProxyForm.tsx"],"sourcesContent":["import {useContext} from 'react';\nimport {Form, type FormProps} from '@remix-run/react';\n\nimport {AppProxyProviderContext} from '../AppProxyProvider';\n\nexport interface AppProxyFormProps extends FormProps {\n action: string;\n}\n\n/**\n * Sets up a Remix `<Form>` component that works when rendered on an app proxy page.\n *\n * Supports any properties accepted by the `<Form>` component.\n *\n * Because Remix doesn't support URL rewriting, any route using this component should <b>match the pathname of the proxy\n * URL exactly</b>, and <b>end in a trailing slash</b> (e.g., `https://<shop>/apps/proxy/`), or set the Remix Form prop\n * `navigate` to `false`.\n *\n * @example\n * <caption>Render a form element in a proxied route.</caption>\n * <description>Use an `AppProxyForm` within an `AppProxy` to create a form.</description>\n * ```ts\n * // /app/routes/apps/appProxy.ts\n * import {\n * AppProxyProvider,\n * AppProxyForm,\n * } from \"@shopify/shopify-app-remix/react\";\n * import { authenticate } from \"~/shopify.server\";\n *\n * export async function loader({ request }) {\n * await authenticate.public.appProxy(request);\n *\n * return json({ appUrl: process.env.SHOPIFY_APP_URL });\n * }\n *\n * export async function action({ request }) {\n * await authenticate.public.appProxy(request);\n *\n * const formData = await request.formData();\n * const field = formData.get(\"field\")?.toString();\n *\n * // Perform actions\n * if (field) {\n * console.log(\"Field:\", field);\n * }\n *\n * // Return JSON to the client\n * return json({ message: \"Success!\" });\n * }\n *\n * export default function App() {\n * const { appUrl } = useLoaderData();\n *\n * return (\n * <AppProxyProvider appUrl={appUrl}>\n * <AppProxyForm action=\"/apps/appProxy\" method=\"post\">\n * <input type=\"text\" name=\"field\" />\n *\n * <input type=\"submit\" name=\"Submit\" />\n * </AppProxyForm>\n * </AppProxyProvider>\n * );\n * }\n * ```\n */\nexport function AppProxyForm(props: AppProxyFormProps) {\n const context = useContext(AppProxyProviderContext);\n\n if (!context) {\n throw new Error(\n 'AppProxyForm must be used within an AppProxyProvider component',\n );\n }\n\n const {children, action, ...otherProps} = props;\n\n return (\n <Form action={context.formatUrl(action, false)} {...otherProps}>\n {children}\n </Form>\n );\n}\n"],"names":["_jsx"],"mappings":";;;;;AASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuDG;AACG,SAAU,YAAY,CAAC,KAAwB,EAAA;AACnD,IAAA,MAAM,OAAO,GAAG,UAAU,CAAC,uBAAuB,CAAC;IAEnD,IAAI,CAAC,OAAO,EAAE;AACZ,QAAA,MAAM,IAAI,KAAK,CACb,gEAAgE,CACjE;IACH;IAEA,MAAM,EAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAC,GAAG,KAAK;IAE/C,QACEA,IAAC,IAAI,EAAA,EAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,EAAA,GAAM,UAAU,YAC3D,QAAQ,EAAA,CACJ;AAEX;;;;"}
1
+ {"version":3,"file":"AppProxyForm.mjs","sources":["../../../../../../src/react/components/AppProxyForm/AppProxyForm.tsx"],"sourcesContent":["import {forwardRef, useContext} from 'react';\nimport {Form, type FormProps} from '@remix-run/react';\n\nimport {AppProxyProviderContext} from '../AppProxyProvider';\n\nexport interface AppProxyFormProps extends FormProps {\n action: string;\n}\n\n/**\n * Sets up a Remix `<Form>` component that works when rendered on an app proxy page.\n *\n * Supports any properties accepted by the `<Form>` component.\n *\n * Because Remix doesn't support URL rewriting, any route using this component should <b>match the pathname of the proxy\n * URL exactly</b>, and <b>end in a trailing slash</b> (e.g., `https://<shop>/apps/proxy/`), or set the Remix Form prop\n * `navigate` to `false`.\n *\n * @example\n * <caption>Render a form element in a proxied route.</caption>\n * <description>Use an `AppProxyForm` within an `AppProxy` to create a form.</description>\n * ```ts\n * // /app/routes/apps/appProxy.ts\n * import {\n * AppProxyProvider,\n * AppProxyForm,\n * } from \"@shopify/shopify-app-remix/react\";\n * import { authenticate } from \"~/shopify.server\";\n *\n * export async function loader({ request }) {\n * await authenticate.public.appProxy(request);\n *\n * return json({ appUrl: process.env.SHOPIFY_APP_URL });\n * }\n *\n * export async function action({ request }) {\n * await authenticate.public.appProxy(request);\n *\n * const formData = await request.formData();\n * const field = formData.get(\"field\")?.toString();\n *\n * // Perform actions\n * if (field) {\n * console.log(\"Field:\", field);\n * }\n *\n * // Return JSON to the client\n * return json({ message: \"Success!\" });\n * }\n *\n * export default function App() {\n * const { appUrl } = useLoaderData();\n *\n * return (\n * <AppProxyProvider appUrl={appUrl}>\n * <AppProxyForm action=\"/apps/appProxy\" method=\"post\">\n * <input type=\"text\" name=\"field\" />\n *\n * <input type=\"submit\" name=\"Submit\" />\n * </AppProxyForm>\n * </AppProxyProvider>\n * );\n * }\n * ```\n * @publicDocs\n */\nexport const AppProxyForm = forwardRef<HTMLFormElement, AppProxyFormProps>(\n function AppProxyForm(props, ref) {\n const context = useContext(AppProxyProviderContext);\n\n if (!context) {\n throw new Error(\n 'AppProxyForm must be used within an AppProxyProvider component',\n );\n }\n\n const {children, action, ...otherProps} = props;\n\n return (\n <Form action={context.formatUrl(action, false)} {...otherProps} ref={ref}>\n {children}\n </Form>\n );\n },\n);\n"],"names":["_jsx"],"mappings":";;;;;AASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwDG;AACI,MAAM,YAAY,GAAG,UAAU,CACpC,SAAS,YAAY,CAAC,KAAK,EAAE,GAAG,EAAA;AAC9B,IAAA,MAAM,OAAO,GAAG,UAAU,CAAC,uBAAuB,CAAC;IAEnD,IAAI,CAAC,OAAO,EAAE;AACZ,QAAA,MAAM,IAAI,KAAK,CACb,gEAAgE,CACjE;IACH;IAEA,MAAM,EAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,EAAC,GAAG,KAAK;IAE/C,QACEA,GAAA,CAAC,IAAI,EAAA,EAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,EAAA,GAAM,UAAU,EAAE,GAAG,EAAE,GAAG,EAAA,QAAA,EACrE,QAAQ,EAAA,CACJ;AAEX,CAAC;;;;"}
@@ -1,5 +1,5 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
- import { useContext } from 'react';
2
+ import { forwardRef, useContext } from 'react';
3
3
  import { AppProxyProviderContext } from '../AppProxyProvider/AppProxyProvider.mjs';
4
4
 
5
5
  /**
@@ -31,15 +31,16 @@ import { AppProxyProviderContext } from '../AppProxyProvider/AppProxyProvider.mj
31
31
  * );
32
32
  * }
33
33
  * ```
34
+ * @publicDocs
34
35
  */
35
- function AppProxyLink(props) {
36
+ const AppProxyLink = forwardRef(function AppProxyLink(props, ref) {
36
37
  const context = useContext(AppProxyProviderContext);
37
38
  if (!context) {
38
39
  throw new Error('AppProxyLink must be used within an AppProxyProvider component');
39
40
  }
40
41
  const { children, href, ...otherProps } = props;
41
- return (jsx("a", { href: context.formatUrl(href), ...otherProps, children: children }));
42
- }
42
+ return (jsx("a", { href: context.formatUrl(href), ...otherProps, ref: ref, children: children }));
43
+ });
43
44
 
44
45
  export { AppProxyLink };
45
46
  //# sourceMappingURL=AppProxyLink.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"AppProxyLink.mjs","sources":["../../../../../../src/react/components/AppProxyLink/AppProxyLink.tsx"],"sourcesContent":["import {useContext} from 'react';\n\nimport {AppProxyProviderContext} from '../AppProxyProvider';\n\nexport interface AppProxyLinkProps extends React.DetailedHTMLProps<\n React.AnchorHTMLAttributes<HTMLAnchorElement>,\n HTMLAnchorElement\n> {\n href: string;\n}\n\n/**\n * Sets up an `<a />` HTML element that works when rendered behind an app proxy.\n *\n * Supports any properties accepted by the `<a />` HTML element.\n *\n * @example\n * <caption>Link to a different route.</caption>\n * <description>Use an `AppProxyLink` within an `AppProxyProvider` to link to a different proxied route.</description>\n * ```ts\n * // /app/routes/**\\/*.ts\n * import {authenticate} from '~/shopify.server';\n * import {AppProxyProvider, AppProxyLink} from '@shopify/shopify-app-remix/react';\n *\n * export async function loader({ request }) {\n * await authenticate.public.appProxy(request);\n *\n * return json({ appUrl: process.env.SHOPIFY_APP_URL });\n * }\n *\n * export default function App() {\n * const { appUrl } = useLoaderData();\n *\n * return (\n * <AppProxyProvider appUrl={appUrl}>\n * <AppProxyLink href=\"/other-proxy-route\">Link to another route</AppProxyLink>\n * </AppProxyProvider>\n * );\n * }\n * ```\n */\nexport function AppProxyLink(props: AppProxyLinkProps) {\n const context = useContext(AppProxyProviderContext);\n\n if (!context) {\n throw new Error(\n 'AppProxyLink must be used within an AppProxyProvider component',\n );\n }\n\n const {children, href, ...otherProps} = props;\n\n return (\n <a href={context.formatUrl(href)} {...otherProps}>\n {children}\n </a>\n );\n}\n"],"names":["_jsx"],"mappings":";;;;AAWA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BG;AACG,SAAU,YAAY,CAAC,KAAwB,EAAA;AACnD,IAAA,MAAM,OAAO,GAAG,UAAU,CAAC,uBAAuB,CAAC;IAEnD,IAAI,CAAC,OAAO,EAAE;AACZ,QAAA,MAAM,IAAI,KAAK,CACb,gEAAgE,CACjE;IACH;IAEA,MAAM,EAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,UAAU,EAAC,GAAG,KAAK;AAE7C,IAAA,QACEA,GAAA,CAAA,GAAA,EAAA,EAAG,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,KAAM,UAAU,EAAA,QAAA,EAC7C,QAAQ,EAAA,CACP;AAER;;;;"}
1
+ {"version":3,"file":"AppProxyLink.mjs","sources":["../../../../../../src/react/components/AppProxyLink/AppProxyLink.tsx"],"sourcesContent":["import {forwardRef, useContext} from 'react';\n\nimport {AppProxyProviderContext} from '../AppProxyProvider';\n\nexport interface AppProxyLinkProps extends React.DetailedHTMLProps<\n React.AnchorHTMLAttributes<HTMLAnchorElement>,\n HTMLAnchorElement\n> {\n href: string;\n}\n\n/**\n * Sets up an `<a />` HTML element that works when rendered behind an app proxy.\n *\n * Supports any properties accepted by the `<a />` HTML element.\n *\n * @example\n * <caption>Link to a different route.</caption>\n * <description>Use an `AppProxyLink` within an `AppProxyProvider` to link to a different proxied route.</description>\n * ```ts\n * // /app/routes/**\\/*.ts\n * import {authenticate} from '~/shopify.server';\n * import {AppProxyProvider, AppProxyLink} from '@shopify/shopify-app-remix/react';\n *\n * export async function loader({ request }) {\n * await authenticate.public.appProxy(request);\n *\n * return json({ appUrl: process.env.SHOPIFY_APP_URL });\n * }\n *\n * export default function App() {\n * const { appUrl } = useLoaderData();\n *\n * return (\n * <AppProxyProvider appUrl={appUrl}>\n * <AppProxyLink href=\"/other-proxy-route\">Link to another route</AppProxyLink>\n * </AppProxyProvider>\n * );\n * }\n * ```\n * @publicDocs\n */\nexport const AppProxyLink = forwardRef<HTMLAnchorElement, AppProxyLinkProps>(\n function AppProxyLink(props, ref) {\n const context = useContext(AppProxyProviderContext);\n\n if (!context) {\n throw new Error(\n 'AppProxyLink must be used within an AppProxyProvider component',\n );\n }\n\n const {children, href, ...otherProps} = props;\n\n return (\n <a href={context.formatUrl(href)} {...otherProps} ref={ref}>\n {children}\n </a>\n );\n },\n);\n"],"names":["_jsx"],"mappings":";;;;AAWA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BG;AACI,MAAM,YAAY,GAAG,UAAU,CACpC,SAAS,YAAY,CAAC,KAAK,EAAE,GAAG,EAAA;AAC9B,IAAA,MAAM,OAAO,GAAG,UAAU,CAAC,uBAAuB,CAAC;IAEnD,IAAI,CAAC,OAAO,EAAE;AACZ,QAAA,MAAM,IAAI,KAAK,CACb,gEAAgE,CACjE;IACH;IAEA,MAAM,EAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,UAAU,EAAC,GAAG,KAAK;IAE7C,QACEA,WAAG,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,KAAM,UAAU,EAAE,GAAG,EAAE,GAAG,YACvD,QAAQ,EAAA,CACP;AAER,CAAC;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"AppProxyProvider.mjs","sources":["../../../../../../src/react/components/AppProxyProvider/AppProxyProvider.tsx"],"sourcesContent":["import {createContext, useEffect, useState} from 'react';\n\nexport interface AppProxyProviderProps {\n /**\n * The URL where the app is hosted. You can set this from the `SHOPIFY_APP_URL` environment variable.\n */\n appUrl: string;\n\n /**\n * The children to render.\n */\n children?: React.ReactNode;\n}\n\ntype FormatUrlFunction = (\n url: string | undefined,\n addOrigin?: boolean,\n) => string | undefined;\n\ninterface AppProxyProviderContextProps {\n appUrl: string;\n formatUrl: FormatUrlFunction;\n requestUrl?: URL;\n}\n\nexport const AppProxyProviderContext =\n createContext<AppProxyProviderContextProps | null>(null);\n\n/**\n * Sets up a page to render behind a Shopify app proxy, enabling JavaScript and CSS to be loaded from the app.\n *\n * Also provides components that enable using other components such as links and forms within proxies.\n *\n * > Caution:\n * Because Remix doesn't support URL rewriting, any route using this component should <b>match the pathname of the proxy\n * URL exactly</b>, and <b>end in a trailing slash</b> (e.g., `https://<shop>/apps/proxy/`).\n *\n * @example\n * <caption>Wrap a route with an AppProxyProvider component.</caption>\n * <description>Wrap your route component in the `AppProxyProvider` component and pass in your app URL.</description>\n * ```ts\n * // /app/routes/**\\/*.ts\n * import {authenticate} from '~/shopify.server';\n * import {AppProxyProvider} from '@shopify/shopify-app-remix/react';\n *\n * export async function loader({ request }) {\n * await authenticate.public.appProxy(request);\n *\n * return json({ appUrl: process.env.SHOPIFY_APP_URL });\n * }\n *\n * export default function App() {\n * const { appUrl } = useLoaderData();\n *\n * return (\n * <AppProxyProvider appUrl={appUrl}>\n * Page content\n * </AppProxyProvider>\n * );\n * }\n * ```\n */\nexport function AppProxyProvider(props: AppProxyProviderProps) {\n const {children, appUrl} = props;\n const [requestUrl, setRequestUrl] = useState<URL | undefined>();\n\n useEffect(\n () => setRequestUrl(new URL(window.location.href)),\n [setRequestUrl],\n );\n\n return (\n <AppProxyProviderContext.Provider\n value={{appUrl, requestUrl, formatUrl: formatProxyUrl(requestUrl)}}\n >\n <base href={appUrl} />\n\n {children}\n </AppProxyProviderContext.Provider>\n );\n}\n\nfunction formatProxyUrl(requestUrl: URL | undefined): FormatUrlFunction {\n return (url: string | undefined, addOrigin = true) => {\n if (!url) {\n return url;\n }\n\n let finalUrl = url;\n\n if (addOrigin && requestUrl && finalUrl.startsWith('/')) {\n finalUrl = new URL(`${requestUrl.origin}${url}`).href;\n }\n if (!finalUrl.endsWith('/')) {\n finalUrl = `${finalUrl}/`;\n }\n\n return finalUrl;\n };\n}\n"],"names":["_jsxs","_jsx"],"mappings":";;;MAyBa,uBAAuB,GAClC,aAAa,CAAsC,IAAI;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCG;AACG,SAAU,gBAAgB,CAAC,KAA4B,EAAA;AAC3D,IAAA,MAAM,EAAC,QAAQ,EAAE,MAAM,EAAC,GAAG,KAAK;IAChC,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,EAAmB;IAE/D,SAAS,CACP,MAAM,aAAa,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAClD,CAAC,aAAa,CAAC,CAChB;AAED,IAAA,QACEA,IAAA,CAAC,uBAAuB,CAAC,QAAQ,EAAA,EAC/B,KAAK,EAAE,EAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,cAAc,CAAC,UAAU,CAAC,EAAC,EAAA,QAAA,EAAA,CAElEC,GAAA,CAAA,MAAA,EAAA,EAAM,IAAI,EAAE,MAAM,EAAA,CAAI,EAErB,QAAQ,CAAA,EAAA,CACwB;AAEvC;AAEA,SAAS,cAAc,CAAC,UAA2B,EAAA;AACjD,IAAA,OAAO,CAAC,GAAuB,EAAE,SAAS,GAAG,IAAI,KAAI;QACnD,IAAI,CAAC,GAAG,EAAE;AACR,YAAA,OAAO,GAAG;QACZ;QAEA,IAAI,QAAQ,GAAG,GAAG;QAElB,IAAI,SAAS,IAAI,UAAU,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;AACvD,YAAA,QAAQ,GAAG,IAAI,GAAG,CAAC,GAAG,UAAU,CAAC,MAAM,CAAA,EAAG,GAAG,CAAA,CAAE,CAAC,CAAC,IAAI;QACvD;QACA,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;AAC3B,YAAA,QAAQ,GAAG,CAAA,EAAG,QAAQ,CAAA,CAAA,CAAG;QAC3B;AAEA,QAAA,OAAO,QAAQ;AACjB,IAAA,CAAC;AACH;;;;"}
1
+ {"version":3,"file":"AppProxyProvider.mjs","sources":["../../../../../../src/react/components/AppProxyProvider/AppProxyProvider.tsx"],"sourcesContent":["import {createContext, useEffect, useState} from 'react';\n\n/**\n * Props for the `AppProxyProvider` component.\n * @publicDocs\n */\nexport interface AppProxyProviderProps {\n /**\n * The URL where the app is hosted. You can set this from the `SHOPIFY_APP_URL` environment variable.\n */\n appUrl: string;\n\n /**\n * The children to render.\n */\n children?: React.ReactNode;\n}\n\ntype FormatUrlFunction = (\n url: string | undefined,\n addOrigin?: boolean,\n) => string | undefined;\n\ninterface AppProxyProviderContextProps {\n appUrl: string;\n formatUrl: FormatUrlFunction;\n requestUrl?: URL;\n}\n\nexport const AppProxyProviderContext =\n createContext<AppProxyProviderContextProps | null>(null);\n\n/**\n * Sets up a page to render behind a Shopify app proxy, enabling JavaScript and CSS to be loaded from the app.\n *\n * Also provides components that enable using other components such as links and forms within proxies.\n *\n * > Caution:\n * Because Remix doesn't support URL rewriting, any route using this component should <b>match the pathname of the proxy\n * URL exactly</b>, and <b>end in a trailing slash</b> (e.g., `https://<shop>/apps/proxy/`).\n *\n * @example\n * <caption>Wrap a route with an AppProxyProvider component.</caption>\n * <description>Wrap your route component in the `AppProxyProvider` component and pass in your app URL.</description>\n * ```ts\n * // /app/routes/**\\/*.ts\n * import {authenticate} from '~/shopify.server';\n * import {AppProxyProvider} from '@shopify/shopify-app-remix/react';\n *\n * export async function loader({ request }) {\n * await authenticate.public.appProxy(request);\n *\n * return json({ appUrl: process.env.SHOPIFY_APP_URL });\n * }\n *\n * export default function App() {\n * const { appUrl } = useLoaderData();\n *\n * return (\n * <AppProxyProvider appUrl={appUrl}>\n * Page content\n * </AppProxyProvider>\n * );\n * }\n * ```\n */\nexport function AppProxyProvider(props: AppProxyProviderProps) {\n const {children, appUrl} = props;\n const [requestUrl, setRequestUrl] = useState<URL | undefined>();\n\n useEffect(\n () => setRequestUrl(new URL(window.location.href)),\n [setRequestUrl],\n );\n\n return (\n <AppProxyProviderContext.Provider\n value={{appUrl, requestUrl, formatUrl: formatProxyUrl(requestUrl)}}\n >\n <base href={appUrl} />\n\n {children}\n </AppProxyProviderContext.Provider>\n );\n}\n\nfunction formatProxyUrl(requestUrl: URL | undefined): FormatUrlFunction {\n return (url: string | undefined, addOrigin = true) => {\n if (!url) {\n return url;\n }\n\n let finalUrl = url;\n\n if (addOrigin && requestUrl && finalUrl.startsWith('/')) {\n finalUrl = new URL(`${requestUrl.origin}${url}`).href;\n }\n if (!finalUrl.endsWith('/')) {\n finalUrl = `${finalUrl}/`;\n }\n\n return finalUrl;\n };\n}\n"],"names":["_jsxs","_jsx"],"mappings":";;;MA6Ba,uBAAuB,GAClC,aAAa,CAAsC,IAAI;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCG;AACG,SAAU,gBAAgB,CAAC,KAA4B,EAAA;AAC3D,IAAA,MAAM,EAAC,QAAQ,EAAE,MAAM,EAAC,GAAG,KAAK;IAChC,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,EAAmB;IAE/D,SAAS,CACP,MAAM,aAAa,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAClD,CAAC,aAAa,CAAC,CAChB;AAED,IAAA,QACEA,IAAA,CAAC,uBAAuB,CAAC,QAAQ,EAAA,EAC/B,KAAK,EAAE,EAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,cAAc,CAAC,UAAU,CAAC,EAAC,EAAA,QAAA,EAAA,CAElEC,GAAA,CAAA,MAAA,EAAA,EAAM,IAAI,EAAE,MAAM,EAAA,CAAI,EAErB,QAAQ,CAAA,EAAA,CACwB;AAEvC;AAEA,SAAS,cAAc,CAAC,UAA2B,EAAA;AACjD,IAAA,OAAO,CAAC,GAAuB,EAAE,SAAS,GAAG,IAAI,KAAI;QACnD,IAAI,CAAC,GAAG,EAAE;AACR,YAAA,OAAO,GAAG;QACZ;QAEA,IAAI,QAAQ,GAAG,GAAG;QAElB,IAAI,SAAS,IAAI,UAAU,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;AACvD,YAAA,QAAQ,GAAG,IAAI,GAAG,CAAC,GAAG,UAAU,CAAC,MAAM,CAAA,EAAG,GAAG,CAAA,CAAE,CAAC,CAAC,IAAI;QACvD;QACA,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;AAC3B,YAAA,QAAQ,GAAG,CAAA,EAAG,QAAQ,CAAA,CAAA,CAAG;QAC3B;AAEA,QAAA,OAAO,QAAQ;AACjB,IAAA,CAAC;AACH;;;;"}
@@ -15,8 +15,8 @@ function redirectFactory(params, request, shop) {
15
15
  init,
16
16
  });
17
17
  logger.debug('Redirecting', { shop, url: parsedUrl.toString() });
18
- const isSameOrigin = parsedUrl.origin === config.appUrl;
19
- if (isSameOrigin || url.startsWith('/')) {
18
+ const isSameOrigin = parsedUrl.origin === new URL(config.appUrl).origin;
19
+ if (isSameOrigin) {
20
20
  searchParams.forEach((value, key) => {
21
21
  if (!parsedUrl.searchParams.has(key)) {
22
22
  parsedUrl.searchParams.set(key, value);
@@ -1 +1 @@
1
- {"version":3,"file":"redirect.mjs","sources":["../../../../../../../src/server/authenticate/admin/helpers/redirect.ts"],"sourcesContent":["import {\n TypedResponse,\n redirect as remixRedirect,\n} from '@remix-run/server-runtime';\n\nimport {BasicParams} from '../../../types';\nimport {getSessionTokenHeader} from '../../helpers/get-session-token-header';\n\nimport {renderAppBridge} from './render-app-bridge';\nimport {redirectWithAppBridgeHeaders} from './redirect-with-app-bridge-headers';\n\nexport type RedirectTarget = '_self' | '_parent' | '_top' | '_blank';\nexport type RedirectInit = number | (ResponseInit & {target?: RedirectTarget});\nexport type RedirectFunction = (\n url: string,\n init?: RedirectInit,\n) => TypedResponse<never>;\n\ninterface ParseURLOptions {\n params: BasicParams;\n url: string;\n base: string;\n shop: string;\n init: RedirectInit;\n}\n\ninterface ParsedURL {\n url: URL;\n target: RedirectTarget;\n}\n\nexport function redirectFactory(\n params: BasicParams,\n request: Request,\n shop: string,\n): RedirectFunction {\n const {config, logger} = params;\n\n return function redirect(url, init: RedirectInit) {\n const {searchParams} = new URL(request.url);\n const {url: parsedUrl, target} = parseURL({\n params,\n url,\n base: config.appUrl,\n shop,\n init,\n });\n\n logger.debug('Redirecting', {shop, url: parsedUrl.toString()});\n\n const isSameOrigin = parsedUrl.origin === config.appUrl;\n if (isSameOrigin || url.startsWith('/')) {\n searchParams.forEach((value, key) => {\n if (!parsedUrl.searchParams.has(key)) {\n parsedUrl.searchParams.set(key, value);\n }\n });\n }\n\n if (target === '_self') {\n if (isBounceRequest(request)) {\n throw renderAppBridge(params, request, {\n url: parsedUrl.toString(),\n target,\n });\n } else {\n return remixRedirect(parsedUrl.toString(), init);\n }\n } else if (isDataRequest(request)) {\n throw redirectWithAppBridgeHeaders(parsedUrl.toString());\n } else if (isEmbeddedRequest(request)) {\n throw renderAppBridge(params, request, {\n url: parsedUrl.toString(),\n target,\n });\n }\n return remixRedirect(url, init);\n };\n}\n\nfunction isBounceRequest(request: Request) {\n return (\n Boolean(getSessionTokenHeader(request)) &&\n request.headers.has('X-Shopify-Bounce')\n );\n}\n\nfunction isDataRequest(request: Request) {\n const isGet = request.method === 'GET';\n const sessionTokenHeader = Boolean(getSessionTokenHeader(request));\n\n return (\n sessionTokenHeader &&\n !isBounceRequest(request) &&\n (!isEmbeddedRequest(request) || !isGet)\n );\n}\n\nfunction isEmbeddedRequest(request: Request) {\n const {searchParams} = new URL(request.url);\n\n return searchParams.get('embedded') === '1';\n}\n\nfunction parseURL({params, base, init, shop, url}: ParseURLOptions): ParsedURL {\n let target: RedirectTarget | undefined =\n typeof init !== 'number' && init?.target ? init.target : undefined;\n\n if (isAdminRemotePath(url)) {\n const {config} = params;\n\n const adminPath = getAdminRemotePath(url);\n const cleanShopName = shop.replace('.myshopify.com', '');\n\n if (!target) {\n target = config.isEmbeddedApp ? '_parent' : '_self';\n }\n\n return {\n url: new URL(\n `https://admin.shopify.com/store/${cleanShopName}${adminPath}`,\n ),\n target,\n };\n } else {\n return {\n url: new URL(url, base),\n target: target ?? '_self',\n };\n }\n}\n\nconst ADMIN_REGEX = /^shopify:\\/*admin\\//i;\n\nfunction isAdminRemotePath(url: string) {\n return ADMIN_REGEX.test(url);\n}\n\nfunction getAdminRemotePath(url: string | URL) {\n const parsedUrl = removeRestrictedParams(new URL(url)).href;\n return parsedUrl.replace(ADMIN_REGEX, '/');\n}\n\nconst embeddedFrameParamsToRemove = [\n 'hmac',\n 'locale',\n 'protocol',\n 'session',\n 'id_token',\n 'shop',\n 'timestamp',\n 'host',\n 'embedded',\n // sent when clicking rel=\"home\" nav item\n 'appLoadId',\n];\n\nfunction removeRestrictedParams(url: URL | string) {\n const newUrl = new URL(url);\n embeddedFrameParamsToRemove.forEach((param) =>\n newUrl.searchParams.delete(param),\n );\n return newUrl;\n}\n"],"names":["redirect","remixRedirect"],"mappings":"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"}
1
+ {"version":3,"file":"redirect.mjs","sources":["../../../../../../../src/server/authenticate/admin/helpers/redirect.ts"],"sourcesContent":["import {\n TypedResponse,\n redirect as remixRedirect,\n} from '@remix-run/server-runtime';\n\nimport {BasicParams} from '../../../types';\nimport {getSessionTokenHeader} from '../../helpers/get-session-token-header';\n\nimport {renderAppBridge} from './render-app-bridge';\nimport {redirectWithAppBridgeHeaders} from './redirect-with-app-bridge-headers';\n\nexport type RedirectTarget = '_self' | '_parent' | '_top' | '_blank';\nexport type RedirectInit = number | (ResponseInit & {target?: RedirectTarget});\nexport type RedirectFunction = (\n url: string,\n init?: RedirectInit,\n) => TypedResponse<never>;\n\ninterface ParseURLOptions {\n params: BasicParams;\n url: string;\n base: string;\n shop: string;\n init: RedirectInit;\n}\n\ninterface ParsedURL {\n url: URL;\n target: RedirectTarget;\n}\n\nexport function redirectFactory(\n params: BasicParams,\n request: Request,\n shop: string,\n): RedirectFunction {\n const {config, logger} = params;\n\n return function redirect(url, init: RedirectInit) {\n const {searchParams} = new URL(request.url);\n const {url: parsedUrl, target} = parseURL({\n params,\n url,\n base: config.appUrl,\n shop,\n init,\n });\n\n logger.debug('Redirecting', {shop, url: parsedUrl.toString()});\n\n const isSameOrigin = parsedUrl.origin === new URL(config.appUrl).origin;\n if (isSameOrigin) {\n searchParams.forEach((value, key) => {\n if (!parsedUrl.searchParams.has(key)) {\n parsedUrl.searchParams.set(key, value);\n }\n });\n }\n\n if (target === '_self') {\n if (isBounceRequest(request)) {\n throw renderAppBridge(params, request, {\n url: parsedUrl.toString(),\n target,\n });\n } else {\n return remixRedirect(parsedUrl.toString(), init);\n }\n } else if (isDataRequest(request)) {\n throw redirectWithAppBridgeHeaders(parsedUrl.toString());\n } else if (isEmbeddedRequest(request)) {\n throw renderAppBridge(params, request, {\n url: parsedUrl.toString(),\n target,\n });\n }\n return remixRedirect(url, init);\n };\n}\n\nfunction isBounceRequest(request: Request) {\n return (\n Boolean(getSessionTokenHeader(request)) &&\n request.headers.has('X-Shopify-Bounce')\n );\n}\n\nfunction isDataRequest(request: Request) {\n const isGet = request.method === 'GET';\n const sessionTokenHeader = Boolean(getSessionTokenHeader(request));\n\n return (\n sessionTokenHeader &&\n !isBounceRequest(request) &&\n (!isEmbeddedRequest(request) || !isGet)\n );\n}\n\nfunction isEmbeddedRequest(request: Request) {\n const {searchParams} = new URL(request.url);\n\n return searchParams.get('embedded') === '1';\n}\n\nfunction parseURL({params, base, init, shop, url}: ParseURLOptions): ParsedURL {\n let target: RedirectTarget | undefined =\n typeof init !== 'number' && init?.target ? init.target : undefined;\n\n if (isAdminRemotePath(url)) {\n const {config} = params;\n\n const adminPath = getAdminRemotePath(url);\n const cleanShopName = shop.replace('.myshopify.com', '');\n\n if (!target) {\n target = config.isEmbeddedApp ? '_parent' : '_self';\n }\n\n return {\n url: new URL(\n `https://admin.shopify.com/store/${cleanShopName}${adminPath}`,\n ),\n target,\n };\n } else {\n return {\n url: new URL(url, base),\n target: target ?? '_self',\n };\n }\n}\n\nconst ADMIN_REGEX = /^shopify:\\/*admin\\//i;\n\nfunction isAdminRemotePath(url: string) {\n return ADMIN_REGEX.test(url);\n}\n\nfunction getAdminRemotePath(url: string | URL) {\n const parsedUrl = removeRestrictedParams(new URL(url)).href;\n return parsedUrl.replace(ADMIN_REGEX, '/');\n}\n\nconst embeddedFrameParamsToRemove = [\n 'hmac',\n 'locale',\n 'protocol',\n 'session',\n 'id_token',\n 'shop',\n 'timestamp',\n 'host',\n 'embedded',\n // sent when clicking rel=\"home\" nav item\n 'appLoadId',\n];\n\nfunction removeRestrictedParams(url: URL | string) {\n const newUrl = new URL(url);\n embeddedFrameParamsToRemove.forEach((param) =>\n newUrl.searchParams.delete(param),\n );\n return newUrl;\n}\n"],"names":["redirect","remixRedirect"],"mappings":"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"}
@@ -56,7 +56,7 @@ function authenticateWebhookFactory(params) {
56
56
  apiVersion: check.apiVersion,
57
57
  shop: check.domain,
58
58
  topic: check.topic,
59
- webhookId: check.eventId,
59
+ webhookId: check.webhookId,
60
60
  payload: JSON.parse(rawBody),
61
61
  session: undefined,
62
62
  admin: undefined,
@@ -1 +1 @@
1
- {"version":3,"file":"authenticate.mjs","sources":["../../../../../../src/server/authenticate/webhooks/authenticate.ts"],"sourcesContent":["import {WebhookValidationErrorReason, WebhookType} from '@shopify/shopify-api';\n\nimport type {BasicParams} from '../../types';\nimport {adminClientFactory} from '../../clients';\nimport {handleClientErrorFactory} from '../admin/helpers';\nimport {ensureValidOfflineSession} from '../../helpers';\n\nimport type {\n AuthenticateWebhook,\n WebhookContext,\n WebhookContextWithoutSession,\n} from './types';\n\nexport function authenticateWebhookFactory<Topics extends string>(\n params: BasicParams,\n): AuthenticateWebhook<Topics> {\n const {api, logger} = params;\n\n return async function authenticate(\n request: Request,\n ): Promise<WebhookContext<Topics>> {\n if (request.method !== 'POST') {\n logger.debug(\n 'Received a non-POST request for a webhook. Only POST requests are allowed.',\n {url: request.url, method: request.method},\n );\n throw new Response(undefined, {\n status: 405,\n statusText: 'Method not allowed',\n });\n }\n\n const rawBody = await request.text();\n\n const check = await api.webhooks.validate({\n rawBody,\n rawRequest: request,\n });\n\n if (!check.valid) {\n if (check.reason === WebhookValidationErrorReason.InvalidHmac) {\n logger.debug('Webhook HMAC validation failed', check);\n throw new Response(undefined, {\n status: 401,\n statusText: 'Unauthorized',\n });\n } else {\n logger.debug('Webhook validation failed', check);\n throw new Response(undefined, {status: 400, statusText: 'Bad Request'});\n }\n }\n const session = await ensureValidOfflineSession(params, check.domain);\n\n let webhookContext: WebhookContextWithoutSession<Topics>;\n\n if (check.webhookType === WebhookType.Webhooks) {\n webhookContext = {\n apiVersion: check.apiVersion,\n shop: check.domain,\n topic: check.topic as Topics,\n webhookId: check.webhookId,\n payload: JSON.parse(rawBody),\n subTopic: check.subTopic || undefined,\n session: undefined,\n admin: undefined,\n webhookType: check.webhookType,\n name: check.name,\n triggeredAt: check.triggeredAt,\n eventId: check.eventId,\n };\n } else {\n webhookContext = {\n apiVersion: check.apiVersion,\n shop: check.domain,\n topic: check.topic as Topics,\n webhookId: check.eventId,\n payload: JSON.parse(rawBody),\n session: undefined,\n admin: undefined,\n webhookType: check.webhookType,\n handle: check.handle,\n action: check.action,\n resourceId: check.resourceId,\n triggeredAt: check.triggeredAt,\n eventId: check.eventId,\n };\n }\n\n if (!session) {\n return webhookContext;\n }\n\n const admin = adminClientFactory({\n params,\n session,\n handleClientError: handleClientErrorFactory({request}),\n });\n\n return {\n ...webhookContext,\n session,\n admin,\n };\n };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"authenticate.mjs","sources":["../../../../../../src/server/authenticate/webhooks/authenticate.ts"],"sourcesContent":["import {WebhookValidationErrorReason, WebhookType} from '@shopify/shopify-api';\n\nimport type {BasicParams} from '../../types';\nimport {adminClientFactory} from '../../clients';\nimport {handleClientErrorFactory} from '../admin/helpers';\nimport {ensureValidOfflineSession} from '../../helpers';\n\nimport type {\n AuthenticateWebhook,\n WebhookContext,\n WebhookContextWithoutSession,\n} from './types';\n\nexport function authenticateWebhookFactory<Topics extends string>(\n params: BasicParams,\n): AuthenticateWebhook<Topics> {\n const {api, logger} = params;\n\n return async function authenticate(\n request: Request,\n ): Promise<WebhookContext<Topics>> {\n if (request.method !== 'POST') {\n logger.debug(\n 'Received a non-POST request for a webhook. Only POST requests are allowed.',\n {url: request.url, method: request.method},\n );\n throw new Response(undefined, {\n status: 405,\n statusText: 'Method not allowed',\n });\n }\n\n const rawBody = await request.text();\n\n const check = await api.webhooks.validate({\n rawBody,\n rawRequest: request,\n });\n\n if (!check.valid) {\n if (check.reason === WebhookValidationErrorReason.InvalidHmac) {\n logger.debug('Webhook HMAC validation failed', check);\n throw new Response(undefined, {\n status: 401,\n statusText: 'Unauthorized',\n });\n } else {\n logger.debug('Webhook validation failed', check);\n throw new Response(undefined, {status: 400, statusText: 'Bad Request'});\n }\n }\n const session = await ensureValidOfflineSession(params, check.domain);\n\n let webhookContext: WebhookContextWithoutSession<Topics>;\n\n if (check.webhookType === WebhookType.Webhooks) {\n webhookContext = {\n apiVersion: check.apiVersion,\n shop: check.domain,\n topic: check.topic as Topics,\n webhookId: check.webhookId,\n payload: JSON.parse(rawBody),\n subTopic: check.subTopic || undefined,\n session: undefined,\n admin: undefined,\n webhookType: check.webhookType,\n name: check.name,\n triggeredAt: check.triggeredAt,\n eventId: check.eventId,\n };\n } else {\n webhookContext = {\n apiVersion: check.apiVersion,\n shop: check.domain,\n topic: check.topic as Topics,\n webhookId: check.webhookId,\n payload: JSON.parse(rawBody),\n session: undefined,\n admin: undefined,\n webhookType: check.webhookType,\n handle: check.handle,\n action: check.action,\n resourceId: check.resourceId,\n triggeredAt: check.triggeredAt,\n eventId: check.eventId,\n };\n }\n\n if (!session) {\n return webhookContext;\n }\n\n const admin = adminClientFactory({\n params,\n session,\n handleClientError: handleClientErrorFactory({request}),\n });\n\n return {\n ...webhookContext,\n session,\n admin,\n };\n };\n}\n"],"names":[],"mappings":";;;;;;;AAaM,SAAU,0BAA0B,CACxC,MAAmB,EAAA;AAEnB,IAAA,MAAM,EAAC,GAAG,EAAE,MAAM,EAAC,GAAG,MAAM;AAE5B,IAAA,OAAO,eAAe,YAAY,CAChC,OAAgB,EAAA;AAEhB,QAAA,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE;AAC7B,YAAA,MAAM,CAAC,KAAK,CACV,4EAA4E,EAC5E,EAAC,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAC,CAC3C;AACD,YAAA,MAAM,IAAI,QAAQ,CAAC,SAAS,EAAE;AAC5B,gBAAA,MAAM,EAAE,GAAG;AACX,gBAAA,UAAU,EAAE,oBAAoB;AACjC,aAAA,CAAC;QACJ;AAEA,QAAA,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE;QAEpC,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC;YACxC,OAAO;AACP,YAAA,UAAU,EAAE,OAAO;AACpB,SAAA,CAAC;AAEF,QAAA,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE;YAChB,IAAI,KAAK,CAAC,MAAM,KAAK,4BAA4B,CAAC,WAAW,EAAE;AAC7D,gBAAA,MAAM,CAAC,KAAK,CAAC,gCAAgC,EAAE,KAAK,CAAC;AACrD,gBAAA,MAAM,IAAI,QAAQ,CAAC,SAAS,EAAE;AAC5B,oBAAA,MAAM,EAAE,GAAG;AACX,oBAAA,UAAU,EAAE,cAAc;AAC3B,iBAAA,CAAC;YACJ;iBAAO;AACL,gBAAA,MAAM,CAAC,KAAK,CAAC,2BAA2B,EAAE,KAAK,CAAC;AAChD,gBAAA,MAAM,IAAI,QAAQ,CAAC,SAAS,EAAE,EAAC,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,aAAa,EAAC,CAAC;YACzE;QACF;QACA,MAAM,OAAO,GAAG,MAAM,yBAAyB,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;AAErE,QAAA,IAAI,cAAoD;QAExD,IAAI,KAAK,CAAC,WAAW,KAAK,WAAW,CAAC,QAAQ,EAAE;AAC9C,YAAA,cAAc,GAAG;gBACf,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,IAAI,EAAE,KAAK,CAAC,MAAM;gBAClB,KAAK,EAAE,KAAK,CAAC,KAAe;gBAC5B,SAAS,EAAE,KAAK,CAAC,SAAS;AAC1B,gBAAA,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;AAC5B,gBAAA,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,SAAS;AACrC,gBAAA,OAAO,EAAE,SAAS;AAClB,gBAAA,KAAK,EAAE,SAAS;gBAChB,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,OAAO,EAAE,KAAK,CAAC,OAAO;aACvB;QACH;aAAO;AACL,YAAA,cAAc,GAAG;gBACf,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,IAAI,EAAE,KAAK,CAAC,MAAM;gBAClB,KAAK,EAAE,KAAK,CAAC,KAAe;gBAC5B,SAAS,EAAE,KAAK,CAAC,SAAS;AAC1B,gBAAA,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;AAC5B,gBAAA,OAAO,EAAE,SAAS;AAClB,gBAAA,KAAK,EAAE,SAAS;gBAChB,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,OAAO,EAAE,KAAK,CAAC,OAAO;aACvB;QACH;QAEA,IAAI,CAAC,OAAO,EAAE;AACZ,YAAA,OAAO,cAAc;QACvB;QAEA,MAAM,KAAK,GAAG,kBAAkB,CAAC;YAC/B,MAAM;YACN,OAAO;AACP,YAAA,iBAAiB,EAAE,wBAAwB,CAAC,EAAC,OAAO,EAAC,CAAC;AACvD,SAAA,CAAC;QAEF,OAAO;AACL,YAAA,GAAG,cAAc;YACjB,OAAO;YACP,KAAK;SACN;AACH,IAAA,CAAC;AACH;;;;"}