@sanity/preview-url-secret
Advanced tools
Comparing version 2.0.7 to 2.1.0
@@ -9,2 +9,9 @@ <!-- markdownlint-disable --><!-- textlint-disable --> | ||
## [2.1.0](https://github.com/sanity-io/visual-editing/compare/preview-url-secret-v2.0.7...preview-url-secret-v2.1.0) (2025-01-10) | ||
### Features | ||
* add Vercel Protection Bypass tool ([#2479](https://github.com/sanity-io/visual-editing/issues/2479)) ([7e58143](https://github.com/sanity-io/visual-editing/commit/7e58143e3f70751dbd424641045b218d7e9085b4)) | ||
## [2.0.7](https://github.com/sanity-io/visual-editing/compare/preview-url-secret-v2.0.6...preview-url-secret-v2.0.7) (2025-01-09) | ||
@@ -11,0 +18,0 @@ |
@@ -22,2 +22,5 @@ /** @internal */ | ||
/** @internal */ | ||
export declare const fetchVercelProtectionBypassSecret: '*[_id == "sanity-preview-url-secret.vercel-protection-bypass" && _type == "sanity.vercelProtectionBypass"][0].secret' | ||
/** @internal */ | ||
export declare const isDev: boolean | ||
@@ -61,2 +64,20 @@ | ||
/** @internal */ | ||
export declare const urlSearchParamVercelProtectionBypass = 'x-vercel-protection-bypass' | ||
/** @internal */ | ||
export declare const urlSearchParamVercelSetBypassCookie = 'x-vercel-set-bypass-cookie' | ||
/** @internal */ | ||
export declare const vercelProtectionBypassSchemaId: 'sanity-preview-url-secret.vercel-protection-bypass' | ||
/** @internal */ | ||
export declare const vercelProtectionBypassSchemaType = 'sanity.vercelProtectionBypass' | ||
/** | ||
* @see https://vercel.com/docs/security/deployment-protection/methods-to-bypass-deployment-protection/protection-bypass-automation#advanced-configuration | ||
* @internal | ||
*/ | ||
export declare type VercelSetBypassCookieValue = 'samesitenone' | 'true' | ||
export {} |
@@ -1,2 +0,2 @@ | ||
const schemaType = "sanity.previewUrlSecret", schemaIdPrefix = "sanity-preview-url-secret", schemaIdSingleton = `${schemaIdPrefix}.share-access`, schemaTypeSingleton = "sanity.previewUrlShareAccess", apiVersion = "2023-11-09", urlSearchParamPreviewSecret = "sanity-preview-secret", urlSearchParamPreviewPathname = "sanity-preview-pathname", urlSearchParamPreviewPerspective = "sanity-preview-perspective", isDev = process.env.NODE_ENV === "development", SECRET_TTL = 60 * 60, fetchSecretQuery = ( | ||
const schemaType = "sanity.previewUrlSecret", schemaIdPrefix = "sanity-preview-url-secret", schemaIdSingleton = `${schemaIdPrefix}.share-access`, schemaTypeSingleton = "sanity.previewUrlShareAccess", apiVersion = "2023-11-09", urlSearchParamPreviewSecret = "sanity-preview-secret", urlSearchParamPreviewPathname = "sanity-preview-pathname", urlSearchParamPreviewPerspective = "sanity-preview-perspective", urlSearchParamVercelProtectionBypass = "x-vercel-protection-bypass", urlSearchParamVercelSetBypassCookie = "x-vercel-set-bypass-cookie", isDev = process.env.NODE_ENV === "development", SECRET_TTL = 60 * 60, fetchSecretQuery = ( | ||
/* groq */ | ||
@@ -21,2 +21,5 @@ `*[_type == "${schemaType}" && secret == $secret && dateTime(_updatedAt) > dateTime(now()) - ${SECRET_TTL}][0]{ | ||
`*[_type == "${schemaType}" && dateTime(_updatedAt) <= dateTime(now()) - ${SECRET_TTL}]` | ||
), vercelProtectionBypassSchemaType = "sanity.vercelProtectionBypass", vercelProtectionBypassSchemaId = `${schemaIdPrefix}.vercel-protection-bypass`, fetchVercelProtectionBypassSecret = ( | ||
/* groq */ | ||
`*[_id == "${vercelProtectionBypassSchemaId}" && _type == "${vercelProtectionBypassSchemaType}"][0].secret` | ||
), tag = "sanity.preview-url-secret", perspectiveCookieName = "sanity-preview-perspective"; | ||
@@ -30,2 +33,3 @@ export { | ||
fetchSharedAccessSecretQuery, | ||
fetchVercelProtectionBypassSecret, | ||
isDev, | ||
@@ -40,4 +44,8 @@ perspectiveCookieName, | ||
urlSearchParamPreviewPerspective, | ||
urlSearchParamPreviewSecret | ||
urlSearchParamPreviewSecret, | ||
urlSearchParamVercelProtectionBypass, | ||
urlSearchParamVercelSetBypassCookie, | ||
vercelProtectionBypassSchemaId, | ||
vercelProtectionBypassSchemaType | ||
}; | ||
//# sourceMappingURL=constants.js.map |
@@ -1,2 +0,2 @@ | ||
import { apiVersion, urlSearchParamPreviewSecret, urlSearchParamPreviewPerspective, urlSearchParamPreviewPathname, fetchSecretQuery, fetchSharedAccessSecretQuery, tag, isDev } from "./constants.js"; | ||
import { apiVersion, urlSearchParamPreviewSecret, urlSearchParamPreviewPerspective, urlSearchParamPreviewPathname, urlSearchParamVercelProtectionBypass, urlSearchParamVercelSetBypassCookie, fetchSecretQuery, fetchSharedAccessSecretQuery, tag, isDev } from "./constants.js"; | ||
function createClientWithConfig(client) { | ||
@@ -28,6 +28,9 @@ if (!client) | ||
const redirectUrl = new URL(unsafeRedirectTo, "http://localhost"); | ||
url.searchParams.has("x-vercel-protection-bypass") && (redirectUrl.searchParams.set( | ||
"x-vercel-protection-bypass", | ||
url.searchParams.get("x-vercel-protection-bypass") | ||
), redirectUrl.searchParams.set("x-vercel-set-bypass-cookie", "samesitenone")); | ||
url.searchParams.has(urlSearchParamVercelProtectionBypass) && (redirectUrl.searchParams.set( | ||
urlSearchParamVercelProtectionBypass, | ||
url.searchParams.get(urlSearchParamVercelProtectionBypass) | ||
), redirectUrl.searchParams.set( | ||
urlSearchParamVercelSetBypassCookie, | ||
"samesitenone" | ||
)); | ||
const { pathname, search, hash } = redirectUrl; | ||
@@ -34,0 +37,0 @@ redirectTo = `${pathname}${search}${hash}`; |
@@ -7,3 +7,3 @@ /** @alpha */ | ||
url: URL, | ||
secret: string, | ||
secret: string | null, | ||
redirectTo: string, | ||
@@ -10,0 +10,0 @@ perspective: string, |
@@ -1,5 +0,5 @@ | ||
import { urlSearchParamPreviewPathname, urlSearchParamPreviewSecret, urlSearchParamPreviewPerspective } from "./constants.js"; | ||
import { urlSearchParamPreviewPathname, urlSearchParamPreviewSecret, urlSearchParamPreviewPerspective, urlSearchParamVercelProtectionBypass, urlSearchParamVercelSetBypassCookie } from "./constants.js"; | ||
function withoutSecretSearchParams(url) { | ||
const newUrl = new URL(url), { searchParams } = newUrl; | ||
return searchParams.delete(urlSearchParamPreviewPathname), searchParams.delete(urlSearchParamPreviewSecret), searchParams.delete(urlSearchParamPreviewPerspective), newUrl; | ||
return searchParams.delete(urlSearchParamPreviewPathname), searchParams.delete(urlSearchParamPreviewSecret), searchParams.delete(urlSearchParamPreviewPerspective), searchParams.delete(urlSearchParamVercelProtectionBypass), searchParams.delete(urlSearchParamVercelSetBypassCookie), newUrl; | ||
} | ||
@@ -11,3 +11,3 @@ function hasSecretSearchParams(url) { | ||
const newUrl = new URL(url), { searchParams } = newUrl; | ||
return searchParams.set(urlSearchParamPreviewSecret, secret), searchParams.set(urlSearchParamPreviewPathname, redirectTo), searchParams.set(urlSearchParamPreviewPerspective, perspective), newUrl; | ||
return secret && (searchParams.set(urlSearchParamPreviewSecret, secret), searchParams.set(urlSearchParamPreviewPathname, redirectTo)), searchParams.set(urlSearchParamPreviewPerspective, perspective), newUrl; | ||
} | ||
@@ -14,0 +14,0 @@ export { |
{ | ||
"name": "@sanity/preview-url-secret", | ||
"version": "2.0.7", | ||
"version": "2.1.0", | ||
"homepage": "https://github.com/sanity-io/visual-editing/tree/main/packages/preview-url-secret#readme", | ||
@@ -60,2 +60,8 @@ "bugs": { | ||
}, | ||
"./toggle-vercel-protection-bypass": { | ||
"source": "./src/_exports/toggle-vercel-protection-bypass.ts", | ||
"import": "./dist/toggle-vercel-protection-bypass.js", | ||
"require": "./dist/toggle-vercel-protection-bypass.cjs", | ||
"default": "./dist/toggle-vercel-protection-bypass.js" | ||
}, | ||
"./without-secret-search-params": { | ||
@@ -92,2 +98,5 @@ "source": "./src/_exports/without-secret-search-params.ts", | ||
], | ||
"toggle-vercel-protection-bypass": [ | ||
"./dist/toggle-vercel-protection-bypass.d.ts" | ||
], | ||
"without-secret-search-params": [ | ||
@@ -119,3 +128,3 @@ "./dist/without-secret-search-params.d.ts" | ||
"@sanity/icons": "^3.5.7", | ||
"@sanity/pkg-utils": "6.13.1", | ||
"@sanity/pkg-utils": "6.13.4", | ||
"eslint": "^8.57.1", | ||
@@ -126,4 +135,4 @@ "sanity": "3.69.0", | ||
"@repo/eslint-config": "0.0.0", | ||
"@repo/prettier-config": "0.0.0", | ||
"@repo/package.config": "0.0.0" | ||
"@repo/package.config": "0.0.0", | ||
"@repo/prettier-config": "0.0.0" | ||
}, | ||
@@ -130,0 +139,0 @@ "peerDependencies": { |
@@ -5,2 +5,3 @@ import type { | ||
PreviewUrlSecretSchemaTypeSingleton, | ||
VercelProtectionBypassSchemaType, | ||
} from './types' | ||
@@ -34,2 +35,8 @@ | ||
/** @internal */ | ||
export const urlSearchParamVercelProtectionBypass = 'x-vercel-protection-bypass' | ||
/** @internal */ | ||
export const urlSearchParamVercelSetBypassCookie = 'x-vercel-set-bypass-cookie' | ||
/** @internal */ | ||
export const isDev = process.env.NODE_ENV === 'development' | ||
@@ -67,2 +74,13 @@ | ||
/** @internal */ | ||
export const vercelProtectionBypassSchemaType = | ||
'sanity.vercelProtectionBypass' satisfies VercelProtectionBypassSchemaType | ||
/** @internal */ | ||
export const vercelProtectionBypassSchemaId = `${schemaIdPrefix}.vercel-protection-bypass` as const | ||
/** @internal */ | ||
export const fetchVercelProtectionBypassSecret = | ||
/* groq */ `*[_id == "${vercelProtectionBypassSchemaId}" && _type == "${vercelProtectionBypassSchemaType}"][0].secret` as const | ||
/** | ||
@@ -76,1 +94,3 @@ * Used for tagging `client.fetch` queries | ||
export const perspectiveCookieName = 'sanity-preview-perspective' | ||
export type {VercelSetBypassCookieValue} from './types' |
@@ -5,4 +5,6 @@ import { | ||
urlSearchParamPreviewSecret, | ||
urlSearchParamVercelProtectionBypass, | ||
urlSearchParamVercelSetBypassCookie, | ||
} from './constants' | ||
import type {ParsedPreviewUrl} from './types' | ||
import type {ParsedPreviewUrl, VercelSetBypassCookieValue} from './types' | ||
@@ -25,9 +27,12 @@ /** | ||
// If there's a vercel bypass secret in the redirect URL, we forward it to the redirect to ensure it's set | ||
if (url.searchParams.has('x-vercel-protection-bypass')) { | ||
if (url.searchParams.has(urlSearchParamVercelProtectionBypass)) { | ||
redirectUrl.searchParams.set( | ||
'x-vercel-protection-bypass', | ||
url.searchParams.get('x-vercel-protection-bypass')!, | ||
urlSearchParamVercelProtectionBypass, | ||
url.searchParams.get(urlSearchParamVercelProtectionBypass)!, | ||
) | ||
// samesitenone is required since the request is from an iframe | ||
redirectUrl.searchParams.set('x-vercel-set-bypass-cookie', 'samesitenone') | ||
redirectUrl.searchParams.set( | ||
urlSearchParamVercelSetBypassCookie, | ||
'samesitenone' satisfies VercelSetBypassCookieValue, | ||
) | ||
} | ||
@@ -34,0 +39,0 @@ |
@@ -10,2 +10,5 @@ import type {ClientPerspective} from '@sanity/client' | ||
/** @internal */ | ||
export type VercelProtectionBypassSchemaType = `sanity.vercelProtectionBypass` | ||
/** @internal */ | ||
export type PreviewUrlSecretSchemaTypeSingleton = `sanity.previewUrlShareAccess` | ||
@@ -185,1 +188,7 @@ | ||
) => Promise<string> | ||
/** | ||
* @see https://vercel.com/docs/security/deployment-protection/methods-to-bypass-deployment-protection/protection-bypass-automation#advanced-configuration | ||
* @internal | ||
*/ | ||
export type VercelSetBypassCookieValue = 'samesitenone' | 'true' |
@@ -5,2 +5,4 @@ import { | ||
urlSearchParamPreviewSecret, | ||
urlSearchParamVercelProtectionBypass, | ||
urlSearchParamVercelSetBypassCookie, | ||
} from './constants' | ||
@@ -15,2 +17,4 @@ | ||
searchParams.delete(urlSearchParamPreviewPerspective) | ||
searchParams.delete(urlSearchParamVercelProtectionBypass) | ||
searchParams.delete(urlSearchParamVercelSetBypassCookie) | ||
return newUrl | ||
@@ -27,3 +31,3 @@ } | ||
url: URL, | ||
secret: string, | ||
secret: string | null, | ||
redirectTo: string, | ||
@@ -34,6 +38,11 @@ perspective: string, | ||
const {searchParams} = newUrl | ||
searchParams.set(urlSearchParamPreviewSecret, secret) | ||
searchParams.set(urlSearchParamPreviewPathname, redirectTo) | ||
// Preview secrets are added when preview mode is setup with an `enable` endpoint | ||
if (secret) { | ||
searchParams.set(urlSearchParamPreviewSecret, secret) | ||
searchParams.set(urlSearchParamPreviewPathname, redirectTo) | ||
} | ||
// Always set the perspective that's being used | ||
searchParams.set(urlSearchParamPreviewPerspective, perspective) | ||
return newUrl | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
191019
86
1864