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,246 @@
|
|
|
1
|
+
import {Session, Shopify, ShopifyRestResources} from '@shopify/shopify-api';
|
|
2
|
+
|
|
3
|
+
import type {JSONValue} from '../../types';
|
|
4
|
+
import type {AdminApiContext} from '../../clients';
|
|
5
|
+
import type {FeatureEnabled, FutureFlagOptions} from '../../future/flags';
|
|
6
|
+
|
|
7
|
+
export interface RegisterWebhooksOptions {
|
|
8
|
+
/**
|
|
9
|
+
* The Shopify session used to register webhooks using the Admin API.
|
|
10
|
+
*/
|
|
11
|
+
session: Session;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface Context<Topics = string | number | symbol> {
|
|
15
|
+
/**
|
|
16
|
+
* The API version used for the webhook.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* <caption>Webhook API version.</caption>
|
|
20
|
+
* <description>Get the API version used for webhook request.</description>
|
|
21
|
+
* ```ts
|
|
22
|
+
* // /app/routes/webhooks.tsx
|
|
23
|
+
* import { ActionFunction } from "@remix-run/node";
|
|
24
|
+
* import { authenticate } from "../shopify.server";
|
|
25
|
+
*
|
|
26
|
+
* export const action: ActionFunction = async ({ request }) => {
|
|
27
|
+
* const { apiVersion } = await authenticate.webhook(request);
|
|
28
|
+
* return new Response();
|
|
29
|
+
* };
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
apiVersion: string;
|
|
33
|
+
/**
|
|
34
|
+
* The shop where the webhook was triggered.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* <caption>Webhook shop.</caption>
|
|
38
|
+
* <description>Get the shop that triggered a webhook.</description>
|
|
39
|
+
* ```ts
|
|
40
|
+
* // /app/routes/webhooks.tsx
|
|
41
|
+
* import { ActionFunction } from "@remix-run/node";
|
|
42
|
+
* import { authenticate } from "../shopify.server";
|
|
43
|
+
*
|
|
44
|
+
* export const action: ActionFunction = async ({ request }) => {
|
|
45
|
+
* const { shop } = await authenticate.webhook(request);
|
|
46
|
+
* return new Response();
|
|
47
|
+
* };
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
shop: string;
|
|
51
|
+
/**
|
|
52
|
+
* The topic of the webhook.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* <caption>Webhook topic.</caption>
|
|
56
|
+
* <description>Get the event topic for the webhook.</description>
|
|
57
|
+
* ```ts
|
|
58
|
+
* // /app/routes/webhooks.tsx
|
|
59
|
+
* import { ActionFunction } from "@remix-run/node";
|
|
60
|
+
* import { authenticate } from "../shopify.server";
|
|
61
|
+
*
|
|
62
|
+
* export const action: ActionFunction = async ({ request }) => {
|
|
63
|
+
* const { topic } = await authenticate.webhook(request);
|
|
64
|
+
*
|
|
65
|
+
* switch (topic) {
|
|
66
|
+
* case "APP_UNINSTALLED":
|
|
67
|
+
* // Do something when the app is uninstalled.
|
|
68
|
+
* break;
|
|
69
|
+
* }
|
|
70
|
+
*
|
|
71
|
+
* return new Response();
|
|
72
|
+
* };
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
topic: Topics;
|
|
76
|
+
/**
|
|
77
|
+
* A unique ID for the webhook. Useful to keep track of which events your app has already processed.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* <caption>Webhook ID.</caption>
|
|
81
|
+
* <description>Get the webhook ID.</description>
|
|
82
|
+
* ```ts
|
|
83
|
+
* // /app/routes/webhooks.tsx
|
|
84
|
+
* import { ActionFunction } from "@remix-run/node";
|
|
85
|
+
* import { authenticate } from "../shopify.server";
|
|
86
|
+
*
|
|
87
|
+
* export const action: ActionFunction = async ({ request }) => {
|
|
88
|
+
* const { webhookId } = await authenticate.webhook(request);
|
|
89
|
+
* return new Response();
|
|
90
|
+
* };
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
webhookId: string;
|
|
94
|
+
/**
|
|
95
|
+
* The payload from the webhook request.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* <caption>Webhook payload.</caption>
|
|
99
|
+
* <description>Get the request's POST payload.</description>
|
|
100
|
+
* ```ts
|
|
101
|
+
* // /app/routes/webhooks.tsx
|
|
102
|
+
* import { ActionFunction } from "@remix-run/node";
|
|
103
|
+
* import { authenticate } from "../shopify.server";
|
|
104
|
+
*
|
|
105
|
+
* export const action: ActionFunction = async ({ request }) => {
|
|
106
|
+
* const { payload } = await authenticate.webhook(request);
|
|
107
|
+
* return new Response();
|
|
108
|
+
* };
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
payload: JSONValue;
|
|
112
|
+
/**
|
|
113
|
+
* The sub-topic of the webhook. This is only available for certain webhooks.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* <caption>Webhook sub-topic.</caption>
|
|
117
|
+
* <description>Get the webhook sub-topic.</description>
|
|
118
|
+
* ```ts
|
|
119
|
+
* // /app/routes/webhooks.tsx
|
|
120
|
+
* import { ActionFunction } from "@remix-run/node";
|
|
121
|
+
* import { authenticate } from "../shopify.server";
|
|
122
|
+
*
|
|
123
|
+
* export const action: ActionFunction = async ({ request }) => {
|
|
124
|
+
* const { subTopic } = await authenticate.webhook(request);
|
|
125
|
+
* return new Response();
|
|
126
|
+
* };
|
|
127
|
+
* ```
|
|
128
|
+
*
|
|
129
|
+
*/
|
|
130
|
+
subTopic?: string;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export interface WebhookContextWithoutSession<Topics = string | number | symbol>
|
|
134
|
+
extends Context<Topics> {
|
|
135
|
+
session: undefined;
|
|
136
|
+
admin: undefined;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface LegacyWebhookAdminApiContext<
|
|
140
|
+
Resources extends ShopifyRestResources,
|
|
141
|
+
> {
|
|
142
|
+
/** A REST client. */
|
|
143
|
+
rest: InstanceType<Shopify['clients']['Rest']> & Resources;
|
|
144
|
+
/** A GraphQL client. */
|
|
145
|
+
graphql: InstanceType<Shopify['clients']['Graphql']>;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export type WebhookAdminContext<
|
|
149
|
+
Future extends FutureFlagOptions,
|
|
150
|
+
Resources extends ShopifyRestResources,
|
|
151
|
+
> =
|
|
152
|
+
FeatureEnabled<Future, 'v3_webhookAdminContext'> extends true
|
|
153
|
+
? AdminApiContext<Resources>
|
|
154
|
+
: LegacyWebhookAdminApiContext<Resources>;
|
|
155
|
+
|
|
156
|
+
export interface WebhookContextWithSession<
|
|
157
|
+
Future extends FutureFlagOptions,
|
|
158
|
+
Resources extends ShopifyRestResources,
|
|
159
|
+
Topics = string | number | symbol,
|
|
160
|
+
> extends Context<Topics> {
|
|
161
|
+
/**
|
|
162
|
+
* A session with an offline token for the shop.
|
|
163
|
+
*
|
|
164
|
+
* Returned only if there is a session for the shop.
|
|
165
|
+
*/
|
|
166
|
+
session: Session;
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* An admin context for the webhook.
|
|
170
|
+
*
|
|
171
|
+
* Returned only if there is a session for the shop.
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* <caption>[V3] Webhook admin context.</caption>
|
|
175
|
+
* <description>With the `v3_webhookAdminContext` future flag enabled, use the `admin` object in the context to interact with the Admin API.</description>
|
|
176
|
+
* ```ts
|
|
177
|
+
* // /app/routes/webhooks.tsx
|
|
178
|
+
* import { ActionFunctionArgs } from "@remix-run/node";
|
|
179
|
+
* import { authenticate } from "../shopify.server";
|
|
180
|
+
*
|
|
181
|
+
* export async function action({ request }: ActionFunctionArgs) {
|
|
182
|
+
* const { admin } = await authenticate.webhook(request);
|
|
183
|
+
*
|
|
184
|
+
* const response = await admin?.graphql(
|
|
185
|
+
* `#graphql
|
|
186
|
+
* mutation populateProduct($input: ProductInput!) {
|
|
187
|
+
* productCreate(input: $input) {
|
|
188
|
+
* product {
|
|
189
|
+
* id
|
|
190
|
+
* }
|
|
191
|
+
* }
|
|
192
|
+
* }`,
|
|
193
|
+
* { variables: { input: { title: "Product Name" } } }
|
|
194
|
+
* );
|
|
195
|
+
*
|
|
196
|
+
* const productData = await response.json();
|
|
197
|
+
* return json({ data: productData.data });
|
|
198
|
+
* }
|
|
199
|
+
* ```
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* <caption>Webhook admin context.</caption>
|
|
203
|
+
* <description>Use the `admin` object in the context to interact with the Admin API. This format will be removed in V3 of the package.</description>
|
|
204
|
+
* ```ts
|
|
205
|
+
* // /app/routes/webhooks.tsx
|
|
206
|
+
* import { json, ActionFunctionArgs } from "@remix-run/node";
|
|
207
|
+
* import { authenticate } from "../shopify.server";
|
|
208
|
+
*
|
|
209
|
+
* export async function action({ request }: ActionFunctionArgs) {
|
|
210
|
+
* const { admin } = await authenticate.webhook(request);
|
|
211
|
+
*
|
|
212
|
+
* const response = await admin?.graphql.query<any>({
|
|
213
|
+
* data: {
|
|
214
|
+
* query: `#graphql
|
|
215
|
+
* mutation populateProduct($input: ProductInput!) {
|
|
216
|
+
* productCreate(input: $input) {
|
|
217
|
+
* product {
|
|
218
|
+
* id
|
|
219
|
+
* }
|
|
220
|
+
* }
|
|
221
|
+
* }`,
|
|
222
|
+
* variables: { input: { title: "Product Name" } },
|
|
223
|
+
* },
|
|
224
|
+
* });
|
|
225
|
+
*
|
|
226
|
+
* const productData = response?.body.data;
|
|
227
|
+
* return json({ data: productData.data });
|
|
228
|
+
* }
|
|
229
|
+
* ```
|
|
230
|
+
*/
|
|
231
|
+
admin: WebhookAdminContext<Future, Resources>;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export type WebhookContext<
|
|
235
|
+
Future extends FutureFlagOptions,
|
|
236
|
+
Resources extends ShopifyRestResources,
|
|
237
|
+
Topics = string | number | symbol,
|
|
238
|
+
> =
|
|
239
|
+
| WebhookContextWithoutSession<Topics>
|
|
240
|
+
| WebhookContextWithSession<Future, Resources, Topics>;
|
|
241
|
+
|
|
242
|
+
export type AuthenticateWebhook<
|
|
243
|
+
Future extends FutureFlagOptions,
|
|
244
|
+
Resources extends ShopifyRestResources,
|
|
245
|
+
Topics = string | number | symbol,
|
|
246
|
+
> = (request: Request) => Promise<WebhookContext<Future, Resources, Topics>>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import {boundary} from '../../index';
|
|
4
|
+
|
|
5
|
+
describe('Error boundary', () => {
|
|
6
|
+
it('returns a string when handling an ErrorResponse', () => {
|
|
7
|
+
// WHEN
|
|
8
|
+
const result = boundary.error(new ErrorResponse());
|
|
9
|
+
|
|
10
|
+
// THEN
|
|
11
|
+
expect(result).toEqual(
|
|
12
|
+
<div dangerouslySetInnerHTML={{__html: 'Handling response'}} />,
|
|
13
|
+
);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('returns a string when handling an ErrorResponseImpl', () => {
|
|
17
|
+
// WHEN
|
|
18
|
+
const result = boundary.error(new ErrorResponseImpl());
|
|
19
|
+
|
|
20
|
+
// THEN
|
|
21
|
+
expect(result).toEqual(
|
|
22
|
+
<div dangerouslySetInnerHTML={{__html: 'Handling response'}} />,
|
|
23
|
+
);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('throws an error when handling an unknown error', () => {
|
|
27
|
+
// WHEN
|
|
28
|
+
const result = () => boundary.error(new Error());
|
|
29
|
+
|
|
30
|
+
// THEN
|
|
31
|
+
expect(result).toThrowError();
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
class ErrorResponse extends Error {}
|
|
36
|
+
class ErrorResponseImpl extends Error {}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import {boundary} from '../index';
|
|
2
|
+
import {shopifyApp} from '../../index';
|
|
3
|
+
import {testConfig} from '../../__test-helpers';
|
|
4
|
+
|
|
5
|
+
describe('Headers boundary', () => {
|
|
6
|
+
it('returns only error headers if error headers are present', () => {
|
|
7
|
+
// GIVEN
|
|
8
|
+
const shopify = shopifyApp(testConfig());
|
|
9
|
+
const headers = {
|
|
10
|
+
parentHeaders: new Headers([['parent', 'header']]),
|
|
11
|
+
loaderHeaders: new Headers([['loader', 'header']]),
|
|
12
|
+
actionHeaders: new Headers([['action', 'header']]),
|
|
13
|
+
errorHeaders: new Headers([['error', 'header']]),
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// WHEN
|
|
17
|
+
const result = boundary.headers(headers);
|
|
18
|
+
|
|
19
|
+
// THEN
|
|
20
|
+
expect(result.get('parent')).toBeNull();
|
|
21
|
+
expect(result.get('loader')).toBeNull();
|
|
22
|
+
expect(result.get('action')).toBeNull();
|
|
23
|
+
expect(result.get('error')).toEqual('header');
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('merges parent, loader & action headers if no error headers are present', () => {
|
|
27
|
+
// GIVEN
|
|
28
|
+
const shopify = shopifyApp(testConfig());
|
|
29
|
+
const headers = {
|
|
30
|
+
parentHeaders: new Headers([
|
|
31
|
+
['parent', 'header'],
|
|
32
|
+
['common', 'parent'],
|
|
33
|
+
]),
|
|
34
|
+
loaderHeaders: new Headers([
|
|
35
|
+
['loader', 'header'],
|
|
36
|
+
['common', 'loader'],
|
|
37
|
+
]),
|
|
38
|
+
actionHeaders: new Headers([
|
|
39
|
+
['action', 'header'],
|
|
40
|
+
['common', 'action'],
|
|
41
|
+
]),
|
|
42
|
+
errorHeaders: new Headers(),
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// WHEN
|
|
46
|
+
const result = boundary.headers(headers);
|
|
47
|
+
|
|
48
|
+
// THEN
|
|
49
|
+
expect(result.get('parent')).toEqual('header');
|
|
50
|
+
expect(result.get('loader')).toEqual('header');
|
|
51
|
+
expect(result.get('action')).toEqual('header');
|
|
52
|
+
expect(result.get('common')).toEqual('parent, loader, action');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('returns an empty headers object if no headers are present', () => {
|
|
56
|
+
// GIVEN
|
|
57
|
+
const shopify = shopifyApp(testConfig());
|
|
58
|
+
const headers = {};
|
|
59
|
+
|
|
60
|
+
// WHEN
|
|
61
|
+
const result = boundary.headers(headers as any);
|
|
62
|
+
|
|
63
|
+
// THEN
|
|
64
|
+
expect(result.entries()).toEqual(new Headers().entries());
|
|
65
|
+
});
|
|
66
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export function errorBoundary(error: any) {
|
|
2
|
+
if (
|
|
3
|
+
error.constructor.name === 'ErrorResponse' ||
|
|
4
|
+
error.constructor.name === 'ErrorResponseImpl'
|
|
5
|
+
) {
|
|
6
|
+
return (
|
|
7
|
+
<div
|
|
8
|
+
dangerouslySetInnerHTML={{__html: error.data || 'Handling response'}}
|
|
9
|
+
/>
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
throw error;
|
|
14
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {HeadersArgs} from '@remix-run/server-runtime';
|
|
2
|
+
|
|
3
|
+
export function headersBoundary(headers: HeadersArgs): Headers {
|
|
4
|
+
const {parentHeaders, loaderHeaders, actionHeaders, errorHeaders} = headers;
|
|
5
|
+
|
|
6
|
+
if (errorHeaders && Array.from(errorHeaders.entries()).length > 0) {
|
|
7
|
+
return errorHeaders;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
return new Headers([
|
|
11
|
+
...(parentHeaders ? Array.from(parentHeaders.entries()) : []),
|
|
12
|
+
...(loaderHeaders ? Array.from(loaderHeaders.entries()) : []),
|
|
13
|
+
...(actionHeaders ? Array.from(actionHeaders.entries()) : []),
|
|
14
|
+
]);
|
|
15
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {headersBoundary} from './headers';
|
|
2
|
+
import {errorBoundary} from './error';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A collection of functions that handle the necessary code for error boundaries in routes using authenticate.admin.
|
|
6
|
+
*/
|
|
7
|
+
export const boundary = {
|
|
8
|
+
/**
|
|
9
|
+
* A function that handles errors or thrown responses.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* <caption>Catching errors in a route</caption>
|
|
13
|
+
* ```ts
|
|
14
|
+
* // /app/routes/admin/widgets.ts
|
|
15
|
+
* import { boundary } from "@shopify/shopify-app-remix/server";
|
|
16
|
+
*
|
|
17
|
+
* export function ErrorBoundary() {
|
|
18
|
+
* return boundary.error(useRouteError());
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
error: errorBoundary,
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* A function that sets the appropriate document repsonse headers.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* <caption>Catching errors in a route</caption>
|
|
29
|
+
* ```ts
|
|
30
|
+
* // /app/routes/admin/widgets.ts
|
|
31
|
+
* import { boundary } from "@shopify/shopify-app-remix/server";
|
|
32
|
+
*
|
|
33
|
+
* export const headers = (headersArgs) => {
|
|
34
|
+
* return boundary.headers(headersArgs);
|
|
35
|
+
* };
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
headers: headersBoundary,
|
|
39
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {ReferenceEntityTemplateSchema} from '@shopify/generate-docs';
|
|
2
|
+
|
|
3
|
+
const data: ReferenceEntityTemplateSchema = {
|
|
4
|
+
name: 'Admin API',
|
|
5
|
+
description:
|
|
6
|
+
'Contains objects used to interact with the Admin API.' +
|
|
7
|
+
'\n\nThis object is returned as part of different contexts, such as [`admin`](/docs/api/shopify-app-remix/authenticate/admin), [`unauthenticated.admin`](/docs/api/shopify-app-remix/unauthenticated/unauthenticated-admin), and [`webhook`](/docs/api/shopify-app-remix/authenticate/webhook).',
|
|
8
|
+
category: 'APIs',
|
|
9
|
+
type: 'object',
|
|
10
|
+
isVisualComponent: false,
|
|
11
|
+
definitions: [
|
|
12
|
+
{
|
|
13
|
+
title: 'admin',
|
|
14
|
+
description:
|
|
15
|
+
'Provides utilities that apps can use to make requests to the Admin API.',
|
|
16
|
+
type: 'AdminApiContext',
|
|
17
|
+
},
|
|
18
|
+
],
|
|
19
|
+
jsDocTypeExamples: ['AdminApiContext'],
|
|
20
|
+
related: [
|
|
21
|
+
{
|
|
22
|
+
name: 'Authenticated context',
|
|
23
|
+
subtitle: 'Authenticate requests from Shopify Admin.',
|
|
24
|
+
url: '/docs/api/shopify-app-remix/authenticate/admin',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: 'Unauthenticated context',
|
|
28
|
+
subtitle: 'Interact with the Admin API on non-Shopify requests.',
|
|
29
|
+
url: '/docs/api/shopify-app-remix/unauthenticated/unauthenticated-admin',
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export default data;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import {Session, ShopifyRestResources} from '@shopify/shopify-api';
|
|
2
|
+
|
|
3
|
+
import {BasicParams} from '../../types';
|
|
4
|
+
|
|
5
|
+
import {graphqlClientFactory} from './graphql';
|
|
6
|
+
import {restClientFactory} from './rest';
|
|
7
|
+
import type {AdminApiContext} from './types';
|
|
8
|
+
|
|
9
|
+
interface RestClientOptions {
|
|
10
|
+
params: BasicParams;
|
|
11
|
+
session: Session;
|
|
12
|
+
handleClientError?: (error: any) => Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function adminClientFactory<
|
|
16
|
+
Resources extends ShopifyRestResources = ShopifyRestResources,
|
|
17
|
+
>({
|
|
18
|
+
params,
|
|
19
|
+
handleClientError,
|
|
20
|
+
session,
|
|
21
|
+
}: RestClientOptions): AdminApiContext<Resources> {
|
|
22
|
+
return {
|
|
23
|
+
rest: restClientFactory<Resources>({
|
|
24
|
+
params,
|
|
25
|
+
session,
|
|
26
|
+
handleClientError,
|
|
27
|
+
}),
|
|
28
|
+
graphql: graphqlClientFactory({params, session, handleClientError}),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {AdminOperations} from '@shopify/admin-api-client';
|
|
2
|
+
|
|
3
|
+
import {GraphQLClient} from '../types';
|
|
4
|
+
|
|
5
|
+
import {AdminClientOptions} from './types';
|
|
6
|
+
|
|
7
|
+
// eslint-disable-next-line no-warning-comments
|
|
8
|
+
// TODO: This is actually just a call through to the Shopify API client, but with a different API. We should eventually
|
|
9
|
+
// move this over to the library layer. While doing that, we should also allow the apiVersion to be passed into the REST
|
|
10
|
+
// client request calls.
|
|
11
|
+
export function graphqlClientFactory({
|
|
12
|
+
params,
|
|
13
|
+
handleClientError,
|
|
14
|
+
session,
|
|
15
|
+
}: AdminClientOptions): GraphQLClient<AdminOperations> {
|
|
16
|
+
return async function query(operation, options) {
|
|
17
|
+
const client = new params.api.clients.Graphql({
|
|
18
|
+
session,
|
|
19
|
+
apiVersion: options?.apiVersion,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
// We convert the incoming response to a Response object to bring this client closer to the Remix client.
|
|
24
|
+
const apiResponse = await client.request(operation, {
|
|
25
|
+
variables: options?.variables,
|
|
26
|
+
retries: options?.tries ? options.tries - 1 : 0,
|
|
27
|
+
headers: options?.headers,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
return new Response(JSON.stringify(apiResponse));
|
|
31
|
+
} catch (error) {
|
|
32
|
+
if (handleClientError) {
|
|
33
|
+
throw await handleClientError({error, params, session});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DeleteRequestParams,
|
|
3
|
+
GetRequestParams,
|
|
4
|
+
PostRequestParams,
|
|
5
|
+
PutRequestParams,
|
|
6
|
+
RequestParams,
|
|
7
|
+
Session,
|
|
8
|
+
Shopify,
|
|
9
|
+
ShopifyRestResources,
|
|
10
|
+
} from '@shopify/shopify-api';
|
|
11
|
+
|
|
12
|
+
import type {AdminClientOptions} from './types';
|
|
13
|
+
|
|
14
|
+
export type RestClientWithResources<Resources extends ShopifyRestResources> =
|
|
15
|
+
RemixRestClient & {resources: Resources};
|
|
16
|
+
|
|
17
|
+
export function restClientFactory<
|
|
18
|
+
Resources extends ShopifyRestResources = ShopifyRestResources,
|
|
19
|
+
>({
|
|
20
|
+
params,
|
|
21
|
+
handleClientError,
|
|
22
|
+
session,
|
|
23
|
+
}: AdminClientOptions): RestClientWithResources<Resources> {
|
|
24
|
+
const {api} = params;
|
|
25
|
+
const client = new RemixRestClient({
|
|
26
|
+
params,
|
|
27
|
+
handleClientError,
|
|
28
|
+
session,
|
|
29
|
+
}) as RestClientWithResources<Resources>;
|
|
30
|
+
|
|
31
|
+
if (api.rest) {
|
|
32
|
+
client.resources = {} as Resources;
|
|
33
|
+
|
|
34
|
+
const RestResourceClient = restResourceClientFactory({
|
|
35
|
+
params,
|
|
36
|
+
handleClientError,
|
|
37
|
+
session,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
Object.entries(api.rest).forEach(([name, resource]) => {
|
|
41
|
+
class RemixResource extends resource {
|
|
42
|
+
public static Client = RestResourceClient;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
Reflect.defineProperty(RemixResource, 'name', {
|
|
46
|
+
value: name,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
Reflect.set(client.resources, name, RemixResource);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return client;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
class RemixRestClient {
|
|
57
|
+
public session: Session;
|
|
58
|
+
private params: AdminClientOptions['params'];
|
|
59
|
+
private handleClientError: AdminClientOptions['handleClientError'];
|
|
60
|
+
|
|
61
|
+
constructor({params, session, handleClientError}: AdminClientOptions) {
|
|
62
|
+
this.params = params;
|
|
63
|
+
this.handleClientError = handleClientError;
|
|
64
|
+
this.session = session;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Performs a GET request on the given path.
|
|
69
|
+
*/
|
|
70
|
+
public async get(params: GetRequestParams) {
|
|
71
|
+
return this.makeRequest({
|
|
72
|
+
method: 'GET' as RequestParams['method'],
|
|
73
|
+
...params,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Performs a POST request on the given path.
|
|
79
|
+
*/
|
|
80
|
+
public async post(params: PostRequestParams) {
|
|
81
|
+
return this.makeRequest({
|
|
82
|
+
method: 'POST' as RequestParams['method'],
|
|
83
|
+
...params,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Performs a PUT request on the given path.
|
|
89
|
+
*/
|
|
90
|
+
public async put(params: PutRequestParams) {
|
|
91
|
+
return this.makeRequest({
|
|
92
|
+
method: 'PUT' as RequestParams['method'],
|
|
93
|
+
...params,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Performs a DELETE request on the given path.
|
|
99
|
+
*/
|
|
100
|
+
public async delete(params: DeleteRequestParams) {
|
|
101
|
+
return this.makeRequest({
|
|
102
|
+
method: 'DELETE' as RequestParams['method'],
|
|
103
|
+
...params,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
protected async makeRequest(params: RequestParams): Promise<Response> {
|
|
108
|
+
const originalClient = new this.params.api.clients.Rest({
|
|
109
|
+
session: this.session,
|
|
110
|
+
});
|
|
111
|
+
const originalRequest = Reflect.get(originalClient, 'request');
|
|
112
|
+
|
|
113
|
+
try {
|
|
114
|
+
const apiResponse = await originalRequest.call(originalClient, params);
|
|
115
|
+
|
|
116
|
+
// We use a separate client for REST requests and REST resources because we want to override the API library
|
|
117
|
+
// client class to return a Response object instead.
|
|
118
|
+
return new Response(JSON.stringify(apiResponse.body), {
|
|
119
|
+
headers: apiResponse.headers,
|
|
120
|
+
});
|
|
121
|
+
} catch (error) {
|
|
122
|
+
if (this.handleClientError) {
|
|
123
|
+
throw await this.handleClientError({
|
|
124
|
+
error,
|
|
125
|
+
session: this.session,
|
|
126
|
+
params: this.params,
|
|
127
|
+
});
|
|
128
|
+
} else throw new Error(error);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function restResourceClientFactory({
|
|
134
|
+
params,
|
|
135
|
+
handleClientError,
|
|
136
|
+
session,
|
|
137
|
+
}: AdminClientOptions): Shopify['clients']['Rest'] {
|
|
138
|
+
const {api} = params;
|
|
139
|
+
|
|
140
|
+
const ApiClient = api.clients.Rest;
|
|
141
|
+
return class RestResourceClient extends ApiClient {
|
|
142
|
+
protected async request(requestParams: RequestParams) {
|
|
143
|
+
const originalClient = new api.clients.Rest({session});
|
|
144
|
+
const originalRequest = Reflect.get(originalClient, 'request');
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
// We just call through to the API library client, and handle the error response here, so that data parsing
|
|
148
|
+
// behaves the same way.
|
|
149
|
+
return await originalRequest.call(originalClient, requestParams);
|
|
150
|
+
} catch (error) {
|
|
151
|
+
if (handleClientError) {
|
|
152
|
+
throw await handleClientError({error, params, session});
|
|
153
|
+
} else throw new Error(error);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
}
|