From c36d51b2f644fcf4a12109306ebce4f18a1f94e0 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Tue, 20 Jun 2023 13:54:12 +0100 Subject: [PATCH 01/21] wip --- packages/integrations/vercel/package.json | 3 ++- packages/integrations/vercel/src/lib/fs.ts | 6 +++++- .../vercel/src/serverless/adapter.ts | 14 +++++++++++++- .../vercel/test/edge-middleware.test.js | 18 ++++++++++++++++++ .../test/fixtures/middleware/astro.config.mjs | 7 +++++++ .../test/fixtures/middleware/package.json | 9 +++++++++ .../test/fixtures/middleware/src/middleware.js | 8 ++++++++ .../fixtures/middleware/src/pages/index.astro | 0 8 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 packages/integrations/vercel/test/edge-middleware.test.js create mode 100644 packages/integrations/vercel/test/fixtures/middleware/astro.config.mjs create mode 100644 packages/integrations/vercel/test/fixtures/middleware/package.json create mode 100644 packages/integrations/vercel/test/fixtures/middleware/src/middleware.js create mode 100644 packages/integrations/vercel/test/fixtures/middleware/src/pages/index.astro diff --git a/packages/integrations/vercel/package.json b/packages/integrations/vercel/package.json index acc20f655c4f..b3effb50306f 100644 --- a/packages/integrations/vercel/package.json +++ b/packages/integrations/vercel/package.json @@ -68,6 +68,7 @@ "astro-scripts": "workspace:*", "chai": "^4.3.7", "cheerio": "1.0.0-rc.12", - "mocha": "^9.2.2" + "mocha": "^9.2.2", + "rollup": "^3.20.1" } } diff --git a/packages/integrations/vercel/src/lib/fs.ts b/packages/integrations/vercel/src/lib/fs.ts index 875a0ae9c864..ec434e59df74 100644 --- a/packages/integrations/vercel/src/lib/fs.ts +++ b/packages/integrations/vercel/src/lib/fs.ts @@ -4,7 +4,7 @@ import nodePath from 'node:path'; import { fileURLToPath } from 'node:url'; export async function writeJson(path: PathLike, data: T) { - await fs.writeFile(path, JSON.stringify(data), { encoding: 'utf-8' }); + await fs.writeFile(path, JSON.stringify(data, null, 2), { encoding: 'utf-8' }); } export async function removeDir(dir: PathLike) { @@ -86,3 +86,7 @@ export async function copyFilesToFunction( return commonAncestor; } + +export async function writeFile(path: PathLike, content: string) { + await fs.writeFile(path, content, { encoding: 'utf-8' }); +} diff --git a/packages/integrations/vercel/src/serverless/adapter.ts b/packages/integrations/vercel/src/serverless/adapter.ts index 8a18707702bd..4d023668d240 100644 --- a/packages/integrations/vercel/src/serverless/adapter.ts +++ b/packages/integrations/vercel/src/serverless/adapter.ts @@ -9,7 +9,7 @@ import { type VercelImageConfig, } from '../image/shared.js'; import { exposeEnv } from '../lib/env.js'; -import { getVercelOutput, removeDir, writeJson } from '../lib/fs.js'; +import { getVercelOutput, removeDir, writeFile, writeJson } from '../lib/fs.js'; import { copyDependenciesToFunction } from '../lib/nft.js'; import { getRedirects } from '../lib/redirects.js'; @@ -109,6 +109,9 @@ export default function vercelServerless({ // Remove temporary folder await removeDir(buildTempFolder); + // Write middleware + await writeFile(new URL('./middleware.js', functionFolder), generateMiddlewareCode()); + // Enable ESM // https://aws.amazon.com/blogs/compute/using-node-js-es-modules-and-top-level-await-in-aws-lambda/ await writeJson(new URL(`./package.json`, functionFolder), { @@ -146,3 +149,12 @@ function getRuntime() { const major = version.split('.')[0]; // '16.5.0' --> '16' return `nodejs${major}.x`; } + +function generateMiddlewareCode() { + return ` +import {onRequest} from "somethere"; +export default function middleware(request, context) { + return onRequest(request) +} +`; +} diff --git a/packages/integrations/vercel/test/edge-middleware.test.js b/packages/integrations/vercel/test/edge-middleware.test.js new file mode 100644 index 000000000000..a38f1c503050 --- /dev/null +++ b/packages/integrations/vercel/test/edge-middleware.test.js @@ -0,0 +1,18 @@ +import { loadFixture } from './test-utils.js'; +import { expect } from 'chai'; + +describe('Serverless prerender', () => { + /** @type {import('./test-utils').Fixture} */ + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/middleware/', + }); + }); + + it('build successful', async () => { + await fixture.build(); + expect(await fixture.readFile('../.vercel/output/static/index.html')).to.be.ok; + }); +}); diff --git a/packages/integrations/vercel/test/fixtures/middleware/astro.config.mjs b/packages/integrations/vercel/test/fixtures/middleware/astro.config.mjs new file mode 100644 index 000000000000..9d46508a9328 --- /dev/null +++ b/packages/integrations/vercel/test/fixtures/middleware/astro.config.mjs @@ -0,0 +1,7 @@ +import {defineConfig} from "astro/config"; +import vercel from "@astrojs/vercel/serverless"; + +export default defineConfig({ + adapter: vercel(), + output: 'server' +}); \ No newline at end of file diff --git a/packages/integrations/vercel/test/fixtures/middleware/package.json b/packages/integrations/vercel/test/fixtures/middleware/package.json new file mode 100644 index 000000000000..9ba60852d4cb --- /dev/null +++ b/packages/integrations/vercel/test/fixtures/middleware/package.json @@ -0,0 +1,9 @@ +{ + "name": "@test/vercel-edge-middleware", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/vercel": "workspace:*", + "astro": "workspace:*" + } +} diff --git a/packages/integrations/vercel/test/fixtures/middleware/src/middleware.js b/packages/integrations/vercel/test/fixtures/middleware/src/middleware.js new file mode 100644 index 000000000000..349a0aa79581 --- /dev/null +++ b/packages/integrations/vercel/test/fixtures/middleware/src/middleware.js @@ -0,0 +1,8 @@ +/** + * @type {import("astro").MiddlewareResponseHandler} + */ +export const onRequest = async (context, next) => { + const test = 'something'; + const response = await next(); + return response; +}; diff --git a/packages/integrations/vercel/test/fixtures/middleware/src/pages/index.astro b/packages/integrations/vercel/test/fixtures/middleware/src/pages/index.astro new file mode 100644 index 000000000000..e69de29bb2d1 From c0976534e58043b7c2cf01bf52d34069f0560b28 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Fri, 23 Jun 2023 09:19:41 +0100 Subject: [PATCH 02/21] chore: rebase --- pnpm-lock.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b454bceffd14..ef41f94ae852 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4904,6 +4904,9 @@ importers: mocha: specifier: ^9.2.2 version: 9.2.2 + rollup: + specifier: ^3.20.1 + version: 3.25.1 packages/integrations/vercel/test/fixtures/image: dependencies: @@ -4914,6 +4917,15 @@ importers: specifier: workspace:* version: link:../../../../../astro + packages/integrations/vercel/test/fixtures/middleware: + dependencies: + '@astrojs/vercel': + specifier: workspace:* + version: link:../../.. + astro: + specifier: workspace:* + version: link:../../../../../astro + packages/integrations/vercel/test/fixtures/no-output: dependencies: '@astrojs/vercel': From 26fce13e6b5e298d2e6dd1af4fe520fb1af1938e Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Mon, 26 Jun 2023 13:01:32 +0100 Subject: [PATCH 03/21] feat: expose middleware URL to integrations (#7458) --- .changeset/chilly-pants-fix.md | 24 +++++++++++++++++++ packages/astro/src/@types/astro.ts | 1 + packages/astro/src/core/build/index.ts | 16 ++++++++++++- packages/astro/src/core/build/internal.ts | 1 + .../core/build/plugins/plugin-middleware.ts | 13 +++++++++- packages/astro/src/integrations/index.ts | 21 +++++++++------- packages/astro/test/middleware.test.js | 23 +++++++++++++++++- .../astro/test/ssr-split-manifest.test.js | 4 +++- packages/astro/test/test-adapter.js | 5 +++- .../vercel/src/serverless/adapter.ts | 12 ---------- .../vercel/test/edge-middleware.test.js | 5 ---- 11 files changed, 94 insertions(+), 31 deletions(-) create mode 100644 .changeset/chilly-pants-fix.md diff --git a/.changeset/chilly-pants-fix.md b/.changeset/chilly-pants-fix.md new file mode 100644 index 000000000000..da4f6f89a2f2 --- /dev/null +++ b/.changeset/chilly-pants-fix.md @@ -0,0 +1,24 @@ +--- +'astro': minor +--- + +Astro exposes the middleware file path to the integrations in the hook `astro:build:done` + +```ts +// myIntegration.js +import type { AstroIntegration } from 'astro'; +function integration(): AstroIntegration { + return { + name: "fancy-astro-integration", + hooks: { + 'astro:build:done': ({ middlewareEntryPoint }) => { + if (middlewareEntryPoint) { + // do some operations + } + } + } + } +} +``` + +The `middlewareEntryPoint` is only defined if the user has created an Astro middleware. diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index 43069aa1795d..9f4b23fef944 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -1869,6 +1869,7 @@ export interface AstroIntegration { pages: { pathname: string }[]; dir: URL; routes: RouteData[]; + middlewareEntryPoint: URL | undefined; }) => void | Promise; }; } diff --git a/packages/astro/src/core/build/index.ts b/packages/astro/src/core/build/index.ts index 9e72e6e36fdb..777b7b45537a 100644 --- a/packages/astro/src/core/build/index.ts +++ b/packages/astro/src/core/build/index.ts @@ -8,6 +8,8 @@ import type { } from '../../@types/astro'; import fs from 'fs'; +import { fileURLToPath, pathToFileURL } from 'node:url'; +import { join } from 'node:path'; import * as colors from 'kleur/colors'; import { performance } from 'perf_hooks'; import type * as vite from 'vite'; @@ -28,6 +30,7 @@ import { collectPagesData } from './page-data.js'; import { staticBuild, viteBuild } from './static-build.js'; import type { StaticBuildOptions } from './types.js'; import { getTimeStat } from './util.js'; +import { isServerLikeOutput } from '../../prerender/utils.js'; export interface BuildOptions { mode?: RuntimeMode; @@ -185,13 +188,24 @@ class AstroBuilder { }); debug('build', timerMessage('Additional assets copied', this.timer.assetsStart)); + let middlewareEntryPoint = undefined; + // during the last phase of the build, the emitted code gets copied inside + // `dist/server/` folder, so we need to shred the old URL and make a new one again + if (internals.middlewareEntryPoint && isServerLikeOutput(this.settings.config)) { + const outDir = fileURLToPath(this.settings.config.outDir); + const middlewareRelativePath = fileURLToPath(internals.middlewareEntryPoint).slice( + fileURLToPath(this.settings.config.outDir).length + ); + middlewareEntryPoint = pathToFileURL(join(outDir, 'server', middlewareRelativePath)); + } + // You're done! Time to clean up. await runHookBuildDone({ config: this.settings.config, - buildConfig, pages: pageNames, routes: Object.values(allPages).map((pd) => pd.route), logging: this.logging, + middlewareEntryPoint, }); if (this.logging.level && levels[this.logging.level] <= levels['info']) { diff --git a/packages/astro/src/core/build/internal.ts b/packages/astro/src/core/build/internal.ts index 8c7da07d4319..ca1bac531252 100644 --- a/packages/astro/src/core/build/internal.ts +++ b/packages/astro/src/core/build/internal.ts @@ -84,6 +84,7 @@ export interface BuildInternals { entryPoints: Map; ssrSplitEntryChunks: Map; componentMetadata: SSRResult['componentMetadata']; + middlewareEntryPoint?: URL; } /** diff --git a/packages/astro/src/core/build/plugins/plugin-middleware.ts b/packages/astro/src/core/build/plugins/plugin-middleware.ts index 7e3ea8cb9d9a..2dd75b7168a3 100644 --- a/packages/astro/src/core/build/plugins/plugin-middleware.ts +++ b/packages/astro/src/core/build/plugins/plugin-middleware.ts @@ -11,7 +11,7 @@ const EMPTY_MIDDLEWARE = '\0empty-middleware'; export function vitePluginMiddleware( opts: StaticBuildOptions, - _internals: BuildInternals + internals: BuildInternals ): VitePlugin { return { name: '@astro/plugin-middleware', @@ -41,6 +41,17 @@ export function vitePluginMiddleware( return 'export const onRequest = undefined'; } }, + + writeBundle(_, bundle) { + for (const [chunkName, chunk] of Object.entries(bundle)) { + if (chunk.type === 'asset') { + continue; + } + if (chunk.fileName === 'middleware.mjs') { + internals.middlewareEntryPoint = new URL(chunkName, opts.settings.config.outDir); + } + } + }, }; } diff --git a/packages/astro/src/integrations/index.ts b/packages/astro/src/integrations/index.ts index f0abd1576263..c89dfca02769 100644 --- a/packages/astro/src/integrations/index.ts +++ b/packages/astro/src/integrations/index.ts @@ -343,20 +343,22 @@ export async function runHookBuildGenerated({ } } +type RunHookBuildDone = { + config: AstroConfig; + pages: string[]; + routes: RouteData[]; + logging: LogOptions; + middlewareEntryPoint: URL | undefined; +}; + export async function runHookBuildDone({ config, - buildConfig, pages, routes, logging, -}: { - config: AstroConfig; - buildConfig: BuildConfig; - pages: string[]; - routes: RouteData[]; - logging: LogOptions; -}) { - const dir = isServerLikeOutput(config) ? buildConfig.client : config.outDir; + middlewareEntryPoint, +}: RunHookBuildDone) { + const dir = isServerLikeOutput(config) ? config.build.client : config.outDir; await fs.promises.mkdir(dir, { recursive: true }); for (const integration of config.integrations) { @@ -367,6 +369,7 @@ export async function runHookBuildDone({ pages: pages.map((p) => ({ pathname: p })), dir, routes, + middlewareEntryPoint, }), logging, }); diff --git a/packages/astro/test/middleware.test.js b/packages/astro/test/middleware.test.js index e2c57bafb940..70c0702f3bf8 100644 --- a/packages/astro/test/middleware.test.js +++ b/packages/astro/test/middleware.test.js @@ -2,6 +2,8 @@ import { loadFixture } from './test-utils.js'; import { expect } from 'chai'; import * as cheerio from 'cheerio'; import testAdapter from './test-adapter.js'; +import { fileURLToPath } from 'node:url'; +import { readFileSync, existsSync } from 'node:fs'; describe('Middleware in DEV mode', () => { /** @type {import('./test-utils').Fixture} */ @@ -104,12 +106,19 @@ describe('Middleware in PROD mode, SSG', () => { describe('Middleware API in PROD mode, SSR', () => { /** @type {import('./test-utils').Fixture} */ let fixture; + let middlewarePath; before(async () => { fixture = await loadFixture({ root: './fixtures/middleware-dev/', output: 'server', - adapter: testAdapter({}), + adapter: testAdapter({ + setEntryPoints(entryPointsOrMiddleware) { + if (entryPointsOrMiddleware instanceof URL) { + middlewarePath = entryPointsOrMiddleware; + } + }, + }), }); await fixture.build(); }); @@ -201,6 +210,18 @@ describe('Middleware API in PROD mode, SSR', () => { const text = await response.text(); expect(text.includes('REDACTED')).to.be.true; }); + + it('the integration should receive the path to the middleware', async () => { + expect(middlewarePath).to.not.be.undefined; + try { + const path = fileURLToPath(middlewarePath); + expect(existsSync(path)).to.be.true; + const content = readFileSync(fileURLToPath(middlewarePath), 'utf-8'); + expect(content.length).to.be.greaterThan(0); + } catch (e) { + throw e; + } + }); }); describe('Middleware with tailwind', () => { diff --git a/packages/astro/test/ssr-split-manifest.test.js b/packages/astro/test/ssr-split-manifest.test.js index 5005f6279953..a5a46c38778a 100644 --- a/packages/astro/test/ssr-split-manifest.test.js +++ b/packages/astro/test/ssr-split-manifest.test.js @@ -17,7 +17,9 @@ describe('astro:ssr-manifest, split', () => { output: 'server', adapter: testAdapter({ setEntryPoints(entries) { - entryPoints = entries; + if (entries) { + entryPoints = entries; + } }, setRoutes(routes) { currentRoutes = routes; diff --git a/packages/astro/test/test-adapter.js b/packages/astro/test/test-adapter.js index af5a7777b8c1..39bfe37b31d6 100644 --- a/packages/astro/test/test-adapter.js +++ b/packages/astro/test/test-adapter.js @@ -79,10 +79,13 @@ export default function ( setEntryPoints(entryPoints); } }, - 'astro:build:done': ({ routes }) => { + 'astro:build:done': ({ routes, middlewareEntryPoint }) => { if (setRoutes) { setRoutes(routes); } + if (setEntryPoints) { + setEntryPoints(middlewareEntryPoint); + } }, }, }; diff --git a/packages/integrations/vercel/src/serverless/adapter.ts b/packages/integrations/vercel/src/serverless/adapter.ts index 4d023668d240..aeebc74508e3 100644 --- a/packages/integrations/vercel/src/serverless/adapter.ts +++ b/packages/integrations/vercel/src/serverless/adapter.ts @@ -109,9 +109,6 @@ export default function vercelServerless({ // Remove temporary folder await removeDir(buildTempFolder); - // Write middleware - await writeFile(new URL('./middleware.js', functionFolder), generateMiddlewareCode()); - // Enable ESM // https://aws.amazon.com/blogs/compute/using-node-js-es-modules-and-top-level-await-in-aws-lambda/ await writeJson(new URL(`./package.json`, functionFolder), { @@ -149,12 +146,3 @@ function getRuntime() { const major = version.split('.')[0]; // '16.5.0' --> '16' return `nodejs${major}.x`; } - -function generateMiddlewareCode() { - return ` -import {onRequest} from "somethere"; -export default function middleware(request, context) { - return onRequest(request) -} -`; -} diff --git a/packages/integrations/vercel/test/edge-middleware.test.js b/packages/integrations/vercel/test/edge-middleware.test.js index a38f1c503050..0037adc92c37 100644 --- a/packages/integrations/vercel/test/edge-middleware.test.js +++ b/packages/integrations/vercel/test/edge-middleware.test.js @@ -10,9 +10,4 @@ describe('Serverless prerender', () => { root: './fixtures/middleware/', }); }); - - it('build successful', async () => { - await fixture.build(); - expect(await fixture.readFile('../.vercel/output/static/index.html')).to.be.ok; - }); }); From a31db909ca4751e58ef0f1bfb94ba427669d46b6 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Mon, 26 Jun 2023 13:39:54 +0100 Subject: [PATCH 04/21] feat: build option `extractMiddleware` (#7448) * feat: build option `splitMiddleware` * fix regression * chore: correct config validation * change name as per code suggestion --- .changeset/strong-years-travel.md | 20 ++++++++++++++ packages/astro/src/@types/astro.ts | 23 ++++++++++++++++ packages/astro/src/core/build/index.ts | 21 ++++++++++++++- .../core/build/plugins/plugin-middleware.ts | 7 +++++ .../src/core/build/plugins/plugin-pages.ts | 11 +++++--- packages/astro/src/core/build/static-build.ts | 2 -- packages/astro/src/core/config/schema.ts | 9 +++++++ packages/astro/test/middleware.test.js | 26 +++++++++++++++++++ 8 files changed, 112 insertions(+), 7 deletions(-) create mode 100644 .changeset/strong-years-travel.md diff --git a/.changeset/strong-years-travel.md b/.changeset/strong-years-travel.md new file mode 100644 index 000000000000..28334375ab6d --- /dev/null +++ b/.changeset/strong-years-travel.md @@ -0,0 +1,20 @@ +--- +'astro': minor +--- + +Introduced a new build option for SSR, called `build.excludeMiddleware`. + +```js +// astro.config.mjs +import {defineConfig} from "astro/config"; + +export default defineConfig({ + build: { + excludeMiddleware: true + } +}) +``` + +When enabled, the code that belongs to be middleware **won't** be imported +by the final pages/entry points. The user is responsible to import it and +call it manually. diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index 9f4b23fef944..d030dd1c35aa 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -862,6 +862,29 @@ export interface AstroUserConfig { * ``` */ split?: boolean; + + /** + * @docs + * @name build.excludeMiddleware + * @type {boolean} + * @default {false} + * @version 2.7.0 + * @description + * Defines how the SSR code should be bundled when built. + * + * When enabled, the middleware code is **not** going to be imported by the pages. + * + * It's going to be responsibility of the end user to execute import the code and execute it. + * + * ```js + * { + * build: { + * excludeMiddleware: true + * } + * } + * ``` + */ + excludeMiddleware?: boolean; }; /** diff --git a/packages/astro/src/core/build/index.ts b/packages/astro/src/core/build/index.ts index 777b7b45537a..d3606977e7ab 100644 --- a/packages/astro/src/core/build/index.ts +++ b/packages/astro/src/core/build/index.ts @@ -21,7 +21,7 @@ import { runHookConfigSetup, } from '../../integrations/index.js'; import { createVite } from '../create-vite.js'; -import { debug, info, levels, timerMessage, type LogOptions } from '../logger/core.js'; +import { debug, info, warn, levels, timerMessage, type LogOptions } from '../logger/core.js'; import { printHelp } from '../messages.js'; import { apply as applyPolyfill } from '../polyfill.js'; import { RouteCache } from '../render/route-cache.js'; @@ -240,6 +240,25 @@ class AstroBuilder { `the outDir cannot be the root folder. Please build to a folder such as dist.` ); } + + if (config.build.split === true) { + if (config.output === 'static') { + warn( + this.logging, + 'configuration', + 'The option `build.split` won\'t take effect, because `output` is not `"server"` or `"hybrid"`.' + ); + } + } + if (config.build.excludeMiddleware === true) { + if (config.output === 'static') { + warn( + this.logging, + 'configuration', + 'The option `build.excludeMiddleware` won\'t take effect, because `output` is not `"server"` or `"hybrid"`.' + ); + } + } } /** Stats */ diff --git a/packages/astro/src/core/build/plugins/plugin-middleware.ts b/packages/astro/src/core/build/plugins/plugin-middleware.ts index 2dd75b7168a3..bd8c12c4b2ee 100644 --- a/packages/astro/src/core/build/plugins/plugin-middleware.ts +++ b/packages/astro/src/core/build/plugins/plugin-middleware.ts @@ -39,6 +39,13 @@ export function vitePluginMiddleware( load(id) { if (id === EMPTY_MIDDLEWARE) { return 'export const onRequest = undefined'; + } else if (id === MIDDLEWARE_MODULE_ID) { + this.emitFile({ + type: 'chunk', + preserveSignature: 'strict', + fileName: 'middleware.mjs', + id, + }); } }, diff --git a/packages/astro/src/core/build/plugins/plugin-pages.ts b/packages/astro/src/core/build/plugins/plugin-pages.ts index c40449a39e2e..995980363feb 100644 --- a/packages/astro/src/core/build/plugins/plugin-pages.ts +++ b/packages/astro/src/core/build/plugins/plugin-pages.ts @@ -73,10 +73,13 @@ function vitePluginPages(opts: StaticBuildOptions, internals: BuildInternals): V imports.push(`import { renderers } from "${RENDERERS_MODULE_ID}";`); exports.push(`export { renderers };`); - const middlewareModule = await this.resolve(MIDDLEWARE_MODULE_ID); - if (middlewareModule) { - imports.push(`import { onRequest } from "${middlewareModule.id}";`); - exports.push(`export { onRequest };`); + // The middleware should not be imported by the pages + if (!opts.settings.config.build.excludeMiddleware) { + const middlewareModule = await this.resolve(MIDDLEWARE_MODULE_ID); + if (middlewareModule) { + imports.push(`import { onRequest } from "${middlewareModule.id}";`); + exports.push(`export { onRequest };`); + } } return `${imports.join('\n')}${exports.join('\n')}`; diff --git a/packages/astro/src/core/build/static-build.ts b/packages/astro/src/core/build/static-build.ts index 7d6004c0dd89..c03d2b50fac1 100644 --- a/packages/astro/src/core/build/static-build.ts +++ b/packages/astro/src/core/build/static-build.ts @@ -183,8 +183,6 @@ async function ssrBuild( ); } else if (chunkInfo.facadeModuleId?.startsWith(RESOLVED_SPLIT_MODULE_ID)) { return makeSplitEntryPointFileName(chunkInfo.facadeModuleId, routes); - } else if (chunkInfo.facadeModuleId === MIDDLEWARE_MODULE_ID) { - return 'middleware.mjs'; } else if (chunkInfo.facadeModuleId === SSR_VIRTUAL_MODULE_ID) { return opts.settings.config.build.serverEntry; } else if (chunkInfo.facadeModuleId === RESOLVED_RENDERERS_MODULE_ID) { diff --git a/packages/astro/src/core/config/schema.ts b/packages/astro/src/core/config/schema.ts index 99ef653d0788..bcdca9269bbe 100644 --- a/packages/astro/src/core/config/schema.ts +++ b/packages/astro/src/core/config/schema.ts @@ -25,6 +25,7 @@ const ASTRO_CONFIG_DEFAULTS: AstroUserConfig & any = { redirects: true, inlineStylesheets: 'never', split: false, + excludeMiddlwar: false, }, compressHTML: false, server: { @@ -123,6 +124,10 @@ export const AstroConfigSchema = z.object({ .default(ASTRO_CONFIG_DEFAULTS.build.inlineStylesheets), split: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.build.split), + excludeMiddleware: z + .boolean() + .optional() + .default(ASTRO_CONFIG_DEFAULTS.build.excludeMiddleware), }) .optional() .default({}), @@ -284,6 +289,10 @@ export function createRelativeSchema(cmd: string, fileProtocolRoot: URL) { .default(ASTRO_CONFIG_DEFAULTS.build.inlineStylesheets), split: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.build.split), + excludeMiddleware: z + .boolean() + .optional() + .default(ASTRO_CONFIG_DEFAULTS.build.excludeMiddleware), }) .optional() .default({}), diff --git a/packages/astro/test/middleware.test.js b/packages/astro/test/middleware.test.js index 70c0702f3bf8..9e2213146457 100644 --- a/packages/astro/test/middleware.test.js +++ b/packages/astro/test/middleware.test.js @@ -245,3 +245,29 @@ describe('Middleware with tailwind', () => { expect(bundledCSS.includes('--tw-content')).to.be.true; }); }); + +describe('Middleware, split middleware option', () => { + /** @type {import('./test-utils').Fixture} */ + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/middleware-dev/', + output: 'server', + build: { + excludeMiddleware: true, + }, + adapter: testAdapter({}), + }); + await fixture.build(); + }); + + it('should not render locals data because the page does not export it', async () => { + const app = await fixture.loadTestAdapterApp(); + const request = new Request('http://example.com/'); + const response = await app.render(request); + const html = await response.text(); + const $ = cheerio.load(html); + expect($('p').html()).to.not.equal('bar'); + }); +}); From e3398dffbbda091c2a21ec56898cc58304bd6bef Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Tue, 27 Jun 2023 10:22:45 +0100 Subject: [PATCH 05/21] fix: schema --- packages/astro/src/core/config/schema.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/astro/src/core/config/schema.ts b/packages/astro/src/core/config/schema.ts index bcdca9269bbe..fe6d4b97dce8 100644 --- a/packages/astro/src/core/config/schema.ts +++ b/packages/astro/src/core/config/schema.ts @@ -25,7 +25,7 @@ const ASTRO_CONFIG_DEFAULTS: AstroUserConfig & any = { redirects: true, inlineStylesheets: 'never', split: false, - excludeMiddlwar: false, + excludeMiddleware: false, }, compressHTML: false, server: { From d7c165d84399ccaa87e71421b2b88b98b76584d6 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Wed, 28 Jun 2023 15:16:05 +0100 Subject: [PATCH 06/21] feat: export a new api called `createContext` (#7498) --- .changeset/long-geckos-battle.md | 7 +++++ packages/astro/src/core/endpoint/index.ts | 21 +++++++++----- packages/astro/src/core/middleware/index.ts | 31 +++++++++++++++++++-- 3 files changed, 50 insertions(+), 9 deletions(-) create mode 100644 .changeset/long-geckos-battle.md diff --git a/.changeset/long-geckos-battle.md b/.changeset/long-geckos-battle.md new file mode 100644 index 000000000000..9422ecd77a3b --- /dev/null +++ b/.changeset/long-geckos-battle.md @@ -0,0 +1,7 @@ +--- +'astro': minor +--- + +The module `astro/middleware` exports a new API called `createContext`. + +This a low-level API that adapters can use to create a context that can be consumed by middleware functions. diff --git a/packages/astro/src/core/endpoint/index.ts b/packages/astro/src/core/endpoint/index.ts index dde07cd9c625..33cb113a2d47 100644 --- a/packages/astro/src/core/endpoint/index.ts +++ b/packages/astro/src/core/endpoint/index.ts @@ -31,19 +31,26 @@ type EndpointCallResult = response: Response; }; +type CreateAPIContext = { + request: Request; + params: Params; + site?: string; + props: Record; + adapterName?: string; +}; + +/** + * Creates a context that holds all the information needed to handle an Astro endpoint. + * + * @param {CreateAPIContext} payload + */ export function createAPIContext({ request, params, site, props, adapterName, -}: { - request: Request; - params: Params; - site?: string; - props: Record; - adapterName?: string; -}): APIContext { +}: CreateAPIContext): APIContext { const context = { cookies: new AstroCookies(request), request, diff --git a/packages/astro/src/core/middleware/index.ts b/packages/astro/src/core/middleware/index.ts index f9fb07bd4d98..29c4b78e8048 100644 --- a/packages/astro/src/core/middleware/index.ts +++ b/packages/astro/src/core/middleware/index.ts @@ -1,9 +1,36 @@ -import type { MiddlewareResponseHandler } from '../../@types/astro'; +import type { MiddlewareResponseHandler, Params } from '../../@types/astro'; import { sequence } from './sequence.js'; +import { createAPIContext } from '../endpoint/index.js'; function defineMiddleware(fn: MiddlewareResponseHandler) { return fn; } +/** + * Payload for creating a context to be passed to Astro middleware + */ +export type CreateContext = { + /** + * The incoming request + */ + request: Request; + /** + * Optional parameters + */ + params?: Params; +}; + +/** + * Creates a context to be passed to Astro middleware `onRequest` function. + */ +function createContext({ request, params }: CreateContext) { + return createAPIContext({ + request, + params: params ?? {}, + props: {}, + site: undefined, + }); +} + // NOTE: this export must export only the functions that will be exposed to user-land as officials APIs -export { sequence, defineMiddleware }; +export { sequence, defineMiddleware, createContext }; From 37aef59f9618b2612c85d986a6590878ce0a03f7 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Wed, 28 Jun 2023 16:00:42 +0100 Subject: [PATCH 07/21] feat: bundle the Vercel Edge Middleware function (#7492) --- .changeset/chilly-pants-fix.md | 4 +- .changeset/cool-kids-grin.md | 5 ++ .changeset/good-pigs-fetch.md | 5 ++ packages/astro/src/@types/astro.ts | 5 +- packages/astro/src/core/build/index.ts | 12 ---- .../core/build/plugins/plugin-middleware.ts | 7 ++- .../src/core/build/plugins/plugin-ssr.ts | 2 + packages/astro/src/integrations/index.ts | 32 +++++----- packages/astro/test/test-adapter.js | 6 +- .../vercel/src/serverless/adapter.ts | 21 +++++-- .../vercel/src/serverless/middleware.ts | 62 +++++++++++++++++++ .../vercel/test/edge-middleware.test.js | 13 ++++ 12 files changed, 133 insertions(+), 41 deletions(-) create mode 100644 .changeset/cool-kids-grin.md create mode 100644 .changeset/good-pigs-fetch.md create mode 100644 packages/integrations/vercel/src/serverless/middleware.ts diff --git a/.changeset/chilly-pants-fix.md b/.changeset/chilly-pants-fix.md index da4f6f89a2f2..c862a15dcbc3 100644 --- a/.changeset/chilly-pants-fix.md +++ b/.changeset/chilly-pants-fix.md @@ -2,7 +2,7 @@ 'astro': minor --- -Astro exposes the middleware file path to the integrations in the hook `astro:build:done` +Astro exposes the middleware file path to the integrations in the hook `astro:build:ssr` ```ts // myIntegration.js @@ -11,7 +11,7 @@ function integration(): AstroIntegration { return { name: "fancy-astro-integration", hooks: { - 'astro:build:done': ({ middlewareEntryPoint }) => { + 'astro:build:ssr': ({ middlewareEntryPoint }) => { if (middlewareEntryPoint) { // do some operations } diff --git a/.changeset/cool-kids-grin.md b/.changeset/cool-kids-grin.md new file mode 100644 index 000000000000..190e5eee9d91 --- /dev/null +++ b/.changeset/cool-kids-grin.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Correctly track the middleware during the SSR build. diff --git a/.changeset/good-pigs-fetch.md b/.changeset/good-pigs-fetch.md new file mode 100644 index 000000000000..041580958528 --- /dev/null +++ b/.changeset/good-pigs-fetch.md @@ -0,0 +1,5 @@ +--- +'@astrojs/vercel': minor +--- + + diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index d030dd1c35aa..b83fdc5bf569 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -1879,6 +1879,10 @@ export interface AstroIntegration { * the physical file you should import. */ entryPoints: Map; + /** + * File path of the emitted middleware + */ + middlewareEntryPoint: URL | undefined; }) => void | Promise; 'astro:build:start'?: () => void | Promise; 'astro:build:setup'?: (options: { @@ -1892,7 +1896,6 @@ export interface AstroIntegration { pages: { pathname: string }[]; dir: URL; routes: RouteData[]; - middlewareEntryPoint: URL | undefined; }) => void | Promise; }; } diff --git a/packages/astro/src/core/build/index.ts b/packages/astro/src/core/build/index.ts index d3606977e7ab..fa269bcbd6be 100644 --- a/packages/astro/src/core/build/index.ts +++ b/packages/astro/src/core/build/index.ts @@ -188,24 +188,12 @@ class AstroBuilder { }); debug('build', timerMessage('Additional assets copied', this.timer.assetsStart)); - let middlewareEntryPoint = undefined; - // during the last phase of the build, the emitted code gets copied inside - // `dist/server/` folder, so we need to shred the old URL and make a new one again - if (internals.middlewareEntryPoint && isServerLikeOutput(this.settings.config)) { - const outDir = fileURLToPath(this.settings.config.outDir); - const middlewareRelativePath = fileURLToPath(internals.middlewareEntryPoint).slice( - fileURLToPath(this.settings.config.outDir).length - ); - middlewareEntryPoint = pathToFileURL(join(outDir, 'server', middlewareRelativePath)); - } - // You're done! Time to clean up. await runHookBuildDone({ config: this.settings.config, pages: pageNames, routes: Object.values(allPages).map((pd) => pd.route), logging: this.logging, - middlewareEntryPoint, }); if (this.logging.level && levels[this.logging.level] <= levels['info']) { diff --git a/packages/astro/src/core/build/plugins/plugin-middleware.ts b/packages/astro/src/core/build/plugins/plugin-middleware.ts index bd8c12c4b2ee..f29a8c611272 100644 --- a/packages/astro/src/core/build/plugins/plugin-middleware.ts +++ b/packages/astro/src/core/build/plugins/plugin-middleware.ts @@ -4,6 +4,7 @@ import { addRollupInput } from '../add-rollup-input.js'; import type { BuildInternals } from '../internal.js'; import type { AstroBuildPlugin } from '../plugin'; import type { StaticBuildOptions } from '../types'; +import { viteID } from '../../util.js'; export const MIDDLEWARE_MODULE_ID = '@astro-middleware'; @@ -13,6 +14,7 @@ export function vitePluginMiddleware( opts: StaticBuildOptions, internals: BuildInternals ): VitePlugin { + let resolvedMiddlewareId: string; return { name: '@astro/plugin-middleware', @@ -26,6 +28,7 @@ export function vitePluginMiddleware( `${opts.settings.config.srcDir.pathname}/${MIDDLEWARE_PATH_SEGMENT_NAME}` ); if (middlewareId) { + resolvedMiddlewareId = middlewareId.id; return middlewareId.id; } else { return EMPTY_MIDDLEWARE; @@ -39,7 +42,7 @@ export function vitePluginMiddleware( load(id) { if (id === EMPTY_MIDDLEWARE) { return 'export const onRequest = undefined'; - } else if (id === MIDDLEWARE_MODULE_ID) { + } else if (id === resolvedMiddlewareId) { this.emitFile({ type: 'chunk', preserveSignature: 'strict', @@ -55,7 +58,7 @@ export function vitePluginMiddleware( continue; } if (chunk.fileName === 'middleware.mjs') { - internals.middlewareEntryPoint = new URL(chunkName, opts.settings.config.outDir); + internals.middlewareEntryPoint = new URL(chunkName, opts.settings.config.build.server); } } }, diff --git a/packages/astro/src/core/build/plugins/plugin-ssr.ts b/packages/astro/src/core/build/plugins/plugin-ssr.ts index 486c314340b7..7af30d0f3005 100644 --- a/packages/astro/src/core/build/plugins/plugin-ssr.ts +++ b/packages/astro/src/core/build/plugins/plugin-ssr.ts @@ -141,6 +141,7 @@ export function pluginSSR( manifest, logging: options.logging, entryPoints: internals.entryPoints, + middlewareEntryPoint: internals.middlewareEntryPoint, }); const code = injectManifest(manifest, internals.ssrEntryChunk); mutate(internals.ssrEntryChunk, 'server', code); @@ -267,6 +268,7 @@ export function pluginSSRSplit( manifest, logging: options.logging, entryPoints: internals.entryPoints, + middlewareEntryPoint: internals.middlewareEntryPoint, }); for (const [moduleName, chunk] of internals.ssrSplitEntryChunks) { const code = injectManifest(manifest, chunk); diff --git a/packages/astro/src/integrations/index.ts b/packages/astro/src/integrations/index.ts index c89dfca02769..bd7b76773c99 100644 --- a/packages/astro/src/integrations/index.ts +++ b/packages/astro/src/integrations/index.ts @@ -299,22 +299,30 @@ export async function runHookBuildSetup({ return updatedConfig; } +type RunHookBuildSsr = { + config: AstroConfig; + manifest: SerializedSSRManifest; + logging: LogOptions; + entryPoints: Map; + middlewareEntryPoint: URL | undefined; +}; + export async function runHookBuildSsr({ config, manifest, logging, entryPoints, -}: { - config: AstroConfig; - manifest: SerializedSSRManifest; - logging: LogOptions; - entryPoints: Map; -}) { + middlewareEntryPoint, +}: RunHookBuildSsr) { for (const integration of config.integrations) { if (integration?.hooks?.['astro:build:ssr']) { await withTakingALongTimeMsg({ name: integration.name, - hookResult: integration.hooks['astro:build:ssr']({ manifest, entryPoints }), + hookResult: integration.hooks['astro:build:ssr']({ + manifest, + entryPoints, + middlewareEntryPoint, + }), logging, }); } @@ -348,16 +356,9 @@ type RunHookBuildDone = { pages: string[]; routes: RouteData[]; logging: LogOptions; - middlewareEntryPoint: URL | undefined; }; -export async function runHookBuildDone({ - config, - pages, - routes, - logging, - middlewareEntryPoint, -}: RunHookBuildDone) { +export async function runHookBuildDone({ config, pages, routes, logging }: RunHookBuildDone) { const dir = isServerLikeOutput(config) ? config.build.client : config.outDir; await fs.promises.mkdir(dir, { recursive: true }); @@ -369,7 +370,6 @@ export async function runHookBuildDone({ pages: pages.map((p) => ({ pathname: p })), dir, routes, - middlewareEntryPoint, }), logging, }); diff --git a/packages/astro/test/test-adapter.js b/packages/astro/test/test-adapter.js index 39bfe37b31d6..09d21b4771f9 100644 --- a/packages/astro/test/test-adapter.js +++ b/packages/astro/test/test-adapter.js @@ -74,18 +74,16 @@ export default function ( ...extendAdapter, }); }, - 'astro:build:ssr': ({ entryPoints }) => { + 'astro:build:ssr': ({ entryPoints, middlewareEntryPoint }) => { if (setEntryPoints) { setEntryPoints(entryPoints); + setEntryPoints(middlewareEntryPoint); } }, 'astro:build:done': ({ routes, middlewareEntryPoint }) => { if (setRoutes) { setRoutes(routes); } - if (setEntryPoints) { - setEntryPoints(middlewareEntryPoint); - } }, }, }; diff --git a/packages/integrations/vercel/src/serverless/adapter.ts b/packages/integrations/vercel/src/serverless/adapter.ts index aeebc74508e3..83108e896a5e 100644 --- a/packages/integrations/vercel/src/serverless/adapter.ts +++ b/packages/integrations/vercel/src/serverless/adapter.ts @@ -9,9 +9,11 @@ import { type VercelImageConfig, } from '../image/shared.js'; import { exposeEnv } from '../lib/env.js'; -import { getVercelOutput, removeDir, writeFile, writeJson } from '../lib/fs.js'; +import { getVercelOutput, removeDir, writeJson } from '../lib/fs.js'; import { copyDependenciesToFunction } from '../lib/nft.js'; import { getRedirects } from '../lib/redirects.js'; +import { generateEdgeMiddleware } from './middleware.js'; +import { fileURLToPath } from 'node:url'; const PACKAGE_NAME = '@astrojs/vercel/serverless'; @@ -43,6 +45,8 @@ export default function vercelServerless({ let functionFolder: URL; let serverEntry: string; + const filesToInclude = includeFiles?.map((file) => new URL(file, _config.root)) || []; + return { name: PACKAGE_NAME, hooks: { @@ -80,14 +84,23 @@ export default function vercelServerless({ `); } }, + + 'astro:build:ssr': async ({ middlewareEntryPoint }) => { + if (middlewareEntryPoint) { + const outPath = fileURLToPath(buildTempFolder); + const bundledMiddlewarePath = await generateEdgeMiddleware(middlewareEntryPoint, outPath); + // let's tell the adapter that we need to save this file + filesToInclude.push(bundledMiddlewarePath); + } + }, + 'astro:build:done': async ({ routes }) => { // Merge any includes from `vite.assetsInclude - const inc = includeFiles?.map((file) => new URL(file, _config.root)) || []; if (_config.vite.assetsInclude) { const mergeGlobbedIncludes = (globPattern: unknown) => { if (typeof globPattern === 'string') { const entries = glob.sync(globPattern).map((p) => pathToFileURL(p)); - inc.push(...entries); + filesToInclude.push(...entries); } else if (Array.isArray(globPattern)) { for (const pattern of globPattern) { mergeGlobbedIncludes(pattern); @@ -102,7 +115,7 @@ export default function vercelServerless({ const { handler } = await copyDependenciesToFunction({ entry: new URL(serverEntry, buildTempFolder), outDir: functionFolder, - includeFiles: inc, + includeFiles: filesToInclude, excludeFiles: excludeFiles?.map((file) => new URL(file, _config.root)) || [], }); diff --git a/packages/integrations/vercel/src/serverless/middleware.ts b/packages/integrations/vercel/src/serverless/middleware.ts new file mode 100644 index 000000000000..95f282af9a87 --- /dev/null +++ b/packages/integrations/vercel/src/serverless/middleware.ts @@ -0,0 +1,62 @@ +import { fileURLToPath, pathToFileURL } from 'node:url'; +import esbuild from 'esbuild'; +import { join } from 'node:path'; +import { writeFile } from '../lib/fs.js'; + +/** + * It generates the Vercel Edge Middleware file. + * + * It creates a temporary file, the edge middleware, with some dynamic info. + * + * Then this file gets bundled with esbuild. The bundle phase will inline the Astro middleware code. + * + * @param astroMiddlewareEntryPoint + * @param outPath + * @returns {Promise} The path to the bundled file + */ +export async function generateEdgeMiddleware( + astroMiddlewareEntryPointPath: URL, + outPath: string +): Promise { + const entryPointPathURLAsString = JSON.stringify( + fileURLToPath(astroMiddlewareEntryPointPath).replace(/\\/g, '/') + ); + const code = edgeMiddlewareTemplate(entryPointPathURLAsString); + // https://vercel.com/docs/concepts/functions/edge-middleware#create-edge-middleware + const bundledFilePath = join(outPath, 'middleware.mjs'); + await esbuild.build({ + stdin: { + contents: code, + resolveDir: process.cwd(), + }, + target: 'es2020', + platform: 'browser', + // https://runtime-keys.proposal.wintercg.org/#edge-light + conditions: ['edge-light', 'worker', 'browser'], + external: ['astro/middleware'], + // entryPoints: [middlewareEdgePath], + outfile: bundledFilePath, + allowOverwrite: true, + format: 'esm', + bundle: true, + minify: false, + }); + return pathToFileURL(bundledFilePath); +} + +function edgeMiddlewareTemplate(middlewarePath: string) { + return ` +import { onRequest } from ${middlewarePath}; +import { createAPIContext } from 'astro/middleware'; +export default function middleware(request) { + const url = new URL(request.url); + const next = async () => { + const response = await fetch(url); + return response; + }; + + const ctx = createAPIContext(request); + + return onRequest(ctx, next); +}`; +} diff --git a/packages/integrations/vercel/test/edge-middleware.test.js b/packages/integrations/vercel/test/edge-middleware.test.js index 0037adc92c37..10862bb438d1 100644 --- a/packages/integrations/vercel/test/edge-middleware.test.js +++ b/packages/integrations/vercel/test/edge-middleware.test.js @@ -8,6 +8,19 @@ describe('Serverless prerender', () => { before(async () => { fixture = await loadFixture({ root: './fixtures/middleware/', + build: { + excludeMiddleware: true, + }, }); }); + + it('build successfully the middleware edge file', async () => { + await fixture.build(); + expect( + await fixture.readFile( + // this is abysmal... + '../.vercel/output/functions/render.func/packages/integrations/vercel/test/fixtures/middleware/dist/middleware.mjs' + ) + ).to.be.ok; + }); }); From 5c20fc20fdd008c951f13b9a514965f9e108306a Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Fri, 30 Jun 2023 11:00:39 +0100 Subject: [PATCH 08/21] feat: connect vercel edge middleware to astro (#7523) --- .changeset/brown-shrimps-hug.md | 11 +++ .changeset/good-pigs-fetch.md | 1 + packages/astro/src/core/middleware/index.ts | 73 ++++++++++++++++- packages/integrations/vercel/README.md | 4 +- packages/integrations/vercel/package.json | 2 + packages/integrations/vercel/src/lib/nft.ts | 3 +- .../vercel/src/serverless/adapter.ts | 23 +++++- .../vercel/src/serverless/entrypoint.ts | 10 ++- .../vercel/src/serverless/middleware.ts | 43 +++++++--- .../vercel/test/edge-middleware.test.js | 24 +++--- .../vercel/test/edge-middleware.test.js.snap | 40 ++++++++++ .../test/fixtures/middleware/astro.config.mjs | 11 ++- .../middleware/src/vercel-edge-middleware.js | 5 ++ pnpm-lock.yaml | 80 +++++++++++++++++++ 14 files changed, 300 insertions(+), 30 deletions(-) create mode 100644 .changeset/brown-shrimps-hug.md create mode 100644 packages/integrations/vercel/test/edge-middleware.test.js.snap create mode 100644 packages/integrations/vercel/test/fixtures/middleware/src/vercel-edge-middleware.js diff --git a/.changeset/brown-shrimps-hug.md b/.changeset/brown-shrimps-hug.md new file mode 100644 index 000000000000..fc49318c1c3c --- /dev/null +++ b/.changeset/brown-shrimps-hug.md @@ -0,0 +1,11 @@ +--- +'astro': minor +--- + +Astro now exposes a utility called `trySerializeLocals` via `astro/middleware` module. + +This utility can be used by adapters to validate their `locals` before being sent +to the Astro middleware. + +This function will throw a runtime error if the value passed is not serializable, so +consumers will need to handle that error. diff --git a/.changeset/good-pigs-fetch.md b/.changeset/good-pigs-fetch.md index 041580958528..4907583b9d05 100644 --- a/.changeset/good-pigs-fetch.md +++ b/.changeset/good-pigs-fetch.md @@ -2,4 +2,5 @@ '@astrojs/vercel': minor --- +We are almost there (funny text to kick off the preview release) diff --git a/packages/astro/src/core/middleware/index.ts b/packages/astro/src/core/middleware/index.ts index 29c4b78e8048..47127c674888 100644 --- a/packages/astro/src/core/middleware/index.ts +++ b/packages/astro/src/core/middleware/index.ts @@ -32,5 +32,76 @@ function createContext({ request, params }: CreateContext) { }); } +/** + * Checks whether the passed `value` is serializable. + * + * A serializable value contains plain values. For example, `Proxy`, `Set`, `Map`, functions, etc. + * are not accepted because they can't be serialized. + */ +function isLocalsSerializable(value: unknown): boolean { + let type = typeof value; + let plainObject = true; + if (type === 'object' && isPlainObject(value)) { + for (const [, nestedValue] of Object.entries(value)) { + if (!isLocalsSerializable(nestedValue)) { + plainObject = false; + break; + } + } + } else { + plainObject = false; + } + let result = + value === null || + type === 'string' || + type === 'number' || + type === 'boolean' || + Array.isArray(value) || + plainObject; + + return result; +} + +/** + * + * From [redux-toolkit](https://github.com/reduxjs/redux-toolkit/blob/master/packages/toolkit/src/isPlainObject.ts) + * + * Returns true if the passed value is "plain" object, i.e. an object whose + * prototype is the root `Object.prototype`. This includes objects created + * using object literals, but not for instance for class instances. + */ +function isPlainObject(value: unknown): value is object { + if (typeof value !== 'object' || value === null) return false; + + let proto = Object.getPrototypeOf(value); + if (proto === null) return true; + + let baseProto = proto; + while (Object.getPrototypeOf(baseProto) !== null) { + baseProto = Object.getPrototypeOf(baseProto); + } + + return proto === baseProto; +} + +/** + * It attempts to serialize `value` and return it as a string. + * + * ## Errors + * If the `value` is not serializable if the function will throw a runtime error. + * + * Something is **not serializable** when it contains properties/values like functions, `Map`, `Set`, `Date`, + * and other types that can't be made a string. + * + * @param value + */ +function trySerializeLocals(value: unknown) { + if (isLocalsSerializable(value)) { + return JSON.stringify(value); + } else { + throw new Error("The passed value can't be serialized."); + } +} + // NOTE: this export must export only the functions that will be exposed to user-land as officials APIs -export { sequence, defineMiddleware, createContext }; +export { sequence, defineMiddleware, createContext, trySerializeLocals }; diff --git a/packages/integrations/vercel/README.md b/packages/integrations/vercel/README.md index 6b0848d444be..73c80757f424 100644 --- a/packages/integrations/vercel/README.md +++ b/packages/integrations/vercel/README.md @@ -208,9 +208,9 @@ export default defineConfig({ }); ``` -### Vercel Middleware +### Vercel Edge Middleware -You can use Vercel middleware to intercept a request and redirect before sending a response. Vercel middleware can run for Edge, SSR, and Static deployments. You don't need to install `@vercel/edge` to write middleware, but you do need to install it to use features such as geolocation. For more information see [Vercel’s middleware documentation](https://vercel.com/docs/concepts/functions/edge-middleware). +You can use Vercel edge middleware to intercept a request and redirect before sending a response. Vercel middleware can run for Edge, SSR, and Static deployments. You don't need to install `@vercel/edge` to write middleware, but you do need to install it to use features such as geolocation. For more information see [Vercel’s middleware documentation](https://vercel.com/docs/concepts/functions/edge-middleware). 1. Add a `middleware.js` file to the root of your project: diff --git a/packages/integrations/vercel/package.json b/packages/integrations/vercel/package.json index b3effb50306f..024bf0395dc7 100644 --- a/packages/integrations/vercel/package.json +++ b/packages/integrations/vercel/package.json @@ -64,9 +64,11 @@ }, "devDependencies": { "@types/set-cookie-parser": "^2.4.2", + "@vercel/edge": "^0.3.4", "astro": "workspace:*", "astro-scripts": "workspace:*", "chai": "^4.3.7", + "chai-jest-snapshot": "^2.0.0", "cheerio": "1.0.0-rc.12", "mocha": "^9.2.2", "rollup": "^3.20.1" diff --git a/packages/integrations/vercel/src/lib/nft.ts b/packages/integrations/vercel/src/lib/nft.ts index 46604db902ac..33c740fc9e42 100644 --- a/packages/integrations/vercel/src/lib/nft.ts +++ b/packages/integrations/vercel/src/lib/nft.ts @@ -1,7 +1,5 @@ -import { nodeFileTrace } from '@vercel/nft'; import { relative as relativePath } from 'node:path'; import { fileURLToPath } from 'node:url'; - import { copyFilesToFunction } from './fs.js'; export async function copyDependenciesToFunction({ @@ -23,6 +21,7 @@ export async function copyDependenciesToFunction({ base = new URL('../', base); } + const { nodeFileTrace } = await import('@vercel/nft'); const result = await nodeFileTrace([entryPath], { base: fileURLToPath(base), }); diff --git a/packages/integrations/vercel/src/serverless/adapter.ts b/packages/integrations/vercel/src/serverless/adapter.ts index 83108e896a5e..806e202ee42e 100644 --- a/packages/integrations/vercel/src/serverless/adapter.ts +++ b/packages/integrations/vercel/src/serverless/adapter.ts @@ -14,8 +14,19 @@ import { copyDependenciesToFunction } from '../lib/nft.js'; import { getRedirects } from '../lib/redirects.js'; import { generateEdgeMiddleware } from './middleware.js'; import { fileURLToPath } from 'node:url'; +import type { RequestContext } from '@vercel/edge'; const PACKAGE_NAME = '@astrojs/vercel/serverless'; +export const ASTRO_LOCALS_HEADER = 'x-astro-locals'; +export const VERCEL_EDGE_MIDDLEWARE_FILE = 'vercel-edge-middleware'; + +export type CreateLocals = ({ + request, + context, +}: { + request: Request; + context: RequestContext; +}) => object; function getAdapter(): AstroAdapter { return { @@ -31,6 +42,7 @@ export interface VercelServerlessConfig { analytics?: boolean; imageService?: boolean; imagesConfig?: VercelImageConfig; + createLocals?: CreateLocals; } export default function vercelServerless({ @@ -39,6 +51,7 @@ export default function vercelServerless({ analytics, imageService, imagesConfig, + createLocals, }: VercelServerlessConfig = {}): AstroIntegration { let _config: AstroConfig; let buildTempFolder: URL; @@ -88,7 +101,15 @@ export default function vercelServerless({ 'astro:build:ssr': async ({ middlewareEntryPoint }) => { if (middlewareEntryPoint) { const outPath = fileURLToPath(buildTempFolder); - const bundledMiddlewarePath = await generateEdgeMiddleware(middlewareEntryPoint, outPath); + const vercelEdgeMiddlewareHandlerPath = new URL( + VERCEL_EDGE_MIDDLEWARE_FILE, + _config.srcDir + ); + const bundledMiddlewarePath = await generateEdgeMiddleware( + middlewareEntryPoint, + outPath, + vercelEdgeMiddlewareHandlerPath + ); // let's tell the adapter that we need to save this file filesToInclude.push(bundledMiddlewarePath); } diff --git a/packages/integrations/vercel/src/serverless/entrypoint.ts b/packages/integrations/vercel/src/serverless/entrypoint.ts index 71ad2bfaef7f..3c0e22a28fbf 100644 --- a/packages/integrations/vercel/src/serverless/entrypoint.ts +++ b/packages/integrations/vercel/src/serverless/entrypoint.ts @@ -4,6 +4,7 @@ import { App } from 'astro/app'; import type { IncomingMessage, ServerResponse } from 'node:http'; import { getRequest, setResponse } from './request-transform'; +import { ASTRO_LOCALS_HEADER } from './adapter'; polyfill(globalThis, { exclude: 'window document', @@ -28,7 +29,14 @@ export const createExports = (manifest: SSRManifest) => { return res.end('Not found'); } - await setResponse(app, res, await app.render(request, routeData)); + let locals = {}; + if (request.headers.has(ASTRO_LOCALS_HEADER)) { + let localsAsString = request.headers.get(ASTRO_LOCALS_HEADER); + if (localsAsString) { + locals = JSON.parse(localsAsString); + } + } + await setResponse(app, res, await app.render(request, routeData, locals)); }; return { default: handler }; diff --git a/packages/integrations/vercel/src/serverless/middleware.ts b/packages/integrations/vercel/src/serverless/middleware.ts index 95f282af9a87..d083940a3ab9 100644 --- a/packages/integrations/vercel/src/serverless/middleware.ts +++ b/packages/integrations/vercel/src/serverless/middleware.ts @@ -1,7 +1,7 @@ import { fileURLToPath, pathToFileURL } from 'node:url'; -import esbuild from 'esbuild'; import { join } from 'node:path'; -import { writeFile } from '../lib/fs.js'; +import { ASTRO_LOCALS_HEADER, type CreateLocals } from './adapter.js'; +import { existsSync } from 'fs'; /** * It generates the Vercel Edge Middleware file. @@ -16,14 +16,17 @@ import { writeFile } from '../lib/fs.js'; */ export async function generateEdgeMiddleware( astroMiddlewareEntryPointPath: URL, - outPath: string + outPath: string, + vercelEdgeMiddlewareHandlerPath: URL ): Promise { const entryPointPathURLAsString = JSON.stringify( fileURLToPath(astroMiddlewareEntryPointPath).replace(/\\/g, '/') ); - const code = edgeMiddlewareTemplate(entryPointPathURLAsString); + + const code = edgeMiddlewareTemplate(entryPointPathURLAsString, vercelEdgeMiddlewareHandlerPath); // https://vercel.com/docs/concepts/functions/edge-middleware#create-edge-middleware const bundledFilePath = join(outPath, 'middleware.mjs'); + const esbuild = await import('esbuild'); await esbuild.build({ stdin: { contents: code, @@ -34,7 +37,6 @@ export async function generateEdgeMiddleware( // https://runtime-keys.proposal.wintercg.org/#edge-light conditions: ['edge-light', 'worker', 'browser'], external: ['astro/middleware'], - // entryPoints: [middlewareEdgePath], outfile: bundledFilePath, allowOverwrite: true, format: 'esm', @@ -44,19 +46,36 @@ export async function generateEdgeMiddleware( return pathToFileURL(bundledFilePath); } -function edgeMiddlewareTemplate(middlewarePath: string) { +function edgeMiddlewareTemplate(middlewarePath: string, vercelEdgeMiddlewareHandlerPath: URL) { + const filePathEdgeMiddleware = fileURLToPath(vercelEdgeMiddlewareHandlerPath); + let handlerTemplateImport = ''; + let handlerTemplateCall = '{}'; + if (existsSync(filePathEdgeMiddleware) + '.js' || existsSync(filePathEdgeMiddleware) + '.ts') { + const stringified = JSON.stringify(filePathEdgeMiddleware.replace(/\\/g, '/')); + handlerTemplateImport = `import handler from ${stringified}`; + handlerTemplateCall = `handler({ request, context })`; + } else { + } return ` + ${handlerTemplateImport} import { onRequest } from ${middlewarePath}; -import { createAPIContext } from 'astro/middleware'; -export default function middleware(request) { +import { createContext, trySerializeLocals } from 'astro/middleware'; +export default async function middleware(request, context) { const url = new URL(request.url); - const next = async () => { - const response = await fetch(url); + const ctx = createContext({ + request, + params: {} + }); + ctx.locals = ${handlerTemplateCall}; + const next = async () => { + const response = await fetch(url, { + headers: { + ${JSON.stringify(ASTRO_LOCALS_HEADER)}: trySerializeLocals(ctx.locals) + } + }); return response; }; - const ctx = createAPIContext(request); - return onRequest(ctx, next); }`; } diff --git a/packages/integrations/vercel/test/edge-middleware.test.js b/packages/integrations/vercel/test/edge-middleware.test.js index 10862bb438d1..dd4b25b677bc 100644 --- a/packages/integrations/vercel/test/edge-middleware.test.js +++ b/packages/integrations/vercel/test/edge-middleware.test.js @@ -1,26 +1,30 @@ import { loadFixture } from './test-utils.js'; -import { expect } from 'chai'; +import { expect, use } from 'chai'; +import chaiJestSnapshot from 'chai-jest-snapshot'; + +use(chaiJestSnapshot); describe('Serverless prerender', () => { /** @type {import('./test-utils').Fixture} */ let fixture; + beforeEach(function () { + chaiJestSnapshot.configureUsingMochaContext(this); + }); + before(async () => { + chaiJestSnapshot.resetSnapshotRegistry(); fixture = await loadFixture({ root: './fixtures/middleware/', - build: { - excludeMiddleware: true, - }, }); }); it('build successfully the middleware edge file', async () => { await fixture.build(); - expect( - await fixture.readFile( - // this is abysmal... - '../.vercel/output/functions/render.func/packages/integrations/vercel/test/fixtures/middleware/dist/middleware.mjs' - ) - ).to.be.ok; + const contents = await fixture.readFile( + // this is abysmal... + '../.vercel/output/functions/render.func/packages/integrations/vercel/test/fixtures/middleware/dist/middleware.mjs' + ); + expect(contents).to.matchSnapshot(); }); }); diff --git a/packages/integrations/vercel/test/edge-middleware.test.js.snap b/packages/integrations/vercel/test/edge-middleware.test.js.snap new file mode 100644 index 000000000000..fe82ccff9317 --- /dev/null +++ b/packages/integrations/vercel/test/edge-middleware.test.js.snap @@ -0,0 +1,40 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Serverless prerender build successfully the middleware edge file 1`] = ` +"// test/fixtures/middleware/src/vercel-edge-middleware.js +function vercel_edge_middleware_default({ request, context }) { + return { + title: \\"Hello world\\" + }; +} + +// test/fixtures/middleware/dist/middleware2.mjs +var onRequest = async (context, next) => { + const response = await next(); + return response; +}; + +// +import { createContext, trySerializeLocals } from \\"astro/middleware\\"; +async function middleware(request, context) { + const url = new URL(request.url); + const ctx = createContext({ + request, + params: {} + }); + ctx.locals = vercel_edge_middleware_default({ request, context }); + const next = async () => { + const response = await fetch(url, { + headers: { + \\"x-astro-locals\\": trySerializeLocals(ctx.locals) + } + }); + return response; + }; + return onRequest(ctx, next); +} +export { + middleware as default +}; +" +`; diff --git a/packages/integrations/vercel/test/fixtures/middleware/astro.config.mjs b/packages/integrations/vercel/test/fixtures/middleware/astro.config.mjs index 9d46508a9328..467cf25e72fd 100644 --- a/packages/integrations/vercel/test/fixtures/middleware/astro.config.mjs +++ b/packages/integrations/vercel/test/fixtures/middleware/astro.config.mjs @@ -2,6 +2,15 @@ import {defineConfig} from "astro/config"; import vercel from "@astrojs/vercel/serverless"; export default defineConfig({ - adapter: vercel(), + adapter: vercel({ + createLocals: ({request}) => { + console.log(request); + return { + "foo": "bar" + } + }}), + build: { + excludeMiddleware: true + }, output: 'server' }); \ No newline at end of file diff --git a/packages/integrations/vercel/test/fixtures/middleware/src/vercel-edge-middleware.js b/packages/integrations/vercel/test/fixtures/middleware/src/vercel-edge-middleware.js new file mode 100644 index 000000000000..bf69edb3e8bf --- /dev/null +++ b/packages/integrations/vercel/test/fixtures/middleware/src/vercel-edge-middleware.js @@ -0,0 +1,5 @@ +export default function ({ request, context }) { + return { + title: 'Hello world', + }; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ef41f94ae852..9a82d84c9694 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4889,6 +4889,9 @@ importers: '@types/set-cookie-parser': specifier: ^2.4.2 version: 2.4.2 + '@vercel/edge': + specifier: ^0.3.4 + version: 0.3.4 astro: specifier: workspace:* version: link:../../astro @@ -4898,6 +4901,9 @@ importers: chai: specifier: ^4.3.7 version: 4.3.7 + chai-jest-snapshot: + specifier: ^2.0.0 + version: 2.0.0(chai@4.3.7) cheerio: specifier: 1.0.0-rc.12 version: 1.0.0-rc.12 @@ -9011,6 +9017,10 @@ packages: optional: true dev: false + /@vercel/edge@0.3.4: + resolution: {integrity: sha512-dFU+yAUDQRwpuRGxRDlEO1LMq0y1LGsBgkyryQWe4w15/Fy2/lCnpvdIoAhHl3QvIGAxCLHzwRHsqfLRdpxgJQ==} + dev: true + /@vercel/nft@0.22.6: resolution: {integrity: sha512-gTsFnnT4mGxodr4AUlW3/urY+8JKKB452LwF3m477RFUJTAaDmcz2JqFuInzvdybYIeyIv1sSONEJxsxnbQ5JQ==} engines: {node: '>=14'} @@ -9351,6 +9361,11 @@ packages: type-fest: 1.4.0 dev: false + /ansi-regex@3.0.1: + resolution: {integrity: sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==} + engines: {node: '>=4'} + dev: true + /ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -9878,6 +9893,16 @@ packages: check-error: 1.0.2 dev: true + /chai-jest-snapshot@2.0.0(chai@4.3.7): + resolution: {integrity: sha512-u8jZZjw/0G1t5A8wDfH6K7DAVfMg3g0dsw9wKQURNUyrZX96VojHNrFMmLirq1m0kOvC5icgL/Qh/fu1MZyvUw==} + peerDependencies: + chai: '>=1.9.0' + dependencies: + chai: 4.3.7 + jest-snapshot: 21.2.1 + lodash.values: 4.3.0 + dev: true + /chai-xml@0.4.1(chai@4.3.7): resolution: {integrity: sha512-VUf5Ol4ifOAsgz+lN4tfWENgQtrKxHPWsmpL5wdbqQdkpblZkcDlaT2aFvsPQH219Yvl8vc4064yFErgBIn9bw==} engines: {node: '>= 0.8.0'} @@ -10584,6 +10609,11 @@ packages: /didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + /diff@3.5.0: + resolution: {integrity: sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==} + engines: {node: '>=0.3.1'} + dev: true + /diff@5.0.0: resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==} engines: {node: '>=0.3.1'} @@ -12824,6 +12854,38 @@ packages: minimatch: 3.1.2 dev: false + /jest-diff@21.2.1: + resolution: {integrity: sha512-E5fu6r7PvvPr5qAWE1RaUwIh/k6Zx/3OOkZ4rk5dBJkEWRrUuSgbMt2EO8IUTPTd6DOqU3LW6uTIwX5FRvXoFA==} + dependencies: + chalk: 2.4.2 + diff: 3.5.0 + jest-get-type: 21.2.0 + pretty-format: 21.2.1 + dev: true + + /jest-get-type@21.2.0: + resolution: {integrity: sha512-y2fFw3C+D0yjNSDp7ab1kcd6NUYfy3waPTlD8yWkAtiocJdBRQqNoRqVfMNxgj+IjT0V5cBIHJO0z9vuSSZ43Q==} + dev: true + + /jest-matcher-utils@21.2.1: + resolution: {integrity: sha512-kn56My+sekD43dwQPrXBl9Zn9tAqwoy25xxe7/iY4u+mG8P3ALj5IK7MLHZ4Mi3xW7uWVCjGY8cm4PqgbsqMCg==} + dependencies: + chalk: 2.4.2 + jest-get-type: 21.2.0 + pretty-format: 21.2.1 + dev: true + + /jest-snapshot@21.2.1: + resolution: {integrity: sha512-bpaeBnDpdqaRTzN8tWg0DqOTo2DvD3StOemxn67CUd1p1Po+BUpvePAp44jdJ7Pxcjfg+42o4NHw1SxdCA2rvg==} + dependencies: + chalk: 2.4.2 + jest-diff: 21.2.1 + jest-matcher-utils: 21.2.1 + mkdirp: 0.5.6 + natural-compare: 1.4.0 + pretty-format: 21.2.1 + dev: true + /jest-worker@26.6.2: resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} engines: {node: '>= 10.13.0'} @@ -13121,6 +13183,10 @@ packages: resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} dev: true + /lodash.values@4.3.0: + resolution: {integrity: sha512-r0RwvdCv8id9TUblb/O7rYPwVy6lerCbcawrfdo9iC/1t1wsNMJknO79WNBgwkH0hIeJ08jmvvESbFpNb4jH0Q==} + dev: true + /lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} dev: false @@ -14004,6 +14070,13 @@ packages: /mkdirp-classic@0.5.3: resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + /mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: true + /mkdirp@1.0.4: resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} engines: {node: '>=10'} @@ -15198,6 +15271,13 @@ packages: engines: {node: ^14.13.1 || >=16.0.0} dev: false + /pretty-format@21.2.1: + resolution: {integrity: sha512-ZdWPGYAnYfcVP8yKA3zFjCn8s4/17TeYH28MXuC8vTp0o21eXjbFGcOAXZEaDaOFJjc3h2qa7HQNHNshhvoh2A==} + dependencies: + ansi-regex: 3.0.1 + ansi-styles: 3.2.1 + dev: true + /pretty-format@27.5.1: resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} From 479bb7a7962b942133b51fa194b17dae14efdec5 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Fri, 30 Jun 2023 11:12:54 +0100 Subject: [PATCH 09/21] fix merge conflicts --- packages/integrations/vercel/src/serverless/adapter.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/integrations/vercel/src/serverless/adapter.ts b/packages/integrations/vercel/src/serverless/adapter.ts index f7fefb00e0f5..f0c131e27239 100644 --- a/packages/integrations/vercel/src/serverless/adapter.ts +++ b/packages/integrations/vercel/src/serverless/adapter.ts @@ -43,7 +43,6 @@ export interface VercelServerlessConfig { analytics?: boolean; imageService?: boolean; imagesConfig?: VercelImageConfig; - createLocals?: CreateLocals; } export default function vercelServerless({ @@ -52,7 +51,6 @@ export default function vercelServerless({ analytics, imageService, imagesConfig, - createLocals, }: VercelServerlessConfig = {}): AstroIntegration { let _config: AstroConfig; let buildTempFolder: URL; @@ -165,14 +163,18 @@ export default function vercelServerless({ if (_entryPoints.size) { for (const [route, entryFile] of _entryPoints) { const func = basename(entryFile.toString()).replace(/\.mjs$/, ''); - await createFunctionFolder(func, entryFile, inc); + await createFunctionFolder(func, entryFile, filesToInclude); routeDefinitions.push({ src: route.pattern.source, dest: func, }); } } else { - await createFunctionFolder('render', new URL(serverEntry, buildTempFolder), inc); + await createFunctionFolder( + 'render', + new URL(serverEntry, buildTempFolder), + filesToInclude + ); routeDefinitions.push({ src: '/.*', dest: 'render' }); } From da6a9883ff9fb71ba65aff7bf7954f8b2488aeba Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Fri, 30 Jun 2023 12:56:52 +0100 Subject: [PATCH 10/21] update lock file --- pnpm-lock.yaml | 220 +++++++++++++++++++++++++++++-------------------- 1 file changed, 131 insertions(+), 89 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9a82d84c9694..53d541a2a4e6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -60,8 +60,8 @@ importers: specifier: ^2.8.8 version: 2.8.8 prettier-plugin-astro: - specifier: ^0.8.1 - version: 0.8.1 + specifier: ^0.10.0 + version: 0.10.0 tiny-glob: specifier: ^0.2.9 version: 0.2.9 @@ -127,7 +127,7 @@ importers: examples/basics: dependencies: astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro examples/blog: @@ -142,19 +142,19 @@ importers: specifier: ^1.3.3 version: link:../../packages/integrations/sitemap astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro examples/component: devDependencies: astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro examples/deno: dependencies: astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro devDependencies: '@astrojs/deno': @@ -173,7 +173,7 @@ importers: specifier: ^3.12.2 version: 3.12.2 astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro examples/framework-lit: @@ -185,7 +185,7 @@ importers: specifier: ^0.2.1 version: 0.2.1 astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro lit: specifier: ^2.7.5 @@ -203,13 +203,13 @@ importers: specifier: ^2.2.0 version: link:../../packages/integrations/solid '@astrojs/svelte': - specifier: ^3.0.0 + specifier: ^3.1.0 version: link:../../packages/integrations/svelte '@astrojs/vue': specifier: ^2.2.1 version: link:../../packages/integrations/vue astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro preact: specifier: ^10.15.1 @@ -239,7 +239,7 @@ importers: specifier: ^1.1.3 version: 1.1.3(preact@10.15.1) astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro preact: specifier: ^10.15.1 @@ -257,7 +257,7 @@ importers: specifier: ^18.2.6 version: 18.2.6 astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro react: specifier: ^18.2.0 @@ -272,7 +272,7 @@ importers: specifier: ^2.2.0 version: link:../../packages/integrations/solid astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro solid-js: specifier: ^1.7.6 @@ -281,10 +281,10 @@ importers: examples/framework-svelte: dependencies: '@astrojs/svelte': - specifier: ^3.0.0 + specifier: ^3.1.0 version: link:../../packages/integrations/svelte astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro svelte: specifier: ^3.59.1 @@ -296,7 +296,7 @@ importers: specifier: ^2.2.1 version: link:../../packages/integrations/vue astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro vue: specifier: ^3.3.4 @@ -308,13 +308,13 @@ importers: specifier: ^5.3.0 version: link:../../packages/integrations/node astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro examples/integration: devDependencies: astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro examples/middleware: @@ -323,7 +323,7 @@ importers: specifier: ^5.3.0 version: link:../../packages/integrations/node astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro html-minifier: specifier: ^4.0.0 @@ -332,19 +332,19 @@ importers: examples/minimal: dependencies: astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro examples/non-html-pages: dependencies: astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro examples/portfolio: dependencies: astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro examples/ssr: @@ -353,10 +353,10 @@ importers: specifier: ^5.3.0 version: link:../../packages/integrations/node '@astrojs/svelte': - specifier: ^3.0.0 + specifier: ^3.1.0 version: link:../../packages/integrations/svelte astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro svelte: specifier: ^3.59.1 @@ -365,10 +365,10 @@ importers: examples/with-markdoc: dependencies: '@astrojs/markdoc': - specifier: ^0.3.3 + specifier: ^0.4.0 version: link:../../packages/integrations/markdoc astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro examples/with-markdown-plugins: @@ -377,7 +377,7 @@ importers: specifier: ^2.2.1 version: link:../../packages/markdown/remark astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro hast-util-select: specifier: ^5.0.5 @@ -398,7 +398,7 @@ importers: examples/with-markdown-shiki: dependencies: astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro examples/with-mdx: @@ -410,7 +410,7 @@ importers: specifier: ^2.2.1 version: link:../../packages/integrations/preact astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro preact: specifier: ^10.15.1 @@ -425,7 +425,7 @@ importers: specifier: ^0.4.1 version: 0.4.1(nanostores@0.8.1)(preact@10.15.1) astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro nanostores: specifier: ^0.8.1 @@ -446,7 +446,7 @@ importers: specifier: ^1.6.0 version: 1.6.0 astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro autoprefixer: specifier: ^10.4.14 @@ -464,7 +464,7 @@ importers: examples/with-vite-plugin-pwa: dependencies: astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro vite-plugin-pwa: specifier: 0.14.7 @@ -476,7 +476,7 @@ importers: examples/with-vitest: dependencies: astro: - specifier: ^2.7.0 + specifier: ^2.7.2 version: link:../../packages/astro vitest: specifier: ^0.31.4 @@ -488,7 +488,7 @@ importers: specifier: ^1.5.0 version: 1.5.0 '@astrojs/internal-helpers': - specifier: ^0.1.0 + specifier: ^0.1.1 version: link:../internal-helpers '@astrojs/language-server': specifier: ^1.0.0 @@ -611,26 +611,20 @@ importers: specifier: ^12.0.1 version: 12.0.1 semver: - specifier: ^7.5.2 - version: 7.5.2 + specifier: ^7.5.3 + version: 7.5.3 server-destroy: specifier: ^1.0.1 version: 1.0.1 shiki: specifier: ^0.14.1 version: 0.14.1 - slash: - specifier: ^4.0.0 - version: 4.0.0 string-width: specifier: ^5.1.2 version: 5.1.2 strip-ansi: specifier: ^7.1.0 version: 7.1.0 - supports-esm: - specifier: ^1.0.0 - version: 1.0.0 tsconfig-resolver: specifier: ^3.0.1 version: 3.0.1 @@ -790,8 +784,8 @@ importers: packages/astro-rss: dependencies: fast-xml-parser: - specifier: ^4.2.4 - version: 4.2.4 + specifier: ^4.2.5 + version: 4.2.5 kleur: specifier: ^4.1.5 version: 4.1.5 @@ -974,6 +968,9 @@ importers: react-dom: specifier: ^18.1.0 version: 18.2.0(react@18.2.0) + sass: + specifier: ^1.63.4 + version: 1.63.4 solid-js: specifier: ^1.7.6 version: 1.7.6 @@ -3638,9 +3635,6 @@ importers: mocha: specifier: ^9.2.2 version: 9.2.2 - slash: - specifier: ^4.0.0 - version: 4.0.0 wrangler: specifier: ^2.0.23 version: 2.0.23 @@ -3681,6 +3675,15 @@ importers: specifier: workspace:* version: link:../../../../../astro + packages/integrations/cloudflare/test/fixtures/split: + dependencies: + '@astrojs/cloudflare': + specifier: workspace:* + version: link:../../.. + astro: + specifier: workspace:* + version: link:../../../../../astro + packages/integrations/cloudflare/test/fixtures/with-solid-js: dependencies: '@astrojs/cloudflare': @@ -3977,6 +3980,9 @@ importers: packages/integrations/markdoc: dependencies: + '@astrojs/internal-helpers': + specifier: ^0.1.0 + version: link:../../internal-helpers '@astrojs/prism': specifier: ^2.1.2 version: link:../../astro-prism @@ -4802,8 +4808,8 @@ importers: packages/integrations/svelte: dependencies: '@sveltejs/vite-plugin-svelte': - specifier: ^2.4.1 - version: 2.4.1(svelte@3.59.1)(vite@4.3.9) + specifier: ^2.4.2 + version: 2.4.2(svelte@3.59.1)(vite@4.3.9) svelte2tsx: specifier: ^0.6.15 version: 0.6.15(svelte@3.59.1)(typescript@5.0.2) @@ -4862,7 +4868,7 @@ importers: packages/integrations/vercel: dependencies: '@astrojs/internal-helpers': - specifier: ^0.1.0 + specifier: ^0.1.1 version: link:../../internal-helpers '@astrojs/webapi': specifier: ^2.2.0 @@ -4914,6 +4920,15 @@ importers: specifier: ^3.20.1 version: 3.25.1 + packages/integrations/vercel/test/fixtures/basic: + dependencies: + '@astrojs/vercel': + specifier: workspace:* + version: link:../../.. + astro: + specifier: workspace:* + version: link:../../../../../astro + packages/integrations/vercel/test/fixtures/image: dependencies: '@astrojs/vercel': @@ -7737,10 +7752,6 @@ packages: dependencies: '@lit-labs/ssr-dom-shim': 1.1.1 - /@ljharb/has-package-exports-patterns@0.0.2: - resolution: {integrity: sha512-4/RWEeXDO6bocPONheFe6gX/oQdP/bEpv0oL4HqjPP5DCenBSt0mHgahppY49N0CpsaqffdwPq+TlX9CYOq2Dw==} - dev: false - /@manypkg/find-root@1.1.0: resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} dependencies: @@ -7772,7 +7783,7 @@ packages: nopt: 5.0.0 npmlog: 5.0.1 rimraf: 3.0.2 - semver: 7.5.2 + semver: 7.5.3 tar: 6.1.15 transitivePeerDependencies: - encoding @@ -8181,6 +8192,7 @@ packages: open: 9.1.0 picocolors: 1.0.0 tslib: 2.5.3 + dev: false /@playwright/test@1.29.2: resolution: {integrity: sha512-+3/GPwOgcoF0xLz/opTnahel1/y42PdcgZ4hs+BZGIUjtmEFSXGg+nFoaH3NSmuc7a6GSFwXDJ5L7VXpqzigNg==} @@ -8398,18 +8410,18 @@ packages: string.prototype.matchall: 4.0.8 dev: false - /@sveltejs/vite-plugin-svelte-inspector@1.0.2(@sveltejs/vite-plugin-svelte@2.4.1)(svelte@3.59.1)(vite@4.3.9): - resolution: {integrity: sha512-Cy1dUMcYCnDVV/hPLXa43YZJ2jGKVW5rA0xuNL9dlmYhT0yoS1g7+FOFSRlgk0BXKk/Oc7grs+8BVA5Iz2fr8A==} + /@sveltejs/vite-plugin-svelte-inspector@1.0.3(@sveltejs/vite-plugin-svelte@2.4.2)(svelte@3.59.1)(vite@4.3.9): + resolution: {integrity: sha512-Khdl5jmmPN6SUsVuqSXatKpQTMIifoQPDanaxC84m9JxIibWvSABJyHpyys0Z+1yYrxY5TTEQm+6elh0XCMaOA==} engines: {node: ^14.18.0 || >= 16} peerDependencies: '@sveltejs/vite-plugin-svelte': ^2.2.0 - svelte: ^3.54.0 || ^4.0.0-next.0 + svelte: ^3.54.0 || ^4.0.0 vite: ^4.0.0 peerDependenciesMeta: vite: optional: true dependencies: - '@sveltejs/vite-plugin-svelte': 2.4.1(svelte@3.59.1)(vite@4.3.9) + '@sveltejs/vite-plugin-svelte': 2.4.2(svelte@3.59.1)(vite@4.3.9) debug: 4.3.4 svelte: 3.59.1 vite: 4.3.9(@types/node@18.16.18)(sass@1.63.4) @@ -8417,23 +8429,23 @@ packages: - supports-color dev: false - /@sveltejs/vite-plugin-svelte@2.4.1(svelte@3.59.1)(vite@4.3.9): - resolution: {integrity: sha512-bNNKvoRY89ptY7udeBSCmTdCVwkjmMcZ0j/z9J5MuedT8jPjq0zrknAo/jF1sToAza4NVaAgR9AkZoD9oJJmnA==} + /@sveltejs/vite-plugin-svelte@2.4.2(svelte@3.59.1)(vite@4.3.9): + resolution: {integrity: sha512-ePfcC48ftMKhkT0OFGdOyycYKnnkT6i/buzey+vHRTR/JpQvuPzzhf1PtKqCDQfJRgoPSN2vscXs6gLigx/zGw==} engines: {node: ^14.18.0 || >= 16} peerDependencies: - svelte: ^3.54.0 || ^4.0.0-next.0 + svelte: ^3.54.0 || ^4.0.0 vite: ^4.0.0 peerDependenciesMeta: vite: optional: true dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 1.0.2(@sveltejs/vite-plugin-svelte@2.4.1)(svelte@3.59.1)(vite@4.3.9) + '@sveltejs/vite-plugin-svelte-inspector': 1.0.3(@sveltejs/vite-plugin-svelte@2.4.2)(svelte@3.59.1)(vite@4.3.9) debug: 4.3.4 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.0 svelte: 3.59.1 - svelte-hmr: 0.15.1(svelte@3.59.1) + svelte-hmr: 0.15.2(svelte@3.59.1) vite: 4.3.9(@types/node@18.16.18)(sass@1.63.4) vitefu: 0.2.4(vite@4.3.9) transitivePeerDependencies: @@ -8866,7 +8878,7 @@ packages: grapheme-splitter: 1.0.4 ignore: 5.2.4 natural-compare-lite: 1.4.0 - semver: 7.5.2 + semver: 7.5.3 tsutils: 3.21.0(typescript@5.0.2) typescript: 5.0.2 transitivePeerDependencies: @@ -8940,7 +8952,7 @@ packages: debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 - semver: 7.5.2 + semver: 7.5.3 tsutils: 3.21.0(typescript@5.0.2) typescript: 5.0.2 transitivePeerDependencies: @@ -8961,7 +8973,7 @@ packages: '@typescript-eslint/typescript-estree': 5.60.0(typescript@5.0.2) eslint: 8.43.0 eslint-scope: 5.1.1 - semver: 7.5.2 + semver: 7.5.3 transitivePeerDependencies: - supports-color - typescript @@ -9675,6 +9687,7 @@ packages: /big-integer@1.6.51: resolution: {integrity: sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==} engines: {node: '>=0.6'} + dev: false /binary-extensions@2.2.0: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} @@ -9745,6 +9758,7 @@ packages: engines: {node: '>= 5.10.0'} dependencies: big-integer: 1.6.51 + dev: false /brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} @@ -9809,7 +9823,7 @@ packages: /builtins@5.0.1: resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==} dependencies: - semver: 7.5.2 + semver: 7.5.3 dev: true /bundle-name@3.0.0: @@ -9817,6 +9831,7 @@ packages: engines: {node: '>=12'} dependencies: run-applescript: 5.0.0 + dev: false /busboy@1.6.0: resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} @@ -10194,7 +10209,7 @@ packages: js-string-escape: 1.0.1 lodash: 4.17.21 md5-hex: 3.0.1 - semver: 7.5.2 + semver: 7.5.3 well-known-symbols: 2.0.0 dev: false @@ -10510,6 +10525,7 @@ packages: dependencies: bplist-parser: 0.2.0 untildify: 4.0.0 + dev: false /default-browser@4.0.0: resolution: {integrity: sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==} @@ -10519,6 +10535,7 @@ packages: default-browser-id: 3.0.0 execa: 7.1.1 titleize: 3.0.0 + dev: false /defaults@1.0.4: resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} @@ -10528,6 +10545,7 @@ packages: /define-lazy-prop@3.0.0: resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} engines: {node: '>=12'} + dev: false /define-properties@1.2.0: resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==} @@ -11566,6 +11584,7 @@ packages: onetime: 5.1.2 signal-exit: 3.0.7 strip-final-newline: 2.0.0 + dev: false /execa@6.1.0: resolution: {integrity: sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==} @@ -11594,6 +11613,7 @@ packages: onetime: 6.0.0 signal-exit: 3.0.7 strip-final-newline: 3.0.0 + dev: false /expand-template@2.0.3: resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} @@ -11645,8 +11665,8 @@ packages: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} dev: true - /fast-xml-parser@4.2.4: - resolution: {integrity: sha512-fbfMDvgBNIdDJLdLOwacjFAPYt67tr31H9ZhWSm45CDAxvd0I6WTlSOUo7K2P/K5sA5JgMKG64PI3DMcaFdWpQ==} + /fast-xml-parser@4.2.5: + resolution: {integrity: sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==} hasBin: true dependencies: strnum: 1.0.5 @@ -12135,12 +12155,6 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - /has-package-exports@1.3.0: - resolution: {integrity: sha512-e9OeXPQnmPhYoJ63lXC4wWe34TxEGZDZ3OQX9XRqp2VwsfLl3bQBy7VehLnd34g3ef8CmYlBLGqEMKXuz8YazQ==} - dependencies: - '@ljharb/has-package-exports-patterns': 0.0.2 - dev: false - /has-property-descriptors@1.0.0: resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} dependencies: @@ -12446,6 +12460,7 @@ packages: /human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} + dev: false /human-signals@3.0.1: resolution: {integrity: sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==} @@ -12454,6 +12469,7 @@ packages: /human-signals@4.3.1: resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} engines: {node: '>=14.18.0'} + dev: false /hyperid@3.1.1: resolution: {integrity: sha512-RveV33kIksycSf7HLkq1sHB5wW0OwuX8ot8MYnY++gaaPXGFfKpBncHrAWxdpuEeRlazUMGWefwP1w6o6GaumA==} @@ -12638,11 +12654,13 @@ packages: resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} engines: {node: '>=8'} hasBin: true + dev: false /is-docker@3.0.0: resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} hasBin: true + dev: false /is-extendable@0.1.1: resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} @@ -12677,6 +12695,7 @@ packages: hasBin: true dependencies: is-docker: 3.0.0 + dev: false /is-interactive@2.0.0: resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} @@ -12777,6 +12796,7 @@ packages: /is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} + dev: false /is-stream@3.0.0: resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} @@ -12835,6 +12855,7 @@ packages: engines: {node: '>=8'} dependencies: is-docker: 2.2.1 + dev: false /isarray@0.0.1: resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==} @@ -13953,6 +13974,7 @@ packages: /mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} + dev: false /mimic-fn@4.0.0: resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} @@ -14215,7 +14237,7 @@ packages: resolution: {integrity: sha512-zNy02qivjjRosswoYmPi8hIKJRr8MpQyeKT6qlcq/OnOgA3Rhoae+IYOqsM9V5+JnHWmxKnWOT2GxvtqdtOCXA==} engines: {node: '>=10'} dependencies: - semver: 7.5.2 + semver: 7.5.3 /node-addon-api@6.1.0: resolution: {integrity: sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==} @@ -14328,6 +14350,7 @@ packages: engines: {node: '>=8'} dependencies: path-key: 3.1.1 + dev: false /npm-run-path@5.1.0: resolution: {integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==} @@ -14349,7 +14372,7 @@ packages: dependencies: execa: 6.1.0 parse-package-name: 1.0.0 - semver: 7.5.2 + semver: 7.5.3 validate-npm-package-name: 4.0.0 dev: true @@ -14408,6 +14431,7 @@ packages: engines: {node: '>=6'} dependencies: mimic-fn: 2.1.0 + dev: false /onetime@6.0.0: resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} @@ -14431,6 +14455,7 @@ packages: define-lazy-prop: 3.0.0 is-inside-container: 1.0.0 is-wsl: 2.2.0 + dev: false /optionator@0.8.3: resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==} @@ -15247,6 +15272,15 @@ packages: fast-diff: 1.2.0 dev: true + /prettier-plugin-astro@0.10.0: + resolution: {integrity: sha512-dPzop0gKZyVGpTDQmfy+e7FKXC9JT3mlpfYA2diOVz+Ui+QR1U4G/s+OesKl2Hib2JJOtAYJs/l+ovgT0ljlFA==} + engines: {node: ^14.15.0 || >=16.0.0, pnpm: '>=7.14.0'} + dependencies: + '@astrojs/compiler': 1.5.0 + prettier: 2.8.8 + sass-formatter: 0.7.6 + dev: true + /prettier-plugin-astro@0.8.1: resolution: {integrity: sha512-lJ/mG/Lz/ccSwNtwqpFS126mtMVzFVyYv0ddTF9wqwrEG4seECjKDAyw/oGv915rAcJi8jr89990nqfpmG+qdg==} engines: {node: ^14.15.0 || >=16.0.0, pnpm: '>=7.14.0'} @@ -15255,6 +15289,7 @@ packages: prettier: 2.8.8 sass-formatter: 0.7.6 synckit: 0.8.5 + dev: false /prettier@2.8.8: resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} @@ -15919,6 +15954,7 @@ packages: engines: {node: '>=12'} dependencies: execa: 5.1.1 + dev: false /run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -16013,6 +16049,14 @@ packages: hasBin: true dependencies: lru-cache: 6.0.0 + dev: false + + /semver@7.5.3: + resolution: {integrity: sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 /send@0.18.0: resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} @@ -16072,7 +16116,7 @@ packages: detect-libc: 2.0.1 node-addon-api: 6.1.0 prebuild-install: 7.1.1 - semver: 7.5.2 + semver: 7.5.3 simple-get: 4.0.1 tar-fs: 2.1.1 tunnel-agent: 0.6.0 @@ -16470,6 +16514,7 @@ packages: /strip-final-newline@2.0.0: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} + dev: false /strip-final-newline@3.0.0: resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} @@ -16553,21 +16598,15 @@ packages: dependencies: has-flag: 4.0.0 - /supports-esm@1.0.0: - resolution: {integrity: sha512-96Am8CDqUaC0I2+C/swJ0yEvM8ZnGn4unoers/LSdE4umhX7mELzqyLzx3HnZAluq5PXIsGMKqa7NkqaeHMPcg==} - dependencies: - has-package-exports: 1.3.0 - dev: false - /supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - /svelte-hmr@0.15.1(svelte@3.59.1): - resolution: {integrity: sha512-BiKB4RZ8YSwRKCNVdNxK/GfY+r4Kjgp9jCLEy0DuqAKfmQtpL38cQK3afdpjw4sqSs4PLi3jIPJIFp259NkZtA==} + /svelte-hmr@0.15.2(svelte@3.59.1): + resolution: {integrity: sha512-q/bAruCvFLwvNbeE1x3n37TYFb3mTBJ6TrCq6p2CoFbSTNhDE9oAtEfpy+wmc9So8AG0Tja+X0/mJzX9tSfvIg==} engines: {node: ^12.20 || ^14.13.1 || >= 16} peerDependencies: - svelte: '>=3.19.0' + svelte: ^3.19.0 || ^4.0.0-next.0 dependencies: svelte: 3.59.1 dev: false @@ -16605,6 +16644,7 @@ packages: dependencies: '@pkgr/utils': 2.4.0 tslib: 2.5.3 + dev: false /tailwindcss@3.3.2: resolution: {integrity: sha512-9jPkMiIBXvPc2KywkraqsUfbfj+dHDb+JPWtSJa9MLFdrPyazI7q6WX2sUrm7R9eVR7qqv3Pas7EvQFzxKnI6w==} @@ -16768,6 +16808,7 @@ packages: /titleize@3.0.0: resolution: {integrity: sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==} engines: {node: '>=12'} + dev: false /tmp@0.0.33: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} @@ -17259,6 +17300,7 @@ packages: /untildify@4.0.0: resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} engines: {node: '>=8'} + dev: false /upath@1.2.0: resolution: {integrity: sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==} From 1d0e8f6ec7968b5e8d947b27826ed553325798d3 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Fri, 30 Jun 2023 13:27:29 +0100 Subject: [PATCH 11/21] chore: documentation --- .changeset/good-pigs-fetch.md | 7 +++- packages/integrations/vercel/README.md | 55 ++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/.changeset/good-pigs-fetch.md b/.changeset/good-pigs-fetch.md index 4907583b9d05..4a463044e50a 100644 --- a/.changeset/good-pigs-fetch.md +++ b/.changeset/good-pigs-fetch.md @@ -2,5 +2,10 @@ '@astrojs/vercel': minor --- -We are almost there (funny text to kick off the preview release) +Support for Vercel Edge Middleware via Astro middleware. +When a project uses the new option Astro `build.excludeMiddleware`, the +`@astrojs/vercel/serverless` adapter will automatically create a Vercel Edge Middleware +that will automatically communicate with the Astro Middleware. + +Check the [documentation](https://github.com/withastro/astro/blob/main/packages/integrations/vercel/README.md##vercel-edge-middleware-with-astro-middleware) for more details. diff --git a/packages/integrations/vercel/README.md b/packages/integrations/vercel/README.md index 452888b7281c..ced5b4927acd 100644 --- a/packages/integrations/vercel/README.md +++ b/packages/integrations/vercel/README.md @@ -262,6 +262,61 @@ You can use Vercel edge middleware to intercept a request and redirect before se > **Warning** > **Trying to rewrite?** Currently rewriting a request with middleware only works for static files. +### Vercel Edge Middleware with Astro middleware + +The `@astrojs/vercel/serverless` adapter can automatically create the vercel edge middleware when you have an Astro middleware in you code base. + +This is an opt-in feature, and the `build.excludeMiddleware` option needs to be set to `true`: + +```js +// astro.config.mjs +import {defineConfig} from "astro/config"; +import vercel from "@astrojs/vercel"; +export default definConfig({ + output: "server", + adapter: vercel(), + build: { + excludeMiddleware: true + } +}) +``` + +Optionally, you can create a known file called `vercel-edge-middleware.(js|ts)` in the [`srcDir`](https://docs.astro.build/en/reference/configuration-reference/#srcdir) folder to create [`Astro.locals`](https://docs.astro.build/en/reference/api-reference/#astrolocals). + +```js +// src/vercel-edge-middleware.js + +export default function({ request, context }) { + // do something with request and context + return { + title: "Spider-man's blog" + } +} +``` + +The data returned by this function will be passed to Astro middleware. + +The function: +- must export a **default** function; +- must **return** an `object`; +- accepts an object with a `request` and `context` as properties; +- `request` is typed as [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request); +- `context` is typed as [`RequestContext`](https://vercel.com/docs/concepts/functions/edge-functions/vercel-edge-package#requestcontext); + +#### Limitations and constraints + +When you opt in this feature, there are few constraints to take into consideration: +- the Vercel Edge middleware will always be the **first** function to receive the `Request` and the last function to receive `Response`. + + This an architectural constraint that follows the [boundaries set by Vercel](https://vercel.com/docs/concepts/functions/edge-middleware). +- you're allowed to use `request` and `context` only to produce an `Astro.locals` object. + + Operations like redirects, etc. should be delegated to Astro middleware +- `Astro.locals` **must be serializable**, failing to do so will result in a **runtime error**. + + This means that you **can't** store complex types like `Map`, `function`, `Set`, etc. + + ## Troubleshooting **A few known complex packages (example: [puppeteer](https://github.com/puppeteer/puppeteer)) do not support bundling and therefore will not work properly with this adapter.** By default, Vercel doesn't include npm installed files & packages from your project's `./node_modules` folder. To address this, the `@astrojs/vercel` adapter automatically bundles your final build output using `esbuild`. From 54e6a1843a30585b634d854c79f54b167c17a2d9 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Tue, 4 Jul 2023 09:55:41 +0100 Subject: [PATCH 12/21] chore: rebase --- .../astro/src/core/build/plugins/index.ts | 2 +- .../core/build/plugins/plugin-middleware.ts | 9 +- pnpm-lock.yaml | 213 +++++++++--------- 3 files changed, 111 insertions(+), 113 deletions(-) diff --git a/packages/astro/src/core/build/plugins/index.ts b/packages/astro/src/core/build/plugins/index.ts index 160e18fdd8a6..3a44824d6119 100644 --- a/packages/astro/src/core/build/plugins/index.ts +++ b/packages/astro/src/core/build/plugins/index.ts @@ -19,7 +19,7 @@ export function registerAllPlugins({ internals, options, register }: AstroBuildP register(pluginAnalyzer(internals)); register(pluginInternals(internals)); register(pluginRenderers(options)); - register(pluginMiddleware(options)); + register(pluginMiddleware(options, internals)); register(pluginPages(options, internals)); register(pluginCSS(options, internals)); register(astroHeadBuildPlugin(internals)); diff --git a/packages/astro/src/core/build/plugins/plugin-middleware.ts b/packages/astro/src/core/build/plugins/plugin-middleware.ts index 89eb1ef41bc1..6db39733ef83 100644 --- a/packages/astro/src/core/build/plugins/plugin-middleware.ts +++ b/packages/astro/src/core/build/plugins/plugin-middleware.ts @@ -3,7 +3,7 @@ import { MIDDLEWARE_PATH_SEGMENT_NAME } from '../../constants.js'; import { addRollupInput } from '../add-rollup-input.js'; import type { AstroBuildPlugin } from '../plugin'; import type { StaticBuildOptions } from '../types'; -import { viteID } from '../../util.js'; +import type { BuildInternals } from '../internal'; export const MIDDLEWARE_MODULE_ID = '@astro-middleware'; @@ -64,13 +64,16 @@ export function vitePluginMiddleware( }; } -export function pluginMiddleware(opts: StaticBuildOptions): AstroBuildPlugin { +export function pluginMiddleware( + opts: StaticBuildOptions, + internals: BuildInternals +): AstroBuildPlugin { return { build: 'ssr', hooks: { 'build:before': () => { return { - vitePlugin: vitePluginMiddleware(opts), + vitePlugin: vitePluginMiddleware(opts, internals), }; }, }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 53d541a2a4e6..07bb4948cfab 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -30,11 +30,11 @@ importers: specifier: ^18.16.18 version: 18.16.18 '@typescript-eslint/eslint-plugin': - specifier: ^5.60.0 - version: 5.60.0(@typescript-eslint/parser@5.60.0)(eslint@8.43.0)(typescript@5.0.2) + specifier: 6.0.0-alpha.158 + version: 6.0.0-alpha.158(@typescript-eslint/parser@6.0.0-alpha.158)(eslint@8.43.0)(typescript@5.0.2) '@typescript-eslint/parser': - specifier: ^5.60.0 - version: 5.60.0(eslint@8.43.0)(typescript@5.0.2) + specifier: 6.0.0-alpha.158 + version: 6.0.0-alpha.158(eslint@8.43.0)(typescript@5.0.2) esbuild: specifier: ^0.17.19 version: 0.17.19 @@ -127,7 +127,7 @@ importers: examples/basics: dependencies: astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro examples/blog: @@ -142,19 +142,19 @@ importers: specifier: ^1.3.3 version: link:../../packages/integrations/sitemap astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro examples/component: devDependencies: astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro examples/deno: dependencies: astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro devDependencies: '@astrojs/deno': @@ -173,7 +173,7 @@ importers: specifier: ^3.12.2 version: 3.12.2 astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro examples/framework-lit: @@ -185,7 +185,7 @@ importers: specifier: ^0.2.1 version: 0.2.1 astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro lit: specifier: ^2.7.5 @@ -209,7 +209,7 @@ importers: specifier: ^2.2.1 version: link:../../packages/integrations/vue astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro preact: specifier: ^10.15.1 @@ -239,7 +239,7 @@ importers: specifier: ^1.1.3 version: 1.1.3(preact@10.15.1) astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro preact: specifier: ^10.15.1 @@ -257,7 +257,7 @@ importers: specifier: ^18.2.6 version: 18.2.6 astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro react: specifier: ^18.2.0 @@ -272,7 +272,7 @@ importers: specifier: ^2.2.0 version: link:../../packages/integrations/solid astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro solid-js: specifier: ^1.7.6 @@ -284,7 +284,7 @@ importers: specifier: ^3.1.0 version: link:../../packages/integrations/svelte astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro svelte: specifier: ^3.59.1 @@ -296,7 +296,7 @@ importers: specifier: ^2.2.1 version: link:../../packages/integrations/vue astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro vue: specifier: ^3.3.4 @@ -308,13 +308,13 @@ importers: specifier: ^5.3.0 version: link:../../packages/integrations/node astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro examples/integration: devDependencies: astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro examples/middleware: @@ -323,7 +323,7 @@ importers: specifier: ^5.3.0 version: link:../../packages/integrations/node astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro html-minifier: specifier: ^4.0.0 @@ -332,19 +332,19 @@ importers: examples/minimal: dependencies: astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro examples/non-html-pages: dependencies: astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro examples/portfolio: dependencies: astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro examples/ssr: @@ -356,7 +356,7 @@ importers: specifier: ^3.1.0 version: link:../../packages/integrations/svelte astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro svelte: specifier: ^3.59.1 @@ -368,7 +368,7 @@ importers: specifier: ^0.4.0 version: link:../../packages/integrations/markdoc astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro examples/with-markdown-plugins: @@ -377,7 +377,7 @@ importers: specifier: ^2.2.1 version: link:../../packages/markdown/remark astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro hast-util-select: specifier: ^5.0.5 @@ -398,7 +398,7 @@ importers: examples/with-markdown-shiki: dependencies: astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro examples/with-mdx: @@ -410,7 +410,7 @@ importers: specifier: ^2.2.1 version: link:../../packages/integrations/preact astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro preact: specifier: ^10.15.1 @@ -425,7 +425,7 @@ importers: specifier: ^0.4.1 version: 0.4.1(nanostores@0.8.1)(preact@10.15.1) astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro nanostores: specifier: ^0.8.1 @@ -446,7 +446,7 @@ importers: specifier: ^1.6.0 version: 1.6.0 astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro autoprefixer: specifier: ^10.4.14 @@ -464,7 +464,7 @@ importers: examples/with-vite-plugin-pwa: dependencies: astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro vite-plugin-pwa: specifier: 0.14.7 @@ -476,7 +476,7 @@ importers: examples/with-vitest: dependencies: astro: - specifier: ^2.7.2 + specifier: ^2.7.3 version: link:../../packages/astro vitest: specifier: ^0.31.4 @@ -485,8 +485,8 @@ importers: packages/astro: dependencies: '@astrojs/compiler': - specifier: ^1.5.0 - version: 1.5.0 + specifier: ^1.5.3 + version: 1.5.3 '@astrojs/internal-helpers': specifier: ^0.1.1 version: link:../internal-helpers @@ -3574,6 +3574,9 @@ importers: mocha: specifier: ^9.2.2 version: 9.2.2 + node-fetch-native: + specifier: ^1.2.0 + version: 1.2.0 which-pm-runs: specifier: ^1.1.0 version: 1.1.0 @@ -5505,14 +5508,14 @@ packages: sisteransi: 1.0.5 dev: false - /@astrojs/compiler@1.5.0: - resolution: {integrity: sha512-k04X/7nlMklU0HQUScxbCTf5n8/Vr+0U0bawb9QWulWxd6qJf3FmBrNATgTYiltjB4pc5HBqmmttAfFi7m4lLg==} + /@astrojs/compiler@1.5.3: + resolution: {integrity: sha512-/HSFkJ+Yv+WUWSq0QVsIlhBKam5VUpGV+s8MvPguC/krHmw4Ww9TIgmfJSvV8/BN0sHJB7pCgf7yInae1zb+TQ==} /@astrojs/language-server@1.0.0: resolution: {integrity: sha512-oEw7AwJmzjgy6HC9f5IdrphZ1GVgfV/+7xQuyf52cpTiRWd/tJISK3MsKP0cDkVlfodmNABNFnAaAWuLZEiiiA==} hasBin: true dependencies: - '@astrojs/compiler': 1.5.0 + '@astrojs/compiler': 1.5.3 '@jridgewell/trace-mapping': 0.3.18 '@vscode/emmet-helper': 2.8.8 events: 3.3.0 @@ -8857,47 +8860,48 @@ packages: /@types/yargs-parser@21.0.0: resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==} - /@typescript-eslint/eslint-plugin@5.60.0(@typescript-eslint/parser@5.60.0)(eslint@8.43.0)(typescript@5.0.2): - resolution: {integrity: sha512-78B+anHLF1TI8Jn/cD0Q00TBYdMgjdOn980JfAVa9yw5sop8nyTfVOQAv6LWywkOGLclDBtv5z3oxN4w7jxyNg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /@typescript-eslint/eslint-plugin@6.0.0-alpha.158(@typescript-eslint/parser@6.0.0-alpha.158)(eslint@8.43.0)(typescript@5.0.2): + resolution: {integrity: sha512-fzcdANIIKtQxen+IdXue1u4EHY8h84M8L+eSSYgQQUxJy7tTN4EfBK4jlAAVxGCE+TkmTzBMe52hMAV0PwNLiQ==} + engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: - '@typescript-eslint/parser': ^5.0.0 - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha + eslint: ^7.0.0 || ^8.0.0 typescript: '*' peerDependenciesMeta: typescript: optional: true dependencies: '@eslint-community/regexpp': 4.5.1 - '@typescript-eslint/parser': 5.60.0(eslint@8.43.0)(typescript@5.0.2) - '@typescript-eslint/scope-manager': 5.60.0 - '@typescript-eslint/type-utils': 5.60.0(eslint@8.43.0)(typescript@5.0.2) - '@typescript-eslint/utils': 5.60.0(eslint@8.43.0)(typescript@5.0.2) + '@typescript-eslint/parser': 6.0.0-alpha.158(eslint@8.43.0)(typescript@5.0.2) + '@typescript-eslint/scope-manager': 6.0.0-alpha.158 + '@typescript-eslint/type-utils': 6.0.0-alpha.158(eslint@8.43.0)(typescript@5.0.2) + '@typescript-eslint/utils': 6.0.0-alpha.158(eslint@8.43.0)(typescript@5.0.2) debug: 4.3.4 eslint: 8.43.0 grapheme-splitter: 1.0.4 ignore: 5.2.4 - natural-compare-lite: 1.4.0 + natural-compare: 1.4.0 semver: 7.5.3 - tsutils: 3.21.0(typescript@5.0.2) + ts-api-utils: 1.0.1(typescript@5.0.2) typescript: 5.0.2 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/parser@5.60.0(eslint@8.43.0)(typescript@5.0.2): - resolution: {integrity: sha512-jBONcBsDJ9UoTWrARkRRCgDz6wUggmH5RpQVlt7BimSwaTkTjwypGzKORXbR4/2Hqjk9hgwlon2rVQAjWNpkyQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /@typescript-eslint/parser@6.0.0-alpha.158(eslint@8.43.0)(typescript@5.0.2): + resolution: {integrity: sha512-LJ7qo0yfk4bxYw2A2OCwUeiGumsU4YCebu29dIxC2lK/aT398KazALqMzPC4z6544OS6zYVM2WI9uyCZ8wgj+Q==} + engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + eslint: ^7.0.0 || ^8.0.0 typescript: '*' peerDependenciesMeta: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 5.60.0 - '@typescript-eslint/types': 5.60.0 - '@typescript-eslint/typescript-estree': 5.60.0(typescript@5.0.2) + '@typescript-eslint/scope-manager': 6.0.0-alpha.158 + '@typescript-eslint/types': 6.0.0-alpha.158 + '@typescript-eslint/typescript-estree': 6.0.0-alpha.158(typescript@5.0.2) + '@typescript-eslint/visitor-keys': 6.0.0-alpha.158 debug: 4.3.4 eslint: 8.43.0 typescript: 5.0.2 @@ -8905,72 +8909,72 @@ packages: - supports-color dev: true - /@typescript-eslint/scope-manager@5.60.0: - resolution: {integrity: sha512-hakuzcxPwXi2ihf9WQu1BbRj1e/Pd8ZZwVTG9kfbxAMZstKz8/9OoexIwnmLzShtsdap5U/CoQGRCWlSuPbYxQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /@typescript-eslint/scope-manager@6.0.0-alpha.158: + resolution: {integrity: sha512-59HcplMM9ZcdtfVe6pgFzereN49OKeVc/FZsymAaxe9QqGXby665pr2/IHcmFh3cnpgNdRQu+DaD5N538AprjA==} + engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 5.60.0 - '@typescript-eslint/visitor-keys': 5.60.0 + '@typescript-eslint/types': 6.0.0-alpha.158 + '@typescript-eslint/visitor-keys': 6.0.0-alpha.158 dev: true - /@typescript-eslint/type-utils@5.60.0(eslint@8.43.0)(typescript@5.0.2): - resolution: {integrity: sha512-X7NsRQddORMYRFH7FWo6sA9Y/zbJ8s1x1RIAtnlj6YprbToTiQnM6vxcMu7iYhdunmoC0rUWlca13D5DVHkK2g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /@typescript-eslint/type-utils@6.0.0-alpha.158(eslint@8.43.0)(typescript@5.0.2): + resolution: {integrity: sha512-fjUFPY92+0RzyRKs185Rpoaw4z4vt5qoxd6kHLLHjqKxO7xNsOF4nPPjRXlKfbVAUHecPqbFBRmElWCuaEjMdg==} + engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: - eslint: '*' + eslint: ^7.0.0 || ^8.0.0 typescript: '*' peerDependenciesMeta: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 5.60.0(typescript@5.0.2) - '@typescript-eslint/utils': 5.60.0(eslint@8.43.0)(typescript@5.0.2) + '@typescript-eslint/typescript-estree': 6.0.0-alpha.158(typescript@5.0.2) + '@typescript-eslint/utils': 6.0.0-alpha.158(eslint@8.43.0)(typescript@5.0.2) debug: 4.3.4 eslint: 8.43.0 - tsutils: 3.21.0(typescript@5.0.2) + ts-api-utils: 1.0.1(typescript@5.0.2) typescript: 5.0.2 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/types@5.60.0: - resolution: {integrity: sha512-ascOuoCpNZBccFVNJRSC6rPq4EmJ2NkuoKnd6LDNyAQmdDnziAtxbCGWCbefG1CNzmDvd05zO36AmB7H8RzKPA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /@typescript-eslint/types@6.0.0-alpha.158: + resolution: {integrity: sha512-xfJnAaGKN1b/cz37T4FtQfCBKwA7fn1qxa/5UZmKT1FwI/J+lybk+dHdhU2KvNGJ/53/vGf0OObUzejf7oByLg==} + engines: {node: ^16.0.0 || >=18.0.0} dev: true - /@typescript-eslint/typescript-estree@5.60.0(typescript@5.0.2): - resolution: {integrity: sha512-R43thAuwarC99SnvrBmh26tc7F6sPa2B3evkXp/8q954kYL6Ro56AwASYWtEEi+4j09GbiNAHqYwNNZuNlARGQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /@typescript-eslint/typescript-estree@6.0.0-alpha.158(typescript@5.0.2): + resolution: {integrity: sha512-1hskAlZ2pliy1DQ1VM3Tu+JUQMtaWaLmMGOOmmI9H7yfudsopV7AOCk+NO1FWIATWIeUvPI33T09WKRdZGO4yg==} + engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: typescript: '*' peerDependenciesMeta: typescript: optional: true dependencies: - '@typescript-eslint/types': 5.60.0 - '@typescript-eslint/visitor-keys': 5.60.0 + '@typescript-eslint/types': 6.0.0-alpha.158 + '@typescript-eslint/visitor-keys': 6.0.0-alpha.158 debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 semver: 7.5.3 - tsutils: 3.21.0(typescript@5.0.2) + ts-api-utils: 1.0.1(typescript@5.0.2) typescript: 5.0.2 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/utils@5.60.0(eslint@8.43.0)(typescript@5.0.2): - resolution: {integrity: sha512-ba51uMqDtfLQ5+xHtwlO84vkdjrqNzOnqrnwbMHMRY8Tqeme8C2Q8Fc7LajfGR+e3/4LoYiWXUM6BpIIbHJ4hQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /@typescript-eslint/utils@6.0.0-alpha.158(eslint@8.43.0)(typescript@5.0.2): + resolution: {integrity: sha512-HDpGNQnbE09Kun4+IjnaWoARmhAdSbR6MTeaA0K12vzCg9M3rL2z72jzP0z4n7bGRJsNAoH+0SKSgcJ9NL8Bhw==} + engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + eslint: ^7.0.0 || ^8.0.0 dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.43.0) '@types/json-schema': 7.0.11 '@types/semver': 7.5.0 - '@typescript-eslint/scope-manager': 5.60.0 - '@typescript-eslint/types': 5.60.0 - '@typescript-eslint/typescript-estree': 5.60.0(typescript@5.0.2) + '@typescript-eslint/scope-manager': 6.0.0-alpha.158 + '@typescript-eslint/types': 6.0.0-alpha.158 + '@typescript-eslint/typescript-estree': 6.0.0-alpha.158(typescript@5.0.2) eslint: 8.43.0 eslint-scope: 5.1.1 semver: 7.5.3 @@ -8979,11 +8983,11 @@ packages: - typescript dev: true - /@typescript-eslint/visitor-keys@5.60.0: - resolution: {integrity: sha512-wm9Uz71SbCyhUKgcaPRauBdTegUyY/ZWl8gLwD/i/ybJqscrrdVSFImpvUz16BLPChIeKBK5Fa9s6KDQjsjyWw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /@typescript-eslint/visitor-keys@6.0.0-alpha.158: + resolution: {integrity: sha512-/1xiY3B2Du3a8YaKpF3MtNZRlzDRChJAb8kbt4mQ6h3XGLd8ZGRN8l971nbX632p78kETaJ+JgCGtrgJpQZO+g==} + engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 5.60.0 + '@typescript-eslint/types': 6.0.0-alpha.158 eslint-visitor-keys: 3.4.1 dev: true @@ -11963,7 +11967,7 @@ packages: defu: 6.1.2 https-proxy-agent: 5.0.1 mri: 1.2.0 - node-fetch-native: 1.1.1 + node-fetch-native: 1.2.0 pathe: 1.1.0 tar: 6.1.14 transitivePeerDependencies: @@ -14192,10 +14196,6 @@ packages: /napi-build-utils@1.0.2: resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} - /natural-compare-lite@1.4.0: - resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} - dev: true - /natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true @@ -14247,8 +14247,8 @@ packages: engines: {node: '>=10.5.0'} dev: false - /node-fetch-native@1.1.1: - resolution: {integrity: sha512-9VvspTSUp2Sxbl+9vbZTlFGq9lHwE8GDVVekxx6YsNd1YH59sb3Ba8v3Y3cD8PkLNcileGGcA21PFjVl0jzDaw==} + /node-fetch-native@1.2.0: + resolution: {integrity: sha512-5IAMBTl9p6PaAjYCnMv5FmqIF6GcZnawAVnzaCG0rX2aYZJ4CxEkZNtVPuTRug7fL7wyM5BQYTlAzcyMPi6oTQ==} dev: false /node-fetch@2.6.11: @@ -15276,7 +15276,7 @@ packages: resolution: {integrity: sha512-dPzop0gKZyVGpTDQmfy+e7FKXC9JT3mlpfYA2diOVz+Ui+QR1U4G/s+OesKl2Hib2JJOtAYJs/l+ovgT0ljlFA==} engines: {node: ^14.15.0 || >=16.0.0, pnpm: '>=7.14.0'} dependencies: - '@astrojs/compiler': 1.5.0 + '@astrojs/compiler': 1.5.3 prettier: 2.8.8 sass-formatter: 0.7.6 dev: true @@ -15285,7 +15285,7 @@ packages: resolution: {integrity: sha512-lJ/mG/Lz/ccSwNtwqpFS126mtMVzFVyYv0ddTF9wqwrEG4seECjKDAyw/oGv915rAcJi8jr89990nqfpmG+qdg==} engines: {node: ^14.15.0 || >=16.0.0, pnpm: '>=7.14.0'} dependencies: - '@astrojs/compiler': 1.5.0 + '@astrojs/compiler': 1.5.3 prettier: 2.8.8 sass-formatter: 0.7.6 synckit: 0.8.5 @@ -16868,6 +16868,15 @@ packages: /trough@2.1.0: resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==} + /ts-api-utils@1.0.1(typescript@5.0.2): + resolution: {integrity: sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==} + engines: {node: '>=16.13.0'} + peerDependencies: + typescript: '>=4.2.0' + dependencies: + typescript: 5.0.2 + dev: true + /ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} @@ -16897,10 +16906,6 @@ packages: strip-json-comments: 2.0.1 dev: true - /tslib@1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - dev: true - /tslib@2.1.0: resolution: {integrity: sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==} dev: true @@ -16908,16 +16913,6 @@ packages: /tslib@2.5.3: resolution: {integrity: sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==} - /tsutils@3.21.0(typescript@5.0.2): - resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} - engines: {node: '>= 6'} - peerDependencies: - typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' - dependencies: - tslib: 1.14.1 - typescript: 5.0.2 - dev: true - /tty-table@4.2.1: resolution: {integrity: sha512-xz0uKo+KakCQ+Dxj1D/tKn2FSyreSYWzdkL/BYhgN6oMW808g8QRMuh1atAV9fjTPbWBjfbkKQpI/5rEcnAc7g==} engines: {node: '>=8.0.0'} From 3fad96c5c74ab82847bde8113ce4c77721b173d5 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Tue, 4 Jul 2023 10:14:00 +0100 Subject: [PATCH 13/21] fix: lint --- packages/astro/src/core/build/index.ts | 4 ---- packages/astro/src/core/build/static-build.ts | 1 - packages/astro/test/test-adapter.js | 2 +- packages/integrations/vercel/src/serverless/middleware.ts | 2 +- 4 files changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/astro/src/core/build/index.ts b/packages/astro/src/core/build/index.ts index f5e59e574d20..11e2b1fa9fc5 100644 --- a/packages/astro/src/core/build/index.ts +++ b/packages/astro/src/core/build/index.ts @@ -1,8 +1,5 @@ import type { AstroConfig, AstroSettings, ManifestData, RuntimeMode } from '../../@types/astro'; - import fs from 'fs'; -import { fileURLToPath, pathToFileURL } from 'node:url'; -import { join } from 'node:path'; import * as colors from 'kleur/colors'; import { performance } from 'perf_hooks'; import type * as vite from 'vite'; @@ -23,7 +20,6 @@ import { collectPagesData } from './page-data.js'; import { staticBuild, viteBuild } from './static-build.js'; import type { StaticBuildOptions } from './types.js'; import { getTimeStat } from './util.js'; -import { isServerLikeOutput } from '../../prerender/utils.js'; export interface BuildOptions { mode?: RuntimeMode; diff --git a/packages/astro/src/core/build/static-build.ts b/packages/astro/src/core/build/static-build.ts index 452702f32226..9bef0d681760 100644 --- a/packages/astro/src/core/build/static-build.ts +++ b/packages/astro/src/core/build/static-build.ts @@ -26,7 +26,6 @@ import { generatePages } from './generate.js'; import { trackPageData } from './internal.js'; import { createPluginContainer, type AstroBuildPluginContainer } from './plugin.js'; import { registerAllPlugins } from './plugins/index.js'; -import { MIDDLEWARE_MODULE_ID } from './plugins/plugin-middleware.js'; import { ASTRO_PAGE_RESOLVED_MODULE_ID } from './plugins/plugin-pages.js'; import { RESOLVED_RENDERERS_MODULE_ID } from './plugins/plugin-renderers.js'; import { RESOLVED_SPLIT_MODULE_ID, SSR_VIRTUAL_MODULE_ID } from './plugins/plugin-ssr.js'; diff --git a/packages/astro/test/test-adapter.js b/packages/astro/test/test-adapter.js index 09d21b4771f9..ed79e5f2102e 100644 --- a/packages/astro/test/test-adapter.js +++ b/packages/astro/test/test-adapter.js @@ -80,7 +80,7 @@ export default function ( setEntryPoints(middlewareEntryPoint); } }, - 'astro:build:done': ({ routes, middlewareEntryPoint }) => { + 'astro:build:done': ({ routes }) => { if (setRoutes) { setRoutes(routes); } diff --git a/packages/integrations/vercel/src/serverless/middleware.ts b/packages/integrations/vercel/src/serverless/middleware.ts index d083940a3ab9..2f05756c612b 100644 --- a/packages/integrations/vercel/src/serverless/middleware.ts +++ b/packages/integrations/vercel/src/serverless/middleware.ts @@ -1,6 +1,6 @@ import { fileURLToPath, pathToFileURL } from 'node:url'; import { join } from 'node:path'; -import { ASTRO_LOCALS_HEADER, type CreateLocals } from './adapter.js'; +import { ASTRO_LOCALS_HEADER } from './adapter.js'; import { existsSync } from 'fs'; /** From 1163ec4f4caf56a8935827697f8de05832ca77e0 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Wed, 5 Jul 2023 09:17:05 +0100 Subject: [PATCH 14/21] Update .changeset/brown-shrimps-hug.md Co-authored-by: Bjorn Lu --- .changeset/brown-shrimps-hug.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/brown-shrimps-hug.md b/.changeset/brown-shrimps-hug.md index fc49318c1c3c..1c40fc380926 100644 --- a/.changeset/brown-shrimps-hug.md +++ b/.changeset/brown-shrimps-hug.md @@ -2,9 +2,9 @@ 'astro': minor --- -Astro now exposes a utility called `trySerializeLocals` via `astro/middleware` module. +The `astro/middleware` module exports a new utility called `trySerializeLocals`. -This utility can be used by adapters to validate their `locals` before being sent +This utility can be used by adapters to validate their `locals` before sending it to the Astro middleware. This function will throw a runtime error if the value passed is not serializable, so From d6d2dec91114a33c330755182cffb78ee1e1f0b0 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Wed, 5 Jul 2023 09:21:47 +0100 Subject: [PATCH 15/21] Apply suggestions from code review Co-authored-by: Bjorn Lu --- .changeset/long-geckos-battle.md | 2 +- packages/astro/src/@types/astro.ts | 2 +- packages/integrations/vercel/README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.changeset/long-geckos-battle.md b/.changeset/long-geckos-battle.md index 9422ecd77a3b..3c1a993bec5c 100644 --- a/.changeset/long-geckos-battle.md +++ b/.changeset/long-geckos-battle.md @@ -2,6 +2,6 @@ 'astro': minor --- -The module `astro/middleware` exports a new API called `createContext`. +The `astro/middleware` module exports a new API called `createContext`. This a low-level API that adapters can use to create a context that can be consumed by middleware functions. diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index 8a3eaee460fe..6b8e5ca141fa 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -855,7 +855,7 @@ export interface AstroUserConfig { * @name build.excludeMiddleware * @type {boolean} * @default {false} - * @version 2.7.0 + * @version 2.8.0 * @description * Defines how the SSR code should be bundled when built. * diff --git a/packages/integrations/vercel/README.md b/packages/integrations/vercel/README.md index ced5b4927acd..771140369d80 100644 --- a/packages/integrations/vercel/README.md +++ b/packages/integrations/vercel/README.md @@ -272,7 +272,7 @@ This is an opt-in feature, and the `build.excludeMiddleware` option needs to be // astro.config.mjs import {defineConfig} from "astro/config"; import vercel from "@astrojs/vercel"; -export default definConfig({ +export default defineConfig({ output: "server", adapter: vercel(), build: { From 255c76edb370aeeb527cfee079c017c1a28f9ea8 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Wed, 5 Jul 2023 09:28:25 +0100 Subject: [PATCH 16/21] chore: update documentation --- packages/integrations/vercel/README.md | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/packages/integrations/vercel/README.md b/packages/integrations/vercel/README.md index 771140369d80..3d9ce2317313 100644 --- a/packages/integrations/vercel/README.md +++ b/packages/integrations/vercel/README.md @@ -283,9 +283,16 @@ export default defineConfig({ Optionally, you can create a known file called `vercel-edge-middleware.(js|ts)` in the [`srcDir`](https://docs.astro.build/en/reference/configuration-reference/#srcdir) folder to create [`Astro.locals`](https://docs.astro.build/en/reference/api-reference/#astrolocals). +Typings requires the [`@vercel/edge`](https://www.npmjs.com/package/@vercel/edge) package. + ```js // src/vercel-edge-middleware.js - +/** + * + * @param options.request {Request} + * @param options.context {import("@vercel/edge").RequestContext} + * @returns {object} + */ export default function({ request, context }) { // do something with request and context return { @@ -294,6 +301,20 @@ export default function({ request, context }) { } ``` +If you use TypeScript, you can type the function as follows: + +```ts +// src/vercel-edge-middleware.ts +import type {RequestContext} from "@vercel/edge"; + +export default function ({request, context}: { request: Request, context: RequestContext }) { + // do something with request and context + return { + title: "Spider-man's blog" + } +} +``` + The data returned by this function will be passed to Astro middleware. The function: From 88489b60676bd561daaca2bb620091e9b44541fa Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Wed, 5 Jul 2023 14:39:53 +0100 Subject: [PATCH 17/21] Apply suggestions from code review Co-authored-by: Sarah Rainsberger --- .changeset/strong-years-travel.md | 4 ++-- packages/astro/src/@types/astro.ts | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.changeset/strong-years-travel.md b/.changeset/strong-years-travel.md index 28334375ab6d..3067e01b48be 100644 --- a/.changeset/strong-years-travel.md +++ b/.changeset/strong-years-travel.md @@ -16,5 +16,5 @@ export default defineConfig({ ``` When enabled, the code that belongs to be middleware **won't** be imported -by the final pages/entry points. The user is responsible to import it and -call it manually. +by the final pages/entry points. The user is responsible for importing it and +calling it manually. diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index 6b8e5ca141fa..e21082db26fe 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -857,11 +857,9 @@ export interface AstroUserConfig { * @default {false} * @version 2.8.0 * @description - * Defines how the SSR code should be bundled when built. - * - * When enabled, the middleware code is **not** going to be imported by the pages. + * Defines whether or not any SSR middleware code will be bundled when built. * - * It's going to be responsibility of the end user to execute import the code and execute it. + * When enabled, middleware code is not bundled and imported by all pages during the build. To instead execute and import middleware code manually, set `build.excludeMiddleware: true`: * * ```js * { From 3cc0519526378be9c086af8801f9784643cbf718 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Wed, 5 Jul 2023 14:40:47 +0100 Subject: [PATCH 18/21] Apply suggestions from code review Co-authored-by: Sarah Rainsberger --- packages/integrations/vercel/README.md | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/packages/integrations/vercel/README.md b/packages/integrations/vercel/README.md index 3d9ce2317313..27bfb93a84e2 100644 --- a/packages/integrations/vercel/README.md +++ b/packages/integrations/vercel/README.md @@ -281,7 +281,7 @@ export default defineConfig({ }) ``` -Optionally, you can create a known file called `vercel-edge-middleware.(js|ts)` in the [`srcDir`](https://docs.astro.build/en/reference/configuration-reference/#srcdir) folder to create [`Astro.locals`](https://docs.astro.build/en/reference/api-reference/#astrolocals). +Optionally, you can create a file recognized by the adapter named `vercel-edge-middleware.(js|ts)` in the [`srcDir`](https://docs.astro.build/en/reference/configuration-reference/#srcdir) folder to create [`Astro.locals`](https://docs.astro.build/en/reference/api-reference/#astrolocals). Typings requires the [`@vercel/edge`](https://www.npmjs.com/package/@vercel/edge) package. @@ -326,16 +326,10 @@ The function: #### Limitations and constraints -When you opt in this feature, there are few constraints to take into consideration: -- the Vercel Edge middleware will always be the **first** function to receive the `Request` and the last function to receive `Response`. - - This an architectural constraint that follows the [boundaries set by Vercel](https://vercel.com/docs/concepts/functions/edge-middleware). -- you're allowed to use `request` and `context` only to produce an `Astro.locals` object. - - Operations like redirects, etc. should be delegated to Astro middleware -- `Astro.locals` **must be serializable**, failing to do so will result in a **runtime error**. - - This means that you **can't** store complex types like `Map`, `function`, `Set`, etc. +When you opt in to this feature, there are few constraints to note: +- The Vercel Edge middleware will always be the **first** function to receive the `Request` and the last function to receive `Response`. This an architectural constraint that follows the [boundaries set by Vercel](https://vercel.com/docs/concepts/functions/edge-middleware). +- Only `request` and `context` may be used to produce an `Astro.locals` object. Operations like redirects, etc. should be delegated to Astro middleware. +- `Astro.locals` **must be serializable**. Failing to do so will result in a **runtime error**. This means that you **cannot** store complex types like `Map`, `function`, `Set`, etc. ## Troubleshooting From 1c0a2ca969042b0755c1fd5006ae1836c2817a01 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Wed, 5 Jul 2023 14:42:25 +0100 Subject: [PATCH 19/21] code suggestions --- packages/integrations/vercel/src/serverless/adapter.ts | 9 --------- .../vercel/test/fixtures/middleware/astro.config.mjs | 8 +------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/packages/integrations/vercel/src/serverless/adapter.ts b/packages/integrations/vercel/src/serverless/adapter.ts index f0c131e27239..9d799a7bf5bf 100644 --- a/packages/integrations/vercel/src/serverless/adapter.ts +++ b/packages/integrations/vercel/src/serverless/adapter.ts @@ -15,20 +15,11 @@ import { copyDependenciesToFunction } from '../lib/nft.js'; import { getRedirects } from '../lib/redirects.js'; import { generateEdgeMiddleware } from './middleware.js'; import { fileURLToPath } from 'node:url'; -import type { RequestContext } from '@vercel/edge'; const PACKAGE_NAME = '@astrojs/vercel/serverless'; export const ASTRO_LOCALS_HEADER = 'x-astro-locals'; export const VERCEL_EDGE_MIDDLEWARE_FILE = 'vercel-edge-middleware'; -export type CreateLocals = ({ - request, - context, -}: { - request: Request; - context: RequestContext; -}) => object; - function getAdapter(): AstroAdapter { return { name: PACKAGE_NAME, diff --git a/packages/integrations/vercel/test/fixtures/middleware/astro.config.mjs b/packages/integrations/vercel/test/fixtures/middleware/astro.config.mjs index 467cf25e72fd..321a8bde3e1a 100644 --- a/packages/integrations/vercel/test/fixtures/middleware/astro.config.mjs +++ b/packages/integrations/vercel/test/fixtures/middleware/astro.config.mjs @@ -2,13 +2,7 @@ import {defineConfig} from "astro/config"; import vercel from "@astrojs/vercel/serverless"; export default defineConfig({ - adapter: vercel({ - createLocals: ({request}) => { - console.log(request); - return { - "foo": "bar" - } - }}), + adapter: vercel(), build: { excludeMiddleware: true }, From e001471980138438cbd5bd6762d1862f656e0289 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Wed, 5 Jul 2023 14:43:35 +0100 Subject: [PATCH 20/21] code suggestions --- packages/integrations/vercel/src/lib/nft.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/integrations/vercel/src/lib/nft.ts b/packages/integrations/vercel/src/lib/nft.ts index 33c740fc9e42..752f87251bc7 100644 --- a/packages/integrations/vercel/src/lib/nft.ts +++ b/packages/integrations/vercel/src/lib/nft.ts @@ -21,6 +21,10 @@ export async function copyDependenciesToFunction({ base = new URL('../', base); } + // The Vite bundle includes an import to `@vercel/nft` for some reason, + // and that trips up `@vercel/nft` itself during the adapter build. Using a + // dynamic import helps prevent the issue. + // TODO: investigate why const { nodeFileTrace } = await import('@vercel/nft'); const result = await nodeFileTrace([entryPath], { base: fileURLToPath(base), From 8d7b6fcbb28d5417c72139d23fc9f436965cde35 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Wed, 5 Jul 2023 14:45:03 +0100 Subject: [PATCH 21/21] Apply suggestions from code review Co-authored-by: Sarah Rainsberger --- packages/integrations/vercel/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/integrations/vercel/README.md b/packages/integrations/vercel/README.md index 27bfb93a84e2..19d841a2f10f 100644 --- a/packages/integrations/vercel/README.md +++ b/packages/integrations/vercel/README.md @@ -235,7 +235,7 @@ export default defineConfig({ ### Vercel Edge Middleware -You can use Vercel edge middleware to intercept a request and redirect before sending a response. Vercel middleware can run for Edge, SSR, and Static deployments. You don't need to install `@vercel/edge` to write middleware, but you do need to install it to use features such as geolocation. For more information see [Vercel’s middleware documentation](https://vercel.com/docs/concepts/functions/edge-middleware). +You can use Vercel Edge middleware to intercept a request and redirect before sending a response. Vercel middleware can run for Edge, SSR, and Static deployments. You may not need to install this package for your middleware. `@vercel/edge` is only required to use some middleware features such as geolocation. For more information see [Vercel’s middleware documentation](https://vercel.com/docs/concepts/functions/edge-middleware). 1. Add a `middleware.js` file to the root of your project: @@ -264,7 +264,7 @@ You can use Vercel edge middleware to intercept a request and redirect before se ### Vercel Edge Middleware with Astro middleware -The `@astrojs/vercel/serverless` adapter can automatically create the vercel edge middleware when you have an Astro middleware in you code base. +The `@astrojs/vercel/serverless` adapter can automatically create the Vercel Edge middleware from an Astro middleware in your code base. This is an opt-in feature, and the `build.excludeMiddleware` option needs to be set to `true`: