diff --git a/packages/node/CHANGELOG.md b/packages/node/CHANGELOG.md index 738cfc36..ed830f8d 100644 --- a/packages/node/CHANGELOG.md +++ b/packages/node/CHANGELOG.md @@ -734,7 +734,7 @@ { darkMode: true }, { expires: '1 month', - }, + } ); const prefs = Astro.cookies.get('prefs').json(); diff --git a/packages/node/package.json b/packages/node/package.json index f8042499..2fc6c35b 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -11,10 +11,7 @@ "url": "https://github.com/withastro/astro.git", "directory": "packages/integrations/node" }, - "keywords": [ - "withastro", - "astro-adapter" - ], + "keywords": ["withastro", "astro-adapter"], "bugs": "https://github.com/withastro/astro/issues", "homepage": "https://docs.astro.build/en/guides/integrations-guide/node/", "exports": { @@ -23,9 +20,7 @@ "./preview.js": "./dist/preview.js", "./package.json": "./package.json" }, - "files": [ - "dist" - ], + "files": ["dist"], "scripts": { "build": "tsc", "test": "astro-scripts test \"test/**/*.test.js\"" diff --git a/packages/node/src/index.ts b/packages/node/src/index.ts index 36d9ee30..eb3c98a9 100644 --- a/packages/node/src/index.ts +++ b/packages/node/src/index.ts @@ -73,7 +73,7 @@ export default function createIntegration(userOptions: UserOptions): AstroIntegr if (config.output === 'static') { logger.warn( - `\`output: "server"\` or \`output: "hybrid"\` is required to use this adapter.`, + `\`output: "server"\` or \`output: "hybrid"\` is required to use this adapter.` ); } }, diff --git a/packages/node/src/log-listening-on.ts b/packages/node/src/log-listening-on.ts index 7e299740..2f774c31 100644 --- a/packages/node/src/log-listening-on.ts +++ b/packages/node/src/log-listening-on.ts @@ -8,20 +8,20 @@ import type { Options } from './types.js'; export async function logListeningOn( logger: AstroIntegrationLogger, server: http.Server | https.Server, - options: Pick, + options: Pick ) { await new Promise((resolve) => server.once('listening', resolve)); const protocol = server instanceof https.Server ? 'https' : 'http'; // Allow to provide host value at runtime const host = getResolvedHostForHttpServer( - process.env.HOST !== undefined && process.env.HOST !== '' ? process.env.HOST : options.host, + process.env.HOST !== undefined && process.env.HOST !== '' ? process.env.HOST : options.host ); const { port } = server.address() as AddressInfo; const address = getNetworkAddress(protocol, host, port); if (host === undefined) { logger.info( - `Server listening on \n local: ${address.local[0]} \t\n network: ${address.network[0]}\n`, + `Server listening on \n local: ${address.local[0]} \t\n network: ${address.network[0]}\n` ); } else { logger.info(`Server listening on ${address.local[0]}`); @@ -32,9 +32,11 @@ function getResolvedHostForHttpServer(host: string | boolean) { if (host === false) { // Use a secure default return 'localhost'; + // biome-ignore lint/style/noUselessElse: } else if (host === true) { // If passed --host in the CLI without arguments return undefined; // undefined typically means 0.0.0.0 or :: (listen on all IPs) + // biome-ignore lint/style/noUselessElse: } else { return host; } @@ -49,29 +51,32 @@ const wildcardHosts = new Set(['0.0.0.0', '::', '0000:0000:0000:0000:0000:0000:0 // this code from vite https://github.com/vitejs/vite/blob/d09bbd093a4b893e78f0bbff5b17c7cf7821f403/packages/vite/src/node/utils.ts#L892-L914 export function getNetworkAddress( + // biome-ignore lint/style/useDefaultParameterLast: protocol: 'http' | 'https' = 'http', hostname: string | undefined, port: number, - base?: string, + base?: string ) { const NetworkAddress: NetworkAddressOpt = { local: [], network: [], }; + // biome-ignore lint/complexity/noForEach: Object.values(os.networkInterfaces()) .flatMap((nInterface) => nInterface ?? []) .filter( (detail) => + // biome-ignore lint/complexity/useOptionalChain: detail && detail.address && (detail.family === 'IPv4' || // @ts-expect-error Node 18.0 - 18.3 returns number - detail.family === 4), + detail.family === 4) ) .forEach((detail) => { let host = detail.address.replace( '127.0.0.1', - hostname === undefined || wildcardHosts.has(hostname) ? 'localhost' : hostname, + hostname === undefined || wildcardHosts.has(hostname) ? 'localhost' : hostname ); // ipv6 host if (host.includes(':')) { diff --git a/packages/node/src/middleware.ts b/packages/node/src/middleware.ts index 5cc4c4a4..5bb10491 100644 --- a/packages/node/src/middleware.ts +++ b/packages/node/src/middleware.ts @@ -15,7 +15,7 @@ export default function createMiddleware(app: NodeApp): RequestHandler { const logger = app.getAdapterLogger(); // using spread args because express trips up if the function's // stringified body includes req, res, next, locals directly - return async function (...args) { + return async (...args) => { // assume normal invocation at first const [req, res, next, locals] = args; // short circuit if it is an error invocation @@ -23,6 +23,7 @@ export default function createMiddleware(app: NodeApp): RequestHandler { const error = req; if (next) { return next(error); + // biome-ignore lint/style/noUselessElse: } else { throw error; } @@ -33,6 +34,7 @@ export default function createMiddleware(app: NodeApp): RequestHandler { logger.error(`Could not render ${req.url}`); console.error(err); if (!res.headersSent) { + // biome-ignore lint/style/noUnusedTemplateLiteral: res.writeHead(500, `Server error`); res.end(); } diff --git a/packages/node/src/preview.ts b/packages/node/src/preview.ts index 518155c4..7e9415df 100644 --- a/packages/node/src/preview.ts +++ b/packages/node/src/preview.ts @@ -8,7 +8,7 @@ import { createServer } from './standalone.js'; type ServerModule = ReturnType; type MaybeServerModule = Partial; -const createPreviewServer: CreatePreviewServer = async function (preview) { +const createPreviewServer: CreatePreviewServer = async (preview) => { let ssrHandler: ServerModule['handler']; let options: ServerModule['options']; try { @@ -16,19 +16,21 @@ const createPreviewServer: CreatePreviewServer = async function (preview) { const ssrModule: MaybeServerModule = await import(preview.serverEntrypoint.toString()); if (typeof ssrModule.handler === 'function') { ssrHandler = ssrModule.handler; + // biome-ignore lint/style/noNonNullAssertion: options = ssrModule.options!; } else { throw new AstroError( - `The server entrypoint doesn't have a handler. Are you sure this is the right file?`, + `The server entrypoint doesn't have a handler. Are you sure this is the right file?` ); } } catch (err) { if ((err as any).code === 'ERR_MODULE_NOT_FOUND') { throw new AstroError( `The server entrypoint ${fileURLToPath( - preview.serverEntrypoint, - )} does not exist. Have you ran a build yet?`, + preview.serverEntrypoint + )} does not exist. Have you ran a build yet?` ); + // biome-ignore lint/style/noUselessElse: } else { throw err; } diff --git a/packages/node/src/serve-app.ts b/packages/node/src/serve-app.ts index 72b4e0fd..2934a01a 100644 --- a/packages/node/src/serve-app.ts +++ b/packages/node/src/serve-app.ts @@ -39,7 +39,7 @@ export function createAppHandler(app: NodeApp): RequestHandler { addCookieHeader: true, locals, routeData, - }), + }) ); await NodeApp.writeResponse(response, res); } else if (next) { diff --git a/packages/node/src/serve-static.ts b/packages/node/src/serve-static.ts index 725f7afa..9221594d 100644 --- a/packages/node/src/serve-static.ts +++ b/packages/node/src/serve-static.ts @@ -29,23 +29,28 @@ export function createStaticHandler(app: NodeApp, options: Options) { let isDirectory = false; try { isDirectory = fs.lstatSync(filePath).isDirectory(); - } catch {} + } catch { } const { trailingSlash = 'ignore' } = options; const hasSlash = urlPath.endsWith('/'); switch (trailingSlash) { case 'never': + // biome-ignore lint/suspicious/noDoubleEquals: if (isDirectory && urlPath != '/' && hasSlash) { + // biome-ignore lint/style/useTemplate: + // biome-ignore lint/suspicious/noFallthroughSwitchClause: pathname = urlPath.slice(0, -1) + (urlQuery ? '?' + urlQuery : ''); res.statusCode = 301; res.setHeader('Location', pathname); return res.end(); + // biome-ignore lint/style/noUselessElse: } else pathname = urlPath; // intentionally fall through case 'ignore': { if (isDirectory && !hasSlash) { + // biome-ignore lint/style/useTemplate: pathname = urlPath + '/index.html'; } else pathname = urlPath; } @@ -53,10 +58,12 @@ export function createStaticHandler(app: NodeApp, options: Options) { case 'always': // trailing slash is not added to "subresources" if (!hasSlash && !isSubresourceRegex.test(urlPath)) { + // biome-ignore lint/style/useTemplate: pathname = urlPath + '/' + (urlQuery ? '?' + urlQuery : ''); res.statusCode = 301; res.setHeader('Location', pathname); return res.end(); + // biome-ignore lint/style/noUselessElse: } else pathname = urlPath; break; } @@ -110,6 +117,7 @@ function resolveClientDir(options: Options) { while (!serverEntryFolderURL.endsWith(serverFolder)) { serverEntryFolderURL = path.dirname(serverEntryFolderURL); } + // biome-ignore lint/style/useTemplate: const serverEntryURL = serverEntryFolderURL + '/entry.mjs'; const clientURL = new URL(appendForwardSlash(rel), serverEntryURL); const client = url.fileURLToPath(clientURL); @@ -117,9 +125,11 @@ function resolveClientDir(options: Options) { } function prependForwardSlash(pth: string) { + // biome-ignore lint/style/useTemplate: return pth.startsWith('/') ? pth : '/' + pth; } function appendForwardSlash(pth: string) { + // biome-ignore lint/style/useTemplate: return pth.endsWith('/') ? pth : pth + '/'; } diff --git a/packages/node/src/standalone.ts b/packages/node/src/standalone.ts index 76e672d2..8ae10a9b 100644 --- a/packages/node/src/standalone.ts +++ b/packages/node/src/standalone.ts @@ -39,6 +39,7 @@ export function createStandaloneHandler(app: NodeApp, options: Options) { return (req: http.IncomingMessage, res: http.ServerResponse) => { try { // validate request path + // biome-ignore lint/style/noNonNullAssertion: decodeURI(req.url!); } catch { res.writeHead(400); @@ -59,7 +60,7 @@ export function createServer(listener: http.RequestListener, host: string, port: key: fs.readFileSync(process.env.SERVER_KEY_PATH), cert: fs.readFileSync(process.env.SERVER_CERT_PATH), }, - listener, + listener ); } else { httpServer = http.createServer(listener); diff --git a/packages/node/test/api-route.test.js b/packages/node/test/api-route.test.js index 804a5ccf..5eca5c53 100644 --- a/packages/node/test/api-route.test.js +++ b/packages/node/test/api-route.test.js @@ -27,7 +27,7 @@ describe('API routes', () => { it('Can get the request body', async () => { const { handler } = await import('./fixtures/api-route/dist/server/entry.mjs'); - let { req, res, done } = createRequestAndResponse({ + const { req, res, done } = createRequestAndResponse({ method: 'POST', url: '/recipes', }); @@ -38,9 +38,9 @@ describe('API routes', () => { handler(req, res); - let [buffer] = await done; + const [buffer] = await done; - let json = JSON.parse(buffer.toString('utf-8')); + const json = JSON.parse(buffer.toString('utf-8')); assert.equal(json.length, 1); @@ -50,7 +50,7 @@ describe('API routes', () => { it('Can get binary data', async () => { const { handler } = await import('./fixtures/api-route/dist/server/entry.mjs'); - let { req, res, done } = createRequestAndResponse({ + const { req, res, done } = createRequestAndResponse({ method: 'POST', url: '/binary', }); @@ -61,15 +61,15 @@ describe('API routes', () => { handler(req, res); - let [out] = await done; - let arr = Array.from(new Uint8Array(out.buffer)); + const [out] = await done; + const arr = Array.from(new Uint8Array(out.buffer)); assert.deepEqual(arr, [5, 4, 3, 2, 1]); }); it('Can post large binary data', async () => { const { handler } = await import('./fixtures/api-route/dist/server/entry.mjs'); - let { req, res, done } = createRequestAndResponse({ + const { req, res, done } = createRequestAndResponse({ method: 'POST', url: '/hash', }); @@ -95,17 +95,17 @@ describe('API routes', () => { expectedDigest = hash.digest(); }); - let [out] = await done; + const [out] = await done; assert.deepEqual(new Uint8Array(out.buffer), new Uint8Array(expectedDigest)); }); it('Can bail on streaming', async () => { const { handler } = await import('./fixtures/api-route/dist/server/entry.mjs'); - let { req, res, done } = createRequestAndResponse({ + const { req, res, done } = createRequestAndResponse({ url: '/streaming', }); - let locals = { cancelledByTheServer: false }; + const locals = { cancelledByTheServer: false }; handler(req, res, () => {}, locals); req.send(); diff --git a/packages/node/test/bad-urls.test.js b/packages/node/test/bad-urls.test.js index 9323516e..cdc0158f 100644 --- a/packages/node/test/bad-urls.test.js +++ b/packages/node/test/bad-urls.test.js @@ -39,7 +39,7 @@ describe('Bad URLs', () => { assert.equal( statusCodes.includes(fetchResult.status), true, - `${weirdUrl} returned something else than 400, 404, or 500`, + `${weirdUrl} returned something else than 400, 404, or 500` ); } const stillWork = await fixture.fetch('/'); diff --git a/packages/node/test/encoded.test.js b/packages/node/test/encoded.test.js index edc6ae78..4fc97cf7 100644 --- a/packages/node/test/encoded.test.js +++ b/packages/node/test/encoded.test.js @@ -18,7 +18,7 @@ describe('Encoded Pathname', () => { it('Can get an Astro file', async () => { const { handler } = await import('./fixtures/encoded/dist/server/entry.mjs'); - let { req, res, text } = createRequestAndResponse({ + const { req, res, text } = createRequestAndResponse({ url: '/什么', }); @@ -32,7 +32,7 @@ describe('Encoded Pathname', () => { it('Can get a Markdown file', async () => { const { handler } = await import('./fixtures/encoded/dist/server/entry.mjs'); - let { req, res, text } = createRequestAndResponse({ + const { req, res, text } = createRequestAndResponse({ url: '/blog/什么', }); diff --git a/packages/node/test/errors.test.js b/packages/node/test/errors.test.js index 802fa6e2..9bf4aa29 100644 --- a/packages/node/test/errors.test.js +++ b/packages/node/test/errors.test.js @@ -20,6 +20,7 @@ describe('Errors', () => { }); let devPreview; + // biome-ignore lint/suspicious/noDuplicateTestHooks: before(async () => { // The two tests that need the server to run are skipped // devPreview = await fixture.preview(); @@ -58,7 +59,7 @@ describe('Errors', () => { const $ = cheerio.load(html); assert.equal($('p').text().trim(), 'Internal server error'); - }, + } ); it( @@ -86,6 +87,6 @@ describe('Errors', () => { } else { throw new Error('The response should take at most 2 chunks.'); } - }, + } ); }); diff --git a/packages/node/test/headers.test.js b/packages/node/test/headers.test.js index 00b1766c..f2753517 100644 --- a/packages/node/test/headers.test.js +++ b/packages/node/test/headers.test.js @@ -132,7 +132,7 @@ describe('Node Adapter Headers', () => { async function runTest(url, expectedHeaders) { const { handler } = await import('./fixtures/headers/dist/server/entry.mjs'); - let { req, res, done } = createRequestAndResponse({ + const { req, res, done } = createRequestAndResponse({ method: 'GET', url, }); diff --git a/packages/node/test/image.test.js b/packages/node/test/image.test.js index 5303fe37..c4758f96 100644 --- a/packages/node/test/image.test.js +++ b/packages/node/test/image.test.js @@ -28,7 +28,7 @@ describe.skip('Image endpoint', () => { assert.equal(res.status, 200); const resImage = await fixture.fetch( - '/_image?href=/_astro/some_penguin.97ef5f92.png&w=50&f=webp', + '/_image?href=/_astro/some_penguin.97ef5f92.png&w=50&f=webp' ); assert.equal(resImage.status, 200); diff --git a/packages/node/test/locals.test.js b/packages/node/test/locals.test.js index 6d277607..b8e3ed40 100644 --- a/packages/node/test/locals.test.js +++ b/packages/node/test/locals.test.js @@ -18,23 +18,23 @@ describe('API routes', () => { it('Can use locals added by node middleware', async () => { const { handler } = await import('./fixtures/locals/dist/server/entry.mjs'); - let { req, res, text } = createRequestAndResponse({ + const { req, res, text } = createRequestAndResponse({ url: '/from-node-middleware', }); - let locals = { foo: 'bar' }; + const locals = { foo: 'bar' }; handler(req, res, () => {}, locals); req.send(); - let html = await text(); + const html = await text(); assert.equal(html.includes('

bar

'), true); }); it('Throws an error when provided non-objects as locals', async () => { const { handler } = await import('./fixtures/locals/dist/server/entry.mjs'); - let { req, res, done } = createRequestAndResponse({ + const { req, res, done } = createRequestAndResponse({ url: '/from-node-middleware', }); @@ -62,19 +62,19 @@ describe('API routes', () => { it('Can access locals in API', async () => { const { handler } = await import('./fixtures/locals/dist/server/entry.mjs'); - let { req, res, done } = createRequestAndResponse({ + const { req, res, done } = createRequestAndResponse({ method: 'POST', url: '/api', }); - let locals = { foo: 'bar' }; + const locals = { foo: 'bar' }; handler(req, res, () => {}, locals); req.send(); - let [buffer] = await done; + const [buffer] = await done; - let json = JSON.parse(buffer.toString('utf-8')); + const json = JSON.parse(buffer.toString('utf-8')); assert.equal(json.foo, 'bar'); }); diff --git a/packages/node/test/node-middleware.test.js b/packages/node/test/node-middleware.test.js index d1b016a5..eeb193c7 100644 --- a/packages/node/test/node-middleware.test.js +++ b/packages/node/test/node-middleware.test.js @@ -23,7 +23,7 @@ describe('behavior from middleware, standalone', () => { }); await fixture.build(); const { startServer } = await fixture.loadAdapterEntryModule(); - let res = startServer(); + const res = startServer(); server = res.server; await waitServerListen(server.server); }); @@ -31,6 +31,7 @@ describe('behavior from middleware, standalone', () => { after(async () => { await server.stop(); await fixture.clean(); + // biome-ignore lint/performance/noDelete: delete process.env.PRERENDER; }); @@ -71,10 +72,12 @@ describe('behavior from middleware, middleware', () => { after(async () => { server.close(); await fixture.clean(); + // biome-ignore lint/performance/noDelete: delete process.env.PRERENDER; }); it('when mode is standalone', async () => { + // biome-ignore lint/style/noUnusedTemplateLiteral: const res = await fetch(`http://localhost:8888/ssr`); assert.equal(res.status, 200); diff --git a/packages/node/test/prerender-404-500.test.js b/packages/node/test/prerender-404-500.test.js index 2535fcb3..86226c50 100644 --- a/packages/node/test/prerender-404-500.test.js +++ b/packages/node/test/prerender-404-500.test.js @@ -34,7 +34,7 @@ describe('Prerender 404', () => { }); await fixture.build(); const { startServer } = await fixture.loadAdapterEntryModule(); - let res = startServer(); + const res = startServer(); server = res.server; await waitServerListen(server.server); }); @@ -42,6 +42,7 @@ describe('Prerender 404', () => { after(async () => { await server.stop(); await fixture.clean(); + // biome-ignore lint/performance/noDelete: delete process.env.PRERENDER; }); @@ -124,7 +125,7 @@ describe('Prerender 404', () => { }); await fixture.build(); const { startServer } = await fixture.loadAdapterEntryModule(); - let res = startServer(); + const res = startServer(); server = res.server; await waitServerListen(server.server); }); @@ -132,6 +133,7 @@ describe('Prerender 404', () => { after(async () => { await server.stop(); await fixture.clean(); + // biome-ignore lint/performance/noDelete: delete process.env.PRERENDER; }); @@ -193,7 +195,7 @@ describe('Hybrid 404', () => { }); await fixture.build(); const { startServer } = await fixture.loadAdapterEntryModule(); - let res = startServer(); + const res = startServer(); server = res.server; await waitServerListen(server.server); }); @@ -201,6 +203,7 @@ describe('Hybrid 404', () => { after(async () => { await server.stop(); await fixture.clean(); + // biome-ignore lint/performance/noDelete: delete process.env.PRERENDER; }); @@ -255,7 +258,7 @@ describe('Hybrid 404', () => { }); await fixture.build(); const { startServer } = await fixture.loadAdapterEntryModule(); - let res = startServer(); + const res = startServer(); server = res.server; await waitServerListen(server.server); }); @@ -263,6 +266,7 @@ describe('Hybrid 404', () => { after(async () => { await server.stop(); await fixture.clean(); + // biome-ignore lint/performance/noDelete: delete process.env.PRERENDER; }); diff --git a/packages/node/test/prerender.test.js b/packages/node/test/prerender.test.js index e699a1b3..0684ff63 100644 --- a/packages/node/test/prerender.test.js +++ b/packages/node/test/prerender.test.js @@ -30,7 +30,7 @@ describe('Prerendering', () => { }); await fixture.build(); const { startServer } = await fixture.loadAdapterEntryModule(); - let res = startServer(); + const res = startServer(); server = res.server; await waitServerListen(server.server); }); @@ -38,6 +38,7 @@ describe('Prerendering', () => { after(async () => { await server.stop(); await fixture.clean(); + // biome-ignore lint/performance/noDelete: delete process.env.PRERENDER; }); @@ -105,7 +106,7 @@ describe('Prerendering', () => { }); await fixture.build(); const { startServer } = await fixture.loadAdapterEntryModule(); - let res = startServer(); + const res = startServer(); server = res.server; await waitServerListen(server.server); }); @@ -113,6 +114,7 @@ describe('Prerendering', () => { after(async () => { await server.stop(); await fixture.clean(); + // biome-ignore lint/performance/noDelete: delete process.env.PRERENDER; }); @@ -181,7 +183,7 @@ describe('Prerendering', () => { }); await fixture.build(); const { startServer } = await fixture.loadAdapterEntryModule(); - let res = startServer(); + const res = startServer(); server = res.server; await waitServerListen(server.server); }); @@ -189,6 +191,7 @@ describe('Prerendering', () => { after(async () => { await server.stop(); await fixture.clean(); + // biome-ignore lint/performance/noDelete: delete process.env.PRERENDER; }); @@ -233,10 +236,12 @@ describe('Prerendering', () => { after(async () => { await devServer.stop(); + // biome-ignore lint/performance/noDelete: delete process.env.PRERENDER; }); it('Can render SSR route', async () => { + // biome-ignore lint/style/noUnusedTemplateLiteral: const res = await fixture.fetch(`/one`); const html = await res.text(); const $ = cheerio.load(html); @@ -246,6 +251,7 @@ describe('Prerendering', () => { }); it('Can render prerendered route', async () => { + // biome-ignore lint/style/noUnusedTemplateLiteral: const res = await fixture.fetch(`/two`); const html = await res.text(); const $ = cheerio.load(html); @@ -277,7 +283,7 @@ describe('Hybrid rendering', () => { }); await fixture.build(); const { startServer } = await fixture.loadAdapterEntryModule(); - let res = startServer(); + const res = startServer(); server = res.server; await waitServerListen(server.server); }); @@ -285,6 +291,7 @@ describe('Hybrid rendering', () => { after(async () => { await server.stop(); await fixture.clean(); + // biome-ignore lint/performance/noDelete: delete process.env.PRERENDER; }); @@ -350,7 +357,7 @@ describe('Hybrid rendering', () => { }); await fixture.build(); const { startServer } = await fixture.loadAdapterEntryModule(); - let res = startServer(); + const res = startServer(); server = res.server; await waitServerListen(server.server); }); @@ -358,6 +365,7 @@ describe('Hybrid rendering', () => { after(async () => { await server.stop(); await fixture.clean(); + // biome-ignore lint/performance/noDelete: delete process.env.PRERENDER; }); @@ -415,7 +423,7 @@ describe('Hybrid rendering', () => { }); await fixture.build(); const { startServer } = await fixture.loadAdapterEntryModule(); - let res = startServer(); + const res = startServer(); server = res.server; await waitServerListen(server.server); }); @@ -423,6 +431,7 @@ describe('Hybrid rendering', () => { after(async () => { await server.stop(); await fixture.clean(); + // biome-ignore lint/performance/noDelete: delete process.env.PRERENDER; }); diff --git a/packages/node/test/test-utils.js b/packages/node/test/test-utils.js index 10faba5c..4f273756 100644 --- a/packages/node/test/test-utils.js +++ b/packages/node/test/test-utils.js @@ -20,18 +20,18 @@ export function loadFixture(inlineConfig) { } export function createRequestAndResponse(reqOptions) { - let req = httpMocks.createRequest(reqOptions); + const req = httpMocks.createRequest(reqOptions); - let res = httpMocks.createResponse({ + const res = httpMocks.createResponse({ eventEmitter: EventEmitter, req, }); - let done = toPromise(res); + const done = toPromise(res); // Get the response as text const text = async () => { - let chunks = await done; + const chunks = await done; return buffersToString(chunks); }; @@ -45,19 +45,20 @@ export function toPromise(res) { const write = res.write; res.write = function (data, encoding) { if (ArrayBuffer.isView(data) && !Buffer.isBuffer(data)) { + // biome-ignore lint/style/noParameterAssign: data = Buffer.from(data.buffer); } return write.call(this, data, encoding); }; res.on('end', () => { - let chunks = res._getChunks(); + const chunks = res._getChunks(); resolve(chunks); }); }); } export function buffersToString(buffers) { - let decoder = new TextDecoder(); + const decoder = new TextDecoder(); let str = ''; for (const buffer of buffers) { str += decoder.decode(buffer); diff --git a/packages/node/test/trailing-slash.test.js b/packages/node/test/trailing-slash.test.js index 9ea8fcdd..6f6a2a3b 100644 --- a/packages/node/test/trailing-slash.test.js +++ b/packages/node/test/trailing-slash.test.js @@ -32,7 +32,7 @@ describe('Trailing slash', () => { }); await fixture.build(); const { startServer } = await fixture.loadAdapterEntryModule(); - let res = startServer(); + const res = startServer(); server = res.server; await waitServerListen(server.server); }); @@ -40,6 +40,7 @@ describe('Trailing slash', () => { after(async () => { await server.stop(); await fixture.clean(); + // biome-ignore lint/performance/noDelete: delete process.env.PRERENDER; }); @@ -103,7 +104,7 @@ describe('Trailing slash', () => { }); await fixture.build(); const { startServer } = await fixture.loadAdapterEntryModule(); - let res = startServer(); + const res = startServer(); server = res.server; await waitServerListen(server.server); }); @@ -111,6 +112,7 @@ describe('Trailing slash', () => { after(async () => { await server.stop(); await fixture.clean(); + // biome-ignore lint/performance/noDelete: delete process.env.PRERENDER; }); @@ -177,7 +179,7 @@ describe('Trailing slash', () => { }); await fixture.build(); const { startServer } = await fixture.loadAdapterEntryModule(); - let res = startServer(); + const res = startServer(); server = res.server; await waitServerListen(server.server); }); @@ -185,6 +187,7 @@ describe('Trailing slash', () => { after(async () => { await server.stop(); await fixture.clean(); + // biome-ignore lint/performance/noDelete: delete process.env.PRERENDER; }); @@ -241,7 +244,7 @@ describe('Trailing slash', () => { }); await fixture.build(); const { startServer } = await fixture.loadAdapterEntryModule(); - let res = startServer(); + const res = startServer(); server = res.server; await waitServerListen(server.server); }); @@ -249,6 +252,7 @@ describe('Trailing slash', () => { after(async () => { await server.stop(); await fixture.clean(); + // biome-ignore lint/performance/noDelete: delete process.env.PRERENDER; }); @@ -308,7 +312,7 @@ describe('Trailing slash', () => { }); await fixture.build(); const { startServer } = await fixture.loadAdapterEntryModule(); - let res = startServer(); + const res = startServer(); server = res.server; await waitServerListen(server.server); }); @@ -316,6 +320,7 @@ describe('Trailing slash', () => { after(async () => { await server.stop(); await fixture.clean(); + // biome-ignore lint/performance/noDelete: delete process.env.PRERENDER; }); @@ -390,7 +395,7 @@ describe('Trailing slash', () => { }); await fixture.build(); const { startServer } = await fixture.loadAdapterEntryModule(); - let res = startServer(); + const res = startServer(); server = res.server; await waitServerListen(server.server); }); @@ -398,6 +403,7 @@ describe('Trailing slash', () => { after(async () => { await server.stop(); await fixture.clean(); + // biome-ignore lint/performance/noDelete: delete process.env.PRERENDER; }); diff --git a/packages/node/test/url.test.js b/packages/node/test/url.test.js index 77ca4583..81b357b7 100644 --- a/packages/node/test/url.test.js +++ b/packages/node/test/url.test.js @@ -20,7 +20,7 @@ describe('URL', () => { it('return http when non-secure', async () => { const { handler } = await import('./fixtures/url/dist/server/entry.mjs'); - let { req, res, text } = createRequestAndResponse({ + const { req, res, text } = createRequestAndResponse({ url: '/', }); @@ -33,7 +33,7 @@ describe('URL', () => { it('return https when secure', async () => { const { handler } = await import('./fixtures/url/dist/server/entry.mjs'); - let { req, res, text } = createRequestAndResponse({ + const { req, res, text } = createRequestAndResponse({ socket: new TLSSocket(), url: '/', }); @@ -47,7 +47,7 @@ describe('URL', () => { it('return http when the X-Forwarded-Proto header is set to http', async () => { const { handler } = await import('./fixtures/url/dist/server/entry.mjs'); - let { req, res, text } = createRequestAndResponse({ + const { req, res, text } = createRequestAndResponse({ headers: { 'X-Forwarded-Proto': 'http' }, url: '/', }); @@ -61,7 +61,7 @@ describe('URL', () => { it('return https when the X-Forwarded-Proto header is set to https', async () => { const { handler } = await import('./fixtures/url/dist/server/entry.mjs'); - let { req, res, text } = createRequestAndResponse({ + const { req, res, text } = createRequestAndResponse({ headers: { 'X-Forwarded-Proto': 'https' }, url: '/', }); @@ -75,7 +75,7 @@ describe('URL', () => { it('includes forwarded host and port in the url', async () => { const { handler } = await import('./fixtures/url/dist/server/entry.mjs'); - let { req, res, text } = createRequestAndResponse({ + const { req, res, text } = createRequestAndResponse({ headers: { 'X-Forwarded-Proto': 'https', 'X-Forwarded-Host': 'abc.xyz', @@ -95,7 +95,7 @@ describe('URL', () => { it('accepts port in forwarded host and forwarded port', async () => { const { handler } = await import('./fixtures/url/dist/server/entry.mjs'); - let { req, res, text } = createRequestAndResponse({ + const { req, res, text } = createRequestAndResponse({ headers: { 'X-Forwarded-Proto': 'https', 'X-Forwarded-Host': 'abc.xyz:444', diff --git a/packages/node/tsconfig.json b/packages/node/tsconfig.json index b9feb9b9..18443cdd 100644 --- a/packages/node/tsconfig.json +++ b/packages/node/tsconfig.json @@ -1,8 +1,6 @@ { "extends": "../../tsconfig.base.json", - "include": [ - "src" - ], + "include": ["src"], "compilerOptions": { "outDir": "./dist" } diff --git a/packages/vercel/CHANGELOG.md b/packages/vercel/CHANGELOG.md index 4a8d6343..0d6b8778 100644 --- a/packages/vercel/CHANGELOG.md +++ b/packages/vercel/CHANGELOG.md @@ -1234,7 +1234,7 @@ { darkMode: true }, { expires: '1 month', - }, + } ); const prefs = Astro.cookies.get('prefs').json(); diff --git a/packages/vercel/package.json b/packages/vercel/package.json index 0b6ed9e6..494af148 100644 --- a/packages/vercel/package.json +++ b/packages/vercel/package.json @@ -10,10 +10,7 @@ "url": "https://github.com/withastro/astro.git", "directory": "packages/integrations/vercel" }, - "keywords": [ - "withastro", - "astro-adapter" - ], + "keywords": ["withastro", "astro-adapter"], "bugs": "https://github.com/withastro/astro/issues", "homepage": "https://docs.astro.build/en/guides/integrations-guide/vercel/", "exports": { @@ -31,18 +28,11 @@ }, "typesVersions": { "*": { - "serverless": [ - "dist/serverless/adapter.d.ts" - ], - "static": [ - "dist/static/adapter.d.ts" - ] + "serverless": ["dist/serverless/adapter.d.ts"], + "static": ["dist/static/adapter.d.ts"] } }, - "files": [ - "dist", - "types.d.ts" - ], + "files": ["dist", "types.d.ts"], "scripts": { "build": "tsc", "test": "astro-scripts test --timeout 50000 \"test/**/!(hosted).test.js\"", diff --git a/packages/vercel/src/image/build-service.ts b/packages/vercel/src/image/build-service.ts index e793b896..ab2a49e0 100644 --- a/packages/vercel/src/image/build-service.ts +++ b/packages/vercel/src/image/build-service.ts @@ -53,6 +53,7 @@ const service: ExternalImageService = { options.width && searchParams.append('w', options.width.toString()); options.quality && searchParams.append('q', options.quality.toString()); + // biome-ignore lint/style/useTemplate: return '/_vercel/image?' + searchParams; }, }; diff --git a/packages/vercel/src/image/shared-dev-service.ts b/packages/vercel/src/image/shared-dev-service.ts index 8ca87e99..4edf11d3 100644 --- a/packages/vercel/src/image/shared-dev-service.ts +++ b/packages/vercel/src/image/shared-dev-service.ts @@ -15,6 +15,7 @@ export const baseDevService: Omit = { options.width && searchParams.append('w', options.width.toString()); options.quality && searchParams.append('q', options.quality.toString()); + // biome-ignore lint/style/useTemplate: return '/_image?' + searchParams; }, parseURL(url) { @@ -25,8 +26,10 @@ export const baseDevService: Omit = { } const transform = { + // biome-ignore lint/style/noNonNullAssertion: src: params.get('href')!, - width: params.has('w') ? parseInt(params.get('w')!) : undefined, + // biome-ignore lint/style/noNonNullAssertion: + width: params.has('w') ? Number.parseInt(params.get('w')!) : undefined, quality: params.get('q'), }; diff --git a/packages/vercel/src/image/shared.ts b/packages/vercel/src/image/shared.ts index da9342f2..dfae0d06 100644 --- a/packages/vercel/src/image/shared.ts +++ b/packages/vercel/src/image/shared.ts @@ -68,7 +68,7 @@ export function getAstroImageConfig( imagesConfig: VercelImageConfig | undefined, command: string, devImageService: DevImageService, - astroImageConfig: AstroConfig['image'], + astroImageConfig: AstroConfig['image'] ) { let devService = '@astrojs/vercel/dev-image-service'; @@ -105,7 +105,7 @@ export function getAstroImageConfig( export function sharedValidateOptions( options: ImageTransform, serviceConfig: Record, - mode: 'development' | 'production', + mode: 'development' | 'production' ) { const vercelImageOptions = serviceConfig as VercelImageConfig; @@ -145,6 +145,7 @@ export function sharedValidateOptions( } else { if (!configuredWidths.includes(options.width)) { const nearestWidth = configuredWidths.reduce((prev, curr) => { + // biome-ignore lint/style/noNonNullAssertion: return Math.abs(curr - options.width!) < Math.abs(prev - options.width!) ? curr : prev; }); diff --git a/packages/vercel/src/lib/nft.ts b/packages/vercel/src/lib/nft.ts index 7f21f3f2..61dcd8f9 100644 --- a/packages/vercel/src/lib/nft.ts +++ b/packages/vercel/src/lib/nft.ts @@ -18,7 +18,7 @@ export async function copyDependenciesToFunction( logger: AstroIntegrationLogger; }, // we want to pass the caching by reference, and not by value - cache: object, + cache: object ): Promise<{ handler: string }> { const entryPath = fileURLToPath(entry); logger.info(`Bundling function ${relativePath(fileURLToPath(outDir), entryPath)}`); @@ -44,6 +44,7 @@ export async function copyDependenciesToFunction( for (const error of result.warnings) { if (error.message.startsWith('Failed to resolve dependency')) { + // biome-ignore lint/style/noNonNullAssertion: const [, module, file] = /Cannot find module '(.+?)' loaded from (.+)/.exec(error.message)!; // The import(astroRemark) sometimes fails to resolve, but it's not a problem @@ -54,11 +55,11 @@ export async function copyDependenciesToFunction( if (entryPath === file) { logger.debug( - `[@astrojs/vercel] The module "${module}" couldn't be resolved. This may not be a problem, but it's worth checking.`, + `[@astrojs/vercel] The module "${module}" couldn't be resolved. This may not be a problem, but it's worth checking.` ); } else { logger.debug( - `[@astrojs/vercel] The module "${module}" inside the file "${file}" couldn't be resolved. This may not be a problem, but it's worth checking.`, + `[@astrojs/vercel] The module "${module}" inside the file "${file}" couldn't be resolved. This may not be a problem, but it's worth checking.` ); } } @@ -66,6 +67,7 @@ export async function copyDependenciesToFunction( // such as this html file in "main" meant for nw instead of node: // https://github.com/vercel/nft/issues/311 else if (error.message.startsWith('Failed to parse')) { + // biome-ignore lint/correctness/noUnnecessaryContinue: continue; } else { throw error; @@ -75,7 +77,7 @@ export async function copyDependenciesToFunction( const commonAncestor = await copyFilesToFolder( [...result.fileList].map((file) => new URL(file, base)).concat(includeFiles), outDir, - excludeFiles, + excludeFiles ); return { diff --git a/packages/vercel/src/lib/redirects.ts b/packages/vercel/src/lib/redirects.ts index 1e476cb1..54c883b3 100644 --- a/packages/vercel/src/lib/redirects.ts +++ b/packages/vercel/src/lib/redirects.ts @@ -49,19 +49,19 @@ function getMatchPattern(segments: RoutePart[][]) { return segment[0].spread ? '(?:\\/(.*?))?' : segment - .map((part) => { - if (part) - return part.dynamic - ? '([^/]+?)' - : part.content - .normalize() - .replace(/\?/g, '%3F') - .replace(/#/g, '%23') - .replace(/%5B/g, '[') - .replace(/%5D/g, ']') - .replace(/[*+?^${}()|[\]\\]/g, '\\$&'); - }) - .join(''); + .map((part) => { + if (part) + return part.dynamic + ? '([^/]+?)' + : part.content + .normalize() + .replace(/\?/g, '%3F') + .replace(/#/g, '%23') + .replace(/%5B/g, '[') + .replace(/%5D/g, ']') + .replace(/[*+?^${}()|[\]\\]/g, '\\$&'); + }) + .join(''); }) .join('/'); } @@ -72,6 +72,7 @@ function getReplacePattern(segments: RoutePart[][]) { for (const segment of segments) { for (const part of segment) { + // biome-ignore lint/style/useTemplate: if (part.dynamic) result += '$' + ++n; else result += part.content; } @@ -89,8 +90,10 @@ function getRedirectLocation(route: RouteData, config: AstroConfig): string { const pattern = getReplacePattern(route.redirectRoute.segments); const path = config.trailingSlash === 'always' ? appendForwardSlash(pattern) : pattern; return pathJoin(config.base, path); + // biome-ignore lint/style/noUselessElse: } else if (typeof route.redirect === 'object') { return pathJoin(config.base, route.redirect.destination); + // biome-ignore lint/style/noUselessElse: } else { return pathJoin(config.base, route.redirect || ''); } @@ -114,7 +117,7 @@ export function escapeRegex(content: string) { } export function getRedirects(routes: RouteData[], config: AstroConfig): VercelRoute[] { - let redirects: VercelRoute[] = []; + const redirects: VercelRoute[] = []; for (const route of routes) { if (route.type === 'redirect') { @@ -127,11 +130,13 @@ export function getRedirects(routes: RouteData[], config: AstroConfig): VercelRo if (config.trailingSlash === 'always') { redirects.push({ src: config.base + getMatchPattern(route.segments), + // biome-ignore lint/style/useTemplate: headers: { Location: config.base + getReplacePattern(route.segments) + '/' }, status: 308, }); } else if (config.trailingSlash === 'never') { redirects.push({ + // biome-ignore lint/style/useTemplate: src: config.base + getMatchPattern(route.segments) + '/', headers: { Location: config.base + getReplacePattern(route.segments) }, status: 308, diff --git a/packages/vercel/src/lib/speed-insights.ts b/packages/vercel/src/lib/speed-insights.ts index 8e363953..033a705c 100644 --- a/packages/vercel/src/lib/speed-insights.ts +++ b/packages/vercel/src/lib/speed-insights.ts @@ -19,6 +19,7 @@ export function getSpeedInsightsViteConfig(enabled?: boolean) { export function exposeEnv(envs: string[]): Record { const mapped: Record = {}; + // biome-ignore lint/complexity/noForEach: envs .filter((env) => process.env[env]) .forEach((env) => { diff --git a/packages/vercel/src/lib/web-analytics.ts b/packages/vercel/src/lib/web-analytics.ts index d6ee4d78..e994ab65 100644 --- a/packages/vercel/src/lib/web-analytics.ts +++ b/packages/vercel/src/lib/web-analytics.ts @@ -7,6 +7,7 @@ export async function getInjectableWebAnalyticsContent({ }: { mode: 'development' | 'production'; }) { + // biome-ignore lint/style/noUnusedTemplateLiteral: const base = `window.va = window.va || function () { (window.vaq = window.vaq || []).push(arguments); };`; if (mode === 'development') { diff --git a/packages/vercel/src/serverless/adapter.ts b/packages/vercel/src/serverless/adapter.ts index 364d2c86..1d7e64de 100644 --- a/packages/vercel/src/serverless/adapter.ts +++ b/packages/vercel/src/serverless/adapter.ts @@ -194,9 +194,11 @@ export default function vercelServerless({ }: VercelServerlessConfig = {}): AstroIntegration { if (maxDuration) { if (typeof maxDuration !== 'number') { + // biome-ignore lint/style/noUnusedTemplateLiteral: throw new TypeError(`maxDuration must be a number`, { cause: maxDuration }); } if (maxDuration <= 0) { + // biome-ignore lint/style/noUnusedTemplateLiteral: throw new TypeError(`maxDuration must be a positive number`, { cause: maxDuration }); } } @@ -217,10 +219,11 @@ export default function vercelServerless({ 'astro:config:setup': async ({ command, config, updateConfig, injectScript, logger }) => { if (maxDuration && maxDuration > 900) { logger.warn( - `maxDuration is set to ${maxDuration} seconds, which is longer than the maximum allowed duration of 900 seconds.`, + `maxDuration is set to ${maxDuration} seconds, which is longer than the maximum allowed duration of 900 seconds.` ); logger.warn( - `Please make sure that your plan allows for this duration. See https://vercel.com/docs/functions/serverless-functions/runtimes#maxduration for more information.`, + // biome-ignore lint/style/noUnusedTemplateLiteral: + `Please make sure that your plan allows for this duration. See https://vercel.com/docs/functions/serverless-functions/runtimes#maxduration for more information.` ); } @@ -229,7 +232,7 @@ export default function vercelServerless({ 'head-inline', await getInjectableWebAnalyticsContent({ mode: command === 'dev' ? 'development' : 'production', - }), + }) ); } if (command === 'build' && speedInsights?.enabled) { @@ -243,9 +246,10 @@ export default function vercelServerless({ if (vercelConfig.trailingSlash === true && config.trailingSlash === 'always') { logger.warn( '\n' + - `\tYour "vercel.json" \`trailingSlash\` configuration (set to \`true\`) will conflict with your Astro \`trailinglSlash\` configuration (set to \`"always"\`).\n` + - `\tThis would cause infinite redirects under certain conditions and throw an \`ERR_TOO_MANY_REDIRECTS\` error.\n` + - `\tTo prevent this, your Astro configuration is updated to \`"ignore"\` during builds.\n`, + `\tYour "vercel.json" \`trailingSlash\` configuration (set to \`true\`) will conflict with your Astro \`trailinglSlash\` configuration (set to \`"always"\`).\n` + + // biome-ignore lint/style/noUnusedTemplateLiteral: + `\tThis would cause infinite redirects under certain conditions and throw an \`ERR_TOO_MANY_REDIRECTS\` error.\n` + + `\tTo prevent this, your Astro configuration is updated to \`"ignore"\` during builds.\n` ); updateConfig({ trailingSlash: 'ignore', @@ -277,27 +281,32 @@ export default function vercelServerless({ imagesConfig, command, devImageService, - config.image, + config.image ), }); }, 'astro:config:done': ({ setAdapter, config, logger }) => { if (functionPerRoute === true) { logger.warn( + // biome-ignore lint/style/noUnusedTemplateLiteral: `\n` + - `\tVercel's hosting plans might have limits to the number of functions you can create.\n` + - `\tMake sure to check your plan carefully to avoid incurring additional costs.\n` + - `\tYou can set functionPerRoute: false to prevent surpassing the limit.\n`, + `\tVercel's hosting plans might have limits to the number of functions you can create.\n` + + // biome-ignore lint/style/noUnusedTemplateLiteral: + `\tMake sure to check your plan carefully to avoid incurring additional costs.\n` + + // biome-ignore lint/style/noUnusedTemplateLiteral: + `\tYou can set functionPerRoute: false to prevent surpassing the limit.\n` ); logger.warn( + // biome-ignore lint/style/noUnusedTemplateLiteral: `\n` + - `\t\`functionPerRoute\` is deprecated and will be removed in a future version of the adapter.\n`, + // biome-ignore lint/style/noUnusedTemplateLiteral: + `\t\`functionPerRoute\` is deprecated and will be removed in a future version of the adapter.\n` ); } setAdapter( - getAdapter({ functionPerRoute, edgeMiddleware, middlewareSecret, skewProtection }), + getAdapter({ functionPerRoute, edgeMiddleware, middlewareSecret, skewProtection }) ); _config = config; @@ -306,13 +315,13 @@ export default function vercelServerless({ if (config.output === 'static') { throw new AstroError( - '`output: "server"` or `output: "hybrid"` is required to use the serverless adapter.', + '`output: "server"` or `output: "hybrid"` is required to use the serverless adapter.' ); } }, 'astro:build:ssr': async ({ entryPoints, middlewareEntryPoint }) => { _entryPoints = new Map( - Array.from(entryPoints).filter(([routeData]) => !routeData.prerender), + Array.from(entryPoints).filter(([routeData]) => !routeData.prerender) ); _middlewareEntryPoint = middlewareEntryPoint; }, @@ -397,12 +406,13 @@ export default function vercelServerless({ await builder.buildMiddlewareFolder( _middlewareEntryPoint, MIDDLEWARE_PATH, - middlewareSecret, + middlewareSecret ); } const fourOhFourRoute = routes.find((route) => route.pathname === '/404'); // Output configuration // https://vercel.com/docs/build-output-api/v3#build-output-configuration + // biome-ignore lint/style/noUnusedTemplateLiteral: await writeJson(new URL(`./config.json`, _config.outDir), { version: 3, routes: [ @@ -416,31 +426,31 @@ export default function vercelServerless({ ...routeDefinitions, ...(fourOhFourRoute ? [ - { - src: '/.*', - dest: fourOhFourRoute.prerender - ? '/404.html' - : _middlewareEntryPoint - ? MIDDLEWARE_PATH - : NODE_PATH, - status: 404, - }, - ] + { + src: '/.*', + dest: fourOhFourRoute.prerender + ? '/404.html' + : _middlewareEntryPoint + ? MIDDLEWARE_PATH + : NODE_PATH, + status: 404, + }, + ] : []), ], ...(imageService || imagesConfig ? { - images: imagesConfig - ? { - ...imagesConfig, - domains: [...imagesConfig.domains, ..._config.image.domains], - remotePatterns: [ - ...(imagesConfig.remotePatterns ?? []), - ..._config.image.remotePatterns, - ], - } - : getDefaultImageConfig(_config.image), - } + images: imagesConfig + ? { + ...imagesConfig, + domains: [...imagesConfig.domains, ..._config.image.domains], + remotePatterns: [ + ...(imagesConfig.remotePatterns ?? []), + ..._config.image.remotePatterns, + ], + } + : getDefaultImageConfig(_config.image), + } : {}), }); @@ -472,8 +482,8 @@ class VercelBuilder { readonly includeFiles: URL[], readonly logger: AstroIntegrationLogger, readonly maxDuration?: number, - readonly runtime = getRuntime(process, logger), - ) {} + readonly runtime = getRuntime(process, logger) + ) { } async buildServerlessFolder(entry: URL, functionName: string) { const { config, includeFiles, excludeFiles, logger, NTF_CACHE, runtime, maxDuration } = this; @@ -491,7 +501,7 @@ class VercelBuilder { excludeFiles, logger, }, - NTF_CACHE, + NTF_CACHE ); // Enable ESM @@ -513,7 +523,7 @@ class VercelBuilder { await this.buildServerlessFolder(entry, functionName); const prerenderConfig = new URL( `./functions/${functionName}.prerender-config.json`, - this.config.outDir, + this.config.outDir ); // https://vercel.com/docs/build-output-api/v3/primitives#prerender-configuration-file await writeJson(prerenderConfig, { @@ -533,9 +543,10 @@ class VercelBuilder { new URL(VERCEL_EDGE_MIDDLEWARE_FILE, this.config.srcDir), new URL('./middleware.mjs', functionFolder), middlewareSecret, - this.logger, + this.logger ); + // biome-ignore lint/style/noUnusedTemplateLiteral: await writeJson(new URL(`./.vc-config.json`, functionFolder), { runtime: 'edge', entrypoint: 'middleware.mjs', @@ -549,10 +560,14 @@ function getRuntime(process: NodeJS.Process, logger: AstroIntegrationLogger): Ru const support = SUPPORTED_NODE_VERSIONS[major]; if (support === undefined) { logger.warn( + // biome-ignore lint/style/noUnusedTemplateLiteral: + // biome-ignore lint/style/useTemplate: `\n` + - `\tThe local Node.js version (${major}) is not supported by Vercel Serverless Functions.\n` + - `\tYour project will use Node.js 18 as the runtime instead.\n` + - `\tConsider switching your local version to 18.\n`, + `\tThe local Node.js version (${major}) is not supported by Vercel Serverless Functions.\n` + + // biome-ignore lint/style/noUnusedTemplateLiteral: + `\tYour project will use Node.js 18 as the runtime instead.\n` + + // biome-ignore lint/style/noUnusedTemplateLiteral: + `\tConsider switching your local version to 18.\n` ); return 'nodejs18.x'; } @@ -562,26 +577,29 @@ function getRuntime(process: NodeJS.Process, logger: AstroIntegrationLogger): Ru if (support.status === 'retiring') { if (support.warnDate && new Date() >= support.warnDate) { logger.warn( - `Your project is being built for Node.js ${major} as the runtime, which is retiring by ${support.removal}.`, + `Your project is being built for Node.js ${major} as the runtime, which is retiring by ${support.removal}.` ); } return `nodejs${major}.x`; } if (support.status === 'beta') { logger.warn( - `Your project is being built for Node.js ${major} as the runtime, which is currently in beta for Vercel Serverless Functions.`, + `Your project is being built for Node.js ${major} as the runtime, which is currently in beta for Vercel Serverless Functions.` ); return `nodejs${major}.x`; } if (support.status === 'deprecated') { const removeDate = new Intl.DateTimeFormat(undefined, { dateStyle: 'long' }).format( - support.removal, + support.removal ); logger.warn( + // biome-ignore lint/style/noUnusedTemplateLiteral: + // biome-ignore lint/style/useTemplate: `\n` + - `\tYour project is being built for Node.js ${major} as the runtime.\n` + - `\tThis version is deprecated by Vercel Serverless Functions, and scheduled to be disabled on ${removeDate}.\n` + - `\tConsider upgrading your local version to 18.\n`, + `\tYour project is being built for Node.js ${major} as the runtime.\n` + + `\tThis version is deprecated by Vercel Serverless Functions, and scheduled to be disabled on ${removeDate}.\n` + + // biome-ignore lint/style/noUnusedTemplateLiteral: + `\tConsider upgrading your local version to 18.\n` ); return `nodejs${major}.x`; } diff --git a/packages/vercel/src/serverless/entrypoint.ts b/packages/vercel/src/serverless/entrypoint.ts index a881d701..31f78bb8 100644 --- a/packages/vercel/src/serverless/entrypoint.ts +++ b/packages/vercel/src/serverless/entrypoint.ts @@ -19,7 +19,7 @@ await import('astro/env/setup') export const createExports = ( manifest: SSRManifest, - { middlewareSecret, skewProtection }: { middlewareSecret: string; skewProtection: boolean }, + { middlewareSecret, skewProtection }: { middlewareSecret: string; skewProtection: boolean } ) => { const app = new NodeApp(manifest); const handler = async (req: IncomingMessage, res: ServerResponse) => { diff --git a/packages/vercel/src/serverless/middleware.ts b/packages/vercel/src/serverless/middleware.ts index 07d0843b..ca84bff3 100644 --- a/packages/vercel/src/serverless/middleware.ts +++ b/packages/vercel/src/serverless/middleware.ts @@ -26,13 +26,13 @@ export async function generateEdgeMiddleware( vercelEdgeMiddlewareHandlerPath: URL, outPath: URL, middlewareSecret: string, - logger: AstroIntegrationLogger, + logger: AstroIntegrationLogger ): Promise { const code = edgeMiddlewareTemplate( astroMiddlewareEntryPointPath, vercelEdgeMiddlewareHandlerPath, middlewareSecret, - logger, + logger ); // https://vercel.com/docs/concepts/functions/edge-middleware#create-edge-middleware const bundledFilePath = fileURLToPath(outPath); @@ -57,6 +57,7 @@ export async function generateEdgeMiddleware( name: 'esbuild-namespace-node-built-in-modules', setup(build) { const filter = new RegExp(builtinModules.map((mod) => `(^${mod}$)`).join('|')); + // biome-ignore lint/style/useTemplate: build.onResolve({ filter }, (args) => ({ path: 'node:' + args.path, external: true })); }, }, @@ -69,20 +70,22 @@ function edgeMiddlewareTemplate( astroMiddlewareEntryPointPath: URL, vercelEdgeMiddlewareHandlerPath: URL, middlewareSecret: string, - logger: AstroIntegrationLogger, + logger: AstroIntegrationLogger ) { const middlewarePath = JSON.stringify( - fileURLToPath(astroMiddlewareEntryPointPath).replace(/\\/g, '/'), + fileURLToPath(astroMiddlewareEntryPointPath).replace(/\\/g, '/') ); const filePathEdgeMiddleware = fileURLToPath(vercelEdgeMiddlewareHandlerPath); let handlerTemplateImport = ''; let handlerTemplateCall = '{}'; + // biome-ignore lint/style/useTemplate: if (existsSync(filePathEdgeMiddleware + '.js') || existsSync(filePathEdgeMiddleware + '.ts')) { logger.warn( - 'Usage of `vercel-edge-middleware.js` is deprecated. You can now use the `waitUntil(promise)` function directly as `ctx.locals.waitUntil(promise)`.', + 'Usage of `vercel-edge-middleware.js` is deprecated. You can now use the `waitUntil(promise)` function directly as `ctx.locals.waitUntil(promise)`.' ); const stringified = JSON.stringify(filePathEdgeMiddleware.replace(/\\/g, '/')); handlerTemplateImport = `import handler from ${stringified}`; + // biome-ignore lint/style/noUnusedTemplateLiteral: handlerTemplateCall = `await handler({ request, context })`; } else { } diff --git a/packages/vercel/src/speed-insights.ts b/packages/vercel/src/speed-insights.ts index cd2ae7fe..e8634a27 100644 --- a/packages/vercel/src/speed-insights.ts +++ b/packages/vercel/src/speed-insights.ts @@ -7,8 +7,11 @@ type Options = { path: string; analyticsId: string }; const getConnectionSpeed = () => { return 'connection' in navigator && + // biome-ignore lint/complexity/useLiteralKeys: navigator['connection'] && + // biome-ignore lint/complexity/useLiteralKeys: 'effectiveType' in (navigator['connection'] as unknown as { effectiveType: string }) + // biome-ignore lint/complexity/useLiteralKeys: ? (navigator['connection'] as unknown as { effectiveType: string })['effectiveType'] : ''; }; diff --git a/packages/vercel/src/static/adapter.ts b/packages/vercel/src/static/adapter.ts index efe3d2da..bb576299 100644 --- a/packages/vercel/src/static/adapter.ts +++ b/packages/vercel/src/static/adapter.ts @@ -74,7 +74,7 @@ export default function vercelStatic({ 'head-inline', await getInjectableWebAnalyticsContent({ mode: command === 'dev' ? 'development' : 'production', - }), + }) ); } if (command === 'build' && speedInsights?.enabled) { @@ -95,7 +95,7 @@ export default function vercelStatic({ imagesConfig, command, devImageService, - config.image, + config.image ), }); }, @@ -128,27 +128,29 @@ export default function vercelStatic({ { handle: 'filesystem' }, ...(routes.find((route) => route.pathname === '/404') ? [ - { - src: `/.*`, - dest: `/404.html`, - status: 404, - }, - ] + { + // biome-ignore lint/style/noUnusedTemplateLiteral: + src: `/.*`, + // biome-ignore lint/style/noUnusedTemplateLiteral: + dest: `/404.html`, + status: 404, + }, + ] : []), ], ...(imageService || imagesConfig ? { - images: imagesConfig - ? { - ...imagesConfig, - domains: [...imagesConfig.domains, ..._config.image.domains], - remotePatterns: [ - ...(imagesConfig.remotePatterns ?? []), - ..._config.image.remotePatterns, - ], - } - : getDefaultImageConfig(_config.image), - } + images: imagesConfig + ? { + ...imagesConfig, + domains: [...imagesConfig.domains, ..._config.image.domains], + remotePatterns: [ + ...(imagesConfig.remotePatterns ?? []), + ..._config.image.remotePatterns, + ], + } + : getDefaultImageConfig(_config.image), + } : {}), }); }, diff --git a/packages/vercel/test/edge-middleware.test.js b/packages/vercel/test/edge-middleware.test.js index 9ae583a1..4e67433d 100644 --- a/packages/vercel/test/edge-middleware.test.js +++ b/packages/vercel/test/edge-middleware.test.js @@ -14,7 +14,7 @@ describe('Vercel edge middleware', () => { it('an edge function is created', async () => { const contents = await build.readFile( - '../.vercel/output/functions/_middleware.func/.vc-config.json', + '../.vercel/output/functions/_middleware.func/.vc-config.json' ); const contentsJSON = JSON.parse(contents); assert.equal(contentsJSON.runtime, 'edge'); @@ -26,14 +26,14 @@ describe('Vercel edge middleware', () => { const { routes } = JSON.parse(contents); assert.equal( routes.some((route) => route.dest === '_middleware'), - true, + true ); }); it('edge sets Set-Cookie headers', async () => { - let entry = new URL( + const entry = new URL( '../.vercel/output/functions/_middleware.func/middleware.mjs', - build.config.outDir, + build.config.outDir ); const module = await import(entry); const request = new Request('http://example.com/foo'); @@ -50,7 +50,7 @@ describe('Vercel edge middleware', () => { await fixture.build(); const contents = await fixture.readFile( // this is abysmal... - '../.vercel/output/functions/render.func/www/withastro/astro/packages/integrations/vercel/test/fixtures/middleware-with-edge-file/dist/middleware.mjs', + '../.vercel/output/functions/render.func/www/withastro/astro/packages/integrations/vercel/test/fixtures/middleware-with-edge-file/dist/middleware.mjs' ); console.log(contents); // assert.equal(contents.includes('title:')).to.be.true; @@ -66,7 +66,7 @@ describe('Vercel edge middleware', () => { await fixture.build(); const contents = await fixture.readFile( // this is abysmal... - '../.vercel/output/functions/render.func/www/withastro/astro/packages/integrations/vercel/test/fixtures/middleware-without-edge-file/dist/middleware.mjs', + '../.vercel/output/functions/render.func/www/withastro/astro/packages/integrations/vercel/test/fixtures/middleware-without-edge-file/dist/middleware.mjs' ); console.log(contents); // assert.equal(contents.includes('title:')).to.be.false; diff --git a/packages/vercel/test/hosted/hosted.test.js b/packages/vercel/test/hosted/hosted.test.js index e090188a..d7c2ece2 100644 --- a/packages/vercel/test/hosted/hosted.test.js +++ b/packages/vercel/test/hosted/hosted.test.js @@ -6,7 +6,8 @@ const VERCEL_TEST_URL = 'https://astro-vercel-image-test.vercel.app'; describe('Hosted Vercel Tests', () => { it('Image endpoint works', async () => { const image = await fetch( - VERCEL_TEST_URL + '/_image?href=%2F_astro%2Fpenguin.e9c64733.png&w=300&f=webp', + // biome-ignore lint/style/useTemplate: + VERCEL_TEST_URL + '/_image?href=%2F_astro%2Fpenguin.e9c64733.png&w=300&f=webp' ); assert.equal(image.status, 200); diff --git a/packages/vercel/test/isr.test.js b/packages/vercel/test/isr.test.js index fb957aa7..a8df2c0e 100644 --- a/packages/vercel/test/isr.test.js +++ b/packages/vercel/test/isr.test.js @@ -15,7 +15,7 @@ describe('ISR', () => { it('generates expected prerender config', async () => { const vcConfig = JSON.parse( - await fixture.readFile('../.vercel/output/functions/_isr.prerender-config.json'), + await fixture.readFile('../.vercel/output/functions/_isr.prerender-config.json') ); assert.deepEqual(vcConfig, { expiration: 120, diff --git a/packages/vercel/test/max-duration.test.js b/packages/vercel/test/max-duration.test.js index d5e26fc1..2a769866 100644 --- a/packages/vercel/test/max-duration.test.js +++ b/packages/vercel/test/max-duration.test.js @@ -15,7 +15,7 @@ describe('maxDuration', () => { it('makes it to vercel function configuration', async () => { const vcConfig = JSON.parse( - await fixture.readFile('../.vercel/output/functions/_render.func/.vc-config.json'), + await fixture.readFile('../.vercel/output/functions/_render.func/.vc-config.json') ); assert.equal(vcConfig.maxDuration, 60); }); diff --git a/packages/vercel/test/redirects.test.js b/packages/vercel/test/redirects.test.js index 9d4f9499..57de308e 100644 --- a/packages/vercel/test/redirects.test.js +++ b/packages/vercel/test/redirects.test.js @@ -77,7 +77,7 @@ describe('Redirects', () => { const config = await getConfig(); assert.equal( config.routes.find((r) => r.src === '/'), - undefined, + undefined ); }); }); diff --git a/packages/vercel/test/server-islands.test.js b/packages/vercel/test/server-islands.test.js index 0306bb8b..f4f17670 100644 --- a/packages/vercel/test/server-islands.test.js +++ b/packages/vercel/test/server-islands.test.js @@ -16,7 +16,7 @@ describe('Server Islands', () => { it('server islands route is in the config', async () => { const config = JSON.parse(await fixture.readFile('../.vercel/output/config.json')); let found = null; - for (let route of config.routes) { + for (const route of config.routes) { if (route.src?.includes('_server-islands')) { found = route; break; diff --git a/packages/vercel/test/serverless-prerender.test.js b/packages/vercel/test/serverless-prerender.test.js index 61e23930..5b75418c 100644 --- a/packages/vercel/test/serverless-prerender.test.js +++ b/packages/vercel/test/serverless-prerender.test.js @@ -20,7 +20,7 @@ describe('Serverless prerender', () => { it('outDir is tree-shaken if not needed', async () => { const [file] = await fixture.glob( - '../.vercel/output/functions/_render.func/packages/integrations/vercel/test/fixtures/serverless-prerender/.vercel/output/_functions/pages/_image.astro.mjs', + '../.vercel/output/functions/_render.func/packages/integrations/vercel/test/fixtures/serverless-prerender/.vercel/output/_functions/pages/_image.astro.mjs' ); const contents = await fixture.readFile(file); assert.ok(!contents.includes('const outDir ='), "outDir is tree-shaken if it's not imported"); @@ -30,8 +30,8 @@ describe('Serverless prerender', () => { it.skip('includeFiles work', async () => { assert.ok( await fixture.readFile( - '../.vercel/output/functions/render.func/packages/integrations/vercel/test/fixtures/serverless-prerender/dist/middleware.mjs', - ), + '../.vercel/output/functions/render.func/packages/integrations/vercel/test/fixtures/serverless-prerender/dist/middleware.mjs' + ) ); }); }); diff --git a/packages/vercel/test/serverless-with-dynamic-routes.test.js b/packages/vercel/test/serverless-with-dynamic-routes.test.js index 3f961383..0967f864 100644 --- a/packages/vercel/test/serverless-with-dynamic-routes.test.js +++ b/packages/vercel/test/serverless-with-dynamic-routes.test.js @@ -18,10 +18,10 @@ describe('Serverless with dynamic routes', () => { it('build successful', async () => { assert.ok(await fixture.readFile('../.vercel/output/static/index.html')); assert.ok( - await fixture.readFile('../.vercel/output/functions/[id]/index.astro.func/.vc-config.json'), + await fixture.readFile('../.vercel/output/functions/[id]/index.astro.func/.vc-config.json') ); assert.ok( - await fixture.readFile('../.vercel/output/functions/api/[id].js.func/.vc-config.json'), + await fixture.readFile('../.vercel/output/functions/api/[id].js.func/.vc-config.json') ); }); }); diff --git a/packages/vercel/test/split.test.js b/packages/vercel/test/split.test.js index 4105db7f..e64a4dc6 100644 --- a/packages/vercel/test/split.test.js +++ b/packages/vercel/test/split.test.js @@ -26,7 +26,7 @@ describe('build: split', () => { assert.equal(config.routes.length, 5); assert.equal( config.routes.some((route) => route.dest === 'prerender.astro'), - false, + false ); }); }); diff --git a/packages/vercel/test/streaming.test.js b/packages/vercel/test/streaming.test.js index 1e4b0f11..a0172a7e 100644 --- a/packages/vercel/test/streaming.test.js +++ b/packages/vercel/test/streaming.test.js @@ -15,7 +15,7 @@ describe('streaming', () => { it('makes it to vercel function configuration', async () => { const vcConfig = JSON.parse( - await fixture.readFile('../.vercel/output/functions/_render.func/.vc-config.json'), + await fixture.readFile('../.vercel/output/functions/_render.func/.vc-config.json') ); assert.equal(vcConfig.supportsResponseStreaming, true); }); diff --git a/packages/vercel/tsconfig.json b/packages/vercel/tsconfig.json index b9feb9b9..18443cdd 100644 --- a/packages/vercel/tsconfig.json +++ b/packages/vercel/tsconfig.json @@ -1,8 +1,6 @@ { "extends": "../../tsconfig.base.json", - "include": [ - "src" - ], + "include": ["src"], "compilerOptions": { "outDir": "./dist" }