Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@sanity/preview-url-secret

Package Overview
Dependencies
Maintainers
41
Versions
147
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sanity/preview-url-secret - npm Package Compare versions

Comparing version 1.0.3-canary.1 to 1.1.0

dist/_chunks/constants-BZ2GbOYw.js

8

CHANGELOG.md
# Changelog
## [1.1.0](https://github.com/sanity-io/visual-editing/compare/preview-url-secret-v1.0.2...preview-url-secret-v1.1.0) (2023-11-16)
### Features
* add `getRedirectTo` utility ([03591b5](https://github.com/sanity-io/visual-editing/commit/03591b50d60675d3d1a0eed1b66c7e528a63a1b7))
* return when the secret expires ([8f2c1ce](https://github.com/sanity-io/visual-editing/commit/8f2c1ceefcce73728488b2a3db73cbbee21cf34f))
## [1.0.2](https://github.com/sanity-io/visual-editing/compare/preview-url-secret-v1.0.1...preview-url-secret-v1.0.2) (2023-11-16)

@@ -4,0 +12,0 @@

48

dist/create-secret.js

@@ -1,47 +0,1 @@

import { uuid } from '@sanity/uuid';
import { apiVersion, SECRET_TTL, schemaIdPrefix, tag, schemaType, deleteExpiredSecretsQuery } from './_chunks/constants-iLpfgSLF.js';
function generateUrlSecret() {
if (typeof crypto !== "undefined") {
const array = new Uint8Array(16);
crypto.getRandomValues(array);
let key = "";
for (let i = 0; i < array.length; i++) {
key += array[i].toString(16).padStart(2, "0");
}
key = btoa(key).replace(/\+/g, "-").replace(/\//g, "_").replace(/[=]+$/, "");
return key;
}
return Math.random().toString(36).slice(2);
}
async function createPreviewSecret(_client, source, studioUrl, userId, id = uuid()) {
const client = _client.withConfig({
apiVersion
});
try {
const expiresAt = new Date(Date.now() + 1e3 * SECRET_TTL);
const _id = `${schemaIdPrefix}.${id}`;
const newSecret = generateUrlSecret();
const patch = client.patch(_id).set({
secret: newSecret,
source,
studioUrl,
userId
});
await client.transaction().createOrReplace({
_id,
_type: schemaType
}).patch(patch).commit({
tag
});
return {
secret: newSecret,
expiresAt
};
} finally {
await client.delete({
query: deleteExpiredSecretsQuery
});
}
}
export { createPreviewSecret };
//# sourceMappingURL=create-secret.js.map
import{uuid as t}from"@sanity/uuid";import{a as e,S as a,s as r,t as n,c as o,d as s}from"./_chunks/constants-BZ2GbOYw.js";async function c(c,i,p,u,l=t()){const d=c.withConfig({apiVersion:e});try{const t=new Date(Date.now()+1e3*a),e=`${r}.${l}`,s=function(){if("undefined"!=typeof crypto){const t=new Uint8Array(16);crypto.getRandomValues(t);let e="";for(let a=0;a<t.length;a++)e+=t[a].toString(16).padStart(2,"0");return e=btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/[=]+$/,""),e}return Math.random().toString(36).slice(2)}(),c=d.patch(e).set({secret:s,source:i,studioUrl:p,userId:u});return await d.transaction().createOrReplace({_id:e,_type:o}).patch(c).commit({tag:n}),{secret:s,expiresAt:t}}finally{await d.delete({query:s})}}export{c as createPreviewSecret};//# sourceMappingURL=create-secret.js.map

@@ -1,27 +0,1 @@

import { urlSearchParamPreviewSecret, urlSearchParamPreviewPathname } from './_chunks/constants-iLpfgSLF.js';
function definePreviewUrl(options) {
const {
draftMode,
origin,
preview = "/"
} = options;
const productionUrl = new URL(preview, origin);
const enableDraftModeUrl = draftMode.enable ? new URL(draftMode.enable, origin) : void 0;
return async context => {
const previewUrl = new URL(context.previewSearchParam || preview, productionUrl);
if (enableDraftModeUrl) {
const enableDraftModeRequestUrl = new URL(enableDraftModeUrl);
const {
searchParams
} = enableDraftModeRequestUrl;
searchParams.set(urlSearchParamPreviewSecret, context.previewUrlSecret);
if (previewUrl.pathname !== enableDraftModeRequestUrl.pathname) {
searchParams.set(urlSearchParamPreviewPathname, previewUrl.pathname);
}
return enableDraftModeRequestUrl.toString();
}
return previewUrl.toString();
};
}
export { definePreviewUrl };
//# sourceMappingURL=define-preview-url.js.map
import{u as e,b as n}from"./_chunks/constants-BZ2GbOYw.js";function r(r){const{draftMode:t,origin:a,preview:s="/"}=r,o=new URL(s,a),i=t.enable?new URL(t.enable,a):void 0;return async r=>{const t=new URL(r.previewSearchParam||s,o);if(i){const a=new URL(i),{searchParams:s}=a;return s.set(e,r.previewUrlSecret),t.pathname!==a.pathname&&s.set(n,t.pathname),a.toString()}return t.toString()}}export{r as definePreviewUrl};//# sourceMappingURL=define-preview-url.js.map

@@ -1,9 +0,1 @@

import { urlSearchParamPreviewPathname } from './_chunks/constants-iLpfgSLF.js';
function getRedirectTo(url) {
if (url.searchParams.has(urlSearchParamPreviewPathname)) {
return new URL(url.searchParams.get(urlSearchParamPreviewPathname), url.origin);
}
return url;
}
export { getRedirectTo };
//# sourceMappingURL=get-redirect-to.js.map
import{b as r}from"./_chunks/constants-BZ2GbOYw.js";function s(s){return s.searchParams.has(r)?new URL(s.searchParams.get(r),s.origin):s}export{s as getRedirectTo};//# sourceMappingURL=get-redirect-to.js.map

@@ -1,85 +0,1 @@

import { apiVersion, urlSearchParamPreviewSecret, urlSearchParamPreviewPathname, fetchSecretQuery, tag, isDev } from './_chunks/constants-iLpfgSLF.js';
function createClientWithConfig(client) {
if (!client) {
throw new TypeError("`client` is required");
}
if (!client.config().token) {
throw new TypeError("`client` must have a `token` specified");
}
return client.withConfig({
// Userland might be using an API version that's too old to use perspectives
apiVersion,
// We can't use the CDN, the secret is typically validated rigth after it's created
useCdn: false,
// The documents that hold secrets are never drafts
perspective: "published",
// Don't waste time returning a source map, we don't need it
resultSourceMap: false,
// @ts-expect-error - If stega is enabled, make sure it's disabled
stega: false
});
}
function parsePreviewUrl(unsafeUrl) {
const url = new URL(unsafeUrl, "http://localhost");
const secret = url.searchParams.get(urlSearchParamPreviewSecret);
if (!secret) {
throw new Error("Missing secret");
}
let redirectTo = void 0;
const unsafeRedirectTo = url.searchParams.get(urlSearchParamPreviewPathname);
if (unsafeRedirectTo) {
const {
pathname,
search
} = new URL(unsafeRedirectTo, "http://localhost");
redirectTo = `${pathname}${search}`;
}
return {
secret,
redirectTo
};
}
async function validateSecret(client, secret) {
if (typeof EdgeRuntime !== "undefined") {
await new Promise(resolve => setTimeout(resolve, 300));
}
if (!secret || !secret.trim()) {
return false;
}
const result = await client.fetch(fetchSecretQuery, {
secret
}, {
tag,
// @ts-expect-error -- the `cache` option is valid, but not in the types when NextJS typings aren't installed
cache: "no-store"
});
if (!result?._id || !result?._updatedAt || !result?.secret) {
return false;
}
return secret === result.secret;
}
async function validatePreviewUrl(_client, previewUrl) {
const client = createClientWithConfig(_client);
let parsedPreviewUrl;
try {
parsedPreviewUrl = parsePreviewUrl(previewUrl);
} catch (error) {
if (isDev) {
console.error("Failed to parse preview URL", error, {
previewUrl,
client
});
}
return {
isValid: false
};
}
const isValid = await validateSecret(client, parsedPreviewUrl.secret);
const redirectTo = isValid ? parsedPreviewUrl.redirectTo : void 0;
return {
isValid,
redirectTo
};
}
export { urlSearchParamPreviewPathname, urlSearchParamPreviewSecret, validatePreviewUrl };
//# sourceMappingURL=index.js.map
import{a as e,u as t,b as r,f as s,t as i,i as n}from"./_chunks/constants-BZ2GbOYw.js";async function o(o,c){const a=function(t){if(!t)throw new TypeError("`client` is required");if(!t.config().token)throw new TypeError("`client` must have a `token` specified");return t.withConfig({apiVersion:e,useCdn:!1,perspective:"published",resultSourceMap:!1,stega:!1})}(o);let u;try{u=function(e){const s=new URL(e,"http://localhost"),i=s.searchParams.get(t);if(!i)throw new Error("Missing secret");let n;const o=s.searchParams.get(r);if(o){const{pathname:e,search:t}=new URL(o,"http://localhost");n=`${e}${t}`}return{secret:i,redirectTo:n}}(c)}catch(e){return n&&console.error("Failed to parse preview URL",e,{previewUrl:c,client:a}),{isValid:!1}}const h=await async function(e,t){if("undefined"!=typeof EdgeRuntime&&await new Promise((e=>setTimeout(e,300))),!t||!t.trim())return!1;const r=await e.fetch(s,{secret:t},{tag:i,cache:"no-store"});return!!(r?._id&&r?._updatedAt&&r?.secret)&&t===r.secret}(a,u.secret);return{isValid:h,redirectTo:h?u.redirectTo:void 0}}export{r as urlSearchParamPreviewPathname,t as urlSearchParamPreviewSecret,o as validatePreviewUrl};//# sourceMappingURL=index.js.map

@@ -1,9 +0,1 @@

import { urlSearchParamPreviewPathname, urlSearchParamPreviewSecret } from './_chunks/constants-iLpfgSLF.js';
function withoutSecretSearchParams(url) {
const newUrl = new URL(url);
newUrl.searchParams.delete(urlSearchParamPreviewPathname);
newUrl.searchParams.delete(urlSearchParamPreviewSecret);
return newUrl;
}
export { withoutSecretSearchParams };
//# sourceMappingURL=without-secret-search-params.js.map
import{b as e,u as s}from"./_chunks/constants-BZ2GbOYw.js";function a(a){const r=new URL(a);return r.searchParams.delete(e),r.searchParams.delete(s),r}export{a as withoutSecretSearchParams};//# sourceMappingURL=without-secret-search-params.js.map
{
"name": "@sanity/preview-url-secret",
"version": "1.0.3-canary.1",
"version": "1.1.0",
"homepage": "https://github.com/sanity-io/visual-editing/tree/main/packages/preview-url-secret#readme",

@@ -99,9 +99,2 @@ "bugs": {

],
"scripts": {
"prebuild": "rimraf dist",
"build": "pkg build --strict && pkg --strict",
"lint": "eslint .",
"prepublishOnly": "pnpm build",
"watch": "pkg watch --strict"
},
"browserslist": [

@@ -170,3 +163,2 @@ "> 0.2% and last 2 versions and supports es6-module and supports es6-module-dynamic-import and not dead and not IE 11",

"@typescript-eslint/parser": "^6.11.0",
"channels": "workspace:*",
"eslint": "^8.53.0",

@@ -176,3 +168,4 @@ "eslint-config-prettier": "^9.0.0",

"eslint-plugin-simple-import-sort": "^10.0.0",
"typescript": "^5.2.2"
"typescript": "^5.2.2",
"channels": "0.0.0"
},

@@ -187,3 +180,9 @@ "peerDependencies": {

"access": "public"
},
"scripts": {
"prebuild": "rimraf dist",
"build": "pkg build --strict && pkg --strict",
"lint": "eslint .",
"watch": "pkg watch --strict"
}
}
}

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

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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc