shopify-app-js 0.0.1-security → 1.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.
Potentially problematic release.
This version of shopify-app-js might be problematic. Click here for more details.
- package/.changeset/README.md +8 -0
- package/.changeset/config.json +14 -0
- package/.changeset/flat-clouds-camp.md +5 -0
- package/.eslintrc.js +36 -0
- package/.github/CODEOWNERS +1 -0
- package/.github/ISSUE_TEMPLATE/BUG_REPORT.md +36 -0
- package/.github/ISSUE_TEMPLATE/ENHANCEMENT.md +9 -0
- package/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md +9 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +34 -0
- package/.github/dependabot.yml +9 -0
- package/.github/workflows/changelog.yml +30 -0
- package/.github/workflows/ci.yml +22 -0
- package/.github/workflows/cla.yml +22 -0
- package/.github/workflows/close-waiting-for-response-issues.yml +20 -0
- package/.github/workflows/main-release.yml +36 -0
- package/.github/workflows/markdown_link_check.yml +14 -0
- package/.github/workflows/markdown_link_checker_config.json +9 -0
- package/.github/workflows/publish-experimental-build.yml +30 -0
- package/.github/workflows/release-candidate.yml +35 -0
- package/.github/workflows/remove-labels-on-activity.yml +16 -0
- package/.github/workflows/stale.yml +26 -0
- package/.prettierignore +5 -0
- package/.prettierrc +1 -0
- package/CODE_OF_CONDUCT.md +46 -0
- package/CONTRIBUTING.md +39 -0
- package/LICENSE.md +9 -0
- package/README.md +62 -3
- package/RELEASING.md +142 -0
- package/loom.config.ts +115 -0
- package/package.json +44 -3
- package/packages/.prettierrc +1 -0
- package/packages/shopify-app-express/CHANGELOG.md +316 -0
- package/packages/shopify-app-express/LICENSE.md +9 -0
- package/packages/shopify-app-express/README.md +93 -0
- package/packages/shopify-app-express/docs/reference/README.md +3 -0
- package/packages/shopify-app-express/docs/reference/auth.md +76 -0
- package/packages/shopify-app-express/docs/reference/cspHeaders.md +24 -0
- package/packages/shopify-app-express/docs/reference/ensureInstalledOnShop.md +17 -0
- package/packages/shopify-app-express/docs/reference/migrating-app-v6-api-lib-to-express-lib.md +345 -0
- package/packages/shopify-app-express/docs/reference/processWebhooks.md +67 -0
- package/packages/shopify-app-express/docs/reference/redirectOutOfApp.md +77 -0
- package/packages/shopify-app-express/docs/reference/redirectToShopifyOrAppRoot.md +20 -0
- package/packages/shopify-app-express/docs/reference/shopifyApp.md +148 -0
- package/packages/shopify-app-express/docs/reference/validateAuthenticatedSession.md +30 -0
- package/packages/shopify-app-express/loom.config.ts +27 -0
- package/packages/shopify-app-express/package.json +54 -0
- package/packages/shopify-app-express/src/__tests__/index.test.ts +100 -0
- package/packages/shopify-app-express/src/__tests__/integration/oauth.test.ts +445 -0
- package/packages/shopify-app-express/src/__tests__/integration/responses.ts +135 -0
- package/packages/shopify-app-express/src/__tests__/integration/types.ts +22 -0
- package/packages/shopify-app-express/src/__tests__/integration/utils.ts +68 -0
- package/packages/shopify-app-express/src/__tests__/integration/webhooks.test.ts +208 -0
- package/packages/shopify-app-express/src/__tests__/redirect-to-auth.test.ts +103 -0
- package/packages/shopify-app-express/src/__tests__/setup-jest.ts +8 -0
- package/packages/shopify-app-express/src/__tests__/test-helper.ts +204 -0
- package/packages/shopify-app-express/src/app-installations.ts +42 -0
- package/packages/shopify-app-express/src/auth/__tests__/auth.test.ts +303 -0
- package/packages/shopify-app-express/src/auth/auth-callback.ts +131 -0
- package/packages/shopify-app-express/src/auth/index.ts +32 -0
- package/packages/shopify-app-express/src/auth/types.ts +13 -0
- package/packages/shopify-app-express/src/config-types.ts +38 -0
- package/packages/shopify-app-express/src/error.ts +8 -0
- package/packages/shopify-app-express/src/index.ts +171 -0
- package/packages/shopify-app-express/src/middlewares/__tests__/csp-headers.test.ts +69 -0
- package/packages/shopify-app-express/src/middlewares/__tests__/ensure-installed-on-shop.test.ts +193 -0
- package/packages/shopify-app-express/src/middlewares/__tests__/redirect-to-shopify-or-app-root.test.ts +59 -0
- package/packages/shopify-app-express/src/middlewares/__tests__/validate-authenticated-session.test.ts +319 -0
- package/packages/shopify-app-express/src/middlewares/csp-headers.ts +31 -0
- package/packages/shopify-app-express/src/middlewares/ensure-installed-on-shop.ts +176 -0
- package/packages/shopify-app-express/src/middlewares/has-valid-access-token.ts +25 -0
- package/packages/shopify-app-express/src/middlewares/index.ts +15 -0
- package/packages/shopify-app-express/src/middlewares/redirect-to-shopify-or-app-root.ts +39 -0
- package/packages/shopify-app-express/src/middlewares/types.ts +6 -0
- package/packages/shopify-app-express/src/middlewares/validate-authenticated-session.ts +142 -0
- package/packages/shopify-app-express/src/redirect-out-of-app.ts +80 -0
- package/packages/shopify-app-express/src/redirect-to-auth.ts +70 -0
- package/packages/shopify-app-express/src/types.ts +26 -0
- package/packages/shopify-app-express/src/version.ts +1 -0
- package/packages/shopify-app-express/src/webhooks/__tests__/process.test.ts +138 -0
- package/packages/shopify-app-express/src/webhooks/index.ts +54 -0
- package/packages/shopify-app-express/src/webhooks/process.ts +22 -0
- package/packages/shopify-app-express/src/webhooks/types.ts +24 -0
- package/packages/shopify-app-express/tsconfig.json +10 -0
- package/packages/shopify-app-remix/.eslintrc.js +3 -0
- package/packages/shopify-app-remix/CHANGELOG.md +569 -0
- package/packages/shopify-app-remix/LICENSE.md +9 -0
- package/packages/shopify-app-remix/README.md +223 -0
- package/packages/shopify-app-remix/docs/build-docs.sh +11 -0
- package/packages/shopify-app-remix/docs/generated/generated_docs_data.json +18650 -0
- package/packages/shopify-app-remix/docs/generated/generated_static_pages.json +540 -0
- package/packages/shopify-app-remix/docs/staticPages/admin.doc.ts +130 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/admin/auth-cors.example.tsx +11 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/admin/auth.example.tsx +19 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/admin/graphql.example.tsx +29 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/admin/headers.example.tsx +10 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/admin/rest-resources.example.tsx +9 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/admin/rest.example.tsx +17 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/future-flags/config.example.ts +8 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/future-flags/unstable.example.ts +9 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/graphql-types/.graphqlrc.ts +16 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/graphql-types/install.npm.example.sh +2 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/graphql-types/install.pnpm.example.sh +2 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/graphql-types/install.yarn.example.sh +2 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/graphql-types/package.json +5 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/graphql-types/run.npm.example.sh +1 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/graphql-types/run.pnpm.example.sh +1 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/graphql-types/run.yarn.example.sh +1 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/webhooks/config.example.ts +19 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/guides/webhooks/endpoint.example.ts +24 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/index/app-provider.example.ts +30 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/index/boundaries.example.ts +9 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/index/create.npm.example.sh +1 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/index/create.pnpm.example.sh +1 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/index/create.yarn.example.sh +1 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/index/embedded-app-auth-strategy-config.example.ts +10 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/index/entry-server.example.ts +12 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/index/install.npm.example.sh +1 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/index/install.pnpm.example.sh +1 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/index/install.yarn.example.sh +1 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/index/shopify-app.example.ts +14 -0
- package/packages/shopify-app-remix/docs/staticPages/examples/index/splat-route.example.ts +11 -0
- package/packages/shopify-app-remix/docs/staticPages/future-flags.doc.ts +94 -0
- package/packages/shopify-app-remix/docs/staticPages/graphql-types.doc.ts +148 -0
- package/packages/shopify-app-remix/docs/staticPages/index.doc.ts +227 -0
- package/packages/shopify-app-remix/docs/staticPages/webhooks.doc.ts +64 -0
- package/packages/shopify-app-remix/docs/tsconfig.docs.json +9 -0
- package/packages/shopify-app-remix/docs/typeOverride.json +1 -0
- package/packages/shopify-app-remix/docs/upcoming_changes.md +153 -0
- package/packages/shopify-app-remix/loom.config.ts +57 -0
- package/packages/shopify-app-remix/package.json +93 -0
- package/packages/shopify-app-remix/src/react/.eslintrc.js +16 -0
- package/packages/shopify-app-remix/src/react/__tests__/test-helper.ts +22 -0
- package/packages/shopify-app-remix/src/react/components/AppProvider/AppProvider.doc.ts +34 -0
- package/packages/shopify-app-remix/src/react/components/AppProvider/AppProvider.tsx +121 -0
- package/packages/shopify-app-remix/src/react/components/AppProvider/__tests__/AppProvider.test.tsx +68 -0
- package/packages/shopify-app-remix/src/react/components/AppProvider/index.ts +1 -0
- package/packages/shopify-app-remix/src/react/components/RemixPolarisLink.tsx +14 -0
- package/packages/shopify-app-remix/src/react/components/index.ts +1 -0
- package/packages/shopify-app-remix/src/react/const.ts +2 -0
- package/packages/shopify-app-remix/src/react/index.ts +1 -0
- package/packages/shopify-app-remix/src/server/.eslintrc.js +16 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/__tests__/request-mock.test.ts +171 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/const.ts +11 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/expect-admin-api-client.ts +119 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/expect-begin-auth-redirect.ts +22 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/expect-document-request-headers.ts +25 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/expect-exit-iframe.ts +37 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/expect-login-redirect.ts +8 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/expect-storefront-api-client.ts +50 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/get-hmac.ts +10 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/get-jwt.ts +31 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/get-thrown-response.ts +17 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/index.ts +14 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/request-mock.ts +169 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/setup-valid-session.ts +45 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/sign-request-cookie.ts +21 -0
- package/packages/shopify-app-remix/src/server/__test-helpers/test-config.ts +112 -0
- package/packages/shopify-app-remix/src/server/__tests__/override-logger.test.ts +101 -0
- package/packages/shopify-app-remix/src/server/__tests__/shopify-app.test.ts +119 -0
- package/packages/shopify-app-remix/src/server/adapters/__tests__/node-app-bridge-url.test.ts +18 -0
- package/packages/shopify-app-remix/src/server/adapters/__tests__/node.test.ts +28 -0
- package/packages/shopify-app-remix/src/server/adapters/node/__tests__/setup-jest.ts +10 -0
- package/packages/shopify-app-remix/src/server/adapters/node/index.ts +20 -0
- package/packages/shopify-app-remix/src/server/adapters/vercel/__tests__/setup-jest.ts +12 -0
- package/packages/shopify-app-remix/src/server/adapters/vercel/index.ts +13 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/__tests__/admin-client.test.ts +181 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/__tests__/doc-request-path.test.ts +151 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/__tests__/exit-i-frame-path.test.ts +99 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/__tests__/patch-session-token-path.test.ts +58 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/__tests__/reject-bot.test.ts +23 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/__tests__/respond-to-options.test.ts +50 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/__tests__/session-token-header-path.test.ts +91 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/authenticate.admin.doc.ts +37 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/authenticate.ts +201 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/billing/__tests__/cancel.test.ts +258 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/billing/__tests__/check.test.ts +254 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/billing/__tests__/mock-responses.ts +65 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/billing/__tests__/request.test.ts +373 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/billing/__tests__/require.test.ts +316 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/billing/authenticate.admin.billing.doc.ts +28 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/billing/cancel.ts +37 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/billing/check.ts +38 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/billing/index.ts +4 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/billing/request.ts +101 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/billing/require.ts +56 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/billing/types.ts +383 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/__tests__/redirect.test.ts +313 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/__tests__/validate-redirect-url.test.ts +84 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/begin-auth.ts +17 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/create-admin-api-context.ts +22 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/ensure-app-is-embedded-if-required.ts +18 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/ensure-session-token-search-param-if-required.ts +25 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/handle-client-error.ts +43 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/index.ts +14 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/redirect-to-auth-page.ts +28 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/redirect-to-bounce-page.ts +23 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/redirect-to-shopify-or-app-root.ts +21 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/redirect-with-app-bridge-headers.ts +13 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/redirect-with-exitiframe.ts +28 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/redirect.ts +83 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/render-app-bridge.ts +46 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/trigger-after-auth-hook.ts +28 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/validate-redirect-url.ts +67 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/helpers/validate-shop-and-host-params.ts +28 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/strategies/__tests__/auth-code-flow/admin-client.test.ts +222 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/strategies/__tests__/auth-code-flow/auth-callback-path.test.ts +395 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/strategies/__tests__/auth-code-flow/auth-path.test.ts +83 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/strategies/__tests__/auth-code-flow/authenticate.test.ts +183 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/strategies/__tests__/auth-code-flow/ensure-installed-on-shop.test.ts +234 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/strategies/__tests__/auth-code-flow/session-token-header-path.test.ts +79 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/strategies/__tests__/token-exchange/admin-client.test.ts +189 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/strategies/__tests__/token-exchange/authenticate.test.ts +310 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/strategies/auth-code-flow.ts +333 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/strategies/token-exchange.ts +169 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/strategies/types.ts +29 -0
- package/packages/shopify-app-remix/src/server/authenticate/admin/types.ts +199 -0
- package/packages/shopify-app-remix/src/server/authenticate/const.ts +15 -0
- package/packages/shopify-app-remix/src/server/authenticate/flow/__tests__/authenticate.test.ts +142 -0
- package/packages/shopify-app-remix/src/server/authenticate/flow/authenticate.flow.doc.ts +34 -0
- package/packages/shopify-app-remix/src/server/authenticate/flow/authenticate.ts +71 -0
- package/packages/shopify-app-remix/src/server/authenticate/flow/types.ts +90 -0
- package/packages/shopify-app-remix/src/server/authenticate/helpers/__tests__/add-response-headers.test.ts +25 -0
- package/packages/shopify-app-remix/src/server/authenticate/helpers/__tests__/app-bridge-url.test.ts +21 -0
- package/packages/shopify-app-remix/src/server/authenticate/helpers/__tests__/idempotent-promise-handler.test.ts +104 -0
- package/packages/shopify-app-remix/src/server/authenticate/helpers/add-response-headers.ts +43 -0
- package/packages/shopify-app-remix/src/server/authenticate/helpers/app-bridge-url.ts +10 -0
- package/packages/shopify-app-remix/src/server/authenticate/helpers/ensure-cors-headers.ts +38 -0
- package/packages/shopify-app-remix/src/server/authenticate/helpers/get-session-token-header.ts +11 -0
- package/packages/shopify-app-remix/src/server/authenticate/helpers/idempotent-promise-handler.ts +45 -0
- package/packages/shopify-app-remix/src/server/authenticate/helpers/index.ts +8 -0
- package/packages/shopify-app-remix/src/server/authenticate/helpers/reject-bot-request.ts +13 -0
- package/packages/shopify-app-remix/src/server/authenticate/helpers/respond-to-invalid-session-token.ts +29 -0
- package/packages/shopify-app-remix/src/server/authenticate/helpers/respond-to-options-request.ts +26 -0
- package/packages/shopify-app-remix/src/server/authenticate/helpers/validate-session-token.ts +32 -0
- package/packages/shopify-app-remix/src/server/authenticate/login/__tests__/login.test.ts +157 -0
- package/packages/shopify-app-remix/src/server/authenticate/login/login.ts +53 -0
- package/packages/shopify-app-remix/src/server/authenticate/public/__tests__/factory.test.ts +224 -0
- package/packages/shopify-app-remix/src/server/authenticate/public/appProxy/__tests__/authenticate.test.ts +282 -0
- package/packages/shopify-app-remix/src/server/authenticate/public/appProxy/authenticate.public.app-proxy.doc.ts +36 -0
- package/packages/shopify-app-remix/src/server/authenticate/public/appProxy/authenticate.ts +90 -0
- package/packages/shopify-app-remix/src/server/authenticate/public/appProxy/types.ts +164 -0
- package/packages/shopify-app-remix/src/server/authenticate/public/checkout/__tests__/authenticate.test.ts +142 -0
- package/packages/shopify-app-remix/src/server/authenticate/public/checkout/authenticate.public.checkout.doc.ts +23 -0
- package/packages/shopify-app-remix/src/server/authenticate/public/checkout/authenticate.ts +45 -0
- package/packages/shopify-app-remix/src/server/authenticate/public/checkout/types.ts +65 -0
- package/packages/shopify-app-remix/src/server/authenticate/public/factory.ts +49 -0
- package/packages/shopify-app-remix/src/server/authenticate/public/index.ts +1 -0
- package/packages/shopify-app-remix/src/server/authenticate/public/types.ts +77 -0
- package/packages/shopify-app-remix/src/server/authenticate/webhooks/__tests__/authenticate.test.ts +207 -0
- package/packages/shopify-app-remix/src/server/authenticate/webhooks/__tests__/mock-responses.ts +45 -0
- package/packages/shopify-app-remix/src/server/authenticate/webhooks/__tests__/register.test.ts +210 -0
- package/packages/shopify-app-remix/src/server/authenticate/webhooks/authenticate.ts +113 -0
- package/packages/shopify-app-remix/src/server/authenticate/webhooks/authenticate.webhooks.doc.ts +28 -0
- package/packages/shopify-app-remix/src/server/authenticate/webhooks/index.ts +1 -0
- package/packages/shopify-app-remix/src/server/authenticate/webhooks/register.ts +48 -0
- package/packages/shopify-app-remix/src/server/authenticate/webhooks/types.ts +246 -0
- package/packages/shopify-app-remix/src/server/boundary/__tests__/error.test.tsx +36 -0
- package/packages/shopify-app-remix/src/server/boundary/__tests__/headers.test.ts +66 -0
- package/packages/shopify-app-remix/src/server/boundary/error.tsx +14 -0
- package/packages/shopify-app-remix/src/server/boundary/headers.ts +15 -0
- package/packages/shopify-app-remix/src/server/boundary/index.ts +39 -0
- package/packages/shopify-app-remix/src/server/boundary/types.ts +4 -0
- package/packages/shopify-app-remix/src/server/clients/admin/authenticate.admin.api.doc.ts +34 -0
- package/packages/shopify-app-remix/src/server/clients/admin/factory.ts +30 -0
- package/packages/shopify-app-remix/src/server/clients/admin/graphql.ts +39 -0
- package/packages/shopify-app-remix/src/server/clients/admin/index.ts +2 -0
- package/packages/shopify-app-remix/src/server/clients/admin/rest.ts +157 -0
- package/packages/shopify-app-remix/src/server/clients/admin/types.ts +178 -0
- package/packages/shopify-app-remix/src/server/clients/index.ts +2 -0
- package/packages/shopify-app-remix/src/server/clients/storefront/authenticate.storefront.api.doc.ts +34 -0
- package/packages/shopify-app-remix/src/server/clients/storefront/factory.ts +32 -0
- package/packages/shopify-app-remix/src/server/clients/storefront/index.ts +2 -0
- package/packages/shopify-app-remix/src/server/clients/storefront/types.ts +31 -0
- package/packages/shopify-app-remix/src/server/clients/types.ts +27 -0
- package/packages/shopify-app-remix/src/server/config-types.ts +293 -0
- package/packages/shopify-app-remix/src/server/errors.ts +3 -0
- package/packages/shopify-app-remix/src/server/future/flags.ts +57 -0
- package/packages/shopify-app-remix/src/server/index.ts +20 -0
- package/packages/shopify-app-remix/src/server/override-logger.ts +42 -0
- package/packages/shopify-app-remix/src/server/shopify-app.doc.ts +45 -0
- package/packages/shopify-app-remix/src/server/shopify-app.ts +198 -0
- package/packages/shopify-app-remix/src/server/types.ts +509 -0
- package/packages/shopify-app-remix/src/server/unauthenticated/admin/__tests__/factory.test.ts +30 -0
- package/packages/shopify-app-remix/src/server/unauthenticated/admin/factory.ts +29 -0
- package/packages/shopify-app-remix/src/server/unauthenticated/admin/index.ts +1 -0
- package/packages/shopify-app-remix/src/server/unauthenticated/admin/types.ts +117 -0
- package/packages/shopify-app-remix/src/server/unauthenticated/admin/unauthenticated.admin.doc.ts +40 -0
- package/packages/shopify-app-remix/src/server/unauthenticated/helpers/get-offline-session.ts +13 -0
- package/packages/shopify-app-remix/src/server/unauthenticated/helpers/index.ts +1 -0
- package/packages/shopify-app-remix/src/server/unauthenticated/storefront/__tests__/factory.test.ts +30 -0
- package/packages/shopify-app-remix/src/server/unauthenticated/storefront/factory.ts +28 -0
- package/packages/shopify-app-remix/src/server/unauthenticated/storefront/index.ts +1 -0
- package/packages/shopify-app-remix/src/server/unauthenticated/storefront/types.ts +39 -0
- package/packages/shopify-app-remix/src/server/unauthenticated/storefront/unauthenticated.storefront.doc.ts +40 -0
- package/packages/shopify-app-remix/src/server/unauthenticated/types.ts +68 -0
- package/packages/shopify-app-remix/src/server/version.ts +1 -0
- package/packages/shopify-app-remix/tsconfig.json +11 -0
- package/packages/shopify-app-session-storage/CHANGELOG.md +149 -0
- package/packages/shopify-app-session-storage/LICENSE.md +9 -0
- package/packages/shopify-app-session-storage/README.md +5 -0
- package/packages/shopify-app-session-storage/implementing-session-storage.md +214 -0
- package/packages/shopify-app-session-storage/loom.config.ts +45 -0
- package/packages/shopify-app-session-storage/package.json +44 -0
- package/packages/shopify-app-session-storage/src/__tests__/setup-jest.ts +8 -0
- package/packages/shopify-app-session-storage/src/abstract-migration-engine.ts +53 -0
- package/packages/shopify-app-session-storage/src/index.ts +3 -0
- package/packages/shopify-app-session-storage/src/rdbms-session-storage-migrator.ts +59 -0
- package/packages/shopify-app-session-storage/src/types.ts +174 -0
- package/packages/shopify-app-session-storage/tsconfig.json +10 -0
- package/packages/shopify-app-session-storage-dynamodb/CHANGELOG.md +150 -0
- package/packages/shopify-app-session-storage-dynamodb/LICENSE.md +9 -0
- package/packages/shopify-app-session-storage-dynamodb/README.md +75 -0
- package/packages/shopify-app-session-storage-dynamodb/loom.config.ts +27 -0
- package/packages/shopify-app-session-storage-dynamodb/package.json +51 -0
- package/packages/shopify-app-session-storage-dynamodb/src/__tests__/dynamodb.test.ts +93 -0
- package/packages/shopify-app-session-storage-dynamodb/src/__tests__/setup-jest.ts +8 -0
- package/packages/shopify-app-session-storage-dynamodb/src/dynamodb.ts +126 -0
- package/packages/shopify-app-session-storage-dynamodb/tsconfig.json +10 -0
- package/packages/shopify-app-session-storage-kv/CHANGELOG.md +204 -0
- package/packages/shopify-app-session-storage-kv/LICENSE.md +9 -0
- package/packages/shopify-app-session-storage-kv/README.md +41 -0
- package/packages/shopify-app-session-storage-kv/loom.config.ts +27 -0
- package/packages/shopify-app-session-storage-kv/package.json +52 -0
- package/packages/shopify-app-session-storage-kv/src/__tests__/kv-namespace-dummy-worker.ts +8 -0
- package/packages/shopify-app-session-storage-kv/src/__tests__/kv.test.ts +22 -0
- package/packages/shopify-app-session-storage-kv/src/__tests__/setup-jest.ts +8 -0
- package/packages/shopify-app-session-storage-kv/src/kv.ts +87 -0
- package/packages/shopify-app-session-storage-kv/tsconfig.json +11 -0
- package/packages/shopify-app-session-storage-memory/CHANGELOG.md +190 -0
- package/packages/shopify-app-session-storage-memory/LICENSE.md +9 -0
- package/packages/shopify-app-session-storage-memory/README.md +19 -0
- package/packages/shopify-app-session-storage-memory/loom.config.ts +27 -0
- package/packages/shopify-app-session-storage-memory/package.json +46 -0
- package/packages/shopify-app-session-storage-memory/src/__tests__/memory.test.ts +12 -0
- package/packages/shopify-app-session-storage-memory/src/__tests__/setup-jest.ts +8 -0
- package/packages/shopify-app-session-storage-memory/src/memory.ts +34 -0
- package/packages/shopify-app-session-storage-memory/tsconfig.json +10 -0
- package/packages/shopify-app-session-storage-mongodb/CHANGELOG.md +208 -0
- package/packages/shopify-app-session-storage-mongodb/LICENSE.md +9 -0
- package/packages/shopify-app-session-storage-mongodb/README.md +30 -0
- package/packages/shopify-app-session-storage-mongodb/loom.config.ts +27 -0
- package/packages/shopify-app-session-storage-mongodb/package.json +49 -0
- package/packages/shopify-app-session-storage-mongodb/src/__tests__/mongodb.test.ts +54 -0
- package/packages/shopify-app-session-storage-mongodb/src/__tests__/setup-jest.ts +8 -0
- package/packages/shopify-app-session-storage-mongodb/src/mongodb.ts +120 -0
- package/packages/shopify-app-session-storage-mongodb/tsconfig.json +10 -0
- package/packages/shopify-app-session-storage-mysql/CHANGELOG.md +220 -0
- package/packages/shopify-app-session-storage-mysql/LICENSE.md +9 -0
- package/packages/shopify-app-session-storage-mysql/README.md +41 -0
- package/packages/shopify-app-session-storage-mysql/loom.config.ts +27 -0
- package/packages/shopify-app-session-storage-mysql/package.json +50 -0
- package/packages/shopify-app-session-storage-mysql/src/__tests__/mysql.test.ts +137 -0
- package/packages/shopify-app-session-storage-mysql/src/__tests__/setup-jest.ts +8 -0
- package/packages/shopify-app-session-storage-mysql/src/migrations.ts +18 -0
- package/packages/shopify-app-session-storage-mysql/src/mysql-connection.ts +108 -0
- package/packages/shopify-app-session-storage-mysql/src/mysql-migrator.ts +53 -0
- package/packages/shopify-app-session-storage-mysql/src/mysql.ts +178 -0
- package/packages/shopify-app-session-storage-mysql/tsconfig.json +10 -0
- package/packages/shopify-app-session-storage-postgresql/CHANGELOG.md +210 -0
- package/packages/shopify-app-session-storage-postgresql/LICENSE.md +9 -0
- package/packages/shopify-app-session-storage-postgresql/README.md +39 -0
- package/packages/shopify-app-session-storage-postgresql/loom.config.ts +27 -0
- package/packages/shopify-app-session-storage-postgresql/package.json +52 -0
- package/packages/shopify-app-session-storage-postgresql/src/__tests__/migrate-to-case-sensitivity.test.ts +344 -0
- package/packages/shopify-app-session-storage-postgresql/src/__tests__/postgresql.test.ts +136 -0
- package/packages/shopify-app-session-storage-postgresql/src/__tests__/setup-jest.ts +8 -0
- package/packages/shopify-app-session-storage-postgresql/src/migrations.ts +70 -0
- package/packages/shopify-app-session-storage-postgresql/src/postgres-connection.ts +94 -0
- package/packages/shopify-app-session-storage-postgresql/src/postgres-migrator.ts +27 -0
- package/packages/shopify-app-session-storage-postgresql/src/postgresql.ts +178 -0
- package/packages/shopify-app-session-storage-postgresql/tsconfig.json +10 -0
- package/packages/shopify-app-session-storage-prisma/CHANGELOG.md +148 -0
- package/packages/shopify-app-session-storage-prisma/LICENSE.md +9 -0
- package/packages/shopify-app-session-storage-prisma/README.md +68 -0
- package/packages/shopify-app-session-storage-prisma/loom.config.ts +27 -0
- package/packages/shopify-app-session-storage-prisma/package.json +51 -0
- package/packages/shopify-app-session-storage-prisma/prisma/migrations/20230425184828_init/migration.sql +11 -0
- package/packages/shopify-app-session-storage-prisma/prisma/migrations/20230906155758_mySession/migration.sql +11 -0
- package/packages/shopify-app-session-storage-prisma/prisma/migrations/migration_lock.toml +3 -0
- package/packages/shopify-app-session-storage-prisma/prisma/schema.prisma +30 -0
- package/packages/shopify-app-session-storage-prisma/src/__tests__/prisma.test.ts +66 -0
- package/packages/shopify-app-session-storage-prisma/src/__tests__/setup-jest.ts +8 -0
- package/packages/shopify-app-session-storage-prisma/src/prisma.ts +145 -0
- package/packages/shopify-app-session-storage-prisma/tsconfig.json +10 -0
- package/packages/shopify-app-session-storage-redis/CHANGELOG.md +200 -0
- package/packages/shopify-app-session-storage-redis/LICENSE.md +9 -0
- package/packages/shopify-app-session-storage-redis/README.md +38 -0
- package/packages/shopify-app-session-storage-redis/loom.config.ts +27 -0
- package/packages/shopify-app-session-storage-redis/package.json +50 -0
- package/packages/shopify-app-session-storage-redis/src/__tests__/migration-test-data.ts +46 -0
- package/packages/shopify-app-session-storage-redis/src/__tests__/redis.conf +2 -0
- package/packages/shopify-app-session-storage-redis/src/__tests__/redis.test.ts +236 -0
- package/packages/shopify-app-session-storage-redis/src/__tests__/setup-jest.ts +8 -0
- package/packages/shopify-app-session-storage-redis/src/migrations.ts +36 -0
- package/packages/shopify-app-session-storage-redis/src/redis-connection.ts +64 -0
- package/packages/shopify-app-session-storage-redis/src/redis-migrator.ts +58 -0
- package/packages/shopify-app-session-storage-redis/src/redis.ts +167 -0
- package/packages/shopify-app-session-storage-redis/tsconfig.json +10 -0
- package/packages/shopify-app-session-storage-sqlite/CHANGELOG.md +202 -0
- package/packages/shopify-app-session-storage-sqlite/LICENSE.md +9 -0
- package/packages/shopify-app-session-storage-sqlite/README.md +25 -0
- package/packages/shopify-app-session-storage-sqlite/loom.config.ts +27 -0
- package/packages/shopify-app-session-storage-sqlite/package.json +51 -0
- package/packages/shopify-app-session-storage-sqlite/src/__tests__/setup-jest.ts +8 -0
- package/packages/shopify-app-session-storage-sqlite/src/__tests__/sqlite.test.ts +44 -0
- package/packages/shopify-app-session-storage-sqlite/src/migrations.ts +54 -0
- package/packages/shopify-app-session-storage-sqlite/src/sqlite-connection.ts +80 -0
- package/packages/shopify-app-session-storage-sqlite/src/sqlite-migrator.ts +34 -0
- package/packages/shopify-app-session-storage-sqlite/src/sqlite.ts +147 -0
- package/packages/shopify-app-session-storage-sqlite/tsconfig.json +10 -0
- package/packages/shopify-app-session-storage-test-utils/CHANGELOG.md +185 -0
- package/packages/shopify-app-session-storage-test-utils/LICENSE.md +9 -0
- package/packages/shopify-app-session-storage-test-utils/loom.config.ts +27 -0
- package/packages/shopify-app-session-storage-test-utils/package.json +48 -0
- package/packages/shopify-app-session-storage-test-utils/src/__tests__/session-test-utils.test.ts +273 -0
- package/packages/shopify-app-session-storage-test-utils/src/battery-of-tests.ts +250 -0
- package/packages/shopify-app-session-storage-test-utils/src/index.ts +2 -0
- package/packages/shopify-app-session-storage-test-utils/src/session-test-utils.ts +24 -0
- package/packages/shopify-app-session-storage-test-utils/src/utils.ts +71 -0
- package/packages/shopify-app-session-storage-test-utils/tsconfig.json +10 -0
- package/tests/setup/build.js +1 -0
- package/tests/setup/setup-jest.ts +8 -0
- package/tsconfig.base.json +41 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# `@shopify/shopify-app-express`
|
|
2
|
+
|
|
3
|
+
<!-- ![Build Status]() -->
|
|
4
|
+
|
|
5
|
+
[](LICENSE.md)
|
|
6
|
+
[](https://badge.fury.io/js/%40shopify%2Fshopify-app-express)
|
|
7
|
+
|
|
8
|
+
This package makes it easy for [Express.js](https://expressjs.com/) apps to integrate with Shopify.
|
|
9
|
+
It builds on the `@shopify/shopify-api` package and creates a middleware layer that allows the app to communicate with and authenticate requests from Shopify.
|
|
10
|
+
|
|
11
|
+
> **Note**: this package will enable your app's backend to work with Shopify APIs, and by default it will behave as an [embedded app](https://shopify.dev/docs/apps/auth/oauth/session-tokens). You'll need to use [Shopify App Bridge](https://shopify.dev/docs/apps/tools/app-bridge) in your frontend to authenticate requests to the backend.
|
|
12
|
+
|
|
13
|
+
## Requirements
|
|
14
|
+
|
|
15
|
+
To follow these usage guides, you will need to:
|
|
16
|
+
|
|
17
|
+
- have a Shopify Partner account and development store
|
|
18
|
+
- have an app already set up on your partner account
|
|
19
|
+
- have a JavaScript package manager such as [yarn](https://yarnpkg.com) installed
|
|
20
|
+
|
|
21
|
+
## Getting started
|
|
22
|
+
|
|
23
|
+
To install this package, you can run this on your terminal:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Create your project folder
|
|
27
|
+
mkdir /my/project/path
|
|
28
|
+
# Set up a new yarn project
|
|
29
|
+
yarn init .
|
|
30
|
+
# You can use your preferred Node package manager
|
|
31
|
+
yarn add @shopify/shopify-app-express
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Then, you can import the package in your app by creating an `index.js` file containing:
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
const express = require('express');
|
|
38
|
+
const {shopifyApp} = require('@shopify/shopify-app-express');
|
|
39
|
+
|
|
40
|
+
const PORT = 8080;
|
|
41
|
+
|
|
42
|
+
const shopify = shopifyApp({
|
|
43
|
+
api: {
|
|
44
|
+
apiKey: 'ApiKeyFromPartnersDashboard',
|
|
45
|
+
apiSecretKey: 'ApiSecretKeyFromPartnersDashboard',
|
|
46
|
+
scopes: ['your_scopes'],
|
|
47
|
+
hostScheme: 'http',
|
|
48
|
+
hostName: `localhost:${PORT}`,
|
|
49
|
+
},
|
|
50
|
+
auth: {
|
|
51
|
+
path: '/api/auth',
|
|
52
|
+
callbackPath: '/api/auth/callback',
|
|
53
|
+
},
|
|
54
|
+
webhooks: {
|
|
55
|
+
path: '/api/webhooks',
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const app = express();
|
|
60
|
+
|
|
61
|
+
app.get(shopify.config.auth.path, shopify.auth.begin());
|
|
62
|
+
app.get(
|
|
63
|
+
shopify.config.auth.callbackPath,
|
|
64
|
+
shopify.auth.callback(),
|
|
65
|
+
shopify.redirectToShopifyOrAppRoot(),
|
|
66
|
+
);
|
|
67
|
+
app.post(
|
|
68
|
+
shopify.config.webhooks.path,
|
|
69
|
+
shopify.processWebhooks({webhookHandlers}),
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
app.get('/', shopify.ensureInstalledOnShop(), (req, res) => {
|
|
73
|
+
res.send('Hello world!');
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
app.listen(PORT, () => console.log('Server started'));
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Once you set the appropriate configuration values, you can then run your Express app as usual, for instance using:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
node ./index.js
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
To load your app within the Shopify Admin app, you need to:
|
|
86
|
+
|
|
87
|
+
1. Update your app's URL in your Partners Dashboard app setup page to `http://localhost:8080`
|
|
88
|
+
1. Update your app's callback URL to `http://localhost:8080/api/auth/callback` in that same page
|
|
89
|
+
1. Go to **Test your app** in Partners Dashboard and select your development store
|
|
90
|
+
|
|
91
|
+
## Next steps
|
|
92
|
+
|
|
93
|
+
Now that your app is up and running, you can learn more about the `shopifyApp` object in [the reference docs](./docs/reference/shopifyApp.md).
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# `shopify.auth`
|
|
2
|
+
|
|
3
|
+
This object contains two express middleware functions: `begin` and `callback`.
|
|
4
|
+
|
|
5
|
+
When setting up the OAuth routes, the app must redirect the user to the appropriate location.
|
|
6
|
+
By default, we recommend using the `shopify.redirectToShopifyOrAppRoot` middleware to load your app in the correct location, but you can choose to redirect anywhere else.
|
|
7
|
+
|
|
8
|
+
## Properties
|
|
9
|
+
|
|
10
|
+
### `begin`
|
|
11
|
+
|
|
12
|
+
`() => RequestHandler`
|
|
13
|
+
|
|
14
|
+
This function returns an Express middleware that initiates an OAuth process with Shopify, by requesting the merchant to approve the selected scopes.
|
|
15
|
+
It doesn't take any arguments, but the route that uses this middleware must match the configuration in `auth.path`.
|
|
16
|
+
|
|
17
|
+
### `callback`
|
|
18
|
+
|
|
19
|
+
`() => RequestHandler`
|
|
20
|
+
|
|
21
|
+
This function returns an Express middleware that completes an OAuth process with Shopify, by validating that the call originated from Shopify and storing a `Session` in the database.
|
|
22
|
+
|
|
23
|
+
The session is available to the following handlers via the `res.locals.shopify.session` object.
|
|
24
|
+
|
|
25
|
+
> **Note**: this middleware **_DOES NOT_** redirect anywhere, so the request **_WILL NOT_** trigger a response by default. If you don't need to perform any actions after OAuth, we recommend using the `shopify.redirectToShopifyOrAppRoot()` middleware.
|
|
26
|
+
|
|
27
|
+
## Example
|
|
28
|
+
|
|
29
|
+
For example, the following callback will check for and request payment after OAuth if the merchant hasn't paid for the app yet.
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
const shopify = shopifyApp({
|
|
33
|
+
api: {
|
|
34
|
+
billing: {
|
|
35
|
+
'My plan': {
|
|
36
|
+
amount: 10,
|
|
37
|
+
currencyCode: 'USD',
|
|
38
|
+
interval: BillingInterval.Every30Days,
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
auth: {
|
|
43
|
+
path: '/auth',
|
|
44
|
+
callbackPath: '/auth/callback',
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
app.get(shopify.config.auth.path, shopify.auth.begin());
|
|
49
|
+
app.get(
|
|
50
|
+
shopify.config.auth.callbackPath,
|
|
51
|
+
shopify.auth.callback(),
|
|
52
|
+
// Request payment if required
|
|
53
|
+
async (req, res, next) => {
|
|
54
|
+
const session = res.locals.shopify.session;
|
|
55
|
+
const hasPayment = await shopify.api.billing.check({
|
|
56
|
+
session,
|
|
57
|
+
plans: ['My plan'],
|
|
58
|
+
isTest: true,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
if (hasPayment) {
|
|
62
|
+
next();
|
|
63
|
+
} else {
|
|
64
|
+
res.redirect(
|
|
65
|
+
await shopify.api.billing.request({
|
|
66
|
+
session,
|
|
67
|
+
plan: 'My plan',
|
|
68
|
+
isTest: true,
|
|
69
|
+
}),
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
// Load the app otherwise
|
|
74
|
+
shopify.redirectToShopifyOrAppRoot(),
|
|
75
|
+
);
|
|
76
|
+
```
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# `shopify.cspHeaders`
|
|
2
|
+
|
|
3
|
+
This function creates an Express middleware that ensures any response will have the `Content-Security-Policy` header set correctly to prevent clickjacking attacks.
|
|
4
|
+
|
|
5
|
+
This middleware behaves slightly differently depending on whether your app is embedded or not.
|
|
6
|
+
|
|
7
|
+
- When embedded, the `Content-Security-Policy` will be set to `frame-ancestors https://admin.shopify.com/ https://[shop].myshopify.com`, where [shop] is dynamically set to the shop domain the app is embedded on.
|
|
8
|
+
- When not embedded, the `Content-Security-Policy` will be set to `frame-ancestors none`.
|
|
9
|
+
|
|
10
|
+
Please visit [our documentation](https://shopify.dev/docs/apps/store/security/iframe-protection) to learn more about setting up iframe protection.
|
|
11
|
+
|
|
12
|
+
## Example
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
const app = express();
|
|
16
|
+
const shopifyApp = shopifyApp({
|
|
17
|
+
//...
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// ...
|
|
21
|
+
app.use(shopifyApp.cspHeaders());
|
|
22
|
+
|
|
23
|
+
// ...
|
|
24
|
+
```
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# `shopify.ensureInstalledOnShop`
|
|
2
|
+
|
|
3
|
+
This function creates an Express middleware that ensures any request to that endpoint belongs to a shop that has already installed the app. You should call this middleware in any endpoint that renders HTML, if your app is embedded.
|
|
4
|
+
|
|
5
|
+
You don't need to use it if your app is not embedded, because you can use `validateAuthenticatedSession` on any non-embedded request.
|
|
6
|
+
If you call this middleware on a non-embedded app, it will behave like `validateAuthenticatedSession` instead.
|
|
7
|
+
|
|
8
|
+
## Example
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
const app = express();
|
|
12
|
+
|
|
13
|
+
// If the app wasn't installed in the shop, Shopify will prompt the merchant for permissions.
|
|
14
|
+
app.use('/', shopify.ensureInstalledOnShop(), (req, res) => {
|
|
15
|
+
res.send('Hello world!');
|
|
16
|
+
});
|
|
17
|
+
```
|
package/packages/shopify-app-express/docs/reference/migrating-app-v6-api-lib-to-express-lib.md
ADDED
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
# Instructions to migrate an app based on v6 API library to use this Express library
|
|
2
|
+
|
|
3
|
+
If you have an Express app that has been migrated to use version 6 of the `@shopify/shopify-api` library, this guide will show how to migrate to using this Express library.
|
|
4
|
+
|
|
5
|
+
> **Note** This guide uses Shopify's node app template to demonstate the migration steps. Your app will likely have additional functionality that will need similar migration.
|
|
6
|
+
|
|
7
|
+
> **Note** If you wish to practice this migration prior to applying it to your own app, create an app with one of the following commands, based on your package manager preference:
|
|
8
|
+
>
|
|
9
|
+
> ```shell
|
|
10
|
+
> yarn create @shopify/app --template https://github.com/Shopify/shopify-app-template-node#cli_three_api_six
|
|
11
|
+
> # or
|
|
12
|
+
> npm init @shopify/app@latest -- --template https://github.com/Shopify/shopify-app-template-node#cli_three_api_six
|
|
13
|
+
> # or
|
|
14
|
+
> pnpm create @shopify/app@latest --template https://github.com/Shopify/shopify-app-template-node#cli_three_api_six
|
|
15
|
+
> ```
|
|
16
|
+
|
|
17
|
+
## Steps
|
|
18
|
+
|
|
19
|
+
### 1. Change into the `web` directory
|
|
20
|
+
|
|
21
|
+
This is root directory of where most of the changes will occur.
|
|
22
|
+
|
|
23
|
+
```shell
|
|
24
|
+
cd web
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### 2. Update the project to use `v1` of the `@shopify/shopify-app-express` package
|
|
28
|
+
|
|
29
|
+
```shell
|
|
30
|
+
yarn remove @shopify/shopify-api cookie-parser express
|
|
31
|
+
yarn add @shopify/shopify-app-express
|
|
32
|
+
# or
|
|
33
|
+
npm uninstall @shopify/shopify-api cookie-parser express
|
|
34
|
+
npm install @shopify/shopify-app-express
|
|
35
|
+
# or
|
|
36
|
+
pnpm uninstall @shopify/shopify-api cookie-parser express
|
|
37
|
+
pnpm install @shopify/shopify-app-express
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### 3. Update the `gdpr.js` file
|
|
41
|
+
|
|
42
|
+
This file needs to be updated to export a structure of webhook handlers that can then be passed to the Shopify Express app object. The comments have been removed from the code below for brevity.
|
|
43
|
+
|
|
44
|
+
```diff
|
|
45
|
+
import { DeliveryMethod } from "@shopify/shopify-api";
|
|
46
|
+
-import shopify from "./shopify.js";
|
|
47
|
+
|
|
48
|
+
-export async function setupGDPRWebHooks(path) {
|
|
49
|
+
+export default {
|
|
50
|
+
- await shopify.webhooks.addHandlers({
|
|
51
|
+
- CUSTOMERS_DATA_REQUEST: {
|
|
52
|
+
- deliveryMethod: DeliveryMethod.Http,
|
|
53
|
+
- callbackUrl: path,
|
|
54
|
+
- callback: async (topic, shop, body, webhookId) => {
|
|
55
|
+
- const payload = JSON.parse(body);
|
|
56
|
+
- },
|
|
57
|
+
+ CUSTOMERS_DATA_REQUEST: {
|
|
58
|
+
+ deliveryMethod: DeliveryMethod.Http,
|
|
59
|
+
+ callbackUrl: "/api/webhooks",
|
|
60
|
+
+ callback: async (topic, shop, body, webhookId) => {
|
|
61
|
+
+ const payload = JSON.parse(body);
|
|
62
|
+
},
|
|
63
|
+
- });
|
|
64
|
+
+ },
|
|
65
|
+
|
|
66
|
+
- await shopify.webhooks.addHandlers({
|
|
67
|
+
- CUSTOMERS_REDACT: {
|
|
68
|
+
- deliveryMethod: DeliveryMethod.Http,
|
|
69
|
+
- callbackUrl: path,
|
|
70
|
+
- callback: async (topic, shop, body, webhookId) => {
|
|
71
|
+
- const payload = JSON.parse(body);
|
|
72
|
+
- },
|
|
73
|
+
+ CUSTOMERS_REDACT: {
|
|
74
|
+
+ deliveryMethod: DeliveryMethod.Http,
|
|
75
|
+
+ callbackUrl: "/api/webhooks",
|
|
76
|
+
+ callback: async (topic, shop, body, webhookId) => {
|
|
77
|
+
+ const payload = JSON.parse(body);
|
|
78
|
+
},
|
|
79
|
+
- });
|
|
80
|
+
+ },
|
|
81
|
+
|
|
82
|
+
- await shopify.webhooks.addHandlers({
|
|
83
|
+
- SHOP_REDACT: {
|
|
84
|
+
- deliveryMethod: DeliveryMethod.Http,
|
|
85
|
+
- callbackUrl: path,
|
|
86
|
+
- callback: async (topic, shop, body, webhookId) => {
|
|
87
|
+
- const payload = JSON.parse(body);
|
|
88
|
+
- },
|
|
89
|
+
+ SHOP_REDACT: {
|
|
90
|
+
+ deliveryMethod: DeliveryMethod.Http,
|
|
91
|
+
+ callbackUrl: "/api/webhooks",
|
|
92
|
+
+ callback: async (topic, shop, body, webhookId) => {
|
|
93
|
+
+ const payload = JSON.parse(body);
|
|
94
|
+
},
|
|
95
|
+
- });
|
|
96
|
+
-}
|
|
97
|
+
+ },
|
|
98
|
+
+};
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### 4. Update the `shopify.js` file
|
|
102
|
+
|
|
103
|
+
When using the Express library, the Shopify API library will be available via the Shopify Express object. The Express object also requires an implementation of `SessionStorage` to manage the storage of sessions on behalf of the application.
|
|
104
|
+
|
|
105
|
+
```diff
|
|
106
|
+
-import "@shopify/shopify-api/adapters/node";
|
|
107
|
+
-import { shopifyApi, BillingInterval, LATEST_API_VERSION } from "@shopify/shopify-api";
|
|
108
|
+
+import { BillingInterval, LATEST_API_VERSION } from "@shopify/shopify-api";
|
|
109
|
+
+import { shopifyApp } from "@shopify/shopify-app-express";
|
|
110
|
+
+import { SQLiteSessionStorage } from "@shopify/shopify-app-session-storage-sqlite";
|
|
111
|
+
let { restResources } = await import(
|
|
112
|
+
`@shopify/shopify-api/rest/admin/${LATEST_API_VERSION}`
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
+const DB_PATH = `${process.cwd()}/database.sqlite`;
|
|
116
|
+
|
|
117
|
+
// The transactions with Shopify will always be marked as test transactions, unless NODE_ENV is production.
|
|
118
|
+
// See the ensureBilling helper to learn more about billing in this template.
|
|
119
|
+
const billingConfig = {
|
|
120
|
+
"My Shopify One-Time Charge": {
|
|
121
|
+
// This is an example configuration that would do a one-time charge for $5 (only USD is currently supported)
|
|
122
|
+
amount: 5.0,
|
|
123
|
+
currencyCode: "USD",
|
|
124
|
+
interval: BillingInterval.OneTime,
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
-const apiConfig = {
|
|
129
|
+
- apiKey: process.env.SHOPIFY_API_KEY,
|
|
130
|
+
- apiSecretKey: process.env.SHOPIFY_API_SECRET,
|
|
131
|
+
- scopes: process.env.SCOPES.split(","),
|
|
132
|
+
- hostName: process.env.HOST.replace(/https?:\/\//, ""),
|
|
133
|
+
- hostScheme: process.env.HOST.split("://")[0],
|
|
134
|
+
- apiVersion: LATEST_API_VERSION,
|
|
135
|
+
- isEmbeddedApp: true,
|
|
136
|
+
- ...(process.env.SHOP_CUSTOM_DOMAIN && {
|
|
137
|
+
- customShopDomains: [process.env.SHOP_CUSTOM_DOMAIN],
|
|
138
|
+
- }),
|
|
139
|
+
- billing: undefined, // or replace with billingConfig above to enable example billing
|
|
140
|
+
- restResources,
|
|
141
|
+
-};
|
|
142
|
+
-
|
|
143
|
+
-const shopify = shopifyApi(apiConfig);
|
|
144
|
+
+const shopify = shopifyApp({
|
|
145
|
+
+ api: {
|
|
146
|
+
+ apiVersion: LATEST_API_VERSION,
|
|
147
|
+
+ billingConfig: undefined, // or replace with billingConfig above to enable example billing
|
|
148
|
+
+ restResources,
|
|
149
|
+
+ },
|
|
150
|
+
+ auth: {
|
|
151
|
+
+ path: "/api/auth",
|
|
152
|
+
+ callbackPath: "/api/auth/callback",
|
|
153
|
+
+ },
|
|
154
|
+
+ webhooks: {
|
|
155
|
+
+ path: "/api/webhooks",
|
|
156
|
+
+ },
|
|
157
|
+
+ // This should be replaced with your preferred storage strategy
|
|
158
|
+
+ sessionStorage: new SQLiteSessionStorage(DB_PATH),
|
|
159
|
+
+});
|
|
160
|
+
|
|
161
|
+
export default shopify;
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
> **Note** All the other API configuration values will default to
|
|
166
|
+
>
|
|
167
|
+
> ```ts
|
|
168
|
+
> {
|
|
169
|
+
> apiKey: process.env.SHOPIFY_API_KEY,
|
|
170
|
+
> apiSecretKey: process.env.SHOPIFY_API_SECRET,
|
|
171
|
+
> scopes: process.env.SCOPES.split(","),
|
|
172
|
+
> hostName: process.env.HOST.replace(/https?:\/\//, ""),
|
|
173
|
+
> hostScheme: process.env.HOST.split("://")[0],
|
|
174
|
+
> isEmbeddedApp: true,
|
|
175
|
+
> }
|
|
176
|
+
> ```
|
|
177
|
+
|
|
178
|
+
### 5. Move the `helpers/product-creater.js` file up one level ...
|
|
179
|
+
|
|
180
|
+
Move the file from the `helpers` directory to the `web` directory. Assuming your terminal is in the `web` directory:
|
|
181
|
+
|
|
182
|
+
```shell
|
|
183
|
+
# Unix OS, e.g., macOS, Linux, etc.
|
|
184
|
+
mv helpers/product-creator.js .
|
|
185
|
+
# Windows
|
|
186
|
+
move helpers\product-creator.js .
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### 6. ... and update it to use the `shopify` Express instance
|
|
190
|
+
|
|
191
|
+
Note that the `ADJECTIVES` and `NOUN` constants remain the same but have been collapsed/hidden below for brevity.
|
|
192
|
+
|
|
193
|
+
```diff
|
|
194
|
+
import { GraphqlQueryError } from "@shopify/shopify-api";
|
|
195
|
+
-import shopify from "../shopify.js";
|
|
196
|
+
+import shopify from "./shopify.js";
|
|
197
|
+
|
|
198
|
+
const ADJECTIVES = [ ...
|
|
199
|
+
];
|
|
200
|
+
|
|
201
|
+
const NOUNS = [ ...
|
|
202
|
+
];
|
|
203
|
+
|
|
204
|
+
export const DEFAULT_PRODUCTS_COUNT = 5;
|
|
205
|
+
const CREATE_PRODUCTS_MUTATION = `
|
|
206
|
+
mutation populateProduct($input: ProductInput!) {
|
|
207
|
+
productCreate(input: $input) {
|
|
208
|
+
product {
|
|
209
|
+
id
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
`;
|
|
214
|
+
|
|
215
|
+
export default async function productCreator(
|
|
216
|
+
session,
|
|
217
|
+
count = DEFAULT_PRODUCTS_COUNT
|
|
218
|
+
) {
|
|
219
|
+
- const client = new shopify.clients.Graphql({ session });
|
|
220
|
+
+ const client = new shopify.api.clients.Graphql({ session });
|
|
221
|
+
|
|
222
|
+
try {
|
|
223
|
+
for (let i = 0; i < count; i++) {
|
|
224
|
+
await client.query({
|
|
225
|
+
data: {
|
|
226
|
+
query: CREATE_PRODUCTS_MUTATION,
|
|
227
|
+
variables: {
|
|
228
|
+
input: {
|
|
229
|
+
title: `${randomTitle()}`,
|
|
230
|
+
variants: [{ price: randomPrice() }],
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
} catch (error) {
|
|
237
|
+
if (error instanceof GraphqlQueryError) {
|
|
238
|
+
throw new Error(
|
|
239
|
+
`${error.message}\n${JSON.stringify(error.response, null, 2)}`
|
|
240
|
+
);
|
|
241
|
+
} else {
|
|
242
|
+
throw error;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function randomTitle() {
|
|
248
|
+
const adjective = ADJECTIVES[Math.floor(Math.random() * ADJECTIVES.length)];
|
|
249
|
+
const noun = NOUNS[Math.floor(Math.random() * NOUNS.length)];
|
|
250
|
+
return `${adjective} ${noun}`;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function randomPrice() {
|
|
254
|
+
return Math.round((Math.random() * 10 + Number.EPSILON) * 100) / 100;
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### 7. Remove unused files
|
|
259
|
+
|
|
260
|
+
The following files can now be deleted, as their functionality has now been incorporated into the Express library.
|
|
261
|
+
|
|
262
|
+
> **Note** These paths are relative to the `web` directory
|
|
263
|
+
|
|
264
|
+
| Filename | Note |
|
|
265
|
+
| ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
266
|
+
| `sqlite-session-storage.js` | An instance of `SQLiteSessionStorage` is passed as a configuration item to `shopifyApp` in `shopify.js`, so that the Shopify Express library can manage session storage directly. |
|
|
267
|
+
| `app_installations.js` | The Shopify Express library uses the session storage to internally track app installations. |
|
|
268
|
+
| `helpers/ensure-billing.js` | :warning: maybe this needs to be retained as an example middleware? |
|
|
269
|
+
| `helpers/redirect-to-auth.js` | This functionality is now incorporated into the Shopify Express library. |
|
|
270
|
+
| `helpers/return-top-level-redirection.js` | This functionality is now incorporated into the Shopify Express library. |
|
|
271
|
+
| `middleware/auth.js` | This functionality is now incorporated into the Shopify Express library. |
|
|
272
|
+
| `middleware/verify-request.js` | This functionality is now incorporated into the Shopify Express library. |
|
|
273
|
+
|
|
274
|
+
### 8. Update the `index.js` file
|
|
275
|
+
|
|
276
|
+
Replace the `index.js` file with the code below.
|
|
277
|
+
|
|
278
|
+
```ts
|
|
279
|
+
import {join} from 'path';
|
|
280
|
+
import {readFileSync} from 'fs';
|
|
281
|
+
import express from 'express';
|
|
282
|
+
import serveStatic from 'serve-static';
|
|
283
|
+
|
|
284
|
+
import shopify from './shopify.js';
|
|
285
|
+
import productCreator from './product-creator.js';
|
|
286
|
+
import GDPRWebhookHandlers from './gdpr.js';
|
|
287
|
+
|
|
288
|
+
const PORT = parseInt(process.env.BACKEND_PORT || process.env.PORT, 10);
|
|
289
|
+
|
|
290
|
+
const STATIC_PATH =
|
|
291
|
+
process.env.NODE_ENV === 'production'
|
|
292
|
+
? `${process.cwd()}/frontend/dist`
|
|
293
|
+
: `${process.cwd()}/frontend/`;
|
|
294
|
+
|
|
295
|
+
const app = express();
|
|
296
|
+
|
|
297
|
+
// Set up Shopify authentication and webhook handling
|
|
298
|
+
app.get(shopify.config.auth.path, shopify.auth.begin());
|
|
299
|
+
app.get(
|
|
300
|
+
shopify.config.auth.callbackPath,
|
|
301
|
+
shopify.auth.callback(),
|
|
302
|
+
shopify.redirectToShopifyOrAppRoot(),
|
|
303
|
+
);
|
|
304
|
+
app.post(
|
|
305
|
+
shopify.config.webhooks.path,
|
|
306
|
+
shopify.processWebhooks({webhookHandlers: GDPRWebhookHandlers}),
|
|
307
|
+
);
|
|
308
|
+
|
|
309
|
+
// All endpoints after this point will require an active session
|
|
310
|
+
app.use('/api/*', shopify.validateAuthenticatedSession());
|
|
311
|
+
|
|
312
|
+
app.use(express.json());
|
|
313
|
+
|
|
314
|
+
app.get('/api/products/count', async (_req, res) => {
|
|
315
|
+
const countData = await shopify.api.rest.Product.count({
|
|
316
|
+
session: res.locals.shopify.session,
|
|
317
|
+
});
|
|
318
|
+
res.status(200).send(countData);
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
app.get('/api/products/create', async (_req, res) => {
|
|
322
|
+
let status = 200;
|
|
323
|
+
let error = null;
|
|
324
|
+
|
|
325
|
+
try {
|
|
326
|
+
await productCreator(res.locals.shopify.session);
|
|
327
|
+
} catch (e) {
|
|
328
|
+
console.log(`Failed to process products/create: ${e.message}`);
|
|
329
|
+
status = 500;
|
|
330
|
+
error = e.message;
|
|
331
|
+
}
|
|
332
|
+
res.status(status).send({success: status === 200, error});
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
app.use(serveStatic(STATIC_PATH, {index: false}));
|
|
336
|
+
|
|
337
|
+
app.use('/*', shopify.ensureInstalledOnShop(), async (_req, res, _next) => {
|
|
338
|
+
return res
|
|
339
|
+
.status(200)
|
|
340
|
+
.set('Content-Type', 'text/html')
|
|
341
|
+
.send(readFileSync(join(STATIC_PATH, 'index.html')));
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
app.listen(PORT);
|
|
345
|
+
```
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# `shopify.processWebhooks()`
|
|
2
|
+
|
|
3
|
+
This function creates an Express middleware that processes webhook requests from Shopify, based on the given handlers.
|
|
4
|
+
|
|
5
|
+
It mounts the handlers onto the `shopify` object, and they're registered in `shopify.auth.callback` after we receive an access token to call the API.
|
|
6
|
+
|
|
7
|
+
This middleware will always respond to Shopify, even if there was an error while handling the webhook.
|
|
8
|
+
|
|
9
|
+
:exclamation: **Important**: Shopify always sends POST requests for webhooks.
|
|
10
|
+
Make sure you use this middleware on a `.post()` route.
|
|
11
|
+
|
|
12
|
+
## Parameters
|
|
13
|
+
|
|
14
|
+
### `webhookHandlers`
|
|
15
|
+
|
|
16
|
+
`{[topic: string]: WebhookHandler | WebhookHandler[]}`
|
|
17
|
+
|
|
18
|
+
Defines the webhooks your app will listen to, and how to handle them. See [the `@shopify/shopify-api` documentation](https://github.com/Shopify/shopify-api-js/blob/main/packages/shopify-api/docs/guides/webhooks.md) for the allowed values.
|
|
19
|
+
|
|
20
|
+
> **Note**: for HTTP webhook handlers, the `callbackUrl` value must match the route where you use this middleware.
|
|
21
|
+
|
|
22
|
+
## Example
|
|
23
|
+
|
|
24
|
+
The following example shows how to setup handlers for the mandatory GDPR webhooks.
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
const {DeliveryMethod} = require('@shopify/shopify-api');
|
|
28
|
+
|
|
29
|
+
const shopify = shopifyApp({
|
|
30
|
+
webhooks: {
|
|
31
|
+
path: '/webhooks',
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const webhookHandlers = {
|
|
36
|
+
CUSTOMERS_DATA_REQUEST: {
|
|
37
|
+
deliveryMethod: DeliveryMethod.Http,
|
|
38
|
+
callbackUrl: shopify.config.webhooks.path,
|
|
39
|
+
callback: async (topic, shop, body, webhookId, apiVersion) => {
|
|
40
|
+
const payload = JSON.parse(body);
|
|
41
|
+
// prepare customers data to send to customer
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
CUSTOMERS_REDACT: {
|
|
45
|
+
deliveryMethod: DeliveryMethod.Http,
|
|
46
|
+
callbackUrl: shopify.config.webhooks.path,
|
|
47
|
+
callback: async (topic, shop, body) => {
|
|
48
|
+
const payload = JSON.parse(body);
|
|
49
|
+
// remove customers data
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
SHOP_REDACT: {
|
|
53
|
+
deliveryMethod: DeliveryMethod.Http,
|
|
54
|
+
callbackUrl: shopify.config.webhooks.path,
|
|
55
|
+
callback: async (topic, shop, body, webhookId, apiVersion) => {
|
|
56
|
+
const payload = JSON.parse(body);
|
|
57
|
+
// remove shop data
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// This must be a .post() endpoint
|
|
63
|
+
app.post(
|
|
64
|
+
shopify.config.webhooks.path,
|
|
65
|
+
shopify.processWebhooks({webhookHandlers}),
|
|
66
|
+
);
|
|
67
|
+
```
|