@shopify/shopify-app-remix 3.8.5 → 4.0.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.
- package/README.md +2 -3
- package/dist/cjs/react/components/AppProvider/AppProvider.js +15 -0
- package/dist/cjs/react/components/AppProvider/AppProvider.js.map +1 -1
- package/dist/cjs/server/adapters/node/index.js +0 -2
- package/dist/cjs/server/adapters/node/index.js.map +1 -1
- package/dist/cjs/server/authenticate/admin/authenticate.js.map +1 -1
- package/dist/cjs/server/authenticate/admin/helpers/create-admin-api-context.js.map +1 -1
- package/dist/cjs/server/authenticate/admin/helpers/trigger-after-auth-hook.js.map +1 -1
- package/dist/cjs/server/authenticate/admin/scope/client/fetch-scopes-details.js.map +1 -1
- package/dist/cjs/server/authenticate/admin/scope/client/revoke-scopes.js.map +1 -1
- package/dist/cjs/server/authenticate/admin/scope/factory.js.map +1 -1
- package/dist/cjs/server/authenticate/admin/scope/query.js.map +1 -1
- package/dist/cjs/server/authenticate/admin/scope/request.js.map +1 -1
- package/dist/cjs/server/authenticate/admin/scope/revoke.js.map +1 -1
- package/dist/cjs/server/authenticate/admin/strategies/auth-code-flow.js.map +1 -1
- package/dist/cjs/server/authenticate/admin/strategies/merchant-custom-app.js.map +1 -1
- package/dist/cjs/server/authenticate/admin/strategies/token-exchange.js.map +1 -1
- package/dist/cjs/server/authenticate/flow/authenticate.js.map +1 -1
- package/dist/cjs/server/authenticate/fulfillment-service/authenticate.js.map +1 -1
- package/dist/cjs/server/authenticate/public/appProxy/authenticate.js.map +1 -1
- package/dist/cjs/server/authenticate/public/factory.js.map +1 -1
- package/dist/cjs/server/authenticate/webhooks/authenticate.js.map +1 -1
- package/dist/cjs/server/clients/admin/factory.js +0 -11
- package/dist/cjs/server/clients/admin/factory.js.map +1 -1
- package/dist/cjs/server/clients/admin/graphql.js +1 -2
- package/dist/cjs/server/clients/admin/graphql.js.map +1 -1
- package/dist/cjs/server/future/flags.js.map +1 -1
- package/dist/cjs/server/index.js +0 -8
- package/dist/cjs/server/index.js.map +1 -1
- package/dist/cjs/server/override-logger.js +2 -2
- package/dist/cjs/server/override-logger.js.map +1 -1
- package/dist/cjs/server/shopify-app.js +1 -2
- package/dist/cjs/server/shopify-app.js.map +1 -1
- package/dist/cjs/server/test-helpers/test-config.js.map +1 -1
- package/dist/cjs/server/types.js.map +1 -1
- package/dist/cjs/server/unauthenticated/admin/factory.js.map +1 -1
- package/dist/cjs/server/version.js +1 -1
- package/dist/cjs/server/version.js.map +1 -1
- package/dist/esm/react/components/AppProvider/AppProvider.mjs +15 -0
- package/dist/esm/react/components/AppProvider/AppProvider.mjs.map +1 -1
- package/dist/esm/server/adapters/node/index.mjs +1 -3
- package/dist/esm/server/adapters/node/index.mjs.map +1 -1
- package/dist/esm/server/authenticate/admin/authenticate.mjs.map +1 -1
- package/dist/esm/server/authenticate/admin/helpers/create-admin-api-context.mjs.map +1 -1
- package/dist/esm/server/authenticate/admin/helpers/trigger-after-auth-hook.mjs.map +1 -1
- package/dist/esm/server/authenticate/admin/scope/client/fetch-scopes-details.mjs.map +1 -1
- package/dist/esm/server/authenticate/admin/scope/client/revoke-scopes.mjs.map +1 -1
- package/dist/esm/server/authenticate/admin/scope/factory.mjs.map +1 -1
- package/dist/esm/server/authenticate/admin/scope/query.mjs.map +1 -1
- package/dist/esm/server/authenticate/admin/scope/request.mjs.map +1 -1
- package/dist/esm/server/authenticate/admin/scope/revoke.mjs.map +1 -1
- package/dist/esm/server/authenticate/admin/strategies/auth-code-flow.mjs.map +1 -1
- package/dist/esm/server/authenticate/admin/strategies/merchant-custom-app.mjs.map +1 -1
- package/dist/esm/server/authenticate/admin/strategies/token-exchange.mjs.map +1 -1
- package/dist/esm/server/authenticate/flow/authenticate.mjs.map +1 -1
- package/dist/esm/server/authenticate/fulfillment-service/authenticate.mjs.map +1 -1
- package/dist/esm/server/authenticate/public/appProxy/authenticate.mjs.map +1 -1
- package/dist/esm/server/authenticate/public/factory.mjs.map +1 -1
- package/dist/esm/server/authenticate/webhooks/authenticate.mjs.map +1 -1
- package/dist/esm/server/clients/admin/factory.mjs +0 -11
- package/dist/esm/server/clients/admin/factory.mjs.map +1 -1
- package/dist/esm/server/clients/admin/graphql.mjs +1 -2
- package/dist/esm/server/clients/admin/graphql.mjs.map +1 -1
- package/dist/esm/server/future/flags.mjs.map +1 -1
- package/dist/esm/server/index.mjs +1 -1
- package/dist/esm/server/index.mjs.map +1 -1
- package/dist/esm/server/override-logger.mjs +2 -2
- package/dist/esm/server/override-logger.mjs.map +1 -1
- package/dist/esm/server/shopify-app.mjs +2 -3
- package/dist/esm/server/shopify-app.mjs.map +1 -1
- package/dist/esm/server/test-helpers/test-config.mjs.map +1 -1
- package/dist/esm/server/types.mjs.map +1 -1
- package/dist/esm/server/unauthenticated/admin/factory.mjs.map +1 -1
- package/dist/esm/server/version.mjs +1 -1
- package/dist/esm/server/version.mjs.map +1 -1
- package/dist/ts/react/components/AppProvider/AppProvider.d.ts.map +1 -1
- package/dist/ts/server/authenticate/admin/authenticate.admin.doc.d.ts.map +1 -1
- package/dist/ts/server/authenticate/admin/authenticate.d.ts +2 -2
- package/dist/ts/server/authenticate/admin/authenticate.d.ts.map +1 -1
- package/dist/ts/server/authenticate/admin/billing/types.d.ts +1 -2
- package/dist/ts/server/authenticate/admin/billing/types.d.ts.map +1 -1
- package/dist/ts/server/authenticate/admin/helpers/create-admin-api-context.d.ts +2 -3
- package/dist/ts/server/authenticate/admin/helpers/create-admin-api-context.d.ts.map +1 -1
- package/dist/ts/server/authenticate/admin/helpers/trigger-after-auth-hook.d.ts +2 -3
- package/dist/ts/server/authenticate/admin/helpers/trigger-after-auth-hook.d.ts.map +1 -1
- package/dist/ts/server/authenticate/admin/scope/client/fetch-scopes-details.d.ts +1 -2
- package/dist/ts/server/authenticate/admin/scope/client/fetch-scopes-details.d.ts.map +1 -1
- package/dist/ts/server/authenticate/admin/scope/client/revoke-scopes.d.ts +1 -2
- package/dist/ts/server/authenticate/admin/scope/client/revoke-scopes.d.ts.map +1 -1
- package/dist/ts/server/authenticate/admin/scope/factory.d.ts +1 -2
- package/dist/ts/server/authenticate/admin/scope/factory.d.ts.map +1 -1
- package/dist/ts/server/authenticate/admin/scope/query.d.ts +1 -2
- package/dist/ts/server/authenticate/admin/scope/query.d.ts.map +1 -1
- package/dist/ts/server/authenticate/admin/scope/request.d.ts +1 -2
- package/dist/ts/server/authenticate/admin/scope/request.d.ts.map +1 -1
- package/dist/ts/server/authenticate/admin/scope/revoke.d.ts +1 -2
- package/dist/ts/server/authenticate/admin/scope/revoke.d.ts.map +1 -1
- package/dist/ts/server/authenticate/admin/strategies/auth-code-flow.d.ts +3 -3
- package/dist/ts/server/authenticate/admin/strategies/auth-code-flow.d.ts.map +1 -1
- package/dist/ts/server/authenticate/admin/strategies/merchant-custom-app.d.ts +2 -2
- package/dist/ts/server/authenticate/admin/strategies/merchant-custom-app.d.ts.map +1 -1
- package/dist/ts/server/authenticate/admin/strategies/token-exchange.d.ts +2 -2
- package/dist/ts/server/authenticate/admin/strategies/token-exchange.d.ts.map +1 -1
- package/dist/ts/server/authenticate/admin/types.d.ts +9 -9
- package/dist/ts/server/authenticate/admin/types.d.ts.map +1 -1
- package/dist/ts/server/authenticate/flow/authenticate.d.ts +1 -3
- package/dist/ts/server/authenticate/flow/authenticate.d.ts.map +1 -1
- package/dist/ts/server/authenticate/flow/types.d.ts +4 -5
- package/dist/ts/server/authenticate/flow/types.d.ts.map +1 -1
- package/dist/ts/server/authenticate/fulfillment-service/authenticate.d.ts +1 -3
- package/dist/ts/server/authenticate/fulfillment-service/authenticate.d.ts.map +1 -1
- package/dist/ts/server/authenticate/fulfillment-service/types.d.ts +4 -5
- package/dist/ts/server/authenticate/fulfillment-service/types.d.ts.map +1 -1
- package/dist/ts/server/authenticate/public/appProxy/authenticate.d.ts +1 -3
- package/dist/ts/server/authenticate/public/appProxy/authenticate.d.ts.map +1 -1
- package/dist/ts/server/authenticate/public/appProxy/types.d.ts +6 -7
- package/dist/ts/server/authenticate/public/appProxy/types.d.ts.map +1 -1
- package/dist/ts/server/authenticate/public/factory.d.ts +1 -3
- package/dist/ts/server/authenticate/public/factory.d.ts.map +1 -1
- package/dist/ts/server/authenticate/public/types.d.ts +2 -3
- package/dist/ts/server/authenticate/public/types.d.ts.map +1 -1
- package/dist/ts/server/authenticate/webhooks/authenticate.d.ts +1 -3
- package/dist/ts/server/authenticate/webhooks/authenticate.d.ts.map +1 -1
- package/dist/ts/server/authenticate/webhooks/types.d.ts +5 -6
- package/dist/ts/server/authenticate/webhooks/types.d.ts.map +1 -1
- package/dist/ts/server/clients/admin/factory.d.ts +3 -4
- package/dist/ts/server/clients/admin/factory.d.ts.map +1 -1
- package/dist/ts/server/clients/admin/graphql.d.ts.map +1 -1
- package/dist/ts/server/clients/admin/types.d.ts +2 -134
- package/dist/ts/server/clients/admin/types.d.ts.map +1 -1
- package/dist/ts/server/config-types.d.ts +14 -16
- package/dist/ts/server/config-types.d.ts.map +1 -1
- package/dist/ts/server/future/flags.d.ts +2 -22
- package/dist/ts/server/future/flags.d.ts.map +1 -1
- package/dist/ts/server/index.d.ts +1 -1
- package/dist/ts/server/index.d.ts.map +1 -1
- package/dist/ts/server/shopify-app.d.ts +1 -2
- package/dist/ts/server/shopify-app.d.ts.map +1 -1
- package/dist/ts/server/test-helpers/test-config.d.ts +2 -2
- package/dist/ts/server/test-helpers/test-config.d.ts.map +1 -1
- package/dist/ts/server/types-contexts.d.ts +17 -31
- package/dist/ts/server/types-contexts.d.ts.map +1 -1
- package/dist/ts/server/types.d.ts +13 -14
- package/dist/ts/server/types.d.ts.map +1 -1
- package/dist/ts/server/unauthenticated/admin/factory.d.ts +1 -3
- package/dist/ts/server/unauthenticated/admin/factory.d.ts.map +1 -1
- package/dist/ts/server/unauthenticated/admin/types.d.ts +5 -6
- package/dist/ts/server/unauthenticated/admin/types.d.ts.map +1 -1
- package/dist/ts/server/unauthenticated/types.d.ts +3 -5
- package/dist/ts/server/unauthenticated/types.d.ts.map +1 -1
- package/dist/ts/server/version.d.ts +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +13 -16
- package/dist/cjs/server/clients/admin/rest.js +0 -132
- package/dist/cjs/server/clients/admin/rest.js.map +0 -1
- package/dist/esm/server/clients/admin/rest.mjs +0 -130
- package/dist/esm/server/clients/admin/rest.mjs.map +0 -1
- package/dist/ts/server/clients/admin/rest.d.ts +0 -39
- package/dist/ts/server/clients/admin/rest.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -54,15 +54,14 @@ Create `app/shopify.server.js`. We will use this file to configure our Shopify a
|
|
|
54
54
|
import '@shopify/shopify-app-remix/server/adapters/node';
|
|
55
55
|
// Memory storage makes it easy to set an app up, but should never be used in production.
|
|
56
56
|
import {MemorySessionStorage} from '@shopify/shopify-app-session-storage-memory';
|
|
57
|
-
|
|
58
|
-
import {LATEST_API_VERSION, shopifyApp} from '@shopify/shopify-app-remix';
|
|
57
|
+
import {ApiVersion, shopifyApp} from '@shopify/shopify-app-remix';
|
|
59
58
|
|
|
60
59
|
const shopify = shopifyApp({
|
|
61
60
|
apiKey: process.env.SHOPIFY_API_KEY!,
|
|
62
61
|
apiSecretKey: process.env.SHOPIFY_API_SECRET!,
|
|
63
62
|
appUrl: process.env.SHOPIFY_APP_URL!,
|
|
64
63
|
scopes: ['read_products'],
|
|
65
|
-
apiVersion:
|
|
64
|
+
apiVersion: ApiVersion.July25,
|
|
66
65
|
sessionStorage: new MemorySessionStorage(),
|
|
67
66
|
});
|
|
68
67
|
export default shopify;
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
4
|
var polaris = require('@shopify/polaris');
|
|
5
5
|
var englishI18n = require('@shopify/polaris/locales/en.json');
|
|
6
|
+
var react = require('@remix-run/react');
|
|
7
|
+
var React = require('react');
|
|
6
8
|
var _const = require('../../const.js');
|
|
7
9
|
var RemixPolarisLink = require('../RemixPolarisLink.js');
|
|
8
10
|
|
|
@@ -71,6 +73,19 @@ var RemixPolarisLink = require('../RemixPolarisLink.js');
|
|
|
71
73
|
*/
|
|
72
74
|
function AppProvider(props) {
|
|
73
75
|
const { children, apiKey, i18n, isEmbeddedApp = true, __APP_BRIDGE_URL = _const.APP_BRIDGE_URL, ...polarisProps } = props;
|
|
76
|
+
const navigate = react.useNavigate();
|
|
77
|
+
React.useEffect(() => {
|
|
78
|
+
const handleNavigate = (event) => {
|
|
79
|
+
const href = event.target?.getAttribute('href');
|
|
80
|
+
if (href) {
|
|
81
|
+
navigate(href);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
addEventListener('shopify:navigate', handleNavigate);
|
|
85
|
+
return () => {
|
|
86
|
+
removeEventListener('shopify:navigate', handleNavigate);
|
|
87
|
+
};
|
|
88
|
+
}, [navigate]);
|
|
74
89
|
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [isEmbeddedApp && jsxRuntime.jsx("script", { src: __APP_BRIDGE_URL, "data-api-key": apiKey }), jsxRuntime.jsx(polaris.AppProvider, { ...polarisProps, linkComponent: RemixPolarisLink.RemixPolarisLink, i18n: i18n || englishI18n, children: children })] }));
|
|
75
90
|
}
|
|
76
91
|
|
|
@@ -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'};\n\nimport {APP_BRIDGE_URL} from '../../const';\nimport {RemixPolarisLink} from '../RemixPolarisLink';\n\nexport interface AppProviderProps\n extends Omit<PolarisAppProviderProps, 'linkComponent' | 'i18n'> {\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 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","_jsxs","_Fragment","_jsx","PolarisAppProvider","RemixPolarisLink"],"mappings":"
|
|
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\n extends Omit<PolarisAppProviderProps, 'linkComponent' | 'i18n'> {\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":";;;;;;;;;;AA0CA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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,13 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var crypto = require('crypto');
|
|
4
3
|
var runtime = require('@shopify/shopify-api/runtime');
|
|
5
4
|
var appBridgeUrl = require('../../authenticate/helpers/app-bridge-url.js');
|
|
6
5
|
require('@remix-run/server-runtime');
|
|
7
6
|
require('isbot');
|
|
8
7
|
require('../../types.js');
|
|
9
8
|
|
|
10
|
-
runtime.setCrypto(crypto);
|
|
11
9
|
runtime.setAbstractRuntimeString(() => {
|
|
12
10
|
return `Remix (Node)`;
|
|
13
11
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../../../src/server/adapters/node/index.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../../../src/server/adapters/node/index.ts"],"sourcesContent":["import {setAbstractRuntimeString} from '@shopify/shopify-api/runtime';\n\nimport {setAppBridgeUrlOverride} from '../../authenticate/helpers';\n\nsetAbstractRuntimeString(() => {\n return `Remix (Node)`;\n});\n\n/* eslint-disable no-process-env */\nif (process.env.APP_BRIDGE_URL) {\n setAppBridgeUrlOverride(process.env.APP_BRIDGE_URL);\n}\n/* eslint-enable no-process-env */\n"],"names":["setAbstractRuntimeString","setAppBridgeUrlOverride"],"mappings":";;;;;;;;AAIAA,gCAAwB,CAAC,MAAK;AAC5B,IAAA,OAAO,cAAc;AACvB,CAAC,CAAC;AAEF;AACA,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE;AAC9B,IAAAC,oCAAuB,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;AACrD;AACA;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authenticate.js","sources":["../../../../../../src/server/authenticate/admin/authenticate.ts"],"sourcesContent":["import {JwtPayload, Session, ShopifyRestResources} from '@shopify/shopify-api';\n\nimport type {BasicParams} from '../../types';\nimport type {AppConfigArg} from '../../config-types';\nimport {\n getSessionTokenHeader,\n ensureCORSHeadersFactory,\n getSessionTokenFromUrlParam,\n respondToBotRequest,\n respondToOptionsRequest,\n validateSessionToken,\n getShopFromRequest,\n} from '../helpers';\n\nimport {\n cancelBillingFactory,\n requestBillingFactory,\n requireBillingFactory,\n checkBillingFactory,\n createUsageRecordFactory,\n updateUsageCappedAmountFactory,\n} from './billing';\nimport type {\n AdminContext,\n AuthenticateAdmin,\n EmbeddedAdminContext,\n NonEmbeddedAdminContext,\n} from './types';\nimport {\n createAdminApiContext,\n ensureAppIsEmbeddedIfRequired,\n ensureSessionTokenSearchParamIfRequired,\n redirectFactory,\n renderAppBridge,\n validateShopAndHostParams,\n} from './helpers';\nimport {AuthorizationStrategy} from './strategies/types';\nimport {scopesApiFactory} from './scope/factory';\n\nexport interface SessionTokenContext {\n shop: string;\n sessionId?: string;\n sessionToken?: string;\n payload?: JwtPayload;\n}\n\ninterface AuthStrategyParams extends BasicParams {\n strategy: AuthorizationStrategy;\n}\n\nexport function authStrategyFactory<\n ConfigArg extends AppConfigArg,\n Resources extends ShopifyRestResources = ShopifyRestResources,\n>({\n strategy,\n ...params\n}: AuthStrategyParams): AuthenticateAdmin<ConfigArg, Resources> {\n const {api, logger, config} = params;\n\n async function respondToBouncePageRequest(request: Request) {\n const url = new URL(request.url);\n\n if (url.pathname === config.auth.patchSessionTokenPath) {\n logger.debug('Rendering bounce page', {\n shop: getShopFromRequest(request),\n });\n throw renderAppBridge({config, logger, api}, request);\n }\n }\n\n async function respondToExitIframeRequest(request: Request) {\n const url = new URL(request.url);\n\n if (url.pathname === config.auth.exitIframePath) {\n const destination = url.searchParams.get('exitIframe')!;\n\n logger.debug('Rendering exit iframe page', {\n shop: getShopFromRequest(request),\n destination,\n });\n throw renderAppBridge({config, logger, api}, request, {url: destination});\n }\n }\n\n type AdminContextBase =\n | EmbeddedAdminContext<ConfigArg, Resources>\n | NonEmbeddedAdminContext<ConfigArg, Resources>;\n\n function createContext(\n request: Request,\n session: Session,\n authStrategy: AuthorizationStrategy,\n sessionToken?: JwtPayload,\n ): AdminContext<ConfigArg, Resources> {\n let context: AdminContextBase = {\n admin: createAdminApiContext<ConfigArg, Resources>(\n session,\n params,\n authStrategy.handleClientError(request),\n ),\n billing: {\n require: requireBillingFactory(params, request, session),\n check: checkBillingFactory(params, request, session),\n request: requestBillingFactory(params, request, session),\n cancel: cancelBillingFactory(params, request, session),\n createUsageRecord: createUsageRecordFactory(params, request, session),\n updateUsageCappedAmount: updateUsageCappedAmountFactory(\n params,\n request,\n session,\n ),\n },\n\n session,\n cors: ensureCORSHeadersFactory(params, request),\n };\n\n context = addEmbeddedFeatures(context, request, session, sessionToken);\n context = addScopesFeatures(context);\n\n return context as AdminContext<ConfigArg, Resources>;\n }\n\n function addEmbeddedFeatures(\n context: AdminContextBase,\n request: Request,\n session: Session,\n sessionToken?: JwtPayload,\n ) {\n if (config.isEmbeddedApp) {\n return {\n ...context,\n sessionToken,\n redirect: redirectFactory(params, request, session.shop),\n };\n }\n return context;\n }\n\n function addScopesFeatures(context: AdminContextBase) {\n return {\n ...context,\n scopes: scopesApiFactory(params, context.session, context.admin),\n };\n }\n\n return async function authenticateAdmin(request: Request) {\n try {\n respondToBotRequest(params, request);\n respondToOptionsRequest(params, request);\n await respondToBouncePageRequest(request);\n await respondToExitIframeRequest(request);\n await strategy.respondToOAuthRequests(request);\n\n // If this is a valid request, but it doesn't have a session token header, this is a document request. We need to\n // ensure we're embedded if needed and we have the information needed to load the session.\n if (!getSessionTokenHeader(request)) {\n validateShopAndHostParams(params, request);\n await ensureAppIsEmbeddedIfRequired(params, request);\n await ensureSessionTokenSearchParamIfRequired(params, request);\n }\n\n logger.info('Authenticating admin request', {\n shop: getShopFromRequest(request),\n });\n\n const {payload, shop, sessionId, sessionToken} =\n await getSessionTokenContext(params, request);\n\n logger.debug('Loading session from storage', {shop, sessionId});\n const existingSession = sessionId\n ? await config.sessionStorage!.loadSession(sessionId)\n : undefined;\n\n const session = await strategy.authenticate(request, {\n session: existingSession,\n sessionToken,\n shop,\n });\n\n return createContext(request, session, strategy, payload);\n } catch (errorOrResponse) {\n if (errorOrResponse instanceof Response) {\n logger.debug('Authenticate returned a response', {\n shop: getShopFromRequest(request),\n });\n ensureCORSHeadersFactory(params, request)(errorOrResponse);\n }\n\n throw errorOrResponse;\n }\n };\n}\n\nasync function getSessionTokenContext(\n params: BasicParams,\n request: Request,\n): Promise<SessionTokenContext> {\n const {api, config, logger} = params;\n\n const headerSessionToken = getSessionTokenHeader(request);\n const searchParamSessionToken = getSessionTokenFromUrlParam(request);\n const sessionToken = (headerSessionToken || searchParamSessionToken)!;\n\n logger.debug('Attempting to authenticate session token', {\n shop: getShopFromRequest(request),\n sessionToken: JSON.stringify({\n header: headerSessionToken,\n search: searchParamSessionToken,\n }),\n });\n\n if (config.isEmbeddedApp) {\n const payload = await validateSessionToken(params, request, sessionToken);\n const dest = new URL(payload.dest);\n const shop = dest.hostname;\n\n logger.debug('Session token is valid - authenticated', {shop, payload});\n const sessionId = config.useOnlineTokens\n ? api.session.getJwtSessionId(shop, payload.sub)\n : api.session.getOfflineId(shop);\n\n return {shop, payload, sessionId, sessionToken};\n }\n\n const url = new URL(request.url);\n const shop = url.searchParams.get('shop')!;\n\n const sessionId = await api.session.getCurrentId({\n isOnline: config.useOnlineTokens,\n rawRequest: request,\n });\n\n return {shop, sessionId, payload: undefined, sessionToken};\n}\n"],"names":["getShopFromRequest","renderAppBridge","request","createAdminApiContext","requireBillingFactory","checkBillingFactory","requestBillingFactory","cancelBillingFactory","createUsageRecordFactory","updateUsageCappedAmountFactory","ensureCORSHeadersFactory","redirectFactory","scopesApiFactory","respondToBotRequest","respondToOptionsRequest","getSessionTokenHeader","validateShopAndHostParams","ensureAppIsEmbeddedIfRequired","ensureSessionTokenSearchParamIfRequired","getSessionTokenFromUrlParam","validateSessionToken"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"authenticate.js","sources":["../../../../../../src/server/authenticate/admin/authenticate.ts"],"sourcesContent":["import {JwtPayload, Session} from '@shopify/shopify-api';\n\nimport type {BasicParams} from '../../types';\nimport type {AppConfigArg} from '../../config-types';\nimport {\n getSessionTokenHeader,\n ensureCORSHeadersFactory,\n getSessionTokenFromUrlParam,\n respondToBotRequest,\n respondToOptionsRequest,\n validateSessionToken,\n getShopFromRequest,\n} from '../helpers';\n\nimport {\n cancelBillingFactory,\n requestBillingFactory,\n requireBillingFactory,\n checkBillingFactory,\n createUsageRecordFactory,\n updateUsageCappedAmountFactory,\n} from './billing';\nimport type {\n AdminContext,\n AuthenticateAdmin,\n EmbeddedAdminContext,\n NonEmbeddedAdminContext,\n} from './types';\nimport {\n createAdminApiContext,\n ensureAppIsEmbeddedIfRequired,\n ensureSessionTokenSearchParamIfRequired,\n redirectFactory,\n renderAppBridge,\n validateShopAndHostParams,\n} from './helpers';\nimport {AuthorizationStrategy} from './strategies/types';\nimport {scopesApiFactory} from './scope/factory';\n\nexport interface SessionTokenContext {\n shop: string;\n sessionId?: string;\n sessionToken?: string;\n payload?: JwtPayload;\n}\n\ninterface AuthStrategyParams extends BasicParams {\n strategy: AuthorizationStrategy;\n}\n\nexport function authStrategyFactory<ConfigArg extends AppConfigArg>({\n strategy,\n ...params\n}: AuthStrategyParams): AuthenticateAdmin<ConfigArg> {\n const {api, logger, config} = params;\n\n async function respondToBouncePageRequest(request: Request) {\n const url = new URL(request.url);\n\n if (url.pathname === config.auth.patchSessionTokenPath) {\n logger.debug('Rendering bounce page', {\n shop: getShopFromRequest(request),\n });\n throw renderAppBridge({config, logger, api}, request);\n }\n }\n\n async function respondToExitIframeRequest(request: Request) {\n const url = new URL(request.url);\n\n if (url.pathname === config.auth.exitIframePath) {\n const destination = url.searchParams.get('exitIframe')!;\n\n logger.debug('Rendering exit iframe page', {\n shop: getShopFromRequest(request),\n destination,\n });\n throw renderAppBridge({config, logger, api}, request, {url: destination});\n }\n }\n\n type AdminContextBase =\n | EmbeddedAdminContext<ConfigArg>\n | NonEmbeddedAdminContext<ConfigArg>;\n\n function createContext(\n request: Request,\n session: Session,\n authStrategy: AuthorizationStrategy,\n sessionToken?: JwtPayload,\n ): AdminContext<ConfigArg> {\n let context: AdminContextBase = {\n admin: createAdminApiContext(\n session,\n params,\n authStrategy.handleClientError(request),\n ),\n billing: {\n require: requireBillingFactory(params, request, session),\n check: checkBillingFactory(params, request, session),\n request: requestBillingFactory(params, request, session),\n cancel: cancelBillingFactory(params, request, session),\n createUsageRecord: createUsageRecordFactory(params, request, session),\n updateUsageCappedAmount: updateUsageCappedAmountFactory(\n params,\n request,\n session,\n ),\n },\n\n session,\n cors: ensureCORSHeadersFactory(params, request),\n };\n\n context = addEmbeddedFeatures(context, request, session, sessionToken);\n context = addScopesFeatures(context);\n\n return context as AdminContext<ConfigArg>;\n }\n\n function addEmbeddedFeatures(\n context: AdminContextBase,\n request: Request,\n session: Session,\n sessionToken?: JwtPayload,\n ) {\n if (config.isEmbeddedApp) {\n return {\n ...context,\n sessionToken,\n redirect: redirectFactory(params, request, session.shop),\n };\n }\n return context;\n }\n\n function addScopesFeatures(context: AdminContextBase) {\n return {\n ...context,\n scopes: scopesApiFactory(params, context.session, context.admin),\n };\n }\n\n return async function authenticateAdmin(request: Request) {\n try {\n respondToBotRequest(params, request);\n respondToOptionsRequest(params, request);\n await respondToBouncePageRequest(request);\n await respondToExitIframeRequest(request);\n await strategy.respondToOAuthRequests(request);\n\n // If this is a valid request, but it doesn't have a session token header, this is a document request. We need to\n // ensure we're embedded if needed and we have the information needed to load the session.\n if (!getSessionTokenHeader(request)) {\n validateShopAndHostParams(params, request);\n await ensureAppIsEmbeddedIfRequired(params, request);\n await ensureSessionTokenSearchParamIfRequired(params, request);\n }\n\n logger.info('Authenticating admin request', {\n shop: getShopFromRequest(request),\n });\n\n const {payload, shop, sessionId, sessionToken} =\n await getSessionTokenContext(params, request);\n\n logger.debug('Loading session from storage', {shop, sessionId});\n const existingSession = sessionId\n ? await config.sessionStorage!.loadSession(sessionId)\n : undefined;\n\n const session = await strategy.authenticate(request, {\n session: existingSession,\n sessionToken,\n shop,\n });\n\n return createContext(request, session, strategy, payload);\n } catch (errorOrResponse) {\n if (errorOrResponse instanceof Response) {\n logger.debug('Authenticate returned a response', {\n shop: getShopFromRequest(request),\n });\n ensureCORSHeadersFactory(params, request)(errorOrResponse);\n }\n\n throw errorOrResponse;\n }\n };\n}\n\nasync function getSessionTokenContext(\n params: BasicParams,\n request: Request,\n): Promise<SessionTokenContext> {\n const {api, config, logger} = params;\n\n const headerSessionToken = getSessionTokenHeader(request);\n const searchParamSessionToken = getSessionTokenFromUrlParam(request);\n const sessionToken = (headerSessionToken || searchParamSessionToken)!;\n\n logger.debug('Attempting to authenticate session token', {\n shop: getShopFromRequest(request),\n sessionToken: JSON.stringify({\n header: headerSessionToken,\n search: searchParamSessionToken,\n }),\n });\n\n if (config.isEmbeddedApp) {\n const payload = await validateSessionToken(params, request, sessionToken);\n const dest = new URL(payload.dest);\n const shop = dest.hostname;\n\n logger.debug('Session token is valid - authenticated', {shop, payload});\n const sessionId = config.useOnlineTokens\n ? api.session.getJwtSessionId(shop, payload.sub)\n : api.session.getOfflineId(shop);\n\n return {shop, payload, sessionId, sessionToken};\n }\n\n const url = new URL(request.url);\n const shop = url.searchParams.get('shop')!;\n\n const sessionId = await api.session.getCurrentId({\n isOnline: config.useOnlineTokens,\n rawRequest: request,\n });\n\n return {shop, sessionId, payload: undefined, sessionToken};\n}\n"],"names":["getShopFromRequest","renderAppBridge","request","createAdminApiContext","requireBillingFactory","checkBillingFactory","requestBillingFactory","cancelBillingFactory","createUsageRecordFactory","updateUsageCappedAmountFactory","ensureCORSHeadersFactory","redirectFactory","scopesApiFactory","respondToBotRequest","respondToOptionsRequest","getSessionTokenHeader","validateShopAndHostParams","ensureAppIsEmbeddedIfRequired","ensureSessionTokenSearchParamIfRequired","getSessionTokenFromUrlParam","validateSessionToken"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-admin-api-context.js","sources":["../../../../../../../src/server/authenticate/admin/helpers/create-admin-api-context.ts"],"sourcesContent":["import {Session
|
|
1
|
+
{"version":3,"file":"create-admin-api-context.js","sources":["../../../../../../../src/server/authenticate/admin/helpers/create-admin-api-context.ts"],"sourcesContent":["import {Session} from '@shopify/shopify-api';\n\nimport type {BasicParams} from '../../../types';\nimport {\n AdminApiContext,\n HandleAdminClientError,\n adminClientFactory,\n} from '../../../clients/admin';\n\nexport function createAdminApiContext(\n session: Session,\n params: BasicParams,\n handleClientError: HandleAdminClientError,\n): AdminApiContext {\n return adminClientFactory({\n session,\n params,\n handleClientError,\n });\n}\n"],"names":["adminClientFactory"],"mappings":";;;;SASgB,qBAAqB,CACnC,OAAgB,EAChB,MAAmB,EACnB,iBAAyC,EAAA;AAEzC,IAAA,OAAOA,0BAAkB,CAAC;QACxB,OAAO;QACP,MAAM;QACN,iBAAiB;AAClB,KAAA,CAAC;AACJ;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trigger-after-auth-hook.js","sources":["../../../../../../../src/server/authenticate/admin/helpers/trigger-after-auth-hook.ts"],"sourcesContent":["import {Session
|
|
1
|
+
{"version":3,"file":"trigger-after-auth-hook.js","sources":["../../../../../../../src/server/authenticate/admin/helpers/trigger-after-auth-hook.ts"],"sourcesContent":["import {Session} from '@shopify/shopify-api';\n\nimport type {BasicParams} from '../../../types';\nimport {AuthorizationStrategy} from '../strategies/types';\n\nimport {createAdminApiContext} from './create-admin-api-context';\n\nexport async function triggerAfterAuthHook(\n params: BasicParams,\n session: Session,\n request: Request,\n authStrategy: AuthorizationStrategy,\n) {\n const {config, logger} = params;\n if (config.hooks.afterAuth) {\n logger.info('Running afterAuth hook', {shop: session.shop});\n\n const admin = createAdminApiContext(\n session,\n params,\n authStrategy.handleClientError(request),\n );\n\n await config.hooks.afterAuth({\n session,\n admin,\n });\n }\n}\n"],"names":["createAdminApiContext"],"mappings":";;;;AAOO,eAAe,oBAAoB,CACxC,MAAmB,EACnB,OAAgB,EAChB,OAAgB,EAChB,YAAmC,EAAA;AAEnC,IAAA,MAAM,EAAC,MAAM,EAAE,MAAM,EAAC,GAAG,MAAM;AAC/B,IAAA,IAAI,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE;AAC1B,QAAA,MAAM,CAAC,IAAI,CAAC,wBAAwB,EAAE,EAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAC,CAAC;AAE3D,QAAA,MAAM,KAAK,GAAGA,2CAAqB,CACjC,OAAO,EACP,MAAM,EACN,YAAY,CAAC,iBAAiB,CAAC,OAAO,CAAC,CACxC;AAED,QAAA,MAAM,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC;YAC3B,OAAO;YACP,KAAK;AACN,SAAA,CAAC;IACJ;AACF;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch-scopes-details.js","sources":["../../../../../../../../src/server/authenticate/admin/scope/client/fetch-scopes-details.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"fetch-scopes-details.js","sources":["../../../../../../../../src/server/authenticate/admin/scope/client/fetch-scopes-details.ts"],"sourcesContent":["import {AdminApiContext} from '../../../../clients';\n\nexport interface FetchScopesDetailResponse {\n app: {\n requestedAccessScopes: {\n handle: string;\n }[];\n optionalAccessScopes: {\n handle: string;\n }[];\n installation: {\n accessScopes: {\n handle: string;\n }[];\n };\n };\n}\n\nconst FETCH_SCOPES_DETAIL_QUERY = `#graphql\nquery FetchAccessScopes{\n app {\n requestedAccessScopes {\n handle\n }\n optionalAccessScopes {\n handle\n }\n installation {\n accessScopes {\n handle\n }\n }\n }\n}`;\n\nexport async function fetchScopeDetail(\n admin: AdminApiContext,\n): Promise<FetchScopesDetailResponse> {\n const fetchScopeDetailResult = await admin.graphql(FETCH_SCOPES_DETAIL_QUERY);\n\n const resultContent = await fetchScopeDetailResult.json();\n return resultContent.data;\n}\n"],"names":[],"mappings":";;AAkBA,MAAM,yBAAyB,GAAG,CAAA;;;;;;;;;;;;;;;EAehC;AAEK,eAAe,gBAAgB,CACpC,KAAsB,EAAA;IAEtB,MAAM,sBAAsB,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,yBAAyB,CAAC;AAE7E,IAAA,MAAM,aAAa,GAAG,MAAM,sBAAsB,CAAC,IAAI,EAAE;IACzD,OAAO,aAAa,CAAC,IAAI;AAC3B;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"revoke-scopes.js","sources":["../../../../../../../../src/server/authenticate/admin/scope/client/revoke-scopes.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"revoke-scopes.js","sources":["../../../../../../../../src/server/authenticate/admin/scope/client/revoke-scopes.ts"],"sourcesContent":["import {AdminApiContext} from '../../../../clients';\n\nexport interface RevokeScopesResponse {\n revoked: {\n handle: string;\n }[];\n userErrors: {\n field: string;\n message: string;\n }[];\n}\n\nconst REVOKE_SCOPE_MUTATION = `#graphql\nmutation AppRevokeAccessScopes($scopes: [String!]!) {\n appRevokeAccessScopes(scopes: $scopes){\n revoked {\n handle\n }\n userErrors {\n field\n message\n }\n }\n}`;\n\nexport async function revokeScopes(\n admin: AdminApiContext,\n scopes: string[],\n): Promise<RevokeScopesResponse> {\n const revokeScopesResult = await admin.graphql(REVOKE_SCOPE_MUTATION, {\n variables: {\n scopes,\n },\n });\n\n const resultContent = await revokeScopesResult.json();\n return resultContent.data.appRevokeAccessScopes;\n}\n"],"names":[],"mappings":";;AAYA,MAAM,qBAAqB,GAAG,CAAA;;;;;;;;;;;EAW5B;AAEK,eAAe,YAAY,CAChC,KAAsB,EACtB,MAAgB,EAAA;IAEhB,MAAM,kBAAkB,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,qBAAqB,EAAE;AACpE,QAAA,SAAS,EAAE;YACT,MAAM;AACP,SAAA;AACF,KAAA,CAAC;AAEF,IAAA,MAAM,aAAa,GAAG,MAAM,kBAAkB,CAAC,IAAI,EAAE;AACrD,IAAA,OAAO,aAAa,CAAC,IAAI,CAAC,qBAAqB;AACjD;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.js","sources":["../../../../../../../src/server/authenticate/admin/scope/factory.ts"],"sourcesContent":["import {Session} from '@shopify/shopify-api';\n\nimport {
|
|
1
|
+
{"version":3,"file":"factory.js","sources":["../../../../../../../src/server/authenticate/admin/scope/factory.ts"],"sourcesContent":["import {Session} from '@shopify/shopify-api';\n\nimport {BasicParams} from '../../../types';\nimport {AdminApiContext} from '../../../clients';\n\nimport {ScopesApiContext} from './types';\nimport {requestScopesFactory} from './request';\nimport {queryScopesFactory} from './query';\nimport {revokeScopesFactory} from './revoke';\n\nexport function scopesApiFactory(\n params: BasicParams,\n session: Session,\n admin: AdminApiContext,\n): ScopesApiContext {\n return {\n query: queryScopesFactory(params, session, admin),\n request: requestScopesFactory(params, session, admin),\n revoke: revokeScopesFactory(params, session, admin),\n };\n}\n"],"names":["queryScopesFactory","requestScopesFactory","revokeScopesFactory"],"mappings":";;;;;;SAUgB,gBAAgB,CAC9B,MAAmB,EACnB,OAAgB,EAChB,KAAsB,EAAA;IAEtB,OAAO;QACL,KAAK,EAAEA,wBAAkB,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC;QACjD,OAAO,EAAEC,4BAAoB,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC;QACrD,MAAM,EAAEC,0BAAmB,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC;KACpD;AACH;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.js","sources":["../../../../../../../src/server/authenticate/admin/scope/query.ts"],"sourcesContent":["import {AuthScopes, Session} from '@shopify/shopify-api';\n\nimport {
|
|
1
|
+
{"version":3,"file":"query.js","sources":["../../../../../../../src/server/authenticate/admin/scope/query.ts"],"sourcesContent":["import {AuthScopes, Session} from '@shopify/shopify-api';\n\nimport {AdminApiContext} from '../../../clients';\nimport type {BasicParams} from '../../../types';\n\nimport {ScopesDetail} from './types';\nimport {\n FetchScopesDetailResponse,\n fetchScopeDetail,\n} from './client/fetch-scopes-details';\n\nexport function queryScopesFactory(\n params: BasicParams,\n session: Session,\n admin: AdminApiContext,\n) {\n return async function queryScopes() {\n const {logger} = params;\n\n logger.debug('Querying scopes details: ', {\n shop: session.shop,\n });\n\n const scopesDetail = await fetchScopeDetail(admin);\n return mapFetchScopeDetail(scopesDetail);\n };\n}\n\nexport function mapFetchScopeDetail(\n scopesDetailResponse: FetchScopesDetailResponse,\n): ScopesDetail {\n const appInformation = scopesDetailResponse.app;\n\n const granted = new AuthScopes(\n appInformation.installation.accessScopes.map((scope) => scope.handle),\n ).toArray(true);\n\n const required = new AuthScopes(\n appInformation.requestedAccessScopes.map((scope) => scope.handle),\n ).toArray(true);\n\n const optional = new AuthScopes(\n appInformation.optionalAccessScopes.map((scope) => scope.handle),\n ).toArray(true);\n\n return {\n granted,\n required,\n optional,\n };\n}\n"],"names":["fetchScopeDetail","AuthScopes"],"mappings":";;;;;SAWgB,kBAAkB,CAChC,MAAmB,EACnB,OAAgB,EAChB,KAAsB,EAAA;IAEtB,OAAO,eAAe,WAAW,GAAA;AAC/B,QAAA,MAAM,EAAC,MAAM,EAAC,GAAG,MAAM;AAEvB,QAAA,MAAM,CAAC,KAAK,CAAC,2BAA2B,EAAE;YACxC,IAAI,EAAE,OAAO,CAAC,IAAI;AACnB,SAAA,CAAC;AAEF,QAAA,MAAM,YAAY,GAAG,MAAMA,mCAAgB,CAAC,KAAK,CAAC;AAClD,QAAA,OAAO,mBAAmB,CAAC,YAAY,CAAC;AAC1C,IAAA,CAAC;AACH;AAEM,SAAU,mBAAmB,CACjC,oBAA+C,EAAA;AAE/C,IAAA,MAAM,cAAc,GAAG,oBAAoB,CAAC,GAAG;AAE/C,IAAA,MAAM,OAAO,GAAG,IAAIC,qBAAU,CAC5B,cAAc,CAAC,YAAY,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,MAAM,CAAC,CACtE,CAAC,OAAO,CAAC,IAAI,CAAC;IAEf,MAAM,QAAQ,GAAG,IAAIA,qBAAU,CAC7B,cAAc,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,MAAM,CAAC,CAClE,CAAC,OAAO,CAAC,IAAI,CAAC;IAEf,MAAM,QAAQ,GAAG,IAAIA,qBAAU,CAC7B,cAAc,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,MAAM,CAAC,CACjE,CAAC,OAAO,CAAC,IAAI,CAAC;IAEf,OAAO;QACL,OAAO;QACP,QAAQ;QACR,QAAQ;KACT;AACH;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.js","sources":["../../../../../../../src/server/authenticate/admin/scope/request.ts"],"sourcesContent":["import {AuthScopes, Session} from '@shopify/shopify-api';\n\nimport
|
|
1
|
+
{"version":3,"file":"request.js","sources":["../../../../../../../src/server/authenticate/admin/scope/request.ts"],"sourcesContent":["import {AuthScopes, Session} from '@shopify/shopify-api';\n\nimport type {BasicParams} from '../../../types';\nimport {redirectToInstallPage} from '../helpers/redirect-to-install-page';\nimport {AdminApiContext} from '../../../clients';\n\nimport {fetchScopeDetail} from './client/fetch-scopes-details';\n\nexport function requestScopesFactory(\n params: BasicParams,\n session: Session,\n admin: AdminApiContext,\n) {\n return async function requestScopes(scopes: string[]) {\n const {logger} = params;\n\n logger.debug('Requesting optional scopes: ', {shop: session.shop, scopes});\n\n if (scopes.length === 0) return;\n if (await alreadyGranted(scopes, admin)) return;\n\n throw await redirectToInstallPage(params, session.shop, scopes);\n };\n\n async function alreadyGranted(scopes: string[], admin: AdminApiContext) {\n const scopesDetail = await fetchScopeDetail(admin);\n const grantedScopes = scopesDetail.app.installation.accessScopes.map(\n (scope) => scope.handle,\n );\n return new AuthScopes(grantedScopes).has(scopes);\n }\n}\n"],"names":["redirectToInstallPage","fetchScopeDetail","AuthScopes"],"mappings":";;;;;;SAQgB,oBAAoB,CAClC,MAAmB,EACnB,OAAgB,EAChB,KAAsB,EAAA;AAEtB,IAAA,OAAO,eAAe,aAAa,CAAC,MAAgB,EAAA;AAClD,QAAA,MAAM,EAAC,MAAM,EAAC,GAAG,MAAM;AAEvB,QAAA,MAAM,CAAC,KAAK,CAAC,8BAA8B,EAAE,EAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,EAAC,CAAC;AAE1E,QAAA,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE;AACzB,QAAA,IAAI,MAAM,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC;YAAE;QAEzC,MAAM,MAAMA,2CAAqB,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;AACjE,IAAA,CAAC;AAED,IAAA,eAAe,cAAc,CAAC,MAAgB,EAAE,KAAsB,EAAA;AACpE,QAAA,MAAM,YAAY,GAAG,MAAMC,mCAAgB,CAAC,KAAK,CAAC;QAClD,MAAM,aAAa,GAAG,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,YAAY,CAAC,GAAG,CAClE,CAAC,KAAK,KAAK,KAAK,CAAC,MAAM,CACxB;QACD,OAAO,IAAIC,qBAAU,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;IAClD;AACF;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"revoke.js","sources":["../../../../../../../src/server/authenticate/admin/scope/revoke.ts"],"sourcesContent":["import {Session} from '@shopify/shopify-api';\n\nimport {
|
|
1
|
+
{"version":3,"file":"revoke.js","sources":["../../../../../../../src/server/authenticate/admin/scope/revoke.ts"],"sourcesContent":["import {Session} from '@shopify/shopify-api';\n\nimport {AdminApiContext} from '../../../clients';\nimport type {BasicParams} from '../../../types';\n\nimport {revokeScopes} from './client/revoke-scopes';\n\nexport function revokeScopesFactory(\n params: BasicParams,\n session: Session,\n admin: AdminApiContext,\n) {\n return async function revoke(scopes: string[]) {\n const {logger} = params;\n\n await validateScopes(scopes);\n\n logger.debug('Revoke scopes: ', {\n shop: session.shop,\n scopes,\n });\n\n const revokeScopesResult = await revokeScopes(admin, scopes);\n if (revokeScopesResult.userErrors?.length > 0) {\n logger.error('Failed to revoke scopes: ', {\n shop: session.shop,\n errors: revokeScopesResult.userErrors,\n });\n\n throw new Response(JSON.stringify(revokeScopesResult.userErrors), {\n status: 422,\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n }\n\n return {\n revoked: revokeScopesResult.revoked.map((scope) => scope.handle),\n };\n };\n}\n\nasync function validateScopes(scopes: string[]) {\n if (!scopes || scopes.length === 0) {\n throw new Response('No scopes provided', {status: 400});\n }\n}\n"],"names":["revokeScopes"],"mappings":";;;;SAOgB,mBAAmB,CACjC,MAAmB,EACnB,OAAgB,EAChB,KAAsB,EAAA;AAEtB,IAAA,OAAO,eAAe,MAAM,CAAC,MAAgB,EAAA;AAC3C,QAAA,MAAM,EAAC,MAAM,EAAC,GAAG,MAAM;AAEvB,QAAA,MAAM,cAAc,CAAC,MAAM,CAAC;AAE5B,QAAA,MAAM,CAAC,KAAK,CAAC,iBAAiB,EAAE;YAC9B,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,MAAM;AACP,SAAA,CAAC;QAEF,MAAM,kBAAkB,GAAG,MAAMA,yBAAY,CAAC,KAAK,EAAE,MAAM,CAAC;QAC5D,IAAI,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,CAAC,EAAE;AAC7C,YAAA,MAAM,CAAC,KAAK,CAAC,2BAA2B,EAAE;gBACxC,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,MAAM,EAAE,kBAAkB,CAAC,UAAU;AACtC,aAAA,CAAC;YAEF,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,UAAU,CAAC,EAAE;AAChE,gBAAA,MAAM,EAAE,GAAG;AACX,gBAAA,OAAO,EAAE;AACP,oBAAA,cAAc,EAAE,kBAAkB;AACnC,iBAAA;AACF,aAAA,CAAC;QACJ;QAEA,OAAO;AACL,YAAA,OAAO,EAAE,kBAAkB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,MAAM,CAAC;SACjE;AACH,IAAA,CAAC;AACH;AAEA,eAAe,cAAc,CAAC,MAAgB,EAAA;IAC5C,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;QAClC,MAAM,IAAI,QAAQ,CAAC,oBAAoB,EAAE,EAAC,MAAM,EAAE,GAAG,EAAC,CAAC;IACzD;AACF;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-code-flow.js","sources":["../../../../../../../src/server/authenticate/admin/strategies/auth-code-flow.ts"],"sourcesContent":["import {\n CookieNotFound,\n GraphqlQueryError,\n HttpResponseError,\n InvalidHmacError,\n InvalidOAuthError,\n Session,\n Shopify,\n ShopifyRestResources,\n} from '@shopify/shopify-api';\n\nimport type {BasicParams} from '../../../types';\nimport {\n beginAuth,\n handleClientErrorFactory,\n redirectToAuthPage,\n redirectToShopifyOrAppRoot,\n redirectWithExitIframe,\n triggerAfterAuthHook,\n validateShopAndHostParams,\n} from '../helpers';\nimport {AppConfig, AppConfigArg} from '../../../config-types';\nimport {getSessionTokenHeader} from '../../helpers';\nimport {HandleAdminClientError} from '../../../clients';\nimport type {\n ApiConfigWithFutureFlags,\n ApiFutureFlags,\n} from '../../../future/flags';\n\nimport {AuthorizationStrategy, SessionContext, OnErrorOptions} from './types';\n\nexport class AuthCodeFlowStrategy<\n Config extends AppConfigArg,\n Resources extends ShopifyRestResources = ShopifyRestResources,\n> implements AuthorizationStrategy\n{\n protected api: Shopify<\n ApiConfigWithFutureFlags<Config['future']>,\n ShopifyRestResources,\n ApiFutureFlags<Config['future']>\n >;\n\n protected config: AppConfig;\n protected logger: Shopify['logger'];\n\n public constructor({api, config, logger}: BasicParams) {\n this.api = api;\n this.config = config;\n this.logger = logger;\n }\n\n public async respondToOAuthRequests(request: Request): Promise<void | never> {\n const {api, config} = this;\n\n const url = new URL(request.url);\n const isAuthRequest = url.pathname === config.auth.path;\n const isAuthCallbackRequest = url.pathname === config.auth.callbackPath;\n\n if (isAuthRequest || isAuthCallbackRequest) {\n const shop = api.utils.sanitizeShop(url.searchParams.get('shop')!);\n if (!shop) throw new Response('Shop param is invalid', {status: 400});\n\n if (isAuthRequest) {\n throw await this.handleAuthBeginRequest(request, shop);\n } else {\n throw await this.handleAuthCallbackRequest(request, shop);\n }\n }\n\n if (!getSessionTokenHeader(request)) {\n // This is a document request that doesn't contain a session token. We check if the app is installed.\n // If the app isn't installed, we initiate the OAuth auth code flow.\n // Requests with a header can only happen after the app is installed.\n await this.ensureInstalledOnShop(request);\n }\n }\n\n public async authenticate(\n request: Request,\n sessionContext: SessionContext,\n ): Promise<Session | never> {\n const {api, config, logger} = this;\n\n const {shop, session} = sessionContext;\n\n if (!session) {\n logger.debug('No session found, redirecting to OAuth', {shop});\n await redirectToAuthPage({config, logger, api}, request, shop);\n } else if (!session.isActive(config.scopes)) {\n logger.debug(\n 'Found a session, but it has expired, redirecting to OAuth',\n {shop},\n );\n await redirectToAuthPage({config, logger, api}, request, shop);\n }\n\n logger.debug('Found a valid session', {shop});\n\n return session!;\n }\n\n public handleClientError(request: Request): HandleAdminClientError {\n const {api, config, logger} = this;\n return handleClientErrorFactory({\n request,\n onError: async ({session, error}: OnErrorOptions) => {\n if (error.response.code === 401) {\n throw await redirectToAuthPage(\n {api, config, logger},\n request,\n session.shop,\n );\n }\n },\n });\n }\n\n private async ensureInstalledOnShop(request: Request) {\n const {api, config, logger} = this;\n\n validateShopAndHostParams({api, config, logger}, request);\n\n const url = new URL(request.url);\n let shop = url.searchParams.get('shop');\n\n // Ensure app is installed\n logger.debug('Ensuring app is installed on shop', {shop});\n\n if (!(await this.hasValidOfflineId(request))) {\n logger.info(\"Could not find a shop, can't authenticate request\");\n throw new Response(undefined, {\n status: 400,\n statusText: 'Bad Request',\n });\n }\n\n const offlineSession = await this.getOfflineSession(request);\n const isEmbedded = url.searchParams.get('embedded') === '1';\n\n if (!offlineSession) {\n logger.info(\"Shop hasn't installed app yet, redirecting to OAuth\", {\n shop,\n });\n if (isEmbedded) {\n redirectWithExitIframe({api, config, logger}, request, shop!);\n } else {\n throw await beginAuth({api, config, logger}, request, false, shop!);\n }\n }\n\n shop = shop || offlineSession.shop;\n\n if (config.isEmbeddedApp && !isEmbedded) {\n try {\n logger.debug('Ensuring offline session is valid before embedding', {\n shop,\n });\n await this.testSession(offlineSession);\n\n logger.debug('Offline session is still valid, embedding app', {shop});\n } catch (error) {\n await this.handleInvalidOfflineSession(error, request, shop);\n }\n }\n }\n\n private async handleAuthBeginRequest(\n request: Request,\n shop: string,\n ): Promise<never> {\n const {api, config, logger} = this;\n\n logger.info('Handling OAuth begin request', {shop});\n\n // If we're loading from an iframe, we need to break out of it\n if (\n config.isEmbeddedApp &&\n request.headers.get('Sec-Fetch-Dest') === 'iframe'\n ) {\n logger.debug('Auth request in iframe detected, exiting iframe', {shop});\n throw redirectWithExitIframe({api, config, logger}, request, shop);\n } else {\n throw await beginAuth({api, config, logger}, request, false, shop);\n }\n }\n\n private async handleAuthCallbackRequest(\n request: Request,\n shop: string,\n ): Promise<never> {\n const {api, config, logger} = this;\n\n logger.info('Handling OAuth callback request', {shop});\n\n try {\n const {session, headers: responseHeaders} = await api.auth.callback({\n rawRequest: request,\n });\n\n await config.sessionStorage!.storeSession(session);\n\n if (config.useOnlineTokens && !session.isOnline) {\n logger.info('Requesting online access token for offline session', {\n shop,\n });\n await beginAuth({api, config, logger}, request, true, shop);\n }\n\n logger.debug('Request is valid, loaded session from OAuth callback', {\n shop: session.shop,\n isOnline: session.isOnline,\n });\n\n await triggerAfterAuthHook<Config, Resources>(\n {api, config, logger},\n session,\n request,\n this,\n );\n\n throw await redirectToShopifyOrAppRoot(\n request,\n {api, config, logger},\n responseHeaders,\n );\n } catch (error) {\n if (error instanceof Response) throw error;\n\n throw await this.oauthCallbackError(error, request, shop);\n }\n }\n\n private async getOfflineSession(\n request: Request,\n ): Promise<Session | undefined> {\n const offlineId = await this.getOfflineSessionId(request);\n return this.config.sessionStorage!.loadSession(offlineId!);\n }\n\n private async hasValidOfflineId(request: Request) {\n return Boolean(await this.getOfflineSessionId(request));\n }\n\n private async getOfflineSessionId(\n request: Request,\n ): Promise<string | undefined> {\n const {api} = this;\n const url = new URL(request.url);\n const shop = url.searchParams.get('shop');\n\n return shop\n ? api.session.getOfflineId(shop)\n : api.session.getCurrentId({isOnline: false, rawRequest: request});\n }\n\n private async testSession(session: Session): Promise<void> {\n const {api} = this;\n\n const client = new api.clients.Graphql({\n session,\n });\n\n await client.request(`#graphql\n query shopifyAppShopName {\n shop {\n name\n }\n }\n `);\n }\n\n private async oauthCallbackError(\n error: Error,\n request: Request,\n shop: string,\n ) {\n const {logger} = this;\n logger.error('Error during OAuth callback', {shop, error: error.message});\n\n if (error instanceof CookieNotFound) {\n return this.handleAuthBeginRequest(request, shop);\n }\n\n if (\n error instanceof InvalidHmacError ||\n error instanceof InvalidOAuthError\n ) {\n return new Response(undefined, {\n status: 400,\n statusText: 'Invalid OAuth Request',\n });\n }\n\n return new Response(undefined, {\n status: 500,\n statusText: 'Internal Server Error',\n });\n }\n\n private async handleInvalidOfflineSession(\n error: Error,\n request: Request,\n shop: string,\n ) {\n const {api, logger, config} = this;\n if (error instanceof HttpResponseError) {\n if (error.response.code === 401) {\n logger.info('Shop session is no longer valid, redirecting to OAuth', {\n shop,\n });\n throw await beginAuth({api, config, logger}, request, false, shop);\n } else {\n const message = JSON.stringify(error.response.body, null, 2);\n logger.error(`Unexpected error during session validation: ${message}`, {\n shop,\n });\n\n throw new Response(undefined, {\n status: error.response.code,\n statusText: error.response.statusText,\n });\n }\n } else if (error instanceof GraphqlQueryError) {\n const context: Record<string, string> = {shop};\n if (error.response) {\n context.response = JSON.stringify(error.body);\n }\n\n logger.error(\n `Unexpected error during session validation: ${error.message}`,\n context,\n );\n\n throw new Response(undefined, {\n status: 500,\n statusText: 'Internal Server Error',\n });\n }\n }\n}\n"],"names":["getSessionTokenHeader","redirectToAuthPage","handleClientErrorFactory","validateShopAndHostParams","redirectWithExitIframe","beginAuth","triggerAfterAuthHook","redirectToShopifyOrAppRoot","CookieNotFound","InvalidHmacError","InvalidOAuthError","HttpResponseError","GraphqlQueryError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"auth-code-flow.js","sources":["../../../../../../../src/server/authenticate/admin/strategies/auth-code-flow.ts"],"sourcesContent":["import {\n CookieNotFound,\n GraphqlQueryError,\n HttpResponseError,\n InvalidHmacError,\n InvalidOAuthError,\n Session,\n Shopify,\n} from '@shopify/shopify-api';\n\nimport type {BasicParams} from '../../../types';\nimport {\n beginAuth,\n handleClientErrorFactory,\n redirectToAuthPage,\n redirectToShopifyOrAppRoot,\n redirectWithExitIframe,\n triggerAfterAuthHook,\n validateShopAndHostParams,\n} from '../helpers';\nimport {AppConfig, AppConfigArg} from '../../../config-types';\nimport {getSessionTokenHeader} from '../../helpers';\nimport {HandleAdminClientError} from '../../../clients';\nimport type {\n ApiConfigWithFutureFlags,\n ApiFutureFlags,\n} from '../../../future/flags';\n\nimport {AuthorizationStrategy, SessionContext, OnErrorOptions} from './types';\n\nexport class AuthCodeFlowStrategy<Config extends AppConfigArg>\n implements AuthorizationStrategy\n{\n protected api: Shopify<\n ApiConfigWithFutureFlags<Config['future']>,\n ApiFutureFlags<Config['future']>\n >;\n\n protected config: AppConfig;\n protected logger: Shopify['logger'];\n\n public constructor({api, config, logger}: BasicParams) {\n this.api = api;\n this.config = config;\n this.logger = logger;\n }\n\n public async respondToOAuthRequests(request: Request): Promise<void | never> {\n const {api, config} = this;\n\n const url = new URL(request.url);\n const isAuthRequest = url.pathname === config.auth.path;\n const isAuthCallbackRequest = url.pathname === config.auth.callbackPath;\n\n if (isAuthRequest || isAuthCallbackRequest) {\n const shop = api.utils.sanitizeShop(url.searchParams.get('shop')!);\n if (!shop) throw new Response('Shop param is invalid', {status: 400});\n\n if (isAuthRequest) {\n throw await this.handleAuthBeginRequest(request, shop);\n } else {\n throw await this.handleAuthCallbackRequest(request, shop);\n }\n }\n\n if (!getSessionTokenHeader(request)) {\n // This is a document request that doesn't contain a session token. We check if the app is installed.\n // If the app isn't installed, we initiate the OAuth auth code flow.\n // Requests with a header can only happen after the app is installed.\n await this.ensureInstalledOnShop(request);\n }\n }\n\n public async authenticate(\n request: Request,\n sessionContext: SessionContext,\n ): Promise<Session | never> {\n const {api, config, logger} = this;\n\n const {shop, session} = sessionContext;\n\n if (!session) {\n logger.debug('No session found, redirecting to OAuth', {shop});\n await redirectToAuthPage({config, logger, api}, request, shop);\n } else if (!session.isActive(config.scopes)) {\n logger.debug(\n 'Found a session, but it has expired, redirecting to OAuth',\n {shop},\n );\n await redirectToAuthPage({config, logger, api}, request, shop);\n }\n\n logger.debug('Found a valid session', {shop});\n\n return session!;\n }\n\n public handleClientError(request: Request): HandleAdminClientError {\n const {api, config, logger} = this;\n return handleClientErrorFactory({\n request,\n onError: async ({session, error}: OnErrorOptions) => {\n if (error.response.code === 401) {\n throw await redirectToAuthPage(\n {api, config, logger},\n request,\n session.shop,\n );\n }\n },\n });\n }\n\n private async ensureInstalledOnShop(request: Request) {\n const {api, config, logger} = this;\n\n validateShopAndHostParams({api, config, logger}, request);\n\n const url = new URL(request.url);\n let shop = url.searchParams.get('shop');\n\n // Ensure app is installed\n logger.debug('Ensuring app is installed on shop', {shop});\n\n if (!(await this.hasValidOfflineId(request))) {\n logger.info(\"Could not find a shop, can't authenticate request\");\n throw new Response(undefined, {\n status: 400,\n statusText: 'Bad Request',\n });\n }\n\n const offlineSession = await this.getOfflineSession(request);\n const isEmbedded = url.searchParams.get('embedded') === '1';\n\n if (!offlineSession) {\n logger.info(\"Shop hasn't installed app yet, redirecting to OAuth\", {\n shop,\n });\n if (isEmbedded) {\n redirectWithExitIframe({api, config, logger}, request, shop!);\n } else {\n throw await beginAuth({api, config, logger}, request, false, shop!);\n }\n }\n\n shop = shop || offlineSession.shop;\n\n if (config.isEmbeddedApp && !isEmbedded) {\n try {\n logger.debug('Ensuring offline session is valid before embedding', {\n shop,\n });\n await this.testSession(offlineSession);\n\n logger.debug('Offline session is still valid, embedding app', {shop});\n } catch (error) {\n await this.handleInvalidOfflineSession(error, request, shop);\n }\n }\n }\n\n private async handleAuthBeginRequest(\n request: Request,\n shop: string,\n ): Promise<never> {\n const {api, config, logger} = this;\n\n logger.info('Handling OAuth begin request', {shop});\n\n // If we're loading from an iframe, we need to break out of it\n if (\n config.isEmbeddedApp &&\n request.headers.get('Sec-Fetch-Dest') === 'iframe'\n ) {\n logger.debug('Auth request in iframe detected, exiting iframe', {shop});\n throw redirectWithExitIframe({api, config, logger}, request, shop);\n } else {\n throw await beginAuth({api, config, logger}, request, false, shop);\n }\n }\n\n private async handleAuthCallbackRequest(\n request: Request,\n shop: string,\n ): Promise<never> {\n const {api, config, logger} = this;\n\n logger.info('Handling OAuth callback request', {shop});\n\n try {\n const {session, headers: responseHeaders} = await api.auth.callback({\n rawRequest: request,\n });\n\n await config.sessionStorage!.storeSession(session);\n\n if (config.useOnlineTokens && !session.isOnline) {\n logger.info('Requesting online access token for offline session', {\n shop,\n });\n await beginAuth({api, config, logger}, request, true, shop);\n }\n\n logger.debug('Request is valid, loaded session from OAuth callback', {\n shop: session.shop,\n isOnline: session.isOnline,\n });\n\n await triggerAfterAuthHook({api, config, logger}, session, request, this);\n\n throw await redirectToShopifyOrAppRoot(\n request,\n {api, config, logger},\n responseHeaders,\n );\n } catch (error) {\n if (error instanceof Response) throw error;\n\n throw await this.oauthCallbackError(error, request, shop);\n }\n }\n\n private async getOfflineSession(\n request: Request,\n ): Promise<Session | undefined> {\n const offlineId = await this.getOfflineSessionId(request);\n return this.config.sessionStorage!.loadSession(offlineId!);\n }\n\n private async hasValidOfflineId(request: Request) {\n return Boolean(await this.getOfflineSessionId(request));\n }\n\n private async getOfflineSessionId(\n request: Request,\n ): Promise<string | undefined> {\n const {api} = this;\n const url = new URL(request.url);\n const shop = url.searchParams.get('shop');\n\n return shop\n ? api.session.getOfflineId(shop)\n : api.session.getCurrentId({isOnline: false, rawRequest: request});\n }\n\n private async testSession(session: Session): Promise<void> {\n const {api} = this;\n\n const client = new api.clients.Graphql({\n session,\n });\n\n await client.request(`#graphql\n query shopifyAppShopName {\n shop {\n name\n }\n }\n `);\n }\n\n private async oauthCallbackError(\n error: Error,\n request: Request,\n shop: string,\n ) {\n const {logger} = this;\n logger.error('Error during OAuth callback', {shop, error: error.message});\n\n if (error instanceof CookieNotFound) {\n return this.handleAuthBeginRequest(request, shop);\n }\n\n if (\n error instanceof InvalidHmacError ||\n error instanceof InvalidOAuthError\n ) {\n return new Response(undefined, {\n status: 400,\n statusText: 'Invalid OAuth Request',\n });\n }\n\n return new Response(undefined, {\n status: 500,\n statusText: 'Internal Server Error',\n });\n }\n\n private async handleInvalidOfflineSession(\n error: Error,\n request: Request,\n shop: string,\n ) {\n const {api, logger, config} = this;\n if (error instanceof HttpResponseError) {\n if (error.response.code === 401) {\n logger.info('Shop session is no longer valid, redirecting to OAuth', {\n shop,\n });\n throw await beginAuth({api, config, logger}, request, false, shop);\n } else {\n const message = JSON.stringify(error.response.body, null, 2);\n logger.error(`Unexpected error during session validation: ${message}`, {\n shop,\n });\n\n throw new Response(undefined, {\n status: error.response.code,\n statusText: error.response.statusText,\n });\n }\n } else if (error instanceof GraphqlQueryError) {\n const context: Record<string, string> = {shop};\n if (error.response) {\n context.response = JSON.stringify(error.body);\n }\n\n logger.error(\n `Unexpected error during session validation: ${error.message}`,\n context,\n );\n\n throw new Response(undefined, {\n status: 500,\n statusText: 'Internal Server Error',\n });\n }\n }\n}\n"],"names":["getSessionTokenHeader","redirectToAuthPage","handleClientErrorFactory","validateShopAndHostParams","redirectWithExitIframe","beginAuth","triggerAfterAuthHook","redirectToShopifyOrAppRoot","CookieNotFound","InvalidHmacError","InvalidOAuthError","HttpResponseError","GraphqlQueryError"],"mappings":";;;;;;;;;;;;;;;MA8Ba,oBAAoB,CAAA;AAGrB,IAAA,GAAG;AAKH,IAAA,MAAM;AACN,IAAA,MAAM;AAEhB,IAAA,WAAA,CAAmB,EAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAc,EAAA;AACnD,QAAA,IAAI,CAAC,GAAG,GAAG,GAAG;AACd,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM;AACpB,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM;IACtB;IAEO,MAAM,sBAAsB,CAAC,OAAgB,EAAA;AAClD,QAAA,MAAM,EAAC,GAAG,EAAE,MAAM,EAAC,GAAG,IAAI;QAE1B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC;QAChC,MAAM,aAAa,GAAG,GAAG,CAAC,QAAQ,KAAK,MAAM,CAAC,IAAI,CAAC,IAAI;QACvD,MAAM,qBAAqB,GAAG,GAAG,CAAC,QAAQ,KAAK,MAAM,CAAC,IAAI,CAAC,YAAY;AAEvE,QAAA,IAAI,aAAa,IAAI,qBAAqB,EAAE;AAC1C,YAAA,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAE,CAAC;AAClE,YAAA,IAAI,CAAC,IAAI;gBAAE,MAAM,IAAI,QAAQ,CAAC,uBAAuB,EAAE,EAAC,MAAM,EAAE,GAAG,EAAC,CAAC;YAErE,IAAI,aAAa,EAAE;gBACjB,MAAM,MAAM,IAAI,CAAC,sBAAsB,CAAC,OAAO,EAAE,IAAI,CAAC;YACxD;iBAAO;gBACL,MAAM,MAAM,IAAI,CAAC,yBAAyB,CAAC,OAAO,EAAE,IAAI,CAAC;YAC3D;QACF;AAEA,QAAA,IAAI,CAACA,2CAAqB,CAAC,OAAO,CAAC,EAAE;;;;AAInC,YAAA,MAAM,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC;QAC3C;IACF;AAEO,IAAA,MAAM,YAAY,CACvB,OAAgB,EAChB,cAA8B,EAAA;QAE9B,MAAM,EAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAC,GAAG,IAAI;AAElC,QAAA,MAAM,EAAC,IAAI,EAAE,OAAO,EAAC,GAAG,cAAc;QAEtC,IAAI,CAAC,OAAO,EAAE;YACZ,MAAM,CAAC,KAAK,CAAC,wCAAwC,EAAE,EAAC,IAAI,EAAC,CAAC;AAC9D,YAAA,MAAMC,qCAAkB,CAAC,EAAC,MAAM,EAAU,GAAG,EAAC,EAAE,OAAO,EAAE,IAAI,CAAC;QAChE;aAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE;YAC3C,MAAM,CAAC,KAAK,CACV,2DAA2D,EAC3D,EAAC,IAAI,EAAC,CACP;AACD,YAAA,MAAMA,qCAAkB,CAAC,EAAC,MAAM,EAAU,GAAG,EAAC,EAAE,OAAO,EAAE,IAAI,CAAC;QAChE;QAEA,MAAM,CAAC,KAAK,CAAC,uBAAuB,EAAE,EAAC,IAAI,EAAC,CAAC;AAE7C,QAAA,OAAO,OAAQ;IACjB;AAEO,IAAA,iBAAiB,CAAC,OAAgB,EAAA;QACvC,MAAM,EAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAC,GAAG,IAAI;AAClC,QAAA,OAAOC,0CAAwB,CAAC;YAC9B,OAAO;YACP,OAAO,EAAE,OAAO,EAAC,OAAO,EAAE,KAAK,EAAiB,KAAI;gBAClD,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,KAAK,GAAG,EAAE;AAC/B,oBAAA,MAAM,MAAMD,qCAAkB,CAC5B,EAAC,GAAG,EAAE,MAAc,CAAC,EACrB,OAAO,EACP,OAAO,CAAC,IAAI,CACb;gBACH;YACF,CAAC;AACF,SAAA,CAAC;IACJ;IAEQ,MAAM,qBAAqB,CAAC,OAAgB,EAAA;QAClD,MAAM,EAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAC,GAAG,IAAI;QAElCE,mDAAyB,CAAC,EAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAC,EAAE,OAAO,CAAC;QAEzD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC;QAChC,IAAI,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC;;QAGvC,MAAM,CAAC,KAAK,CAAC,mCAAmC,EAAE,EAAC,IAAI,EAAC,CAAC;QAEzD,IAAI,EAAE,MAAM,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,EAAE;AAC5C,YAAA,MAAM,CAAC,IAAI,CAAC,mDAAmD,CAAC;AAChE,YAAA,MAAM,IAAI,QAAQ,CAAC,SAAS,EAAE;AAC5B,gBAAA,MAAM,EAAE,GAAG;AACX,gBAAA,UAAU,EAAE,aAAa;AAC1B,aAAA,CAAC;QACJ;QAEA,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC;AAC5D,QAAA,MAAM,UAAU,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,GAAG;QAE3D,IAAI,CAAC,cAAc,EAAE;AACnB,YAAA,MAAM,CAAC,IAAI,CAAC,qDAAqD,EAAE;gBACjE,IAAI;AACL,aAAA,CAAC;YACF,IAAI,UAAU,EAAE;AACd,gBAAAC,6CAAsB,CAAC,EAAC,GAAG,EAAE,MAAc,CAAC,EAAE,OAAO,EAAE,IAAK,CAAC;YAC/D;iBAAO;AACL,gBAAA,MAAM,MAAMC,mBAAS,CAAC,EAAC,GAAG,EAAE,MAAc,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,IAAK,CAAC;YACrE;QACF;AAEA,QAAA,IAAI,GAAG,IAAI,IAAI,cAAc,CAAC,IAAI;AAElC,QAAA,IAAI,MAAM,CAAC,aAAa,IAAI,CAAC,UAAU,EAAE;AACvC,YAAA,IAAI;AACF,gBAAA,MAAM,CAAC,KAAK,CAAC,oDAAoD,EAAE;oBACjE,IAAI;AACL,iBAAA,CAAC;AACF,gBAAA,MAAM,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC;gBAEtC,MAAM,CAAC,KAAK,CAAC,+CAA+C,EAAE,EAAC,IAAI,EAAC,CAAC;YACvE;YAAE,OAAO,KAAK,EAAE;gBACd,MAAM,IAAI,CAAC,2BAA2B,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC;YAC9D;QACF;IACF;AAEQ,IAAA,MAAM,sBAAsB,CAClC,OAAgB,EAChB,IAAY,EAAA;QAEZ,MAAM,EAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAC,GAAG,IAAI;QAElC,MAAM,CAAC,IAAI,CAAC,8BAA8B,EAAE,EAAC,IAAI,EAAC,CAAC;;QAGnD,IACE,MAAM,CAAC,aAAa;YACpB,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,KAAK,QAAQ,EAClD;YACA,MAAM,CAAC,KAAK,CAAC,iDAAiD,EAAE,EAAC,IAAI,EAAC,CAAC;AACvE,YAAA,MAAMD,6CAAsB,CAAC,EAAC,GAAG,EAAE,MAAc,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC;QACpE;aAAO;AACL,YAAA,MAAM,MAAMC,mBAAS,CAAC,EAAC,GAAG,EAAE,MAAc,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC;QACpE;IACF;AAEQ,IAAA,MAAM,yBAAyB,CACrC,OAAgB,EAChB,IAAY,EAAA;QAEZ,MAAM,EAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAC,GAAG,IAAI;QAElC,MAAM,CAAC,IAAI,CAAC,iCAAiC,EAAE,EAAC,IAAI,EAAC,CAAC;AAEtD,QAAA,IAAI;AACF,YAAA,MAAM,EAAC,OAAO,EAAE,OAAO,EAAE,eAAe,EAAC,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC;AAClE,gBAAA,UAAU,EAAE,OAAO;AACpB,aAAA,CAAC;YAEF,MAAM,MAAM,CAAC,cAAe,CAAC,YAAY,CAAC,OAAO,CAAC;YAElD,IAAI,MAAM,CAAC,eAAe,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE;AAC/C,gBAAA,MAAM,CAAC,IAAI,CAAC,oDAAoD,EAAE;oBAChE,IAAI;AACL,iBAAA,CAAC;AACF,gBAAA,MAAMA,mBAAS,CAAC,EAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;YAC7D;AAEA,YAAA,MAAM,CAAC,KAAK,CAAC,sDAAsD,EAAE;gBACnE,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,QAAQ,EAAE,OAAO,CAAC,QAAQ;AAC3B,aAAA,CAAC;AAEF,YAAA,MAAMC,yCAAoB,CAAC,EAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAC,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC;AAEzE,YAAA,MAAM,MAAMC,qDAA0B,CACpC,OAAO,EACP,EAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAC,EACrB,eAAe,CAChB;QACH;QAAE,OAAO,KAAK,EAAE;YACd,IAAI,KAAK,YAAY,QAAQ;AAAE,gBAAA,MAAM,KAAK;YAE1C,MAAM,MAAM,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC;QAC3D;IACF;IAEQ,MAAM,iBAAiB,CAC7B,OAAgB,EAAA;QAEhB,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC;QACzD,OAAO,IAAI,CAAC,MAAM,CAAC,cAAe,CAAC,WAAW,CAAC,SAAU,CAAC;IAC5D;IAEQ,MAAM,iBAAiB,CAAC,OAAgB,EAAA;QAC9C,OAAO,OAAO,CAAC,MAAM,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACzD;IAEQ,MAAM,mBAAmB,CAC/B,OAAgB,EAAA;AAEhB,QAAA,MAAM,EAAC,GAAG,EAAC,GAAG,IAAI;QAClB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC;QAChC,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC;AAEzC,QAAA,OAAO;cACH,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI;AAC/B,cAAE,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,EAAC,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAC,CAAC;IACtE;IAEQ,MAAM,WAAW,CAAC,OAAgB,EAAA;AACxC,QAAA,MAAM,EAAC,GAAG,EAAC,GAAG,IAAI;QAElB,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC;YACrC,OAAO;AACR,SAAA,CAAC;QAEF,MAAM,MAAM,CAAC,OAAO,CAAC,CAAA;;;;;;AAMpB,IAAA,CAAA,CAAC;IACJ;AAEQ,IAAA,MAAM,kBAAkB,CAC9B,KAAY,EACZ,OAAgB,EAChB,IAAY,EAAA;AAEZ,QAAA,MAAM,EAAC,MAAM,EAAC,GAAG,IAAI;AACrB,QAAA,MAAM,CAAC,KAAK,CAAC,6BAA6B,EAAE,EAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAC,CAAC;AAEzE,QAAA,IAAI,KAAK,YAAYC,yBAAc,EAAE;YACnC,OAAO,IAAI,CAAC,sBAAsB,CAAC,OAAO,EAAE,IAAI,CAAC;QACnD;QAEA,IACE,KAAK,YAAYC,2BAAgB;YACjC,KAAK,YAAYC,4BAAiB,EAClC;AACA,YAAA,OAAO,IAAI,QAAQ,CAAC,SAAS,EAAE;AAC7B,gBAAA,MAAM,EAAE,GAAG;AACX,gBAAA,UAAU,EAAE,uBAAuB;AACpC,aAAA,CAAC;QACJ;AAEA,QAAA,OAAO,IAAI,QAAQ,CAAC,SAAS,EAAE;AAC7B,YAAA,MAAM,EAAE,GAAG;AACX,YAAA,UAAU,EAAE,uBAAuB;AACpC,SAAA,CAAC;IACJ;AAEQ,IAAA,MAAM,2BAA2B,CACvC,KAAY,EACZ,OAAgB,EAChB,IAAY,EAAA;QAEZ,MAAM,EAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAC,GAAG,IAAI;AAClC,QAAA,IAAI,KAAK,YAAYC,4BAAiB,EAAE;YACtC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,KAAK,GAAG,EAAE;AAC/B,gBAAA,MAAM,CAAC,IAAI,CAAC,uDAAuD,EAAE;oBACnE,IAAI;AACL,iBAAA,CAAC;AACF,gBAAA,MAAM,MAAMN,mBAAS,CAAC,EAAC,GAAG,EAAE,MAAc,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC;YACpE;iBAAO;AACL,gBAAA,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;AAC5D,gBAAA,MAAM,CAAC,KAAK,CAAC,CAAA,4CAAA,EAA+C,OAAO,EAAE,EAAE;oBACrE,IAAI;AACL,iBAAA,CAAC;AAEF,gBAAA,MAAM,IAAI,QAAQ,CAAC,SAAS,EAAE;AAC5B,oBAAA,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI;AAC3B,oBAAA,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,UAAU;AACtC,iBAAA,CAAC;YACJ;QACF;AAAO,aAAA,IAAI,KAAK,YAAYO,4BAAiB,EAAE;AAC7C,YAAA,MAAM,OAAO,GAA2B,EAAC,IAAI,EAAC;AAC9C,YAAA,IAAI,KAAK,CAAC,QAAQ,EAAE;gBAClB,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC;YAC/C;YAEA,MAAM,CAAC,KAAK,CACV,CAAA,4CAAA,EAA+C,KAAK,CAAC,OAAO,CAAA,CAAE,EAC9D,OAAO,CACR;AAED,YAAA,MAAM,IAAI,QAAQ,CAAC,SAAS,EAAE;AAC5B,gBAAA,MAAM,EAAE,GAAG;AACX,gBAAA,UAAU,EAAE,uBAAuB;AACpC,aAAA,CAAC;QACJ;IACF;AACD;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merchant-custom-app.js","sources":["../../../../../../../src/server/authenticate/admin/strategies/merchant-custom-app.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"merchant-custom-app.js","sources":["../../../../../../../src/server/authenticate/admin/strategies/merchant-custom-app.ts"],"sourcesContent":["import {Session, Shopify, ShopifyError} from '@shopify/shopify-api';\n\nimport {AppConfig, AppConfigArg} from '../../../config-types';\nimport {BasicParams} from '../../../types';\nimport {ApiConfigWithFutureFlags, ApiFutureFlags} from '../../../future/flags';\nimport {HandleAdminClientError} from '../../../clients';\nimport {handleClientErrorFactory} from '../helpers';\nimport {getShopFromRequest} from '../../helpers';\n\nimport {AuthorizationStrategy, OnErrorOptions, SessionContext} from './types';\n\nexport class MerchantCustomAuth<Config extends AppConfigArg>\n implements AuthorizationStrategy\n{\n protected api: Shopify<\n ApiConfigWithFutureFlags<Config['future']>,\n ApiFutureFlags<Config['future']>\n >;\n\n protected config: AppConfig;\n protected logger: Shopify['logger'];\n\n public constructor({api, config, logger}: BasicParams<Config['future']>) {\n this.api = api;\n this.config = config;\n this.logger = logger;\n }\n\n public async respondToOAuthRequests(request: Request): Promise<void> {\n this.logger.debug('Skipping OAuth request for merchant custom app', {\n shop: getShopFromRequest(request),\n });\n }\n\n public async authenticate(\n _request: Request,\n sessionContext: SessionContext,\n ): Promise<Session | never> {\n const {shop} = sessionContext;\n\n this.logger.debug(\n 'Building session from configured access token for merchant custom app',\n {shop},\n );\n const session = this.api.session.customAppSession(shop);\n\n return session;\n }\n\n public handleClientError(request: Request): HandleAdminClientError {\n return handleClientErrorFactory({\n request,\n onError: async ({error}: OnErrorOptions) => {\n if (error.response.code === 401) {\n this.logger.info(\n 'Request failed with 401. Review your API credentials or generate new tokens. https://shopify.dev/docs/apps/build/authentication-authorization/access-token-types/generate-app-access-tokens-admin#rotating-api-credentials-for-admin-created-apps ',\n );\n throw new ShopifyError(\n 'Unauthorized: Access token has been revoked.',\n );\n }\n },\n });\n }\n}\n"],"names":["getShopFromRequest","handleClientErrorFactory","ShopifyError"],"mappings":";;;;;;;;;MAWa,kBAAkB,CAAA;AAGnB,IAAA,GAAG;AAKH,IAAA,MAAM;AACN,IAAA,MAAM;AAEhB,IAAA,WAAA,CAAmB,EAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAgC,EAAA;AACrE,QAAA,IAAI,CAAC,GAAG,GAAG,GAAG;AACd,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM;AACpB,QAAA,IAAI,CAAC,MAAM,GAAG,MAAM;IACtB;IAEO,MAAM,sBAAsB,CAAC,OAAgB,EAAA;AAClD,QAAA,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,gDAAgD,EAAE;AAClE,YAAA,IAAI,EAAEA,qCAAkB,CAAC,OAAO,CAAC;AAClC,SAAA,CAAC;IACJ;AAEO,IAAA,MAAM,YAAY,CACvB,QAAiB,EACjB,cAA8B,EAAA;AAE9B,QAAA,MAAM,EAAC,IAAI,EAAC,GAAG,cAAc;QAE7B,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,uEAAuE,EACvE,EAAC,IAAI,EAAC,CACP;AACD,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC;AAEvD,QAAA,OAAO,OAAO;IAChB;AAEO,IAAA,iBAAiB,CAAC,OAAgB,EAAA;AACvC,QAAA,OAAOC,0CAAwB,CAAC;YAC9B,OAAO;AACP,YAAA,OAAO,EAAE,OAAO,EAAC,KAAK,EAAiB,KAAI;gBACzC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,KAAK,GAAG,EAAE;AAC/B,oBAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,oPAAoP,CACrP;AACD,oBAAA,MAAM,IAAIC,uBAAY,CACpB,8CAA8C,CAC/C;gBACH;YACF,CAAC;AACF,SAAA,CAAC;IACJ;AACD;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-exchange.js","sources":["../../../../../../../src/server/authenticate/admin/strategies/token-exchange.ts"],"sourcesContent":["import {\n HttpResponseError,\n InvalidJwtError,\n RequestedTokenType,\n Session,\n Shopify,\n
|
|
1
|
+
{"version":3,"file":"token-exchange.js","sources":["../../../../../../../src/server/authenticate/admin/strategies/token-exchange.ts"],"sourcesContent":["import {\n HttpResponseError,\n InvalidJwtError,\n RequestedTokenType,\n Session,\n Shopify,\n} from '@shopify/shopify-api';\n\nimport {AppConfig, AppConfigArg} from '../../../config-types';\nimport {BasicParams} from '../../../types';\nimport {\n respondToInvalidSessionToken,\n invalidateAccessToken,\n getShopFromRequest,\n} from '../../helpers';\nimport {handleClientErrorFactory, triggerAfterAuthHook} from '../helpers';\nimport {HandleAdminClientError} from '../../../clients';\nimport type {\n ApiConfigWithFutureFlags,\n ApiFutureFlags,\n} from '../../../future/flags';\n\nimport {AuthorizationStrategy, SessionContext, OnErrorOptions} from './types';\n\nexport class TokenExchangeStrategy<Config extends AppConfigArg>\n implements AuthorizationStrategy\n{\n protected api: Shopify<\n ApiConfigWithFutureFlags<Config['future']>,\n ApiFutureFlags<Config['future']>\n >;\n\n protected config: AppConfig;\n protected logger: Shopify['logger'];\n\n public constructor({api, config, logger}: BasicParams<Config['future']>) {\n this.api = api;\n this.config = config;\n this.logger = logger;\n }\n\n public async respondToOAuthRequests(_request: Request): Promise<void> {}\n\n public async authenticate(\n request: Request,\n sessionContext: SessionContext,\n ): Promise<Session> {\n const {api, config, logger} = this;\n const {shop, session, sessionToken} = sessionContext;\n\n if (!sessionToken) throw new InvalidJwtError();\n\n if (!session || !session.isActive(undefined)) {\n logger.info('No valid session found', {shop});\n logger.info('Requesting offline access token', {shop});\n const {session: offlineSession} = await this.exchangeToken({\n request,\n sessionToken,\n shop,\n requestedTokenType: RequestedTokenType.OfflineAccessToken,\n });\n\n await config.sessionStorage!.storeSession(offlineSession);\n\n let newSession = offlineSession;\n\n if (config.useOnlineTokens) {\n logger.info('Requesting online access token', {shop});\n const {session: onlineSession} = await this.exchangeToken({\n request,\n sessionToken,\n shop,\n requestedTokenType: RequestedTokenType.OnlineAccessToken,\n });\n\n await config.sessionStorage!.storeSession(onlineSession);\n newSession = onlineSession;\n }\n\n logger.debug('Request is valid, loaded session from session token', {\n shop: newSession.shop,\n isOnline: newSession.isOnline,\n });\n\n try {\n await this.handleAfterAuthHook(\n {api, config, logger},\n newSession,\n request,\n sessionToken,\n );\n } catch (errorOrResponse) {\n if (errorOrResponse instanceof Response) {\n throw errorOrResponse;\n }\n\n throw new Response(undefined, {\n status: 500,\n statusText: 'Internal Server Error',\n });\n }\n\n return newSession;\n }\n\n return session!;\n }\n\n public handleClientError(request: Request): HandleAdminClientError {\n const {api, config, logger} = this;\n return handleClientErrorFactory({\n request,\n onError: async ({session, error}: OnErrorOptions) => {\n if (error.response.code === 401) {\n logger.debug('Responding to invalid access token', {\n shop: getShopFromRequest(request),\n });\n await invalidateAccessToken({config, api, logger}, session);\n\n respondToInvalidSessionToken({\n params: {config, api, logger},\n request,\n });\n }\n },\n });\n }\n\n private async exchangeToken({\n request,\n shop,\n sessionToken,\n requestedTokenType,\n }: {\n request: Request;\n shop: string;\n sessionToken: string;\n requestedTokenType: RequestedTokenType;\n }): Promise<{session: Session}> {\n const {api, config, logger} = this;\n\n try {\n return await api.auth.tokenExchange({\n sessionToken,\n shop,\n requestedTokenType,\n });\n } catch (error) {\n if (\n error instanceof InvalidJwtError ||\n (error instanceof HttpResponseError &&\n error.response.code === 400 &&\n error.response.body?.error === 'invalid_subject_token')\n ) {\n throw respondToInvalidSessionToken({\n params: {api, config, logger},\n request,\n retryRequest: true,\n });\n }\n\n throw new Response(undefined, {\n status: 500,\n statusText: 'Internal Server Error',\n });\n }\n }\n\n private async handleAfterAuthHook(\n params: BasicParams,\n session: Session,\n request: Request,\n sessionToken: string,\n ) {\n const {config} = params;\n await config.idempotentPromiseHandler.handlePromise({\n promiseFunction: () => {\n return triggerAfterAuthHook(params, session, request, this);\n },\n identifier: sessionToken,\n });\n }\n}\n"],"names":["InvalidJwtError","RequestedTokenType","handleClientErrorFactory","getShopFromRequest","invalidateAccessToken","respondToInvalidSessionToken","HttpResponseError","triggerAfterAuthHook"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authenticate.js","sources":["../../../../../../src/server/authenticate/flow/authenticate.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"authenticate.js","sources":["../../../../../../src/server/authenticate/flow/authenticate.ts"],"sourcesContent":["import {adminClientFactory} from '../../clients/admin';\nimport {BasicParams} from '../../types';\n\nimport type {AuthenticateFlow, FlowContext} from './types';\n\nexport function authenticateFlowFactory(params: BasicParams): AuthenticateFlow {\n const {api, config, logger} = params;\n\n return async function authenticate(request: Request): Promise<FlowContext> {\n logger.info('Authenticating flow request');\n\n if (request.method !== 'POST') {\n logger.debug(\n 'Received a non-POST request for flow. 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 const result = await api.flow.validate({\n rawBody,\n rawRequest: request,\n });\n\n if (!result.valid) {\n logger.error('Received an invalid flow request', {reason: result.reason});\n\n throw new Response(undefined, {\n status: 400,\n statusText: 'Bad Request',\n });\n }\n\n const payload = JSON.parse(rawBody);\n\n logger.debug('Flow request is valid, looking for an offline session', {\n shop: payload.shopify_domain,\n });\n\n const sessionId = api.session.getOfflineId(payload.shopify_domain);\n const session = await config.sessionStorage!.loadSession(sessionId);\n\n if (!session) {\n logger.info('Flow request could not find session', {\n shop: payload.shopify_domain,\n });\n throw new Response(undefined, {\n status: 400,\n statusText: 'Bad Request',\n });\n }\n\n logger.debug('Found a session for the flow request', {shop: session.shop});\n\n return {\n session,\n payload,\n admin: adminClientFactory({params, session}),\n };\n };\n}\n"],"names":["adminClientFactory"],"mappings":";;;;AAKM,SAAU,uBAAuB,CAAC,MAAmB,EAAA;IACzD,MAAM,EAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAC,GAAG,MAAM;AAEpC,IAAA,OAAO,eAAe,YAAY,CAAC,OAAgB,EAAA;AACjD,QAAA,MAAM,CAAC,IAAI,CAAC,6BAA6B,CAAC;AAE1C,QAAA,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE;AAC7B,YAAA,MAAM,CAAC,KAAK,CACV,uEAAuE,EACvE,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;QACpC,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC;YACrC,OAAO;AACP,YAAA,UAAU,EAAE,OAAO;AACpB,SAAA,CAAC;AAEF,QAAA,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;AACjB,YAAA,MAAM,CAAC,KAAK,CAAC,kCAAkC,EAAE,EAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAC,CAAC;AAEzE,YAAA,MAAM,IAAI,QAAQ,CAAC,SAAS,EAAE;AAC5B,gBAAA,MAAM,EAAE,GAAG;AACX,gBAAA,UAAU,EAAE,aAAa;AAC1B,aAAA,CAAC;QACJ;QAEA,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;AAEnC,QAAA,MAAM,CAAC,KAAK,CAAC,uDAAuD,EAAE;YACpE,IAAI,EAAE,OAAO,CAAC,cAAc;AAC7B,SAAA,CAAC;AAEF,QAAA,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,cAAc,CAAC;QAClE,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,cAAe,CAAC,WAAW,CAAC,SAAS,CAAC;QAEnE,IAAI,CAAC,OAAO,EAAE;AACZ,YAAA,MAAM,CAAC,IAAI,CAAC,qCAAqC,EAAE;gBACjD,IAAI,EAAE,OAAO,CAAC,cAAc;AAC7B,aAAA,CAAC;AACF,YAAA,MAAM,IAAI,QAAQ,CAAC,SAAS,EAAE;AAC5B,gBAAA,MAAM,EAAE,GAAG;AACX,gBAAA,UAAU,EAAE,aAAa;AAC1B,aAAA,CAAC;QACJ;AAEA,QAAA,MAAM,CAAC,KAAK,CAAC,sCAAsC,EAAE,EAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAC,CAAC;QAE1E,OAAO;YACL,OAAO;YACP,OAAO;YACP,KAAK,EAAEA,0BAAkB,CAAC,EAAC,MAAM,EAAE,OAAO,EAAC,CAAC;SAC7C;AACH,IAAA,CAAC;AACH;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authenticate.js","sources":["../../../../../../src/server/authenticate/fulfillment-service/authenticate.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"authenticate.js","sources":["../../../../../../src/server/authenticate/fulfillment-service/authenticate.ts"],"sourcesContent":["import {ShopifyHeader} from '@shopify/shopify-api';\n\nimport {adminClientFactory} from '../../clients/admin';\nimport {BasicParams} from '../../types';\nimport {createOrLoadOfflineSession} from '../helpers';\n\nimport type {\n AuthenticateFulfillmentService,\n FulfillmentServiceContext,\n} from './types';\n\nexport function authenticateFulfillmentServiceFactory(\n params: BasicParams,\n): AuthenticateFulfillmentService {\n const {api, logger} = params;\n\n return async function authenticate(\n request: Request,\n ): Promise<FulfillmentServiceContext> {\n logger.info('Authenticating fulfillment service request');\n\n if (request.method !== 'POST') {\n logger.debug(\n 'Received a non-POST request for fulfillment service. 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 const result = await api.fulfillmentService.validate({\n rawBody,\n rawRequest: request,\n });\n\n if (!result.valid) {\n logger.error('Received an invalid fulfillment service request', {\n reason: result.reason,\n });\n\n throw new Response(undefined, {\n status: 400,\n statusText: 'Bad Request',\n });\n }\n\n const payload = JSON.parse(rawBody);\n const shop = request.headers.get(ShopifyHeader.Domain) || '';\n\n logger.debug(\n 'Fulfillment service request is valid, looking for an offline session',\n {\n shop,\n },\n );\n\n const session = await createOrLoadOfflineSession(shop, params);\n\n if (!session) {\n logger.info('Fulfillment service request could not find session', {\n shop,\n });\n throw new Response(undefined, {\n status: 400,\n statusText: 'Bad Request',\n });\n }\n\n logger.debug('Found a session for the fulfillment service request', {\n shop,\n });\n\n return {\n session,\n payload,\n admin: adminClientFactory({params, session}),\n };\n };\n}\n"],"names":["ShopifyHeader","createOrLoadOfflineSession","adminClientFactory"],"mappings":";;;;;;;;AAWM,SAAU,qCAAqC,CACnD,MAAmB,EAAA;AAEnB,IAAA,MAAM,EAAC,GAAG,EAAE,MAAM,EAAC,GAAG,MAAM;AAE5B,IAAA,OAAO,eAAe,YAAY,CAChC,OAAgB,EAAA;AAEhB,QAAA,MAAM,CAAC,IAAI,CAAC,4CAA4C,CAAC;AAEzD,QAAA,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE;AAC7B,YAAA,MAAM,CAAC,KAAK,CACV,sFAAsF,EACtF,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;QACpC,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,kBAAkB,CAAC,QAAQ,CAAC;YACnD,OAAO;AACP,YAAA,UAAU,EAAE,OAAO;AACpB,SAAA,CAAC;AAEF,QAAA,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;AACjB,YAAA,MAAM,CAAC,KAAK,CAAC,iDAAiD,EAAE;gBAC9D,MAAM,EAAE,MAAM,CAAC,MAAM;AACtB,aAAA,CAAC;AAEF,YAAA,MAAM,IAAI,QAAQ,CAAC,SAAS,EAAE;AAC5B,gBAAA,MAAM,EAAE,GAAG;AACX,gBAAA,UAAU,EAAE,aAAa;AAC1B,aAAA,CAAC;QACJ;QAEA,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;AACnC,QAAA,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAACA,wBAAa,CAAC,MAAM,CAAC,IAAI,EAAE;AAE5D,QAAA,MAAM,CAAC,KAAK,CACV,sEAAsE,EACtE;YACE,IAAI;AACL,SAAA,CACF;QAED,MAAM,OAAO,GAAG,MAAMC,qDAA0B,CAAC,IAAI,EAAE,MAAM,CAAC;QAE9D,IAAI,CAAC,OAAO,EAAE;AACZ,YAAA,MAAM,CAAC,IAAI,CAAC,oDAAoD,EAAE;gBAChE,IAAI;AACL,aAAA,CAAC;AACF,YAAA,MAAM,IAAI,QAAQ,CAAC,SAAS,EAAE;AAC5B,gBAAA,MAAM,EAAE,GAAG;AACX,gBAAA,UAAU,EAAE,aAAa;AAC1B,aAAA,CAAC;QACJ;AAEA,QAAA,MAAM,CAAC,KAAK,CAAC,qDAAqD,EAAE;YAClE,IAAI;AACL,SAAA,CAAC;QAEF,OAAO;YACL,OAAO;YACP,OAAO;YACP,KAAK,EAAEC,0BAAkB,CAAC,EAAC,MAAM,EAAE,OAAO,EAAC,CAAC;SAC7C;AACH,IAAA,CAAC;AACH;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authenticate.js","sources":["../../../../../../../src/server/authenticate/public/appProxy/authenticate.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"authenticate.js","sources":["../../../../../../../src/server/authenticate/public/appProxy/authenticate.ts"],"sourcesContent":["import {adminClientFactory, storefrontClientFactory} from '../../../clients';\nimport {BasicParams} from '../../../types';\n\nimport {\n AppProxyContext,\n AppProxyContextWithSession,\n AuthenticateAppProxy,\n LiquidResponseFunction,\n} from './types';\n\nexport function authenticateAppProxyFactory(\n params: BasicParams,\n): AuthenticateAppProxy {\n const {api, config, logger} = params;\n\n return async function authenticate(\n request: Request,\n ): Promise<AppProxyContext | AppProxyContextWithSession> {\n const url = new URL(request.url);\n const shop = url.searchParams.get('shop')!;\n logger.info('Authenticating app proxy request', {shop});\n\n if (!(await validateAppProxyHmac(params, url))) {\n logger.info('App proxy request has invalid signature', {shop});\n throw new Response(undefined, {\n status: 400,\n statusText: 'Bad Request',\n });\n }\n\n const sessionId = api.session.getOfflineId(shop);\n const session = await config.sessionStorage!.loadSession(sessionId);\n\n if (!session) {\n logger.debug('Could not find offline session, returning empty context', {\n shop,\n ...Object.fromEntries(url.searchParams.entries()),\n });\n\n const context: AppProxyContext = {\n liquid,\n session: undefined,\n admin: undefined,\n storefront: undefined,\n };\n\n return context;\n }\n\n const context: AppProxyContextWithSession = {\n liquid,\n session,\n admin: adminClientFactory({params, session}),\n storefront: storefrontClientFactory({params, session}),\n };\n\n return context;\n };\n}\n\nconst liquid: LiquidResponseFunction = (body, initAndOptions) => {\n const processedBody = processLiquidBody(body);\n\n if (typeof initAndOptions !== 'object') {\n return new Response(processedBody, {\n status: initAndOptions || 200,\n headers: {\n 'Content-Type': 'application/liquid',\n },\n });\n }\n\n const {layout, ...responseInit} = initAndOptions || {};\n const responseBody =\n layout === false ? `{% layout none %} ${processedBody}` : processedBody;\n\n const headers = new Headers(responseInit.headers);\n headers.set('Content-Type', 'application/liquid');\n\n return new Response(responseBody, {\n ...responseInit,\n headers,\n });\n};\n\nasync function validateAppProxyHmac(\n params: BasicParams,\n url: URL,\n): Promise<boolean> {\n const {api, logger} = params;\n\n try {\n let searchParams = new URLSearchParams(url.search);\n if (!searchParams.get('index')) {\n searchParams.delete('index');\n }\n\n let isValid = await api.utils.validateHmac(\n Object.fromEntries(searchParams.entries()),\n {signator: 'appProxy'},\n );\n\n if (!isValid) {\n const cleanPath = url.pathname\n .replace(/^\\//, '')\n .replace(/\\/$/, '')\n .replaceAll('/', '.');\n const data = `routes%2F${cleanPath}`;\n\n searchParams = new URLSearchParams(\n `?_data=${data}&${searchParams.toString().replace(/^\\?/, '')}`,\n );\n\n isValid = await api.utils.validateHmac(\n Object.fromEntries(searchParams.entries()),\n {signator: 'appProxy'},\n );\n\n if (!isValid) {\n const searchParams = new URLSearchParams(\n `?_data=${data}._index&${url.search.replace(/^\\?/, '')}`,\n );\n\n isValid = await api.utils.validateHmac(\n Object.fromEntries(searchParams.entries()),\n {signator: 'appProxy'},\n );\n }\n }\n\n return isValid;\n } catch (error) {\n const shop = url.searchParams.get('shop')!;\n logger.info(error.message, {shop});\n throw new Response(undefined, {status: 400, statusText: 'Bad Request'});\n }\n}\n\nfunction processLiquidBody(body: string) {\n return (\n body\n // Add trailing slashes to relative form action URLs\n .replaceAll(\n /<(form[^>]+)action=\"(\\/[^\"?]+)(\\?[^\"]+)?\">/g,\n '<$1action=\"$2/$3\">',\n )\n // Add trailing slashes to relative link href URLs\n .replaceAll(/<(a[^>]+)href=\"(\\/[^\"?]+)(\\?[^\"]+)?\">/g, '<$1href=\"$2/$3\">')\n );\n}\n"],"names":["adminClientFactory","storefrontClientFactory"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.js","sources":["../../../../../../src/server/authenticate/public/factory.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"factory.js","sources":["../../../../../../src/server/authenticate/public/factory.ts"],"sourcesContent":["import {BasicParams} from '../../types';\n\nimport {authenticateCheckoutFactory} from './checkout/authenticate';\nimport {authenticateAppProxyFactory} from './appProxy/authenticate';\nimport {authenticateCustomerAccountFactory} from './customer-account/authenticate';\nimport {AuthenticatePublic} from './types';\nimport {authenticatePOSFactory} from './pos/authenticate';\n\nexport function authenticatePublicFactory(params: BasicParams) {\n const authenticateCheckout = authenticateCheckoutFactory(params);\n const authenticateAppProxy = authenticateAppProxyFactory(params);\n const authenticateCustomerAccount =\n authenticateCustomerAccountFactory(params);\n const authenticatePOS = authenticatePOSFactory(params);\n\n const context: AuthenticatePublic = {\n checkout: authenticateCheckout,\n appProxy: authenticateAppProxy,\n customerAccount: authenticateCustomerAccount,\n pos: authenticatePOS,\n };\n\n return context;\n}\n"],"names":["authenticateCheckoutFactory","authenticateAppProxyFactory","authenticateCustomerAccountFactory","authenticatePOSFactory"],"mappings":";;;;;;;AAQM,SAAU,yBAAyB,CAAC,MAAmB,EAAA;AAC3D,IAAA,MAAM,oBAAoB,GAAGA,0CAA2B,CAAC,MAAM,CAAC;AAChE,IAAA,MAAM,oBAAoB,GAAGC,wCAA2B,CAAC,MAAM,CAAC;AAChE,IAAA,MAAM,2BAA2B,GAC/BC,iDAAkC,CAAC,MAAM,CAAC;AAC5C,IAAA,MAAM,eAAe,GAAGC,qCAAsB,CAAC,MAAM,CAAC;AAEtD,IAAA,MAAM,OAAO,GAAuB;AAClC,QAAA,QAAQ,EAAE,oBAAoB;AAC9B,QAAA,QAAQ,EAAE,oBAAoB;AAC9B,QAAA,eAAe,EAAE,2BAA2B;AAC5C,QAAA,GAAG,EAAE,eAAe;KACrB;AAED,IAAA,OAAO,OAAO;AAChB;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authenticate.js","sources":["../../../../../../src/server/authenticate/webhooks/authenticate.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"authenticate.js","sources":["../../../../../../src/server/authenticate/webhooks/authenticate.ts"],"sourcesContent":["import {WebhookValidationErrorReason} from '@shopify/shopify-api';\n\nimport type {BasicParams} from '../../types';\nimport {adminClientFactory} from '../../clients';\nimport {handleClientErrorFactory} from '../admin/helpers';\nimport {createOrLoadOfflineSession} 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 createOrLoadOfflineSession(check.domain, params);\n const webhookContext: WebhookContextWithoutSession<Topics> = {\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 };\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","createOrLoadOfflineSession","adminClientFactory","handleClientErrorFactory"],"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,KAAKA,uCAA4B,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,MAAMC,qDAA0B,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC;AACtE,QAAA,MAAM,cAAc,GAAyC;YAC3D,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,IAAI,EAAE,KAAK,CAAC,MAAM;YAClB,KAAK,EAAE,KAAK,CAAC,KAAe;YAC5B,SAAS,EAAE,KAAK,CAAC,SAAS;AAC1B,YAAA,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;AAC5B,YAAA,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,SAAS;AACrC,YAAA,OAAO,EAAE,SAAS;AAClB,YAAA,KAAK,EAAE,SAAS;SACjB;QAED,IAAI,CAAC,OAAO,EAAE;AACZ,YAAA,OAAO,cAAc;QACvB;QAEA,MAAM,KAAK,GAAGC,0BAAkB,CAAC;YAC/B,MAAM;YACN,OAAO;AACP,YAAA,iBAAiB,EAAEC,0CAAwB,CAAC,EAAC,OAAO,EAAC,CAAC;AACvD,SAAA,CAAC;QAEF,OAAO;AACL,YAAA,GAAG,cAAc;YACjB,OAAO;YACP,KAAK;SACN;AACH,IAAA,CAAC;AACH;;;;"}
|
|
@@ -1,20 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var graphql = require('./graphql.js');
|
|
4
|
-
var rest = require('./rest.js');
|
|
5
4
|
|
|
6
5
|
function adminClientFactory({ params, handleClientError, session, }) {
|
|
7
|
-
if (params.config.future.removeRest) {
|
|
8
|
-
return {
|
|
9
|
-
graphql: graphql.graphqlClientFactory({ params, session, handleClientError }),
|
|
10
|
-
};
|
|
11
|
-
}
|
|
12
6
|
return {
|
|
13
|
-
rest: rest.restClientFactory({
|
|
14
|
-
params,
|
|
15
|
-
session,
|
|
16
|
-
handleClientError,
|
|
17
|
-
}),
|
|
18
7
|
graphql: graphql.graphqlClientFactory({ params, session, handleClientError }),
|
|
19
8
|
};
|
|
20
9
|
}
|