@shopify/shopify-app-remix 4.1.1 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/dist/cjs/react/components/AppProvider/AppProvider.js.map +1 -1
  2. package/dist/cjs/react/components/AppProxyLink/AppProxyLink.js.map +1 -1
  3. package/dist/cjs/server/authenticate/admin/strategies/auth-code-flow.js.map +1 -1
  4. package/dist/cjs/server/authenticate/admin/strategies/merchant-custom-app.js.map +1 -1
  5. package/dist/cjs/server/authenticate/admin/strategies/token-exchange.js.map +1 -1
  6. package/dist/cjs/server/authenticate/webhooks/authenticate.js +34 -10
  7. package/dist/cjs/server/authenticate/webhooks/authenticate.js.map +1 -1
  8. package/dist/cjs/server/version.js +1 -1
  9. package/dist/cjs/server/version.js.map +1 -1
  10. package/dist/esm/react/components/AppProvider/AppProvider.mjs.map +1 -1
  11. package/dist/esm/react/components/AppProxyLink/AppProxyLink.mjs.map +1 -1
  12. package/dist/esm/server/authenticate/admin/strategies/auth-code-flow.mjs.map +1 -1
  13. package/dist/esm/server/authenticate/admin/strategies/merchant-custom-app.mjs.map +1 -1
  14. package/dist/esm/server/authenticate/admin/strategies/token-exchange.mjs.map +1 -1
  15. package/dist/esm/server/authenticate/webhooks/authenticate.mjs +35 -11
  16. package/dist/esm/server/authenticate/webhooks/authenticate.mjs.map +1 -1
  17. package/dist/esm/server/version.mjs +1 -1
  18. package/dist/esm/server/version.mjs.map +1 -1
  19. package/dist/ts/react/components/AppProvider/AppProvider.d.ts.map +1 -1
  20. package/dist/ts/react/components/AppProxyLink/AppProxyLink.d.ts.map +1 -1
  21. package/dist/ts/server/authenticate/admin/billing/types.d.ts.map +1 -1
  22. package/dist/ts/server/authenticate/admin/strategies/auth-code-flow.d.ts.map +1 -1
  23. package/dist/ts/server/authenticate/admin/strategies/merchant-custom-app.d.ts.map +1 -1
  24. package/dist/ts/server/authenticate/admin/strategies/token-exchange.d.ts.map +1 -1
  25. package/dist/ts/server/authenticate/admin/types.d.ts.map +1 -1
  26. package/dist/ts/server/authenticate/public/extension/types.d.ts.map +1 -1
  27. package/dist/ts/server/authenticate/webhooks/authenticate.d.ts.map +1 -1
  28. package/dist/ts/server/authenticate/webhooks/types.d.ts +34 -2
  29. package/dist/ts/server/authenticate/webhooks/types.d.ts.map +1 -1
  30. package/dist/ts/server/config-types.d.ts.map +1 -1
  31. package/dist/ts/server/version.d.ts +1 -1
  32. package/dist/tsconfig.build.tsbuildinfo +1 -1
  33. package/package.json +18 -14
  34. package/src/react/components/AppProvider/AppProvider.doc.ts +35 -0
  35. package/src/react/components/AppProvider/AppProvider.tsx +147 -0
  36. package/src/react/components/AppProvider/index.ts +1 -0
  37. package/src/react/components/AppProxyForm/AppProxyForm.doc.ts +28 -0
  38. package/src/react/components/AppProxyForm/AppProxyForm.tsx +82 -0
  39. package/src/react/components/AppProxyForm/index.ts +1 -0
  40. package/src/react/components/AppProxyLink/AppProxyLink.doc.ts +28 -0
  41. package/src/react/components/AppProxyLink/AppProxyLink.tsx +58 -0
  42. package/src/react/components/AppProxyLink/index.ts +1 -0
  43. package/src/react/components/AppProxyProvider/AppProxyProvider.doc.ts +40 -0
  44. package/src/react/components/AppProxyProvider/AppProxyProvider.tsx +100 -0
  45. package/src/react/components/AppProxyProvider/index.ts +5 -0
  46. package/src/react/components/RemixPolarisLink.tsx +14 -0
  47. package/src/react/components/index.ts +4 -0
  48. package/src/react/const.ts +2 -0
  49. package/src/react/index.ts +1 -0
  50. package/src/server/__test-helpers/const.ts +14 -0
  51. package/src/server/__test-helpers/expect-admin-api-client.ts +51 -0
  52. package/src/server/__test-helpers/expect-begin-auth-redirect.ts +22 -0
  53. package/src/server/__test-helpers/expect-document-request-headers.ts +25 -0
  54. package/src/server/__test-helpers/expect-exit-iframe.ts +37 -0
  55. package/src/server/__test-helpers/expect-login-redirect.ts +8 -0
  56. package/src/server/__test-helpers/expect-storefront-api-client.ts +49 -0
  57. package/src/server/__test-helpers/expect-token-refresh.ts +188 -0
  58. package/src/server/__test-helpers/get-hmac.ts +7 -0
  59. package/src/server/__test-helpers/get-jwt.ts +10 -0
  60. package/src/server/__test-helpers/get-thrown-error.ts +19 -0
  61. package/src/server/__test-helpers/get-thrown-response.ts +17 -0
  62. package/src/server/__test-helpers/index.ts +21 -0
  63. package/src/server/__test-helpers/mock-graphql-request.ts +60 -0
  64. package/src/server/__test-helpers/request-mock.ts +169 -0
  65. package/src/server/__test-helpers/setup-embedded-flow.ts +30 -0
  66. package/src/server/__test-helpers/setup-fetch-flow.ts +29 -0
  67. package/src/server/__test-helpers/setup-non-embedded-flow.ts +31 -0
  68. package/src/server/__test-helpers/setup-valid-request.ts +78 -0
  69. package/src/server/__test-helpers/setup-valid-session.ts +28 -0
  70. package/src/server/__test-helpers/sign-request-cookie.ts +21 -0
  71. package/src/server/__test-helpers/test-config.ts +56 -0
  72. package/src/server/adapters/node/index.ts +13 -0
  73. package/src/server/adapters/vercel/index.ts +13 -0
  74. package/src/server/authenticate/admin/authenticate.admin.doc.example.ts +34 -0
  75. package/src/server/authenticate/admin/authenticate.admin.doc.ts +51 -0
  76. package/src/server/authenticate/admin/authenticate.ts +232 -0
  77. package/src/server/authenticate/admin/billing/authenticate.admin.billing.doc.ts +29 -0
  78. package/src/server/authenticate/admin/billing/cancel.ts +38 -0
  79. package/src/server/authenticate/admin/billing/check.ts +41 -0
  80. package/src/server/authenticate/admin/billing/create-usage-record.ts +36 -0
  81. package/src/server/authenticate/admin/billing/helpers.ts +42 -0
  82. package/src/server/authenticate/admin/billing/index.ts +6 -0
  83. package/src/server/authenticate/admin/billing/request.ts +64 -0
  84. package/src/server/authenticate/admin/billing/require.ts +58 -0
  85. package/src/server/authenticate/admin/billing/types.ts +613 -0
  86. package/src/server/authenticate/admin/billing/update-usage-subscription-capped-amount.ts +55 -0
  87. package/src/server/authenticate/admin/helpers/begin-auth.ts +17 -0
  88. package/src/server/authenticate/admin/helpers/create-admin-api-context.ts +20 -0
  89. package/src/server/authenticate/admin/helpers/ensure-app-is-embedded-if-required.ts +18 -0
  90. package/src/server/authenticate/admin/helpers/ensure-session-token-search-param-if-required.ts +25 -0
  91. package/src/server/authenticate/admin/helpers/handle-client-error.ts +45 -0
  92. package/src/server/authenticate/admin/helpers/index.ts +14 -0
  93. package/src/server/authenticate/admin/helpers/redirect-to-auth-page.ts +28 -0
  94. package/src/server/authenticate/admin/helpers/redirect-to-bounce-page.ts +23 -0
  95. package/src/server/authenticate/admin/helpers/redirect-to-install-page.ts +53 -0
  96. package/src/server/authenticate/admin/helpers/redirect-to-shopify-or-app-root.ts +21 -0
  97. package/src/server/authenticate/admin/helpers/redirect-with-app-bridge-headers.ts +13 -0
  98. package/src/server/authenticate/admin/helpers/redirect-with-exitiframe.ts +28 -0
  99. package/src/server/authenticate/admin/helpers/redirect.ts +164 -0
  100. package/src/server/authenticate/admin/helpers/render-app-bridge.ts +46 -0
  101. package/src/server/authenticate/admin/helpers/trigger-after-auth-hook.ts +29 -0
  102. package/src/server/authenticate/admin/helpers/validate-redirect-url.ts +67 -0
  103. package/src/server/authenticate/admin/helpers/validate-shop-and-host-params.ts +46 -0
  104. package/src/server/authenticate/admin/scope/authenticate.admin.scopes.doc.ts +28 -0
  105. package/src/server/authenticate/admin/scope/client/fetch-scopes-details.ts +43 -0
  106. package/src/server/authenticate/admin/scope/client/revoke-scopes.ts +38 -0
  107. package/src/server/authenticate/admin/scope/factory.ts +21 -0
  108. package/src/server/authenticate/admin/scope/query.ts +51 -0
  109. package/src/server/authenticate/admin/scope/request.ts +32 -0
  110. package/src/server/authenticate/admin/scope/revoke.ts +48 -0
  111. package/src/server/authenticate/admin/scope/types.ts +126 -0
  112. package/src/server/authenticate/admin/strategies/auth-code-flow.ts +332 -0
  113. package/src/server/authenticate/admin/strategies/merchant-custom-app.ts +65 -0
  114. package/src/server/authenticate/admin/strategies/token-exchange.ts +188 -0
  115. package/src/server/authenticate/admin/strategies/types.ts +29 -0
  116. package/src/server/authenticate/admin/types.ts +216 -0
  117. package/src/server/authenticate/const.ts +15 -0
  118. package/src/server/authenticate/flow/authenticate.flow.doc.example.ts +39 -0
  119. package/src/server/authenticate/flow/authenticate.flow.doc.ts +47 -0
  120. package/src/server/authenticate/flow/authenticate.ts +68 -0
  121. package/src/server/authenticate/flow/types.ts +85 -0
  122. package/src/server/authenticate/fulfillment-service/authenticate.fulfillment-service.doc.example.ts +52 -0
  123. package/src/server/authenticate/fulfillment-service/authenticate.fulfillment-service.doc.ts +48 -0
  124. package/src/server/authenticate/fulfillment-service/authenticate.ts +82 -0
  125. package/src/server/authenticate/fulfillment-service/types.ts +82 -0
  126. package/src/server/authenticate/helpers/add-response-headers.ts +43 -0
  127. package/src/server/authenticate/helpers/app-bridge-url.ts +10 -0
  128. package/src/server/authenticate/helpers/ensure-cors-headers.ts +38 -0
  129. package/src/server/authenticate/helpers/get-session-token-header.ts +11 -0
  130. package/src/server/authenticate/helpers/get-shop-from-request.ts +4 -0
  131. package/src/server/authenticate/helpers/idempotent-promise-handler.ts +45 -0
  132. package/src/server/authenticate/helpers/index.ts +10 -0
  133. package/src/server/authenticate/helpers/invalidate-access-token.ts +17 -0
  134. package/src/server/authenticate/helpers/reject-bot-request.ts +27 -0
  135. package/src/server/authenticate/helpers/respond-to-invalid-session-token.ts +28 -0
  136. package/src/server/authenticate/helpers/respond-to-options-request.ts +26 -0
  137. package/src/server/authenticate/helpers/validate-session-token.ts +40 -0
  138. package/src/server/authenticate/login/login.ts +53 -0
  139. package/src/server/authenticate/public/appProxy/authenticate.public.app-proxy.doc.example.ts +27 -0
  140. package/src/server/authenticate/public/appProxy/authenticate.public.app-proxy.doc.ts +55 -0
  141. package/src/server/authenticate/public/appProxy/authenticate.ts +150 -0
  142. package/src/server/authenticate/public/appProxy/types.ts +215 -0
  143. package/src/server/authenticate/public/checkout/authenticate.public.checkout.doc.example.offers.ts +21 -0
  144. package/src/server/authenticate/public/checkout/authenticate.public.checkout.doc.example.ts +17 -0
  145. package/src/server/authenticate/public/checkout/authenticate.public.checkout.doc.ts +49 -0
  146. package/src/server/authenticate/public/checkout/authenticate.ts +13 -0
  147. package/src/server/authenticate/public/checkout/types.ts +65 -0
  148. package/src/server/authenticate/public/customer-account/authenticate.public.customerAccount.doc.example.offers.ts +36 -0
  149. package/src/server/authenticate/public/customer-account/authenticate.public.customerAccount.doc.example.ts +18 -0
  150. package/src/server/authenticate/public/customer-account/authenticate.public.customerAccount.doc.ts +49 -0
  151. package/src/server/authenticate/public/customer-account/authenticate.ts +13 -0
  152. package/src/server/authenticate/public/customer-account/types.ts +65 -0
  153. package/src/server/authenticate/public/extension/authenticate.ts +54 -0
  154. package/src/server/authenticate/public/extension/types.ts +11 -0
  155. package/src/server/authenticate/public/factory.ts +24 -0
  156. package/src/server/authenticate/public/index.ts +1 -0
  157. package/src/server/authenticate/public/pos/authenticate.ts +8 -0
  158. package/src/server/authenticate/public/pos/types.ts +65 -0
  159. package/src/server/authenticate/public/types.ts +96 -0
  160. package/src/server/authenticate/webhooks/authenticate.ts +105 -0
  161. package/src/server/authenticate/webhooks/authenticate.webhooks.doc.example.ts +43 -0
  162. package/src/server/authenticate/webhooks/authenticate.webhooks.doc.ts +39 -0
  163. package/src/server/authenticate/webhooks/index.ts +1 -0
  164. package/src/server/authenticate/webhooks/register.ts +48 -0
  165. package/src/server/authenticate/webhooks/types.ts +266 -0
  166. package/src/server/boundary/error.tsx +14 -0
  167. package/src/server/boundary/headers.ts +15 -0
  168. package/src/server/boundary/index.ts +39 -0
  169. package/src/server/boundary/types.ts +4 -0
  170. package/src/server/clients/admin/authenticate.admin.api.doc.ts +34 -0
  171. package/src/server/clients/admin/factory.ts +22 -0
  172. package/src/server/clients/admin/graphql.ts +39 -0
  173. package/src/server/clients/admin/index.ts +2 -0
  174. package/src/server/clients/admin/types.ts +120 -0
  175. package/src/server/clients/index.ts +2 -0
  176. package/src/server/clients/storefront/authenticate.storefront.api.doc.ts +34 -0
  177. package/src/server/clients/storefront/factory.ts +32 -0
  178. package/src/server/clients/storefront/index.ts +2 -0
  179. package/src/server/clients/storefront/types.ts +78 -0
  180. package/src/server/clients/types.ts +47 -0
  181. package/src/server/config-types.ts +309 -0
  182. package/src/server/errors.ts +3 -0
  183. package/src/server/future/flags.ts +62 -0
  184. package/src/server/helpers/create-or-load-offline-session.ts +19 -0
  185. package/src/server/helpers/ensure-offline-token-is-not-expired.ts +32 -0
  186. package/src/server/helpers/ensure-valid-offline-session.ts +15 -0
  187. package/src/server/helpers/index.ts +4 -0
  188. package/src/server/helpers/refresh-token.ts +35 -0
  189. package/src/server/index.ts +24 -0
  190. package/src/server/override-logger.ts +42 -0
  191. package/src/server/shopify-app.doc.ts +45 -0
  192. package/src/server/shopify-app.ts +215 -0
  193. package/src/server/test-helpers/index.ts +1 -0
  194. package/src/server/test-helpers/test-config.ts +79 -0
  195. package/src/server/types-contexts.ts +44 -0
  196. package/src/server/types.ts +507 -0
  197. package/src/server/unauthenticated/admin/factory.ts +23 -0
  198. package/src/server/unauthenticated/admin/index.ts +1 -0
  199. package/src/server/unauthenticated/admin/types.ts +79 -0
  200. package/src/server/unauthenticated/admin/unauthenticated.admin.doc.ts +40 -0
  201. package/src/server/unauthenticated/storefront/factory.ts +28 -0
  202. package/src/server/unauthenticated/storefront/index.ts +1 -0
  203. package/src/server/unauthenticated/storefront/types.ts +105 -0
  204. package/src/server/unauthenticated/storefront/unauthenticated.storefront.doc.ts +40 -0
  205. package/src/server/unauthenticated/types.ts +65 -0
  206. package/src/server/version.ts +1 -0
@@ -0,0 +1,45 @@
1
+ import {ReferenceEntityTemplateSchema} from '@shopify/generate-docs';
2
+
3
+ const data: ReferenceEntityTemplateSchema = {
4
+ name: 'shopifyApp',
5
+ description:
6
+ "Returns a set of functions that can be used by the app's backend to be able to respond to all Shopify requests." +
7
+ '\n\nThe shape of the returned object changes depending on the value of `distribution`. If it is `AppDistribution.ShopifyAdmin`, then only `ShopifyAppBase` objects are returned, otherwise `ShopifyAppLogin` objects are included.',
8
+ category: 'Entrypoints',
9
+ type: 'function',
10
+ isVisualComponent: false,
11
+ definitions: [
12
+ {
13
+ title: 'shopifyApp',
14
+ description: 'Function to create a new Shopify API object.',
15
+ type: 'ShopifyAppGeneratedType',
16
+ },
17
+ {
18
+ title: 'Future flags',
19
+ description:
20
+ 'Set future flags using the `future` configuration field to opt in to upcoming breaking changes.' +
21
+ '\n\nWith this feature, you can prepare for major releases ahead of time, as well as try out new features before they are released.',
22
+ type: 'FutureFlags',
23
+ filePath: 'src/server/future/flags.ts',
24
+ },
25
+ ],
26
+ jsDocTypeExamples: [
27
+ 'ShopifyAppGeneratedType',
28
+ 'ShopifyAppBase',
29
+ 'ShopifyAppLogin',
30
+ ],
31
+ related: [
32
+ {
33
+ name: 'Authenticated contexts',
34
+ subtitle: 'Authenticate requests coming from Shopify.',
35
+ url: '/docs/api/shopify-app-remix/authenticate',
36
+ },
37
+ {
38
+ name: 'Unauthenticated contexts',
39
+ subtitle: 'Interact with the API on non-Shopify requests.',
40
+ url: '/docs/api/shopify-app-remix/unauthenticated',
41
+ },
42
+ ],
43
+ };
44
+
45
+ export default data;
@@ -0,0 +1,215 @@
1
+ import '@shopify/shopify-api/adapters/web-api';
2
+ import {
3
+ ConfigInterface as ApiConfig,
4
+ ShopifyError,
5
+ shopifyApi,
6
+ } from '@shopify/shopify-api';
7
+ import {SessionStorage} from '@shopify/shopify-app-session-storage';
8
+
9
+ import {type AppConfig, type AppConfigArg} from './config-types';
10
+ import {
11
+ AppDistribution,
12
+ type BasicParams,
13
+ type ShopifyApp,
14
+ type ShopifyAppBase,
15
+ type AdminApp,
16
+ type SingleMerchantApp,
17
+ type AppStoreApp,
18
+ } from './types';
19
+ import {SHOPIFY_REMIX_LIBRARY_VERSION} from './version';
20
+ import {registerWebhooksFactory} from './authenticate/webhooks';
21
+ import {authStrategyFactory} from './authenticate/admin/authenticate';
22
+ import {authenticateWebhookFactory} from './authenticate/webhooks/authenticate';
23
+ import {overrideLogger} from './override-logger';
24
+ import {addDocumentResponseHeadersFactory} from './authenticate/helpers';
25
+ import {loginFactory} from './authenticate/login/login';
26
+ import {unauthenticatedAdminContextFactory} from './unauthenticated/admin';
27
+ import {authenticatePublicFactory} from './authenticate/public';
28
+ import {unauthenticatedStorefrontContextFactory} from './unauthenticated/storefront';
29
+ import {AuthCodeFlowStrategy} from './authenticate/admin/strategies/auth-code-flow';
30
+ import {TokenExchangeStrategy} from './authenticate/admin/strategies/token-exchange';
31
+ import {MerchantCustomAuth} from './authenticate/admin/strategies/merchant-custom-app';
32
+ import {IdempotentPromiseHandler} from './authenticate/helpers/idempotent-promise-handler';
33
+ import {authenticateFlowFactory} from './authenticate/flow/authenticate';
34
+ import {authenticateFulfillmentServiceFactory} from './authenticate/fulfillment-service/authenticate';
35
+ import {FutureFlagOptions, logDisabledFutureFlags} from './future/flags';
36
+
37
+ /**
38
+ * Creates an object your app will use to interact with Shopify.
39
+ *
40
+ * @param appConfig Configuration options for your Shopify app, such as the scopes your app needs.
41
+ * @returns `ShopifyApp` An object constructed using your appConfig. It has methods for interacting with Shopify.
42
+ *
43
+ * @example
44
+ * <caption>The minimum viable configuration</caption>
45
+ * ```ts
46
+ * // /shopify.server.ts
47
+ * import { shopifyApp } from "@shopify/shopify-app-remix/server";
48
+ *
49
+ * const shopify = shopifyApp({
50
+ * apiKey: process.env.SHOPIFY_API_KEY!,
51
+ * apiSecretKey: process.env.SHOPIFY_API_SECRET!,
52
+ * scopes: process.env.SCOPES?.split(",")!,
53
+ * appUrl: process.env.SHOPIFY_APP_URL!,
54
+ * });
55
+ * export default shopify;
56
+ * ```
57
+ */
58
+ export function shopifyApp<
59
+ Config extends AppConfigArg<Storage, Future>,
60
+ Storage extends SessionStorage,
61
+ Future extends FutureFlagOptions = Config['future'],
62
+ >(appConfig: Readonly<Config>): ShopifyApp<Config> {
63
+ const api = deriveApi(appConfig);
64
+ const config = deriveConfig<Storage>(appConfig, api.config);
65
+ const logger = overrideLogger(api.logger);
66
+
67
+ if (appConfig.webhooks) {
68
+ api.webhooks.addHandlers(appConfig.webhooks);
69
+ }
70
+
71
+ const params: BasicParams = {api, config, logger};
72
+
73
+ let strategy;
74
+ if (config.distribution === AppDistribution.ShopifyAdmin) {
75
+ strategy = new MerchantCustomAuth(params);
76
+ } else if (
77
+ config.future.unstable_newEmbeddedAuthStrategy &&
78
+ config.isEmbeddedApp
79
+ ) {
80
+ strategy = new TokenExchangeStrategy(params);
81
+ } else {
82
+ strategy = new AuthCodeFlowStrategy(params);
83
+ }
84
+
85
+ const authStrategy = authStrategyFactory<Config>({
86
+ ...params,
87
+ strategy,
88
+ });
89
+
90
+ const shopify:
91
+ | AdminApp<Config>
92
+ | AppStoreApp<Config>
93
+ | SingleMerchantApp<Config> = {
94
+ sessionStorage: config.sessionStorage,
95
+ addDocumentResponseHeaders: addDocumentResponseHeadersFactory(params),
96
+ registerWebhooks: registerWebhooksFactory(params),
97
+ authenticate: {
98
+ admin: authStrategy,
99
+ flow: authenticateFlowFactory(params),
100
+ public: authenticatePublicFactory(params),
101
+ fulfillmentService: authenticateFulfillmentServiceFactory(params),
102
+ webhook: authenticateWebhookFactory<string>(params),
103
+ },
104
+ unauthenticated: {
105
+ admin: unauthenticatedAdminContextFactory(params),
106
+ storefront: unauthenticatedStorefrontContextFactory(params),
107
+ },
108
+ };
109
+
110
+ if (
111
+ isAppStoreApp(shopify, appConfig) ||
112
+ isSingleMerchantApp(shopify, appConfig)
113
+ ) {
114
+ shopify.login = loginFactory(params);
115
+ }
116
+
117
+ logDisabledFutureFlags(config, logger);
118
+
119
+ return shopify as ShopifyApp<Config>;
120
+ }
121
+
122
+ function isAppStoreApp<Config extends AppConfigArg>(
123
+ _shopify: ShopifyAppBase<Config>,
124
+ config: Config,
125
+ ): _shopify is AppStoreApp<Config> {
126
+ return config.distribution === AppDistribution.AppStore;
127
+ }
128
+
129
+ function isSingleMerchantApp<Config extends AppConfigArg>(
130
+ _shopify: ShopifyAppBase<Config>,
131
+ config: Config,
132
+ ): _shopify is SingleMerchantApp<Config> {
133
+ return config.distribution === AppDistribution.SingleMerchant;
134
+ }
135
+
136
+ // This function is only exported so we can unit test it without having to mock the underlying module.
137
+ // It's not available to consumers of the library because it is not exported in the index module, and never should be.
138
+ export function deriveApi(appConfig: AppConfigArg): BasicParams['api'] {
139
+ let appUrl: URL;
140
+ try {
141
+ appUrl = new URL(appConfig.appUrl);
142
+ } catch (error) {
143
+ const message =
144
+ appConfig.appUrl === ''
145
+ ? `Detected an empty appUrl configuration, please make sure to set the necessary environment variables.\n` +
146
+ `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`
147
+ : `Invalid appUrl configuration '${appConfig.appUrl}', please provide a valid URL.`;
148
+ throw new ShopifyError(message);
149
+ }
150
+
151
+ /* eslint-disable no-process-env */
152
+ if (appUrl.hostname === 'localhost' && !appUrl.port && process.env.PORT) {
153
+ appUrl.port = process.env.PORT;
154
+ }
155
+ /* eslint-enable no-process-env */
156
+ appConfig.appUrl = appUrl.origin;
157
+
158
+ let userAgentPrefix = `Shopify Remix Library v${SHOPIFY_REMIX_LIBRARY_VERSION}`;
159
+ if (appConfig.userAgentPrefix) {
160
+ userAgentPrefix = `${appConfig.userAgentPrefix} | ${userAgentPrefix}`;
161
+ }
162
+
163
+ return shopifyApi({
164
+ ...appConfig,
165
+ hostName: appUrl.host,
166
+ hostScheme: appUrl.protocol.replace(':', '') as 'http' | 'https',
167
+ userAgentPrefix,
168
+ isEmbeddedApp: appConfig.isEmbeddedApp ?? true,
169
+ apiVersion: appConfig.apiVersion,
170
+ isCustomStoreApp: appConfig.distribution === AppDistribution.ShopifyAdmin,
171
+ billing: appConfig.billing as ApiConfig['billing'],
172
+ future: {
173
+ unstable_managedPricingSupport: true,
174
+ },
175
+ _logDisabledFutureFlags: false,
176
+ });
177
+ }
178
+
179
+ function deriveConfig<Storage extends SessionStorage>(
180
+ appConfig: AppConfigArg,
181
+ apiConfig: ApiConfig,
182
+ ): AppConfig<Storage> {
183
+ if (
184
+ !appConfig.sessionStorage &&
185
+ appConfig.distribution !== AppDistribution.ShopifyAdmin
186
+ ) {
187
+ throw new ShopifyError(
188
+ 'Please provide a valid session storage. Refer to https://github.com/Shopify/shopify-app-js/blob/main/README.md#session-storage-options for options.',
189
+ );
190
+ }
191
+
192
+ const authPathPrefix = appConfig.authPathPrefix || '/auth';
193
+ appConfig.distribution = appConfig.distribution ?? AppDistribution.AppStore;
194
+
195
+ return {
196
+ ...appConfig,
197
+ ...apiConfig,
198
+ billing: appConfig.billing as ApiConfig['billing'],
199
+ scopes: apiConfig.scopes,
200
+ idempotentPromiseHandler: new IdempotentPromiseHandler(),
201
+ canUseLoginForm: appConfig.distribution !== AppDistribution.ShopifyAdmin,
202
+ useOnlineTokens: appConfig.useOnlineTokens ?? false,
203
+ hooks: appConfig.hooks ?? {},
204
+ sessionStorage: appConfig.sessionStorage as Storage,
205
+ future: appConfig.future ?? {},
206
+ auth: {
207
+ path: authPathPrefix,
208
+ callbackPath: `${authPathPrefix}/callback`,
209
+ patchSessionTokenPath: `${authPathPrefix}/session-token`,
210
+ exitIframePath: `${authPathPrefix}/exit-iframe`,
211
+ loginPath: `${authPathPrefix}/login`,
212
+ },
213
+ distribution: appConfig.distribution,
214
+ };
215
+ }
@@ -0,0 +1 @@
1
+ export {testConfig} from './test-config';
@@ -0,0 +1,79 @@
1
+ import {LogSeverity} from '@shopify/shopify-api';
2
+ import {SessionStorage} from '@shopify/shopify-app-session-storage';
3
+ import {MemorySessionStorage} from '@shopify/shopify-app-session-storage-memory';
4
+ import {
5
+ API_KEY,
6
+ API_SECRET_KEY,
7
+ APP_URL,
8
+ } from '@shopify/shopify-api/test-helpers';
9
+
10
+ import type {AppConfigArg} from '../config-types';
11
+ import type {FutureFlagOptions} from '../future/flags';
12
+
13
+ const TEST_CONFIG = {
14
+ apiKey: API_KEY,
15
+ apiSecretKey: API_SECRET_KEY,
16
+ scopes: ['testScope'] as any,
17
+ appUrl: APP_URL,
18
+ adminApiAccessToken: API_KEY,
19
+ privateAppStorefrontAccessToken: API_KEY,
20
+ logger: {
21
+ level: LogSeverity.Debug,
22
+ },
23
+ sessionStorage: new MemorySessionStorage(),
24
+ isTesting: true,
25
+ } as const;
26
+
27
+ export function testConfig<
28
+ Overrides extends TestOverridesArg,
29
+ Future extends FutureFlagOptions,
30
+ >(
31
+ {future, ...overrides}: Overrides & {future?: Future} = {} as Overrides & {
32
+ future?: Future;
33
+ },
34
+ ): TestConfig<Overrides> {
35
+ return {
36
+ ...TEST_CONFIG,
37
+ ...overrides,
38
+ logger: {
39
+ ...TEST_CONFIG.logger,
40
+ ...(overrides as NonNullable<Overrides>).logger,
41
+ },
42
+ future,
43
+ } as any;
44
+ }
45
+
46
+ /*
47
+ * This type combines both passed in types, by ignoring any keys from Type1 that are present (and not undefined)
48
+ * in Type2, and then adding any keys from Type1 that are not present in Type2.
49
+ *
50
+ * This effectively enables us to create a type that is the const TEST_CONFIG below, plus any overrides passed in with
51
+ * the output being a const object.
52
+ */
53
+ type Modify<Type1, Type2> = {
54
+ [key in keyof Type2 as Type2[key] extends undefined
55
+ ? never
56
+ : key]: Type2[key];
57
+ } & {
58
+ [key in keyof Type1 as key extends keyof Type2 ? never : key]: Type1[key];
59
+ };
60
+
61
+ /*
62
+ * We omit the future prop and then redefine it with a partial of that object so we can pass the fully typed object in
63
+ * to AppConfigArg.
64
+ */
65
+ type TestOverrides = Partial<
66
+ Omit<AppConfigArg<SessionStorage, FutureFlagOptions>, 'future'> & {
67
+ future: Partial<FutureFlagOptions>;
68
+ }
69
+ >;
70
+
71
+ export type TestOverridesArg = undefined | TestOverrides;
72
+
73
+ export type TestConfig<Overrides extends TestOverridesArg> = Modify<
74
+ typeof TEST_CONFIG,
75
+ Overrides
76
+ > & {
77
+ future: FutureFlagOptions;
78
+ logger: AppConfigArg['logger'];
79
+ };
@@ -0,0 +1,44 @@
1
+ // This file contains types we want to export to make it easier for apps to pass the contexts we return as types
2
+
3
+ import type {AppConfigArg} from './config-types';
4
+ import type {ShopifyApp} from './types';
5
+ import type {AdminContext as IAdminContext} from './authenticate/admin/types';
6
+ import type {WebhookContext as IWebhookContext} from './authenticate/webhooks/types';
7
+ import type {
8
+ AppProxyContext as IAppProxyContext,
9
+ AppProxyContextWithSession as IAppProxyContextWithSession,
10
+ } from './authenticate/public/appProxy/types';
11
+ import type {
12
+ AdminApiContext as IAdminApiContext,
13
+ StorefrontContext as IStorefrontContext,
14
+ } from './clients';
15
+
16
+ // Direct re-exports for types without transformations
17
+ export type {UnauthenticatedAdminContext} from './unauthenticated/admin/types';
18
+ export type {UnauthenticatedStorefrontContext} from './unauthenticated/storefront/types';
19
+ export type {FlowContext} from './authenticate/flow/types';
20
+ export type {FulfillmentServiceContext} from './authenticate/fulfillment-service/types';
21
+ export type {ScopesDetail} from './authenticate/admin/scope/types';
22
+ export type {AdminApiContext} from './clients';
23
+ export type {ScopesContext} from './authenticate/admin/types';
24
+ export type {CheckoutContext} from './authenticate/public/checkout/types';
25
+ export type {CustomerAccountContext} from './authenticate/public/customer-account/types';
26
+ export type {StorefrontContext as StorefrontApiContext} from './clients';
27
+
28
+ type ShopifyConfig<App> =
29
+ App extends ShopifyApp<infer Config extends AppConfigArg> ? Config : never;
30
+
31
+ type DefaultApp = ShopifyApp<AppConfigArg>;
32
+
33
+ // Types that need transformations or generic parameters
34
+ export type AdminContext<App = DefaultApp> = IAdminContext<ShopifyConfig<App>>;
35
+
36
+ // Types that need modifications
37
+ export type AppProxyContext = IAppProxyContext | IAppProxyContextWithSession;
38
+
39
+ export type WebhookContext = IWebhookContext<string>;
40
+
41
+ // Extra types for API contexts
42
+ export type AdminGraphqlClient = IAdminApiContext['graphql'];
43
+
44
+ export type StorefrontGraphqlClient = IStorefrontContext['graphql'];