Skip to content

Commit

Permalink
feat(nosecone): Add withVercelToolbar utility function (#2364)
Browse files Browse the repository at this point in the history
This adds a `withVercelToolbar` export to the nosecone package and re-exports it from adapters. This can be used to apply the headers required for the Vercel Toolbar to function on an application deployed to Vercel.
  • Loading branch information
blaine-arcjet authored Nov 29, 2024
1 parent 2bd8bff commit 177d16d
Show file tree
Hide file tree
Showing 4 changed files with 493 additions and 0 deletions.
2 changes: 2 additions & 0 deletions nosecone-next/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import nosecone, { defaults as baseDefaults } from "nosecone";
import type { NoseconeOptions } from "nosecone";

export { withVercelToolbar, type NoseconeOptions } from "nosecone";

export const defaults = {
...baseDefaults,
contentSecurityPolicy: {
Expand Down
2 changes: 2 additions & 0 deletions nosecone-sveltekit/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import nosecone, {
import type { CspDirectives, NoseconeOptions } from "nosecone";
import type { Handle, KitConfig } from "@sveltejs/kit";

export { withVercelToolbar, type NoseconeOptions } from "nosecone";

export const defaults = {
...baseDefaults,
directives: {
Expand Down
145 changes: 145 additions & 0 deletions nosecone/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -698,3 +698,148 @@ export default function nosecone({

return headers;
}

/**
* Augment some Nosecone configuration with the values necessary for using the
* Vercel Toolbar.
*
* Follows the guidance at
* https://vercel.com/docs/workflow-collaboration/vercel-toolbar/managing-toolbar#using-a-content-security-policy
*
* @param config Base configuration for you application
* @returns Augmented configuration to allow Vercel Toolbar
*/
export function withVercelToolbar(config: NoseconeOptions) {
let contentSecurityPolicy = config.contentSecurityPolicy;
if (contentSecurityPolicy === true) {
contentSecurityPolicy = defaults.contentSecurityPolicy;
}

let augmentedContentSecurityPolicy = contentSecurityPolicy;
if (contentSecurityPolicy) {
let scriptSrc = contentSecurityPolicy.directives?.scriptSrc;
if (scriptSrc === true) {
scriptSrc = defaults.contentSecurityPolicy.directives.scriptSrc;
}

let connectSrc = contentSecurityPolicy.directives?.connectSrc;
if (connectSrc === true) {
connectSrc = defaults.contentSecurityPolicy.directives.connectSrc;
}

let imgSrc = contentSecurityPolicy.directives?.imgSrc;
if (imgSrc === true) {
imgSrc = defaults.contentSecurityPolicy.directives.imgSrc;
}

let frameSrc = contentSecurityPolicy.directives?.frameSrc;
if (frameSrc === true) {
frameSrc = defaults.contentSecurityPolicy.directives.frameSrc;
}

let styleSrc = contentSecurityPolicy.directives?.styleSrc;
if (styleSrc === true) {
styleSrc = defaults.contentSecurityPolicy.directives.styleSrc;
}

let fontSrc = contentSecurityPolicy.directives?.fontSrc;
if (fontSrc === true) {
fontSrc = defaults.contentSecurityPolicy.directives.fontSrc;
}

augmentedContentSecurityPolicy = {
...contentSecurityPolicy,
directives: {
...contentSecurityPolicy.directives,
scriptSrc: scriptSrc
? [
...scriptSrc.filter(
(v) => v !== "'none'" && v !== "https://vercel.live",
),
"https://vercel.live",
]
: scriptSrc,
connectSrc: connectSrc
? [
...connectSrc.filter(
(v) =>
v !== "'none'" &&
v !== "https://vercel.live" &&
v !== "wss://ws-us3.pusher.com",
),
"https://vercel.live",
"wss://ws-us3.pusher.com",
]
: connectSrc,
imgSrc: imgSrc
? [
...imgSrc.filter(
(v) =>
v !== "'none'" &&
v !== "https://vercel.live" &&
v !== "https://vercel.com" &&
v !== "data:" &&
v !== "blob:",
),
"https://vercel.live",
"https://vercel.com",
"data:",
"blob:",
]
: imgSrc,
frameSrc: frameSrc
? [
...frameSrc.filter(
(v) => v !== "'none'" && v !== "https://vercel.live",
),
"https://vercel.live",
]
: frameSrc,
styleSrc: styleSrc
? [
...styleSrc.filter(
(v) =>
v !== "'none'" &&
v !== "https://vercel.live" &&
v !== "'unsafe-inline'",
),
"https://vercel.live",
"'unsafe-inline'",
]
: styleSrc,
fontSrc: fontSrc
? [
...fontSrc.filter(
(v) =>
v !== "'none'" &&
v !== "https://vercel.live" &&
v !== "https://assets.vercel.com",
),
"https://vercel.live",
"https://assets.vercel.com",
]
: fontSrc,
},
};
}

let crossOriginEmbedderPolicy = config.crossOriginEmbedderPolicy;
if (crossOriginEmbedderPolicy === true) {
crossOriginEmbedderPolicy = defaults.crossOriginEmbedderPolicy;
}

let augmentedCrossOriginEmbedderPolicy = crossOriginEmbedderPolicy;
if (crossOriginEmbedderPolicy) {
augmentedCrossOriginEmbedderPolicy = {
policy: crossOriginEmbedderPolicy.policy
? "unsafe-none"
: crossOriginEmbedderPolicy.policy,
};
}

return {
...config,
contentSecurityPolicy: augmentedContentSecurityPolicy,
crossOriginEmbedderPolicy: augmentedCrossOriginEmbedderPolicy,
} as const;
}
Loading

0 comments on commit 177d16d

Please sign in to comment.