UNPKG

@shopify/shopify-app-react-router

Version:

Shopify React Router - to simplify the building of Shopify Apps with React Router

161 lines (158 loc) 7.21 kB
import '@shopify/shopify-api/adapters/web-api'; import { ShopifyError, shopifyApi } from '@shopify/shopify-api'; import { AppDistribution } from './types.mjs'; import { SHOPIFY_REACT_ROUTER_LIBRARY_VERSION } from './version.mjs'; import { registerWebhooksFactory } from './authenticate/webhooks/register.mjs'; import { authStrategyFactory } from './authenticate/admin/authenticate.mjs'; import { authenticateWebhookFactory } from './authenticate/webhooks/authenticate.mjs'; import { overrideLogger } from './override-logger.mjs'; import { addDocumentResponseHeadersFactory } from './authenticate/helpers/add-response-headers.mjs'; import 'react-router'; import 'isbot'; import { loginFactory } from './authenticate/login/login.mjs'; import { unauthenticatedAdminContextFactory } from './unauthenticated/admin/factory.mjs'; import { authenticatePublicFactory } from './authenticate/public/factory.mjs'; import { unauthenticatedStorefrontContextFactory } from './unauthenticated/storefront/factory.mjs'; import { createTokenExchangeStrategy } from './authenticate/admin/strategies/token-exchange.mjs'; import { createMerchantCustomAuthStrategy } from './authenticate/admin/strategies/merchant-custom-app.mjs'; import { IdempotentPromiseHandler } from './authenticate/helpers/idempotent-promise-handler.mjs'; import { authenticateFlowFactory } from './authenticate/flow/authenticate.mjs'; import { authenticateFulfillmentServiceFactory } from './authenticate/fulfillment-service/authenticate.mjs'; import { authenticatePOSFactory } from './authenticate/pos/authenticate.mjs'; /** * Creates an object your app will use to interact with Shopify. * * @param appConfig Configuration options for your Shopify app, such as the scopes your app needs. * @returns `ShopifyApp` An object constructed using your appConfig. It has methods for interacting with Shopify. * * @example * <caption>The minimum viable configuration</caption> * ```ts * // /shopify.server.ts * import { shopifyApp } from "@shopify/shopify-app-react-router/server"; * * const shopify = shopifyApp({ * apiKey: process.env.SHOPIFY_API_KEY!, * apiSecretKey: process.env.SHOPIFY_API_SECRET!, * scopes: process.env.SCOPES?.split(",")!, * appUrl: process.env.SHOPIFY_APP_URL!, * }); * export default shopify; * ``` */ function shopifyApp(appConfig) { const api = deriveApi(appConfig); const config = deriveConfig(appConfig, api.config); const logger = overrideLogger(api.logger); if (appConfig.webhooks) { api.webhooks.addHandlers(appConfig.webhooks); } const params = { api, config, logger }; let strategy; if (config.distribution === AppDistribution.ShopifyAdmin) { strategy = createMerchantCustomAuthStrategy(params); } else { strategy = createTokenExchangeStrategy(params); } const authStrategy = authStrategyFactory({ ...params, strategy, }); const shopify = { sessionStorage: config.sessionStorage, addDocumentResponseHeaders: addDocumentResponseHeadersFactory(params), registerWebhooks: registerWebhooksFactory(params), authenticate: { admin: authStrategy, flow: authenticateFlowFactory(params), fulfillmentService: authenticateFulfillmentServiceFactory(params), pos: authenticatePOSFactory(params), public: authenticatePublicFactory(params), webhook: authenticateWebhookFactory(params), }, unauthenticated: { admin: unauthenticatedAdminContextFactory(params), storefront: unauthenticatedStorefrontContextFactory(params), }, }; if (isAppStoreApp(shopify, appConfig) || isSingleMerchantApp(shopify, appConfig)) { shopify.login = loginFactory(params); } return shopify; } function isAppStoreApp(_shopify, config) { return config.distribution === AppDistribution.AppStore; } function isSingleMerchantApp(_shopify, config) { return config.distribution === AppDistribution.SingleMerchant; } // This function is only exported so we can unit test it without having to mock the underlying module. // It's not available to consumers of the library because it is not exported in the index module, and never should be. function deriveApi(appConfig) { let appUrl; try { appUrl = new URL(appConfig.appUrl); } catch (error) { const message = appConfig.appUrl === '' ? `Detected an empty appUrl configuration, please make sure to set the necessary environment variables.\n` + `If you're deploying your app, you can find more information at https://shopify.dev/docs/apps/launch/deployment/deploy-web-app/deploy-to-hosting-service#step-4-set-up-environment-variables` : `Invalid appUrl configuration '${appConfig.appUrl}', please provide a valid URL.`; throw new ShopifyError(message); } /* eslint-disable no-process-env */ if (appUrl.hostname === 'localhost' && !appUrl.port && process.env.PORT) { appUrl.port = process.env.PORT; } /* eslint-enable no-process-env */ appConfig.appUrl = appUrl.origin; let userAgentPrefix = `Shopify React Router Library v${SHOPIFY_REACT_ROUTER_LIBRARY_VERSION}`; if (appConfig.userAgentPrefix) { userAgentPrefix = `${appConfig.userAgentPrefix} | ${userAgentPrefix}`; } return shopifyApi({ ...appConfig, hostName: appUrl.host, hostScheme: appUrl.protocol.replace(':', ''), userAgentPrefix, isEmbeddedApp: true, isCustomStoreApp: appConfig.distribution === AppDistribution.ShopifyAdmin, billing: appConfig.billing, future: { unstable_managedPricingSupport: true, }, _logDisabledFutureFlags: false, }); } function deriveConfig(appConfig, apiConfig) { if (!appConfig.sessionStorage && appConfig.distribution !== AppDistribution.ShopifyAdmin) { throw new ShopifyError('Please provide a valid session storage. Refer to https://github.com/Shopify/shopify-app-js/blob/main/README.md#session-storage-options for options.'); } const authPathPrefix = appConfig.authPathPrefix || '/auth'; appConfig.distribution = appConfig.distribution ?? AppDistribution.AppStore; return { ...appConfig, ...apiConfig, billing: appConfig.billing, scopes: apiConfig.scopes, idempotentPromiseHandler: new IdempotentPromiseHandler(), canUseLoginForm: appConfig.distribution !== AppDistribution.ShopifyAdmin, useOnlineTokens: appConfig.useOnlineTokens ?? false, hooks: appConfig.hooks ?? {}, sessionStorage: appConfig.sessionStorage, future: appConfig.future ?? {}, auth: { path: authPathPrefix, callbackPath: `${authPathPrefix}/callback`, patchSessionTokenPath: `${authPathPrefix}/session-token`, exitIframePath: `${authPathPrefix}/exit-iframe`, loginPath: `${authPathPrefix}/login`, }, distribution: appConfig.distribution, }; } export { deriveApi, shopifyApp }; //# sourceMappingURL=shopify-app.mjs.map