From aa9e8a96785447803b14f839b7196408b85e95b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20G=C3=B3ral?= Date: Mon, 9 Dec 2024 14:44:43 +0700 Subject: [PATCH] feat: add `cookieOptions` option to config (#1557) --- .changeset/ninety-parrots-mate.md | 25 ++++++ packages/api-client/package.json | 1 + packages/api-client/src/index.server.ts | 20 +++-- packages/api-client/src/types/setup.ts | 2 + yarn.lock | 103 +++++++++++++++++------- 5 files changed, 115 insertions(+), 36 deletions(-) create mode 100644 .changeset/ninety-parrots-mate.md diff --git a/.changeset/ninety-parrots-mate.md b/.changeset/ninety-parrots-mate.md new file mode 100644 index 000000000..20b4ec65f --- /dev/null +++ b/.changeset/ninety-parrots-mate.md @@ -0,0 +1,25 @@ +--- +"@vue-storefront/magento-api": minor +--- + +**[ADDED]** `cookieOptions` config. This option allows you to customize the cookie options which are set for a given cookie name. + +Example: +``` +{ + integrations: { + magento: { + location: "@vue-storefront/magento-api/server", + configuration: { + // ... + cookieOptions: { + "vsf-customer": { + secure: process.env.NODE_ENV === 'production', + sameSite: process.env.NODE_ENV === 'production' ? 'none' : 'strict', + } + } + }, + }, + }, +} +``` diff --git a/packages/api-client/package.json b/packages/api-client/package.json index a83376139..63bc5c541 100644 --- a/packages/api-client/package.json +++ b/packages/api-client/package.json @@ -38,6 +38,7 @@ "@graphql-codegen/typescript-operations": "^2.2.3", "@graphql-tools/utils": "^8.6.1", "@rollup/plugin-json": "^6.0.0", + "@types/express": "^4.17.17", "@types/graphql": "^14.5.0", "@types/isomorphic-fetch": "^0.0.36", "cross-fetch": "^3.1.5", diff --git a/packages/api-client/src/index.server.ts b/packages/api-client/src/index.server.ts index 55b7b265f..aef5c0fc9 100644 --- a/packages/api-client/src/index.server.ts +++ b/packages/api-client/src/index.server.ts @@ -1,10 +1,10 @@ /* istanbul ignore file */ import { ApiClientExtension, apiClientFactory } from "@vue-storefront/middleware"; import * as api from "./api"; -import { ClientInstance, Config } from "./types/setup"; -import { createMagentoConnection } from "./helpers/magentoLink"; import { defaultSettings } from "./helpers/apiClient/defaultSettings"; +import { createMagentoConnection } from "./helpers/magentoLink"; import { apolloClientFactory } from "./helpers/magentoLink/graphQl"; +import { ClientInstance, Config } from "./types/setup"; const buildConfig = (settings: Config) => ({ @@ -65,12 +65,16 @@ const onCreate = (settings: Config): { config: Config; client: ClientInstance } const tokenExtension: ApiClientExtension = { name: "tokenExtension", hooks: (req, res) => ({ - beforeCreate: ({ configuration }) => { + beforeCreate: ({ configuration }: { configuration: Config }) => { const cartCookieName: string = configuration.cookies?.cartCookieName || defaultSettings.cookies.cartCookieName; const customerCookieName: string = configuration.cookies?.customerCookieName || defaultSettings.cookies.customerCookieName; const storeCookieName: string = configuration.cookies?.storeCookieName || defaultSettings.cookies.storeCookieName; const currencyCookieName: string = configuration.cookies?.currencyCookieName || defaultSettings.cookies.currencyCookieName; + function setCookie(name: string, value: string) { + res.cookie(name, value, configuration.cookieOptions?.[name]); + } + return { ...configuration, state: { @@ -81,7 +85,7 @@ const tokenExtension: ApiClientExtension = { delete req.cookies[cartCookieName]; return; } - res.cookie(cartCookieName, JSON.stringify(id)); + setCookie(cartCookieName, JSON.stringify(id)); }, getCustomerToken: () => req.cookies[customerCookieName], setCustomerToken: (token) => { @@ -90,16 +94,16 @@ const tokenExtension: ApiClientExtension = { delete req.cookies[customerCookieName]; return; } - res.cookie(customerCookieName, JSON.stringify(token)); + setCookie(customerCookieName, JSON.stringify(token)); }, - getStore: () => configuration?.storeViewCode ?? req.cookies[storeCookieName], + getStore: () => (configuration as any)?.storeViewCode ?? req.cookies[storeCookieName], setStore: (id) => { if (!id) { // eslint-disable-next-line no-param-reassign delete req.cookies[storeCookieName]; return; } - res.cookie(storeCookieName, JSON.stringify(id)); + setCookie(storeCookieName, JSON.stringify(id)); }, getCurrency: () => req.cookies[currencyCookieName], setCurrency: (id) => { @@ -108,7 +112,7 @@ const tokenExtension: ApiClientExtension = { delete req.cookies[currencyCookieName]; return; } - res.cookie(currencyCookieName, JSON.stringify(id)); + setCookie(currencyCookieName, JSON.stringify(id)); }, }, }; diff --git a/packages/api-client/src/types/setup.ts b/packages/api-client/src/types/setup.ts index 29a2b7a54..cb245a094 100644 --- a/packages/api-client/src/types/setup.ts +++ b/packages/api-client/src/types/setup.ts @@ -1,5 +1,6 @@ import { ApolloClient, ApolloClientOptions } from "@apollo/client/core"; import { HttpOptions } from "@apollo/client/link/http/selectHttpOptionsAndBody"; +import type { CookieOptions } from "express"; import { Endpoints } from "./api"; export interface Storage { @@ -100,6 +101,7 @@ export interface Config extends ClientConfig { recaptcha: RecaptchaConfig; imageProvider: string; magentoBaseUrl: string; + cookieOptions?: Record; } export type ClientInstance = ApolloClient; diff --git a/yarn.lock b/yarn.lock index 31d762739..7231183ff 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1932,6 +1932,21 @@ dependencies: "@babel/types" "^7.20.7" +"@types/body-parser@*": + version "1.19.5" + resolved "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz#04ce9a3b677dc8bd681a17da1ab9835dc9d3ede4" + integrity sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg== + dependencies: + "@types/connect" "*" + "@types/node" "*" + +"@types/connect@*": + version "3.4.38" + resolved "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" + integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== + dependencies: + "@types/node" "*" + "@types/cookie@^0.4.1": version "0.4.1" resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" @@ -1947,6 +1962,26 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== +"@types/express-serve-static-core@^4.17.33": + version "4.19.6" + resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz#e01324c2a024ff367d92c66f48553ced0ab50267" + integrity sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + "@types/send" "*" + +"@types/express@^4.17.17": + version "4.17.21" + resolved "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" + integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.33" + "@types/qs" "*" + "@types/serve-static" "*" + "@types/graceful-fs@^4.1.3": version "4.1.6" resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.6.tgz#e14b2576a1c25026b7f02ede1de3b84c3a1efeae" @@ -1961,6 +1996,11 @@ dependencies: graphql "*" +"@types/http-errors@*": + version "2.0.4" + resolved "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f" + integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA== + "@types/is-ci@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/is-ci/-/is-ci-3.0.0.tgz#7e8910af6857601315592436f030aaa3ed9783c3" @@ -2030,6 +2070,11 @@ resolved "https://registry.yarnpkg.com/@types/k6/-/k6-0.37.1.tgz#e8db6269307ad73d4a6d710a5762818bb6149e85" integrity sha512-+FksZAlA+JnDYgOiElQa7+KlUGmzoElRNqRnGB4ICPHbBR6EIqcl81Tdhe1b9dT8M2QVTtQY7++FTHNpIQVFMg== +"@types/mime@^1": + version "1.3.5" + resolved "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" + integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== + "@types/minimist@^1.2.0": version "1.2.2" resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c" @@ -2060,6 +2105,16 @@ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.3.tgz#3e51a17e291d01d17d3fc61422015a933af7a08f" integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA== +"@types/qs@*": + version "6.9.17" + resolved "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz#fc560f60946d0aeff2f914eb41679659d3310e1a" + integrity sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ== + +"@types/range-parser@*": + version "1.2.7" + resolved "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" + integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== + "@types/resolve@1.17.1": version "1.17.1" resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6" @@ -2072,6 +2127,23 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a" integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw== +"@types/send@*": + version "0.17.4" + resolved "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a" + integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA== + dependencies: + "@types/mime" "^1" + "@types/node" "*" + +"@types/serve-static@*": + version "1.15.7" + resolved "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz#22174bbd74fb97fe303109738e9b5c2f3064f714" + integrity sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw== + dependencies: + "@types/http-errors" "*" + "@types/node" "*" + "@types/send" "*" + "@types/set-cookie-parser@^2.4.0": version "2.4.2" resolved "https://registry.yarnpkg.com/@types/set-cookie-parser/-/set-cookie-parser-2.4.2.tgz#b6a955219b54151bfebd4521170723df5e13caad" @@ -7164,16 +7236,7 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -7225,14 +7288,7 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -7835,7 +7891,7 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -7853,15 +7909,6 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"